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 160390
Collapse All | Expand All

(-)a/core.startup/nbproject/project.xml (-1 / +1 lines)
Lines 52-58 Link Here
52
                    <compile-dependency/>
52
                    <compile-dependency/>
53
                    <run-dependency>
53
                    <run-dependency>
54
                        <release-version>1</release-version>
54
                        <release-version>1</release-version>
55
                        <specification-version>2.11</specification-version>
55
                        <specification-version>2.18</specification-version>
56
                    </run-dependency>
56
                    </run-dependency>
57
                </dependency>
57
                </dependency>
58
                <dependency>
58
                <dependency>
(-)a/core.startup/src/org/netbeans/core/startup/ModuleList.java (-170 / +198 lines)
Lines 52-60 Link Here
52
import java.io.FileNotFoundException;
52
import java.io.FileNotFoundException;
53
import java.io.IOException;
53
import java.io.IOException;
54
import java.io.InputStream;
54
import java.io.InputStream;
55
import java.io.ObjectInputStream;
55
import java.io.ObjectOutput;
56
import java.io.ObjectOutput;
57
import java.io.ObjectOutputStream;
56
import java.io.OutputStream;
58
import java.io.OutputStream;
57
import java.io.OutputStreamWriter;
59
import java.io.OutputStreamWriter;
60
import java.io.PushbackInputStream;
58
import java.io.Writer;
61
import java.io.Writer;
59
import java.util.ArrayList;
62
import java.util.ArrayList;
60
import java.util.Arrays;
63
import java.util.Arrays;
Lines 82-87 Link Here
82
import org.openide.filesystems.FileObject;
85
import org.openide.filesystems.FileObject;
83
import org.openide.filesystems.FileRenameEvent;
86
import org.openide.filesystems.FileRenameEvent;
84
import org.openide.filesystems.FileSystem;
87
import org.openide.filesystems.FileSystem;
88
import org.openide.filesystems.FileSystem.AtomicAction;
85
import org.openide.filesystems.FileUtil;
89
import org.openide.filesystems.FileUtil;
86
import org.openide.modules.Dependency;
90
import org.openide.modules.Dependency;
87
import org.openide.modules.InstalledFileLocator;
91
import org.openide.modules.InstalledFileLocator;
Lines 164-316 Link Here
164
        ev.log(Events.START_READ);
168
        ev.log(Events.START_READ);
165
        final Set<Module> read = new HashSet<Module>();
169
        final Set<Module> read = new HashSet<Module>();
166
        try {
170
        try {
167
            folder.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
171
            folder.getFileSystem().runAtomicAction(new ReadInitial(read));
168
                public void run() throws IOException {
169
170
        Map<String, Map<String, Object>> cache = readCache();
171
        String[] names;
172
        if (cache != null) {
173
            names = cache.keySet().toArray(new String[0]);
174
        } else {
175
            FileObject[] children = folder.getChildren();
176
            List<String> arr = new ArrayList<String>(children.length);
177
            for (FileObject f : children) {
178
                if (f.hasExt("ser")) { // NOI18N
179
                // Fine, skip over.
180
                } else if (f.hasExt("xml")) { // NOI18N
181
                    // Assume this is one of ours. Note fixed naming scheme.
182
                    String nameDashes = f.getName(); // NOI18N
183
                    char[] badChars = {'.', '/', '>', '='};
184
                    for (int j = 0; j < 4; j++) {
185
                        if (nameDashes.indexOf(badChars[j]) != -1) {
186
                            throw new IllegalArgumentException("Bad name: " + nameDashes); // NOI18N
187
                        }
188
                    }
189
                    String name = nameDashes.replace('-', '.').intern(); // NOI18N
190
                    arr.add(name);
191
                } else {
192
                    LOG.fine("Strange file encountered in modules folder: " + f);
193
                }
194
            }
195
            names = arr.toArray(new String[0]);
196
        }
197
        ev.log( Events.MODULES_FILE_SCANNED, names.length );
198
199
	XMLReader reader = null;
200
	
201
        for (int i = 0; i < names.length; i++) {
202
            String name = names[i];
203
            FileObject f = null;
204
            try {
205
206
                // Now name is the code name base of the module we expect to find.
207
                // Check its format (throws IllegalArgumentException if bad):
208
                Dependency.create(Dependency.TYPE_MODULE, name);
209
210
                // OK, read it from disk.
211
                Map<String,Object> props = cache == null ? null : cache.get(name);
212
                if (props == null) {
213
                    LOG.log(Level.FINEST, "no cache for {0}", name);
214
                    f = folder.getFileObject(name.replace('.', '-') + ".xml");
215
                    InputStream is = f.getInputStream();
216
                    try {
217
                        props = readStatus(new BufferedInputStream(is),true);
218
                        if (props == null) {
219
                            LOG.warning("Note - failed to parse " + f + " the quick way, falling back on XMLReader");
220
                            is.close();
221
                            is = f.getInputStream();
222
                            InputSource src = new InputSource(is);
223
                            // Make sure any includes etc. are handled properly:
224
                            src.setSystemId(f.getURL().toExternalForm());
225
                            if (reader == null) {
226
                                try {
227
                                    reader = XMLUtil.createXMLReader();
228
                                } catch(SAXException e) {
229
                                    throw (IllegalStateException) new IllegalStateException(e.toString()).initCause(e);
230
                                }
231
                                reader.setEntityResolver(listener);
232
                                reader.setErrorHandler(listener);
233
                            }
234
                            props = readStatus(src,reader);
235
                        }
236
                    } finally {
237
                        is.close();
238
                    }
239
                }
240
                if (! name.equals(props.get("name"))) throw new IOException("Code name mismatch: " /* #25011 */ + name + " vs. " + props.get("name")); // NOI18N
241
                Boolean enabledB = (Boolean)props.get("enabled"); // NOI18N
242
                String jar = (String)props.get("jar"); // NOI18N
243
                File jarFile;
244
                try {
245
                    jarFile = findJarByName(jar, name);
246
                } catch (FileNotFoundException fnfe) {
247
                    //LOG.fine("Cannot find: " + fnfe.getMessage());
248
                    ev.log(Events.MISSING_JAR_FILE, new File(fnfe.getMessage()), enabledB);
249
                    if (!Boolean.FALSE.equals(enabledB)) {
250
                        try {
251
                            f.delete();
252
                        } catch (IOException ioe) {
253
                            LOG.log(Level.WARNING, null, ioe);
254
                        }
255
                    }
256
                    continue;
257
                }
258
259
                ModuleHistory history = new ModuleHistory(jar); // NOI18N
260
                Integer prevReleaseI = (Integer)props.get("release"); // NOI18N
261
                int prevRelease = (prevReleaseI == null ? -1 : prevReleaseI.intValue());
262
                SpecificationVersion prevSpec = (SpecificationVersion)props.get("specversion"); // NOI18N
263
                history.upgrade(prevRelease, prevSpec);
264
                Boolean reloadableB = (Boolean)props.get("reloadable"); // NOI18N
265
                boolean reloadable = (reloadableB != null ? reloadableB.booleanValue() : false);
266
                boolean enabled = (enabledB != null ? enabledB.booleanValue() : false);
267
                Boolean autoloadB = (Boolean)props.get("autoload"); // NOI18N
268
                boolean autoload = (autoloadB != null ? autoloadB.booleanValue() : false);
269
                Boolean eagerB = (Boolean)props.get("eager"); // NOI18N
270
                boolean eager = (eagerB != null ? eagerB.booleanValue() : false);
271
                String installer = (String)props.get("installer"); // NOI18N
272
                if (installer != null) {
273
                    String nameDashes = name.replace('.', '-');
274
                    if (! installer.equals(nameDashes + ".ser")) throw new IOException("Incorrect installer ser name: " + installer); // NOI18N
275
                    // Load from disk in mentioned file.
276
                    FileObject installerSer = folder.getFileObject(nameDashes, "ser"); // NOI18N
277
                    if (installerSer == null) throw new IOException("No such install ser: " + installer + "; I see only: " + Arrays.asList(folder.getChildren())); // NOI18N
278
                    // Hope the stored state is not >Integer.MAX_INT! :-)
279
                    byte[] buf = new byte[(int)installerSer.getSize()];
280
                    InputStream is2 = installerSer.getInputStream();
281
                    try {
282
                        is2.read(buf);
283
                    } finally {
284
                        is2.close();
285
                    }
286
                    history.setInstallerState(buf);
287
                    // Quasi-prop which is stored separately.
288
                    props.put("installerState", buf); // NOI18N
289
                }
290
                Module m = mgr.create(jarFile, history, reloadable, autoload, eager);
291
                read.add(m);
292
                DiskStatus status = new DiskStatus();
293
                status.module = m;
294
                status.file = f;
295
                //status.lastApprovedChange = children[i].lastModified().getTime();
296
                status.pendingInstall = enabled;
297
                // Will only really be flushed if mgr props != disk props, i.e
298
                // if version changed or could not be enabled.
299
                //status.pendingFlush = true;
300
                status.setDiskProps(props);
301
                statuses.put(name, status);
302
            } catch (Exception e) {
303
                LOG.log(Level.WARNING, "Error encountered while reading " + name, e);
304
            }
305
            ev.log( Events.MODULES_FILE_PROCESSED, name );
306
        }
307
        if (LOG.isLoggable(Level.FINE)) {
308
            LOG.fine("read initial XML files: statuses=" + statuses);
309
        }
310
        ev.log(Events.FINISH_READ, read);
311
        // Handle changes in the Modules/ folder on disk by parsing & applying them.
312
        folder.addFileChangeListener(FileUtil.weakFileChangeListener (listener, folder));
313
                }});
314
        } catch (IOException ioe) {
172
        } catch (IOException ioe) {
315
            LOG.log(Level.WARNING, null, ioe);
173
            LOG.log(Level.WARNING, null, ioe);
316
        }
174
        }
Lines 786-834 Link Here
786
     * you have to use a real parser.
644
     * you have to use a real parser.
787
     * @see "#26786"
645
     * @see "#26786"
788
     */
646
     */
789
    private Map<String, Object> readStatus(InputStream is,boolean checkEOF) throws IOException {
647
    private Map<String, Object> readStatus(InputStream is, boolean checkEOF) throws IOException {
648
        PushbackInputStream pbis = new PushbackInputStream(is, 1);
790
        Map<String,Object> m = new HashMap<String,Object>(15);
649
        Map<String,Object> m = new HashMap<String,Object>(15);
791
        if (!expect(is, MODULE_XML_INTRO)) {
650
        if (!expect(pbis, MODULE_XML_INTRO)) {
792
            LOG.fine("Could not read intro");
651
            LOG.fine("Could not read intro");
793
            return null;
652
            return null;
794
        }
653
        }
795
        String name = readTo(is, '"');
654
        String name = readTo(pbis, '"');
796
        if (name == null) {
655
        if (name == null) {
797
            LOG.fine("Could not read code name base");
656
            LOG.fine("Could not read code name base");
798
            return null;
657
            return null;
799
        }
658
        }
800
        m.put("name", name.intern()); // NOI18N
659
        m.put("name", name.intern()); // NOI18N
801
        if (!expect(is, MODULE_XML_INTRO_END)) {
660
        if (!expect(pbis, MODULE_XML_INTRO_END)) {
802
            LOG.fine("Could not read stuff after cnb");
661
            LOG.fine("Could not read stuff after cnb");
803
            return null;
662
            return null;
804
        }
663
        }
805
        // Now we have <param>s some number of times, finally </module>.
664
        // Now we have <param>s some number of times, finally </module>.
806
    PARSE:
665
    PARSE:
807
        while (true) {
666
        while (true) {
808
            int c = is.read();
667
            int c = pbis.read();
809
            switch (c) {
668
            switch (c) {
810
            case ' ':
669
            case ' ':
811
                // <param>
670
                // <param>
812
                if (!expect(is, MODULE_XML_DIV2)) {
671
                if (!expect(pbis, MODULE_XML_DIV2)) {
813
                    LOG.fine("Could not read up to param");
672
                    LOG.fine("Could not read up to param");
814
                    return null;
673
                    return null;
815
                }
674
                }
816
                String k = readTo(is, '"');
675
                String k = readTo(pbis, '"');
817
                if (k == null) {
676
                if (k == null) {
818
                    LOG.fine("Could not read param");
677
                    LOG.fine("Could not read param");
819
                    return null;
678
                    return null;
820
                }
679
                }
821
                k = k.intern();
680
                k = k.intern();
822
                if (is.read() != '>') {
681
                if (pbis.read() != '>') {
823
                    LOG.fine("No > at end of <param> " + k);
682
                    LOG.fine("No > at end of <param> " + k);
824
                    return null;
683
                    return null;
825
                }
684
                }
826
                String v = readTo(is, '<');
685
                String v = readTo(pbis, '<');
827
                if (v == null) {
686
                if (v == null) {
828
                    LOG.fine("Could not read value of " + k);
687
                    LOG.fine("Could not read value of " + k);
829
                    return null;
688
                    return null;
830
                }
689
                }
831
                if (!expect(is, MODULE_XML_DIV3)) {
690
                if (!expect(pbis, MODULE_XML_DIV3)) {
832
                    LOG.fine("Could not read end of param " + k);
691
                    LOG.fine("Could not read end of param " + k);
833
                    return null;
692
                    return null;
834
                }
693
                }
Lines 841-854 Link Here
841
                break;
700
                break;
842
            case '<':
701
            case '<':
843
                // </module>
702
                // </module>
844
                if (!expect(is, MODULE_XML_END)) {
703
                if (!expect(pbis, MODULE_XML_END)) {
845
                    LOG.fine("Strange ending");
704
                    LOG.fine("Strange ending");
846
                    return null;
705
                    return null;
847
                }
706
                }
848
                if (!checkEOF) {
707
                if (!checkEOF) {
849
                    break PARSE;
708
                    break PARSE;
850
                }
709
                }
851
                if (is.read() != -1) {
710
                if (pbis.read() != -1) {
852
                    LOG.fine("Trailing garbage");
711
                    LOG.fine("Trailing garbage");
853
                    return null;
712
                    return null;
854
                }
713
                }
Lines 867-873 Link Here
867
     * Newline conventions are normalized to Unix \n.
726
     * Newline conventions are normalized to Unix \n.
868
     * @return true upon success, false if stream contained something else
727
     * @return true upon success, false if stream contained something else
869
     */
728
     */
870
    private boolean expect(InputStream is, byte[] stuff) throws IOException {
729
    private boolean expect(PushbackInputStream is, byte[] stuff) throws IOException {
871
        int len = stuff.length;
730
        int len = stuff.length;
872
        boolean inNewline = false;
731
        boolean inNewline = false;
873
        for (int i = 0; i < len; ) {
732
        for (int i = 0; i < len; ) {
Lines 890-901 Link Here
890
        if (stuff[len - 1] == 10) {
749
        if (stuff[len - 1] == 10) {
891
            // Expecting something ending in a \n - so we have to
750
            // Expecting something ending in a \n - so we have to
892
            // read any further \r or \n and discard.
751
            // read any further \r or \n and discard.
893
            if (!is.markSupported()) throw new IOException("Mark not supported"); // NOI18N
894
            is.mark(1);
895
            int c = is.read();
752
            int c = is.read();
896
            if (c != -1 && c != 10 && c != 13) {
753
            if (c != -1 && c != 10 && c != 13) {
897
                // Got some non-newline character, push it back!
754
                // Got some non-newline character, push it back!
898
                is.reset();
755
                is.unread(c);
899
            }
756
            }
900
        }
757
        }
901
        return true;
758
        return true;
Lines 939-945 Link Here
939
        }
796
        }
940
    }
797
    }
941
798
942
    private Map<String,Map<String,Object>> readCache() throws IOException {
799
    final Map<String,Map<String,Object>> readCache() throws IOException {
943
        InputStream is = Stamps.getModulesJARs().asStream("all-modules.dat"); // NOI18N
800
        InputStream is = Stamps.getModulesJARs().asStream("all-modules.dat"); // NOI18N
944
        if (is == null) {
801
        if (is == null) {
945
            // schedule write for later
802
            // schedule write for later
Lines 947-979 Link Here
947
            return null;
804
            return null;
948
        }
805
        }
949
        LOG.log(Level.FINEST, "Reading cache all-modules.dat");
806
        LOG.log(Level.FINEST, "Reading cache all-modules.dat");
807
        ObjectInputStream ois = new ObjectInputStream(is);
950
        
808
        
951
        Map<String,Map<String,Object>> ret = new HashMap<String, Map<String, Object>>(1333);
809
        Map<String,Map<String,Object>> ret = new HashMap<String, Map<String, Object>>(1333);
952
        while (is.available() > 0) {
810
        while (is.available() > 0) {
953
            Map<String, Object> prop = readStatus(is, false);
811
            Map<String, Object> prop = readStatus(ois, false);
954
            if (prop == null) {
812
            if (prop == null) {
955
                LOG.log(Level.CONFIG, "Cache is invalid all-modules.dat");
813
                LOG.log(Level.CONFIG, "Cache is invalid all-modules.dat");
956
                return null;
814
                return null;
957
            }
815
            }
816
            Set<?> deps;
817
            try {
818
                deps = (Set<?>) ois.readObject();
819
            } catch (ClassNotFoundException ex) {
820
                throw (IOException)new IOException(ex.getMessage()).initCause(ex);
821
            }
822
            prop.put("deps", deps);
958
            String cnb = (String)prop.get("name"); // NOI18N
823
            String cnb = (String)prop.get("name"); // NOI18N
959
            ret.put(cnb, prop);
824
            ret.put(cnb, prop);
960
        }
825
        }
961
            is.close();
962
826
963
            return ret;
827
964
        }
828
        is.close();
829
830
        return ret;
831
    }
965
832
966
    final void writeCache() {
833
    final void writeCache() {
967
        Stamps.getModulesJARs().scheduleSave(this, "all-modules.dat", false);
834
        Stamps.getModulesJARs().scheduleSave(this, "all-modules.dat", false);
968
    }
835
    }
969
    
836
    
837
    public void cacheReady() {
838
    }
839
970
    public void flushCaches(DataOutputStream os) throws IOException {
840
    public void flushCaches(DataOutputStream os) throws IOException {
841
        ObjectOutputStream oss = new ObjectOutputStream(os);
971
        for (Module m : mgr.getModules()) {
842
        for (Module m : mgr.getModules()) {
972
            if (m.isFixed()) {
843
            if (m.isFixed()) {
973
                continue;
844
                continue;
974
            }
845
            }
975
            Map<String, Object> prop = computeProperties(m);
846
            Map<String, Object> prop = computeProperties(m);
976
            writeStatus(prop, os);
847
            writeStatus(prop, oss);
848
            oss.writeObject(m.getDependencies());
977
        }
849
        }
978
    }
850
    }
979
    
851
    
Lines 1819-1825 Link Here
1819
        }
1691
        }
1820
    }
1692
    }
1821
1693
1822
    public void cacheReady() {
1694
    private class ReadInitial implements AtomicAction {
1695
1696
        private final Set<Module> read;
1697
1698
        public ReadInitial(Set<Module> read) {
1699
            this.read = read;
1700
        }
1701
1702
        public void run() throws IOException {
1703
            Map<String, Map<String, Object>> cache = readCache();
1704
            String[] names;
1705
            if (cache != null) {
1706
                names = cache.keySet().toArray(new String[0]);
1707
            } else {
1708
                FileObject[] children = folder.getChildren();
1709
                List<String> arr = new ArrayList<String>(children.length);
1710
                for (FileObject f : children) {
1711
                    if (f.hasExt("ser")) { // NOI18N
1712
                        // Fine, skip over.
1713
                    } else if (f.hasExt("xml")) {
1714
                        // NOI18N
1715
                        // Assume this is one of ours. Note fixed naming scheme.
1716
                        String nameDashes = f.getName(); // NOI18N
1717
                        char[] badChars = {'.', '/', '>', '='};
1718
                        for (int j = 0; j < 4; j++) {
1719
                            if (nameDashes.indexOf(badChars[j]) != -1) {
1720
                                throw new IllegalArgumentException("Bad name: " + nameDashes); // NOI18N
1721
                            }
1722
                        }
1723
                        String name = nameDashes.replace('-', '.').intern(); // NOI18N
1724
                        arr.add(name);
1725
                    } else {
1726
                        LOG.fine("Strange file encountered in modules folder: " + f);
1727
                    }
1728
                }
1729
                names = arr.toArray(new String[0]);
1730
            }
1731
            ev.log(Events.MODULES_FILE_SCANNED, names.length);
1732
            XMLReader reader = null;
1733
            for (int i = 0; i < names.length; i++) {
1734
                String name = names[i];
1735
                FileObject f = null;
1736
                try {
1737
                    // OK, read it from disk.
1738
                    Map<String, Object> props = cache == null ? null : cache.get(name);
1739
                    if (props == null) {
1740
                        // Now name is the code name base of the module we expect to find.
1741
                        // Check its format (throws IllegalArgumentException if bad):
1742
                        Dependency.create(Dependency.TYPE_MODULE, name);
1743
                        LOG.log(Level.FINEST, "no cache for {0}", name);
1744
                        f = folder.getFileObject(name.replace('.', '-') + ".xml");
1745
                        InputStream is = f.getInputStream();
1746
                        try {
1747
                            props = readStatus(new BufferedInputStream(is), true);
1748
                            if (props == null) {
1749
                                LOG.warning("Note - failed to parse " + f + " the quick way, falling back on XMLReader");
1750
                                is.close();
1751
                                is = f.getInputStream();
1752
                                InputSource src = new InputSource(is);
1753
                                // Make sure any includes etc. are handled properly:
1754
                                src.setSystemId(f.getURL().toExternalForm());
1755
                                if (reader == null) {
1756
                                    try {
1757
                                        reader = XMLUtil.createXMLReader();
1758
                                    } catch (SAXException e) {
1759
                                        throw (IllegalStateException) new IllegalStateException(e.toString()).initCause(e);
1760
                                    }
1761
                                    reader.setEntityResolver(listener);
1762
                                    reader.setErrorHandler(listener);
1763
                                }
1764
                                props = readStatus(src, reader);
1765
                            }
1766
                        } finally {
1767
                            is.close();
1768
                        }
1769
                    }
1770
                    if (!name.equals(props.get("name"))) {
1771
                        throw new IOException("Code name mismatch: " + name + " vs. " + props.get("name")); // NOI18N
1772
                    }
1773
                    Boolean enabledB = (Boolean) props.get("enabled"); // NOI18N
1774
                    String jar = (String) props.get("jar"); // NOI18N
1775
                    File jarFile;
1776
                    try {
1777
                        jarFile = findJarByName(jar, name);
1778
                    } catch (FileNotFoundException fnfe) {
1779
                        //LOG.fine("Cannot find: " + fnfe.getMessage());
1780
                        ev.log(Events.MISSING_JAR_FILE, new File(fnfe.getMessage()), enabledB);
1781
                        if (!Boolean.FALSE.equals(enabledB)) {
1782
                            try {
1783
                                f.delete();
1784
                            } catch (IOException ioe) {
1785
                                LOG.log(Level.WARNING, null, ioe);
1786
                            }
1787
                        }
1788
                        continue;
1789
                    }
1790
                    ModuleHistory history = new ModuleHistory(jar); // NOI18N
1791
                    Integer prevReleaseI = (Integer) props.get("release"); // NOI18N
1792
                    int prevRelease = prevReleaseI == null ? -1 : prevReleaseI.intValue();
1793
                    SpecificationVersion prevSpec = (SpecificationVersion) props.get("specversion"); // NOI18N
1794
                    history.upgrade(prevRelease, prevSpec);
1795
                    Boolean reloadableB = (Boolean) props.get("reloadable"); // NOI18N
1796
                    boolean reloadable = reloadableB != null ? reloadableB.booleanValue() : false;
1797
                    boolean enabled = enabledB != null ? enabledB.booleanValue() : false;
1798
                    Boolean autoloadB = (Boolean) props.get("autoload"); // NOI18N
1799
                    boolean autoload = autoloadB != null ? autoloadB.booleanValue() : false;
1800
                    Boolean eagerB = (Boolean) props.get("eager"); // NOI18N
1801
                    boolean eager = eagerB != null ? eagerB.booleanValue() : false;
1802
                    String installer = (String) props.get("installer"); // NOI18N
1803
                    if (installer != null) {
1804
                        String nameDashes = name.replace('.', '-');
1805
                        if (!installer.equals(nameDashes + ".ser")) {
1806
                            throw new IOException("Incorrect installer ser name: " + installer); // NOI18N
1807
                        }
1808
                        // Load from disk in mentioned file.
1809
                        FileObject installerSer = folder.getFileObject(nameDashes, "ser"); // NOI18N
1810
                        if (installerSer == null) {
1811
                            throw new IOException("No such install ser: " + installer + "; I see only: " + Arrays.asList(folder.getChildren())); // NOI18N
1812
                        }
1813
                        // Hope the stored state is not >Integer.MAX_INT! :-)
1814
                        byte[] buf = new byte[(int) installerSer.getSize()];
1815
                        InputStream is2 = installerSer.getInputStream();
1816
                        try {
1817
                            is2.read(buf);
1818
                        } finally {
1819
                            is2.close();
1820
                        }
1821
                        history.setInstallerState(buf);
1822
                        // Quasi-prop which is stored separately.
1823
                        props.put("installerState", buf); // NOI18N
1824
                    }
1825
                    NbInstaller.register(name, props.get("deps")); // NOI18N
1826
                    Module m = mgr.create(jarFile, history, reloadable, autoload, eager);
1827
                    NbInstaller.register(null, null);
1828
                    read.add(m);
1829
                    DiskStatus status = new DiskStatus();
1830
                    status.module = m;
1831
                    status.file = f;
1832
                    //status.lastApprovedChange = children[i].lastModified().getTime();
1833
                    status.pendingInstall = enabled;
1834
                    // Will only really be flushed if mgr props != disk props, i.e
1835
                    // if version changed or could not be enabled.
1836
                    //status.pendingFlush = true;
1837
                    status.setDiskProps(props);
1838
                    statuses.put(name, status);
1839
                } catch (Exception e) {
1840
                    LOG.log(Level.WARNING, "Error encountered while reading " + name, e);
1841
                }
1842
                ev.log(Events.MODULES_FILE_PROCESSED, name);
1843
            }
1844
            if (LOG.isLoggable(Level.FINE)) {
1845
                LOG.fine("read initial XML files: statuses=" + statuses);
1846
            }
1847
            ev.log(Events.FINISH_READ, read);
1848
            // Handle changes in the Modules/ folder on disk by parsing & applying them.
1849
            folder.addFileChangeListener(FileUtil.weakFileChangeListener(listener, folder));
1850
        }
1823
    }
1851
    }
1824
    
1852
    
1825
}
1853
}
(-)a/core.startup/src/org/netbeans/core/startup/NbInstaller.java (+13 lines)
Lines 700-705 Link Here
700
            }
700
            }
701
        }
701
        }
702
    }
702
    }
703
704
    private static String cacheCnb;
705
    private static Set<Dependency> cacheDeps;
706
    @Override
707
    protected Set<Dependency> loadDependencies(String cnb) {
708
        return cnb.equals(cacheCnb) ? cacheDeps : null;
709
    }
710
    @SuppressWarnings("unchecked")
711
    static void register(String name, Object obj) {
712
        cacheCnb = name;
713
        cacheDeps = (Set<Dependency>)obj;
714
    }
715
703
    
716
    
704
    private AutomaticDependencies autoDepsHandler = null;
717
    private AutomaticDependencies autoDepsHandler = null;
705
    
718
    
(-)a/o.n.bootstrap/manifest.mf (-1 / +1 lines)
Lines 1-4 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.bootstrap/1
2
OpenIDE-Module: org.netbeans.bootstrap/1
3
OpenIDE-Module-Specification-Version: 2.17
3
OpenIDE-Module-Specification-Version: 2.18
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
(-)a/o.n.bootstrap/src/org/netbeans/Module.java (-38 / +69 lines)
Lines 80-86 Link Here
80
    public static final String PROP_MANIFEST = "manifest"; // NOI18N
80
    public static final String PROP_MANIFEST = "manifest"; // NOI18N
81
    public static final String PROP_VALID = "valid"; // NOI18N
81
    public static final String PROP_VALID = "valid"; // NOI18N
82
    public static final String PROP_PROBLEMS = "problems"; // NOI18N
82
    public static final String PROP_PROBLEMS = "problems"; // NOI18N
83
    
83
84
    /** manager which owns this module */
84
    /** manager which owns this module */
85
    protected final ModuleManager mgr;
85
    protected final ModuleManager mgr;
86
    /** event logging (should not be much here) */
86
    /** event logging (should not be much here) */
Lines 306-311 Link Here
306
     */
306
     */
307
    protected void parseManifest() throws InvalidException {
307
    protected void parseManifest() throws InvalidException {
308
        Attributes attr = getManifest().getMainAttributes();
308
        Attributes attr = getManifest().getMainAttributes();
309
309
        // Code name
310
        // Code name
310
        codeName = attr.getValue("OpenIDE-Module"); // NOI18N
311
        codeName = attr.getValue("OpenIDE-Module"); // NOI18N
311
        if (codeName == null) {
312
        if (codeName == null) {
Lines 322-330 Link Here
322
            if (codeName.indexOf(',') != -1) {
323
            if (codeName.indexOf(',') != -1) {
323
                throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N
324
                throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N
324
            }
325
            }
325
            Dependency.create(Dependency.TYPE_MODULE, codeName);
326
            Object[] cnParse = Util.parseCodeName(codeName);
326
            Object[] cnParse = Util.parseCodeName(codeName);
327
            codeNameBase = (String)cnParse[0];
327
            codeNameBase = (String)cnParse[0];
328
            Set<?> deps = mgr.loadDependencies(codeNameBase);
329
            boolean verifyCNBs = deps == null;
330
            if (verifyCNBs) {
331
                Dependency.create(Dependency.TYPE_MODULE, codeName);
332
            }
328
            codeNameRelease = (cnParse[1] != null) ? ((Integer)cnParse[1]).intValue() : -1;
333
            codeNameRelease = (cnParse[1] != null) ? ((Integer)cnParse[1]).intValue() : -1;
329
            if (cnParse[2] != null) throw new NumberFormatException(codeName);
334
            if (cnParse[2] != null) throw new NumberFormatException(codeName);
330
            // Spec vers
335
            // Spec vers
Lines 350-356 Link Here
350
                    if (provide.indexOf(',') != -1) {
355
                    if (provide.indexOf(',') != -1) {
351
                        throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module-Provides: " + provide); // NOI18N
356
                        throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module-Provides: " + provide); // NOI18N
352
                    }
357
                    }
353
                    Dependency.create(Dependency.TYPE_MODULE, provide);
358
                    if (verifyCNBs) {
359
                        Dependency.create(Dependency.TYPE_MODULE, provide);
360
                    }
354
                    if (provide.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Provides: " + provide); // NOI18N
361
                    if (provide.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Provides: " + provide); // NOI18N
355
                    provides[i] = provide;
362
                    provides[i] = provide;
356
                }
363
                }
Lines 382-393 Link Here
382
                        String piece = tok.nextToken();
389
                        String piece = tok.nextToken();
383
                        if (piece.endsWith(".*")) { // NOI18N
390
                        if (piece.endsWith(".*")) { // NOI18N
384
                            String pkg = piece.substring(0, piece.length() - 2);
391
                            String pkg = piece.substring(0, piece.length() - 2);
385
                            Dependency.create(Dependency.TYPE_MODULE, pkg);
392
                            if (verifyCNBs) {
393
                                Dependency.create(Dependency.TYPE_MODULE, pkg);
394
                            }
386
                            if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
395
                            if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
387
                            exports.add(new PackageExport(pkg.replace('.', '/') + '/', false));
396
                            exports.add(new PackageExport(pkg.replace('.', '/') + '/', false));
388
                        } else if (piece.endsWith(".**")) { // NOI18N
397
                        } else if (piece.endsWith(".**")) { // NOI18N
389
                            String pkg = piece.substring(0, piece.length() - 3);
398
                            String pkg = piece.substring(0, piece.length() - 3);
390
                            Dependency.create(Dependency.TYPE_MODULE, pkg);
399
                            if (verifyCNBs) {
400
                                Dependency.create(Dependency.TYPE_MODULE, pkg);
401
                            }
391
                            if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
402
                            if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
392
                            exports.add(new PackageExport(pkg.replace('.', '/') + '/', true));
403
                            exports.add(new PackageExport(pkg.replace('.', '/') + '/', true));
393
                        } else {
404
                        } else {
Lines 414-421 Link Here
414
                        if (piece.indexOf('/') != -1) {
425
                        if (piece.indexOf('/') != -1) {
415
                            throw new IllegalArgumentException("May specify only module code name bases in OpenIDE-Module-Friends, not major release versions: " + piece); // NOI18N
426
                            throw new IllegalArgumentException("May specify only module code name bases in OpenIDE-Module-Friends, not major release versions: " + piece); // NOI18N
416
                        }
427
                        }
417
                        // Indirect way of checking syntax:
428
                        if (verifyCNBs) {
418
                        Dependency.create(Dependency.TYPE_MODULE, piece);
429
                            // Indirect way of checking syntax:
430
                            Dependency.create(Dependency.TYPE_MODULE, piece);
431
                        }
419
                        // OK, add it.
432
                        // OK, add it.
420
                        set.add(piece);
433
                        set.add(piece);
421
                    }
434
                    }
Lines 428-464 Link Here
428
                    this.friendNames = set;
441
                    this.friendNames = set;
429
                }
442
                }
430
            }
443
            }
431
            
444
            initDeps(deps, attr);
432
            
433
            // Dependencies
434
            Set<Dependency> dependencies = new HashSet<Dependency>(20);
435
            // First convert IDE/1 -> org.openide/1, so we never have to deal with
436
            // "IDE deps" internally:
437
            @SuppressWarnings("deprecation")
438
            Set<Dependency> openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N
439
            if (!openideDeps.isEmpty()) {
440
                // If empty, leave it that way; NbInstaller will add it anyway.
441
                Dependency d = openideDeps.iterator().next();
442
                String name = d.getName();
443
                if (!name.startsWith("IDE/")) throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N
444
                dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N
445
                if (dependencies.size() != 1) throw new IllegalStateException("Should be singleton: " + dependencies); // NOI18N
446
                
447
                Util.err.warning("the module " + codeNameBase + " uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html"); // NOI18N
448
            }
449
            dependencies.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N
450
            dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N
451
            String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N
452
            if (pkgdeps != null) {
453
                // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies manifest attribute, which is now deprecated: XXX URL TBD");
454
                dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
455
            }
456
            dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
457
            dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N
458
            dependencies.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N
459
            // Permit the concrete installer to make some changes:
460
            mgr.refineDependencies(this, dependencies);
461
            dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]);
462
        } catch (IllegalArgumentException iae) {
445
        } catch (IllegalArgumentException iae) {
463
            throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N
446
            throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N
464
        }
447
        }
Lines 632-635 Link Here
632
        }
615
        }
633
    }
616
    }
634
617
618
    /** Initializes dependencies of this module
619
     *
620
     * @param knownDeps Set<Dependency> of this module known from different source,
621
     *    can be null
622
     * @param attr attributes in manifest to parse if knownDeps is null
623
     */
624
    private void initDeps(Set<?> knownDeps, Attributes attr)
625
    throws IllegalStateException, IllegalArgumentException {
626
        if (knownDeps != null) {
627
            dependenciesA = knownDeps.toArray(new Dependency[knownDeps.size()]);
628
            knownDeps = null;
629
            return;
630
        }
631
632
        // Dependencies
633
        Set<Dependency> dependencies = new HashSet<Dependency>(20);
634
        // First convert IDE/1 -> org.openide/1, so we never have to deal with
635
        // "IDE deps" internally:
636
        @SuppressWarnings(value = "deprecation")
637
        Set<Dependency> openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N
638
        if (!openideDeps.isEmpty()) {
639
            // If empty, leave it that way; NbInstaller will add it anyway.
640
            Dependency d = openideDeps.iterator().next();
641
            String name = d.getName();
642
            if (!name.startsWith("IDE/")) {
643
                throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N
644
            }
645
            dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N
646
            if (dependencies.size() != 1) {
647
                throw new IllegalStateException("Should be singleton: " + dependencies); // NOI18N
648
            }
649
            Util.err.warning("the module " + codeNameBase + " uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html"); // NOI18N
650
        }
651
        dependencies.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N
652
        dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N
653
        String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N
654
        if (pkgdeps != null) {
655
            // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies manifest attribute, which is now deprecated: XXX URL TBD");
656
            dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
657
        }
658
        dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
659
        dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N
660
        dependencies.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N
661
        // Permit the concrete installer to make some changes:
662
        mgr.refineDependencies(this, dependencies);
663
        dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]);
664
    }
665
635
}
666
}
(-)a/o.n.bootstrap/src/org/netbeans/ModuleInstaller.java (+9 lines)
Lines 203-206 Link Here
203
        return null;
203
        return null;
204
    }
204
    }
205
205
206
    /** Loades dependencies cached from previous run, if possible.
207
     * @param cnb the code name base of the module to get dependencies for
208
     * @return null or set of dependencies for the module
209
     * @since 2.18
210
     */
211
    protected Set<Dependency> loadDependencies(String cnb) {
212
        return null;
213
    }
214
206
}
215
}
(-)a/o.n.bootstrap/src/org/netbeans/ModuleManager.java (+3 lines)
Lines 532-537 Link Here
532
    /** Used by Module to communicate with the ModuleInstaller re. dependencies. */
532
    /** Used by Module to communicate with the ModuleInstaller re. dependencies. */
533
    void refineDependencies(Module m, Set<Dependency> dependencies) {
533
    void refineDependencies(Module m, Set<Dependency> dependencies) {
534
        installer.refineDependencies(m, dependencies);
534
        installer.refineDependencies(m, dependencies);
535
    }
536
    Set<Dependency> loadDependencies(String cnb) {
537
        return installer.loadDependencies(cnb);
535
    }
538
    }
536
    /** Allows the installer to add provides (used to provide name of platform we run on)
539
    /** Allows the installer to add provides (used to provide name of platform we run on)
537
     */
540
     */
(-)a/openide.modules/apichanges.xml (+15 lines)
Lines 47-52 Link Here
47
  	<apidef name="modules">Modules API</apidef>
47
  	<apidef name="modules">Modules API</apidef>
48
  </apidefs>
48
  </apidefs>
49
<changes>
49
<changes>
50
    <change id="DependencyIsSerializable">
51
        <api name="modules"/>
52
        <summary>Dependency class made serializable</summary>
53
        <version major="7" minor="10"/>
54
        <date day="6" month="4" year="2009"/>
55
        <author login="jtulach"/>
56
        <compatibility addition="yes"/>
57
        <description>
58
            <p>
59
                <code>Dependency</code> now implements <code>Serializable</code>
60
            </p>
61
        </description>
62
        <class package="org.openide.modules" name="Dependency"/>
63
        <issue number="160390"/>
64
    </change>
50
    <change id="PatchedPublic">
65
    <change id="PatchedPublic">
51
        <api name="modules"/>
66
        <api name="modules"/>
52
        <summary>Added annotation <code>@PatchedPublic</code></summary>
67
        <summary>Added annotation <code>@PatchedPublic</code></summary>
(-)a/openide.modules/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.modules
2
OpenIDE-Module: org.openide.modules
3
OpenIDE-Module-Localizing-Bundle: org/openide/modules/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/modules/Bundle.properties
4
OpenIDE-Module-Specification-Version: 7.9
4
OpenIDE-Module-Specification-Version: 7.10
5
5
(-)a/openide.modules/src/org/openide/modules/Dependency.java (-2 / +10 lines)
Lines 41-46 Link Here
41
41
42
package org.openide.modules;
42
package org.openide.modules;
43
43
44
import java.io.Serializable;
44
import java.util.Collections;
45
import java.util.Collections;
45
import java.util.HashMap;
46
import java.util.HashMap;
46
import java.util.HashSet;
47
import java.util.HashSet;
Lines 49-59 Link Here
49
import java.util.StringTokenizer;
50
import java.util.StringTokenizer;
50
import org.openide.util.Utilities;
51
import org.openide.util.Utilities;
51
52
52
/** A dependency a module can have.
53
/** A dependency a module can have. Since version 7.10 this class is
54
 * {@link Serializable}.
55
 * 
53
 * @author Jesse Glick
56
 * @author Jesse Glick
54
 * @since 1.24
57
 * @since 1.24
55
 */
58
 */
56
public final class Dependency {
59
public final class Dependency implements Serializable {
60
    static final long serialVersionUID = 9548259318L;
61
57
    /** Dependency on another module. */
62
    /** Dependency on another module. */
58
    public final static int TYPE_MODULE = 1;
63
    public final static int TYPE_MODULE = 1;
59
64
Lines 413-418 Link Here
413
    }
418
    }
414
419
415
    /** Overridden to compare contents. */
420
    /** Overridden to compare contents. */
421
    @Override
416
    public boolean equals(Object o) {
422
    public boolean equals(Object o) {
417
        if (o.getClass() != Dependency.class) {
423
        if (o.getClass() != Dependency.class) {
418
            return false;
424
            return false;
Lines 425-435 Link Here
425
    }
431
    }
426
432
427
    /** Overridden to hash by contents. */
433
    /** Overridden to hash by contents. */
434
    @Override
428
    public int hashCode() {
435
    public int hashCode() {
429
        return 772067 ^ type ^ name.hashCode();
436
        return 772067 ^ type ^ name.hashCode();
430
    }
437
    }
431
438
432
    /** Unspecified string representation for debugging. */
439
    /** Unspecified string representation for debugging. */
440
    @Override
433
    public String toString() {
441
    public String toString() {
434
        StringBuffer buf = new StringBuffer(100);
442
        StringBuffer buf = new StringBuffer(100);
435
443

Return to bug 160390