This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 24357
Collapse All | Expand All

(-)a/autoupdate.services/libsrc/org/netbeans/updater/ModuleUpdater.java (-6 / +146 lines)
Lines 42-47 Link Here
42
package org.netbeans.updater;
42
package org.netbeans.updater;
43
43
44
import java.io.*;
44
import java.io.*;
45
import java.lang.reflect.Method;
45
import java.util.*;
46
import java.util.*;
46
import java.util.jar.*;
47
import java.util.jar.*;
47
48
Lines 354-359 Link Here
354
                try {
355
                try {
355
                    jarFile = new JarFile (nbm);
356
                    jarFile = new JarFile (nbm);
356
                    Enumeration entries = jarFile.entries();
357
                    Enumeration entries = jarFile.entries();
358
                    List <String> list = new ArrayList <String> (jarFile.size());
359
                    List <String> executableList = new ArrayList <String> ();
357
                    while( entries.hasMoreElements() ) {
360
                    while( entries.hasMoreElements() ) {
358
                        JarEntry entry = (JarEntry) entries.nextElement();
361
                        JarEntry entry = (JarEntry) entries.nextElement();
359
                        checkStop();
362
                        checkStop();
Lines 375-388 Link Here
375
                                    File bckFile = new File( getBackupDirectory (cluster), entry.getName() );
378
                                    File bckFile = new File( getBackupDirectory (cluster), entry.getName() );
376
                                    bckFile.getParentFile ().mkdirs ();
379
                                    bckFile.getParentFile ().mkdirs ();
377
                                    // System.out.println("Backing up" ); // NOI18N
380
                                    // System.out.println("Backing up" ); // NOI18N
378
                                    copyStreams( new FileInputStream( destFile ), new FileOutputStream( bckFile ), -1 );
381
                                    copyStreams( new FileInputStream( destFile ), bckFile, -1, list, executableList );
379
                                    if (!destFile.delete() && isWindows()) {
382
                                    if (!destFile.delete() && isWindows()) {
380
                                        trickyDeleteOnWindows(destFile);
383
                                        trickyDeleteOnWindows(destFile);
381
                                    }
384
                                    }
382
                                } else {
385
                                } else {
383
                                    destFile.getParentFile ().mkdirs ();
386
                                    destFile.getParentFile ().mkdirs ();
384
                                }
387
                                }
385
                                bytesRead = copyStreams( jarFile.getInputStream( entry ), new FileOutputStream( destFile ), bytesRead );
388
                                bytesRead = copyStreams( jarFile.getInputStream( entry ), destFile, bytesRead, list, executableList );
386
                                UpdaterFrame.setProgressValue( bytesRead );
389
                                UpdaterFrame.setProgressValue( bytesRead );
387
                            }
390
                            }
388
                        } else if ( entry.getName().startsWith( UPDATE_MAIN_DIR )&&
391
                        } else if ( entry.getName().startsWith( UPDATE_MAIN_DIR )&&
Lines 392-401 Link Here
392
                                entry.getName().substring(UPDATE_MAIN_DIR.length() + 1) );
395
                                entry.getName().substring(UPDATE_MAIN_DIR.length() + 1) );
393
                            destFile.getParentFile ().mkdirs ();
396
                            destFile.getParentFile ().mkdirs ();
394
                            hasMainClass = true;
397
                            hasMainClass = true;
395
                            bytesRead = copyStreams( jarFile.getInputStream( entry ), new FileOutputStream( destFile ), bytesRead );
398
                            bytesRead = copyStreams( jarFile.getInputStream( entry ), destFile, bytesRead, list, executableList );
396
                            UpdaterFrame.setProgressValue( bytesRead );
399
                            UpdaterFrame.setProgressValue( bytesRead );
397
                        }
400
                        }
398
                    }
401
                    }
402
                    fixPermissions(list,executableList);
399
                    if ( hasMainClass ) {                    
403
                    if ( hasMainClass ) {                    
400
                        MainConfig mconfig = new MainConfig (getMainDirString (cluster) + UpdateTracking.FILE_SEPARATOR + JVM_PARAMS_FILE, cluster);
404
                        MainConfig mconfig = new MainConfig (getMainDirString (cluster) + UpdateTracking.FILE_SEPARATOR + JVM_PARAMS_FILE, cluster);
401
                        if (mconfig.isValid()) {
405
                        if (mconfig.isValid()) {
Lines 532-537 Link Here
532
    private String getMainDirString (File activeCluster) {
536
    private String getMainDirString (File activeCluster) {
533
        return getMainDirectory (activeCluster).getPath ();
537
        return getMainDirectory (activeCluster).getPath ();
534
    }
538
    }
539
540
541
    private void fixPermissions(List<String> list, List <String> executableList) {
542
        if (!isWindows() && !list.isEmpty()) {
543
            List<String> commands = new ArrayList<String>();
544
            commands.add("/usr/bin/file");
545
            commands.addAll(list);
546
547
            String filesInfo = readCommandOutput(commands);
548
            List<String> fileExecutables = new ArrayList<String>();
549
            for (String s : filesInfo.split("(?:\r\n|\n|\r)")) {//split by lines
550
                int colonIndex = s.indexOf(":");
551
                if (colonIndex != -1) {
552
                    String filePath = s.substring(0, colonIndex).trim();
553
                    String fileType = s.substring(colonIndex + 1);
554
                    if (fileType.contains("executable") ||
555
                            fileType.contains("dynamic lib") ||
556
                            fileType.contains("shared object") ||
557
                            fileType.contains("shared library") ||
558
                            fileType.contains("universal binary") ||
559
                            fileType.contains("shell script")) {
560
                        boolean exist = false;
561
                        try {
562
                            exist = new File(filePath).exists();
563
                        } catch (Exception e) {
564
                        }
565
                        if(exist) {
566
                            fileExecutables.add(filePath);
567
                            //System.out.println("Executable [/usr/bin/file]: " + filePath);
568
                        }
569
                        
570
                    }
571
                }
572
            }
573
            List <String> allExecutables = new ArrayList<String> ();
574
            allExecutables.addAll(fileExecutables);
575
            for(String s : executableList) {
576
                    if(!allExecutables.contains(s)) {
577
                        //System.out.println("Executable [ interpreter ]: " + s);
578
                        allExecutables.add(s);
579
                    }
580
                }
581
            chmod(allExecutables);
582
        }
583
    }
584
585
    private void chmod(List <String> executables) {
586
        if(executables.isEmpty()) {
587
            return ;
588
        }
589
        if(System.getProperty("java.version").startsWith("1.5")) {
590
            // Find chmod
591
            File chmod = new File("/bin/chmod"); // NOI18N
592
            if (!chmod.isFile()) {
593
                chmod = new File("/usr/bin/chmod"); // NOI18N
594
            }
595
            if (chmod.isFile()) {
596
                List <String> commands = new ArrayList<String>(executables.size() + 2);
597
                commands.add(chmod.getAbsolutePath());
598
                commands.add("a+x"); // NOI18N
599
                commands.addAll(executables);
600
                try {
601
                    System.out.println("Executing command : " + commands);
602
                    new ProcessBuilder(commands).start().waitFor();
603
                } catch (Exception e) {
604
                    e.printStackTrace();
605
                }
606
            }
607
        } else {
608
            // Determine if java.io.File.setExecutable method is supported
609
            try {
610
                Method setExecutableMethod = File.class.getMethod("setExecutable", Boolean.TYPE, Boolean.TYPE);
611
                for(String s : executables) {
612
                    setExecutableMethod.invoke(new File(s), true, false);
613
                }
614
            } catch (Exception e) {
615
                e.printStackTrace();
616
            }
617
        }
618
    }
619
620
    private String readCommandOutput(List<String> command) {
621
        ProcessBuilder builder = new ProcessBuilder(command);
622
        boolean doRun = true;
623
        StringBuilder sb = new StringBuilder();
624
        byte[] bytes = new byte[8192];
625
        int c = 0;
626
627
        try {
628
            Process process = builder.start();
629
            while (doRun) {
630
                try {
631
                    Thread.sleep(20);
632
                } catch (InterruptedException e) {
633
                }
634
                try {
635
                    process.exitValue();
636
                    doRun = false;
637
                } catch (IllegalThreadStateException e) {
638
                    ; // do nothing - the process is still running
639
                }
640
                InputStream is = process.getInputStream();
641
                while ((c = is.read(bytes)) != -1) {
642
                    sb.append(new String(bytes, 0, c));
643
                }
644
            }
645
            return sb.toString();
646
        } catch (IOException e) {
647
            e.printStackTrace();
648
            return new String();
649
        }
650
    }
535
    
651
    
536
     /** Quotes string correctly, eg. removes all quotes from the string and adds 
652
     /** Quotes string correctly, eg. removes all quotes from the string and adds 
537
      * just one at the start and
653
      * just one at the start and
Lines 564-571 Link Here
564
     * @param progressVal The current progress bar value.  If this is
680
     * @param progressVal The current progress bar value.  If this is
565
     *          negative, we don't want to update the progress bar.
681
     *          negative, we don't want to update the progress bar.
566
     */
682
     */
567
    private long copyStreams( InputStream src, OutputStream dest,
683
     private long copyStreams( InputStream src, File destFile,
568
                               long progressVal ) throws java.io.IOException {
684
                               long progressVal, List <String> list, List <String> executableList ) throws java.io.IOException {
685
        OutputStream dest = new FileOutputStream(destFile);
686
        list.add(destFile.getAbsolutePath());
569
687
570
        BufferedInputStream bsrc = new BufferedInputStream( src );
688
        BufferedInputStream bsrc = new BufferedInputStream( src );
571
        BufferedOutputStream bdest = new BufferedOutputStream( dest );
689
        BufferedOutputStream bdest = new BufferedOutputStream( dest );
Lines 574-583 Link Here
574
692
575
        int c;
693
        int c;
576
        byte [] bytes = new byte [8192];
694
        byte [] bytes = new byte [8192];
577
695
        boolean read = false;
578
        try {
696
        try {
579
            while( ( c = bsrc.read(bytes) ) != -1 ) {
697
            while( ( c = bsrc.read(bytes) ) != -1 ) {
580
                bdest.write(bytes, 0, c);
698
                bdest.write(bytes, 0, c);
699
                if (!read) {
700
                    read = true;
701
                    if (c >= 4) { // length of ELF header and min length of "#!/X" string
702
                        if (bytes[0] == '\177' &&
703
                                bytes[1] == 'E' &&
704
                                bytes[2] == 'L' &&
705
                                bytes[3] == 'F') {
706
                            executableList.add(destFile.getAbsolutePath());
707
                        } else if (bytes[0] == '#' && bytes[1] == '!') {
708
                            String s = new String(bytes, 0, c);
709
                            String[] array = s.split("(?:\r\n|\n|\r)");
710
711
                            if (array.length > 0) {
712
                                //read the first line only
713
                                //allow lines like "#! /bin/sh"
714
                                if (array[0].replaceAll("#!(\\s)+/", "#!/").startsWith("#!/")) {
715
                                    executableList.add(destFile.getAbsolutePath());
716
                                }
717
                            }
718
                        }
719
                    }
720
                }
581
                count+=c;
721
                count+=c;
582
                if ( count > 8500 ) {
722
                if ( count > 8500 ) {
583
                    if (progressVal >= 0) {
723
                    if (progressVal >= 0) {
(-)a/autoupdate.services/test/unit/src/org/netbeans/modules/autoupdate/services/ExecutablePermissionsTest.java (+178 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.autoupdate.services;
42
43
import java.io.File;
44
import java.io.IOException;
45
import java.io.InputStream;
46
import java.lang.reflect.Method;
47
import java.util.HashMap;
48
import java.util.Map;
49
import org.netbeans.api.autoupdate.UpdateUnit;
50
import org.netbeans.spi.autoupdate.UpdateItem;
51
import org.netbeans.spi.autoupdate.UpdateProvider;
52
53
/**
54
 *
55
 * @author Dmitry Lipin
56
 */
57
public class ExecutablePermissionsTest extends NbmAdvancedTestCase {
58
59
    private UpdateProvider p = null;
60
    private String testModuleVersion = "1.0";
61
    private String testModuleName = "org.yourorghere.executable.permissions";
62
63
    public ExecutablePermissionsTest(String name) {
64
        super(name);
65
    }
66
67
    @Override
68
    protected void setUp() throws IOException, Exception {
69
        super.setUp();
70
    }
71
72
    @Override
73
    public boolean canRun() {
74
        return super.canRun() && !System.getProperty("os.name").startsWith("Windows");
75
    }
76
77
    private String generateExecutablePermissionsModuleElement() {
78
        String res = "\n<module codenamebase=\"" + testModuleName + "\" " +
79
                "homepage=\"http://www.netbeans.org/\" distribution=\"nbresloc:/org/netbeans/api/autoupdate/data/org-yourorghere-executable-permissions.nbm\" " +
80
                "license=\"standard-nbm-license.txt\" downloadsize=\"5122\" " +
81
                "needsrestart=\"false\" moduleauthor=\"\" " +
82
                "eager=\"false\" " +
83
                "releasedate=\"2006/02/23\">\n";
84
        res += "<manifest OpenIDE-Module=\"" + testModuleName + "\" " +
85
                "OpenIDE-Module-Name=\"" + testModuleName + "\" " +
86
                "AutoUpdate-Show-In-Client=\"true\" " +
87
                "OpenIDE-Module-Specification-Version=\"" + testModuleVersion + "\"/>\n";
88
        res += "</module>";
89
        return res;
90
    }
91
92
    public void testExecutablePermissionsModule() throws IOException {
93
        String os = !org.openide.util.Utilities.isUnix() ? "Windows" : "Unix";
94
        String catalog = generateCatalog(generateExecutablePermissionsModuleElement());
95
96
        p = createUpdateProvider(catalog);
97
        p.refresh(true);
98
99
        Map<String, UpdateUnit> unitImpls = new HashMap<String, UpdateUnit>();
100
        Map<String, UpdateItem> updates = p.getUpdateItems();
101
        assertNotNull("Some modules are installed.", updates);
102
        assertFalse("Some modules are installed.", updates.isEmpty());
103
        assertTrue(testModuleName + " found in parsed items.", updates.keySet().contains(testModuleName + "_" + testModuleVersion));
104
105
        Map<String, UpdateUnit> newImpls = UpdateUnitFactory.getDefault().appendUpdateItems(unitImpls, p);
106
        assertNotNull("Some units found.", newImpls);
107
        assertFalse("Some units found.", newImpls.isEmpty());
108
109
        UpdateUnit u1 = newImpls.get(testModuleName);
110
        installUpdateUnit(u1);
111
        File binDir = new File(userDir, "bin");
112
        File elfFile = new File(binDir, "elf");
113
        File runFile = new File(binDir, "run.sh");
114
        File runSpaceFile = new File(binDir, "run_space.sh");
115
        for (File f : new File[]{elfFile, runFile, runSpaceFile}) {
116
            assertTrue("File " + f + " should exist after module installation", f.exists());
117
            if (System.getProperty("java.version").startsWith("1.5")) {
118
                File ls = new File("/bin/ls");
119
                if (!ls.isFile()) {
120
                    ls = new File("/usr/bin/ls");
121
                }
122
                String output = readCommandOutput(ls.getAbsolutePath(), "-la", f.getAbsolutePath()).trim();
123
                int index = output.indexOf(" ");
124
                assertFalse("Can`t read permissions from output:\n" + output, index == -1);
125
                String permissions = output.substring(0, index);
126
                assertTrue("File " + f + " does not have executable permissions after installation, actual perms : " + permissions,
127
                        permissions.matches(".*x.*x.*x.*"));
128
            } else {
129
                Method canExecuteMethod = null;
130
                try {
131
                    canExecuteMethod = File.class.getMethod("canExecute", new Class[]{});
132
                } catch (Exception e) {
133
                    assertTrue("java.io.File.canExecute method is not accessible", false);
134
                }
135
                boolean canExecute = false;
136
                try {
137
                    canExecute = (Boolean) canExecuteMethod.invoke(f);
138
                } catch (Exception e) {
139
                    assertTrue("File " + f + " is not executable after module installation", canExecute);
140
                    e.printStackTrace();
141
                }
142
            }
143
144
        }
145
    }
146
147
    private String readCommandOutput(String... command) {
148
        ProcessBuilder builder = new ProcessBuilder(command);
149
        boolean doRun = true;
150
        StringBuilder sb = new StringBuilder();
151
        byte[] bytes = new byte[8192];
152
        int c = 0;
153
154
        try {
155
            Process process = builder.start();
156
            while (doRun) {
157
                try {
158
                    Thread.sleep(20);
159
                } catch (InterruptedException e) {
160
                }
161
                try {
162
                    process.exitValue();
163
                    doRun = false;
164
                } catch (IllegalThreadStateException e) {
165
                    ; // do nothing - the process is still running
166
                }
167
                InputStream is = process.getInputStream();
168
                while ((c = is.read(bytes)) != -1) {
169
                    sb.append(new String(bytes, 0, c));
170
                }
171
            }
172
            return sb.toString();
173
        } catch (IOException e) {
174
            e.printStackTrace();
175
            return new String();
176
        }
177
    }
178
}

Return to bug 24357