diff -r bae89dd72ba8 core.startup/nbproject/project.xml --- a/core.startup/nbproject/project.xml Fri Apr 03 08:04:47 2009 +0200 +++ b/core.startup/nbproject/project.xml Fri Apr 03 17:39:12 2009 +0200 @@ -52,7 +52,7 @@ 1 - 2.11 + 2.18 diff -r bae89dd72ba8 core.startup/src/org/netbeans/core/startup/ModuleList.java --- a/core.startup/src/org/netbeans/core/startup/ModuleList.java Fri Apr 03 08:04:47 2009 +0200 +++ b/core.startup/src/org/netbeans/core/startup/ModuleList.java Fri Apr 03 17:39:12 2009 +0200 @@ -52,9 +52,12 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; import java.io.ObjectOutput; +import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.PushbackInputStream; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; @@ -82,6 +85,7 @@ import org.openide.filesystems.FileObject; import org.openide.filesystems.FileRenameEvent; import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileSystem.AtomicAction; import org.openide.filesystems.FileUtil; import org.openide.modules.Dependency; import org.openide.modules.InstalledFileLocator; @@ -164,153 +168,7 @@ ev.log(Events.START_READ); final Set read = new HashSet(); try { - folder.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() { - public void run() throws IOException { - - Map> cache = readCache(); - String[] names; - if (cache != null) { - names = cache.keySet().toArray(new String[0]); - } else { - FileObject[] children = folder.getChildren(); - List arr = new ArrayList(children.length); - for (FileObject f : children) { - if (f.hasExt("ser")) { // NOI18N - // Fine, skip over. - } else if (f.hasExt("xml")) { // NOI18N - // Assume this is one of ours. Note fixed naming scheme. - String nameDashes = f.getName(); // NOI18N - char[] badChars = {'.', '/', '>', '='}; - for (int j = 0; j < 4; j++) { - if (nameDashes.indexOf(badChars[j]) != -1) { - throw new IllegalArgumentException("Bad name: " + nameDashes); // NOI18N - } - } - String name = nameDashes.replace('-', '.').intern(); // NOI18N - arr.add(name); - } else { - LOG.fine("Strange file encountered in modules folder: " + f); - } - } - names = arr.toArray(new String[0]); - } - ev.log( Events.MODULES_FILE_SCANNED, names.length ); - - XMLReader reader = null; - - for (int i = 0; i < names.length; i++) { - String name = names[i]; - FileObject f = null; - try { - - // Now name is the code name base of the module we expect to find. - // Check its format (throws IllegalArgumentException if bad): - Dependency.create(Dependency.TYPE_MODULE, name); - - // OK, read it from disk. - Map props = cache == null ? null : cache.get(name); - if (props == null) { - LOG.log(Level.FINEST, "no cache for {0}", name); - f = folder.getFileObject(name.replace('.', '-') + ".xml"); - InputStream is = f.getInputStream(); - try { - props = readStatus(new BufferedInputStream(is),true); - if (props == null) { - LOG.warning("Note - failed to parse " + f + " the quick way, falling back on XMLReader"); - is.close(); - is = f.getInputStream(); - InputSource src = new InputSource(is); - // Make sure any includes etc. are handled properly: - src.setSystemId(f.getURL().toExternalForm()); - if (reader == null) { - try { - reader = XMLUtil.createXMLReader(); - } catch(SAXException e) { - throw (IllegalStateException) new IllegalStateException(e.toString()).initCause(e); - } - reader.setEntityResolver(listener); - reader.setErrorHandler(listener); - } - props = readStatus(src,reader); - } - } finally { - is.close(); - } - } - if (! name.equals(props.get("name"))) throw new IOException("Code name mismatch: " /* #25011 */ + name + " vs. " + props.get("name")); // NOI18N - Boolean enabledB = (Boolean)props.get("enabled"); // NOI18N - String jar = (String)props.get("jar"); // NOI18N - File jarFile; - try { - jarFile = findJarByName(jar, name); - } catch (FileNotFoundException fnfe) { - //LOG.fine("Cannot find: " + fnfe.getMessage()); - ev.log(Events.MISSING_JAR_FILE, new File(fnfe.getMessage()), enabledB); - if (!Boolean.FALSE.equals(enabledB)) { - try { - f.delete(); - } catch (IOException ioe) { - LOG.log(Level.WARNING, null, ioe); - } - } - continue; - } - - ModuleHistory history = new ModuleHistory(jar); // NOI18N - Integer prevReleaseI = (Integer)props.get("release"); // NOI18N - int prevRelease = (prevReleaseI == null ? -1 : prevReleaseI.intValue()); - SpecificationVersion prevSpec = (SpecificationVersion)props.get("specversion"); // NOI18N - history.upgrade(prevRelease, prevSpec); - Boolean reloadableB = (Boolean)props.get("reloadable"); // NOI18N - boolean reloadable = (reloadableB != null ? reloadableB.booleanValue() : false); - boolean enabled = (enabledB != null ? enabledB.booleanValue() : false); - Boolean autoloadB = (Boolean)props.get("autoload"); // NOI18N - boolean autoload = (autoloadB != null ? autoloadB.booleanValue() : false); - Boolean eagerB = (Boolean)props.get("eager"); // NOI18N - boolean eager = (eagerB != null ? eagerB.booleanValue() : false); - String installer = (String)props.get("installer"); // NOI18N - if (installer != null) { - String nameDashes = name.replace('.', '-'); - if (! installer.equals(nameDashes + ".ser")) throw new IOException("Incorrect installer ser name: " + installer); // NOI18N - // Load from disk in mentioned file. - FileObject installerSer = folder.getFileObject(nameDashes, "ser"); // NOI18N - if (installerSer == null) throw new IOException("No such install ser: " + installer + "; I see only: " + Arrays.asList(folder.getChildren())); // NOI18N - // Hope the stored state is not >Integer.MAX_INT! :-) - byte[] buf = new byte[(int)installerSer.getSize()]; - InputStream is2 = installerSer.getInputStream(); - try { - is2.read(buf); - } finally { - is2.close(); - } - history.setInstallerState(buf); - // Quasi-prop which is stored separately. - props.put("installerState", buf); // NOI18N - } - Module m = mgr.create(jarFile, history, reloadable, autoload, eager); - read.add(m); - DiskStatus status = new DiskStatus(); - status.module = m; - status.file = f; - //status.lastApprovedChange = children[i].lastModified().getTime(); - status.pendingInstall = enabled; - // Will only really be flushed if mgr props != disk props, i.e - // if version changed or could not be enabled. - //status.pendingFlush = true; - status.setDiskProps(props); - statuses.put(name, status); - } catch (Exception e) { - LOG.log(Level.WARNING, "Error encountered while reading " + name, e); - } - ev.log( Events.MODULES_FILE_PROCESSED, name ); - } - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("read initial XML files: statuses=" + statuses); - } - ev.log(Events.FINISH_READ, read); - // Handle changes in the Modules/ folder on disk by parsing & applying them. - folder.addFileChangeListener(FileUtil.weakFileChangeListener (listener, folder)); - }}); + folder.getFileSystem().runAtomicAction(new ReadInitial(read)); } catch (IOException ioe) { LOG.log(Level.WARNING, null, ioe); } @@ -786,49 +644,50 @@ * you have to use a real parser. * @see "#26786" */ - private Map readStatus(InputStream is,boolean checkEOF) throws IOException { + private Map readStatus(InputStream is, boolean checkEOF) throws IOException { + PushbackInputStream pbis = new PushbackInputStream(is, 1); Map m = new HashMap(15); - if (!expect(is, MODULE_XML_INTRO)) { + if (!expect(pbis, MODULE_XML_INTRO)) { LOG.fine("Could not read intro"); return null; } - String name = readTo(is, '"'); + String name = readTo(pbis, '"'); if (name == null) { LOG.fine("Could not read code name base"); return null; } m.put("name", name.intern()); // NOI18N - if (!expect(is, MODULE_XML_INTRO_END)) { + if (!expect(pbis, MODULE_XML_INTRO_END)) { LOG.fine("Could not read stuff after cnb"); return null; } // Now we have s some number of times, finally . PARSE: while (true) { - int c = is.read(); + int c = pbis.read(); switch (c) { case ' ': // - if (!expect(is, MODULE_XML_DIV2)) { + if (!expect(pbis, MODULE_XML_DIV2)) { LOG.fine("Could not read up to param"); return null; } - String k = readTo(is, '"'); + String k = readTo(pbis, '"'); if (k == null) { LOG.fine("Could not read param"); return null; } k = k.intern(); - if (is.read() != '>') { + if (pbis.read() != '>') { LOG.fine("No > at end of " + k); return null; } - String v = readTo(is, '<'); + String v = readTo(pbis, '<'); if (v == null) { LOG.fine("Could not read value of " + k); return null; } - if (!expect(is, MODULE_XML_DIV3)) { + if (!expect(pbis, MODULE_XML_DIV3)) { LOG.fine("Could not read end of param " + k); return null; } @@ -841,14 +700,14 @@ break; case '<': // - if (!expect(is, MODULE_XML_END)) { + if (!expect(pbis, MODULE_XML_END)) { LOG.fine("Strange ending"); return null; } if (!checkEOF) { break PARSE; } - if (is.read() != -1) { + if (pbis.read() != -1) { LOG.fine("Trailing garbage"); return null; } @@ -867,7 +726,7 @@ * Newline conventions are normalized to Unix \n. * @return true upon success, false if stream contained something else */ - private boolean expect(InputStream is, byte[] stuff) throws IOException { + private boolean expect(PushbackInputStream is, byte[] stuff) throws IOException { int len = stuff.length; boolean inNewline = false; for (int i = 0; i < len; ) { @@ -890,12 +749,10 @@ if (stuff[len - 1] == 10) { // Expecting something ending in a \n - so we have to // read any further \r or \n and discard. - if (!is.markSupported()) throw new IOException("Mark not supported"); // NOI18N - is.mark(1); int c = is.read(); if (c != -1 && c != 10 && c != 13) { // Got some non-newline character, push it back! - is.reset(); + is.unread(c); } } return true; @@ -939,7 +796,7 @@ } } - private Map> readCache() throws IOException { + final Map> readCache() throws IOException { InputStream is = Stamps.getModulesJARs().asStream("all-modules.dat"); // NOI18N if (is == null) { // schedule write for later @@ -947,33 +804,48 @@ return null; } LOG.log(Level.FINEST, "Reading cache all-modules.dat"); + ObjectInputStream ois = new ObjectInputStream(is); Map> ret = new HashMap>(1333); while (is.available() > 0) { - Map prop = readStatus(is, false); + Map prop = readStatus(ois, false); if (prop == null) { LOG.log(Level.CONFIG, "Cache is invalid all-modules.dat"); return null; } + Set deps; + try { + deps = (Set) ois.readObject(); + } catch (ClassNotFoundException ex) { + throw (IOException)new IOException(ex.getMessage()).initCause(ex); + } + prop.put("deps", deps); String cnb = (String)prop.get("name"); // NOI18N ret.put(cnb, prop); } - is.close(); - return ret; - } + + is.close(); + + return ret; + } final void writeCache() { Stamps.getModulesJARs().scheduleSave(this, "all-modules.dat", false); } + public void cacheReady() { + } + public void flushCaches(DataOutputStream os) throws IOException { + ObjectOutputStream oss = new ObjectOutputStream(os); for (Module m : mgr.getModules()) { if (m.isFixed()) { continue; } Map prop = computeProperties(m); - writeStatus(prop, os); + writeStatus(prop, oss); + oss.writeObject(m.getDependencies()); } } @@ -1819,7 +1691,163 @@ } } - public void cacheReady() { + private class ReadInitial implements AtomicAction { + + private final Set read; + + public ReadInitial(Set read) { + this.read = read; + } + + public void run() throws IOException { + Map> cache = readCache(); + String[] names; + if (cache != null) { + names = cache.keySet().toArray(new String[0]); + } else { + FileObject[] children = folder.getChildren(); + List arr = new ArrayList(children.length); + for (FileObject f : children) { + if (f.hasExt("ser")) { // NOI18N + // Fine, skip over. + } else if (f.hasExt("xml")) { + // NOI18N + // Assume this is one of ours. Note fixed naming scheme. + String nameDashes = f.getName(); // NOI18N + char[] badChars = {'.', '/', '>', '='}; + for (int j = 0; j < 4; j++) { + if (nameDashes.indexOf(badChars[j]) != -1) { + throw new IllegalArgumentException("Bad name: " + nameDashes); // NOI18N + } + } + String name = nameDashes.replace('-', '.').intern(); // NOI18N + arr.add(name); + } else { + LOG.fine("Strange file encountered in modules folder: " + f); + } + } + names = arr.toArray(new String[0]); + } + ev.log(Events.MODULES_FILE_SCANNED, names.length); + XMLReader reader = null; + for (int i = 0; i < names.length; i++) { + String name = names[i]; + FileObject f = null; + try { + // OK, read it from disk. + Map props = cache == null ? null : cache.get(name); + if (props == null) { + // Now name is the code name base of the module we expect to find. + // Check its format (throws IllegalArgumentException if bad): + Dependency.create(Dependency.TYPE_MODULE, name); + LOG.log(Level.FINEST, "no cache for {0}", name); + f = folder.getFileObject(name.replace('.', '-') + ".xml"); + InputStream is = f.getInputStream(); + try { + props = readStatus(new BufferedInputStream(is), true); + if (props == null) { + LOG.warning("Note - failed to parse " + f + " the quick way, falling back on XMLReader"); + is.close(); + is = f.getInputStream(); + InputSource src = new InputSource(is); + // Make sure any includes etc. are handled properly: + src.setSystemId(f.getURL().toExternalForm()); + if (reader == null) { + try { + reader = XMLUtil.createXMLReader(); + } catch (SAXException e) { + throw (IllegalStateException) new IllegalStateException(e.toString()).initCause(e); + } + reader.setEntityResolver(listener); + reader.setErrorHandler(listener); + } + props = readStatus(src, reader); + } + } finally { + is.close(); + } + } + if (!name.equals(props.get("name"))) { + throw new IOException("Code name mismatch: " + name + " vs. " + props.get("name")); // NOI18N + } + Boolean enabledB = (Boolean) props.get("enabled"); // NOI18N + String jar = (String) props.get("jar"); // NOI18N + File jarFile; + try { + jarFile = findJarByName(jar, name); + } catch (FileNotFoundException fnfe) { + //LOG.fine("Cannot find: " + fnfe.getMessage()); + ev.log(Events.MISSING_JAR_FILE, new File(fnfe.getMessage()), enabledB); + if (!Boolean.FALSE.equals(enabledB)) { + try { + f.delete(); + } catch (IOException ioe) { + LOG.log(Level.WARNING, null, ioe); + } + } + continue; + } + ModuleHistory history = new ModuleHistory(jar); // NOI18N + Integer prevReleaseI = (Integer) props.get("release"); // NOI18N + int prevRelease = prevReleaseI == null ? -1 : prevReleaseI.intValue(); + SpecificationVersion prevSpec = (SpecificationVersion) props.get("specversion"); // NOI18N + history.upgrade(prevRelease, prevSpec); + Boolean reloadableB = (Boolean) props.get("reloadable"); // NOI18N + boolean reloadable = reloadableB != null ? reloadableB.booleanValue() : false; + boolean enabled = enabledB != null ? enabledB.booleanValue() : false; + Boolean autoloadB = (Boolean) props.get("autoload"); // NOI18N + boolean autoload = autoloadB != null ? autoloadB.booleanValue() : false; + Boolean eagerB = (Boolean) props.get("eager"); // NOI18N + boolean eager = eagerB != null ? eagerB.booleanValue() : false; + String installer = (String) props.get("installer"); // NOI18N + if (installer != null) { + String nameDashes = name.replace('.', '-'); + if (!installer.equals(nameDashes + ".ser")) { + throw new IOException("Incorrect installer ser name: " + installer); // NOI18N + } + // Load from disk in mentioned file. + FileObject installerSer = folder.getFileObject(nameDashes, "ser"); // NOI18N + if (installerSer == null) { + throw new IOException("No such install ser: " + installer + "; I see only: " + Arrays.asList(folder.getChildren())); // NOI18N + } + // Hope the stored state is not >Integer.MAX_INT! :-) + byte[] buf = new byte[(int) installerSer.getSize()]; + InputStream is2 = installerSer.getInputStream(); + try { + is2.read(buf); + } finally { + is2.close(); + } + history.setInstallerState(buf); + // Quasi-prop which is stored separately. + props.put("installerState", buf); // NOI18N + } + NbInstaller.register(name, props.get("deps")); // NOI18N + Module m = mgr.create(jarFile, history, reloadable, autoload, eager); + NbInstaller.register(null, null); + read.add(m); + DiskStatus status = new DiskStatus(); + status.module = m; + status.file = f; + //status.lastApprovedChange = children[i].lastModified().getTime(); + status.pendingInstall = enabled; + // Will only really be flushed if mgr props != disk props, i.e + // if version changed or could not be enabled. + //status.pendingFlush = true; + status.setDiskProps(props); + statuses.put(name, status); + } catch (Exception e) { + LOG.log(Level.WARNING, "Error encountered while reading " + name, e); + } + ev.log(Events.MODULES_FILE_PROCESSED, name); + } + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("read initial XML files: statuses=" + statuses); + } + ev.log(Events.FINISH_READ, read); + // Handle changes in the Modules/ folder on disk by parsing & applying them. + folder.addFileChangeListener(FileUtil.weakFileChangeListener(listener, folder)); + } } } diff -r bae89dd72ba8 core.startup/src/org/netbeans/core/startup/NbInstaller.java --- a/core.startup/src/org/netbeans/core/startup/NbInstaller.java Fri Apr 03 08:04:47 2009 +0200 +++ b/core.startup/src/org/netbeans/core/startup/NbInstaller.java Fri Apr 03 17:39:12 2009 +0200 @@ -700,6 +700,19 @@ } } } + + private static String cacheCnb; + private static Set cacheDeps; + @Override + protected Set loadDependencies(String cnb) { + return cnb.equals(cacheCnb) ? cacheDeps : null; + } + @SuppressWarnings("unchecked") + static void register(String name, Object obj) { + cacheCnb = name; + cacheDeps = (Set)obj; + } + private AutomaticDependencies autoDepsHandler = null; diff -r bae89dd72ba8 o.n.bootstrap/manifest.mf --- a/o.n.bootstrap/manifest.mf Fri Apr 03 08:04:47 2009 +0200 +++ b/o.n.bootstrap/manifest.mf Fri Apr 03 17:39:12 2009 +0200 @@ -1,4 +1,4 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.bootstrap/1 -OpenIDE-Module-Specification-Version: 2.17 +OpenIDE-Module-Specification-Version: 2.18 OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties diff -r bae89dd72ba8 o.n.bootstrap/src/org/netbeans/Module.java --- a/o.n.bootstrap/src/org/netbeans/Module.java Fri Apr 03 08:04:47 2009 +0200 +++ b/o.n.bootstrap/src/org/netbeans/Module.java Fri Apr 03 17:39:12 2009 +0200 @@ -80,7 +80,7 @@ public static final String PROP_MANIFEST = "manifest"; // NOI18N public static final String PROP_VALID = "valid"; // NOI18N public static final String PROP_PROBLEMS = "problems"; // NOI18N - + /** manager which owns this module */ protected final ModuleManager mgr; /** event logging (should not be much here) */ @@ -306,6 +306,7 @@ */ protected void parseManifest() throws InvalidException { Attributes attr = getManifest().getMainAttributes(); + // Code name codeName = attr.getValue("OpenIDE-Module"); // NOI18N if (codeName == null) { @@ -322,9 +323,13 @@ if (codeName.indexOf(',') != -1) { throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N } - Dependency.create(Dependency.TYPE_MODULE, codeName); Object[] cnParse = Util.parseCodeName(codeName); codeNameBase = (String)cnParse[0]; + Set deps = mgr.loadDependencies(codeNameBase); + boolean verifyCNBs = deps == null; + if (verifyCNBs) { + Dependency.create(Dependency.TYPE_MODULE, codeName); + } codeNameRelease = (cnParse[1] != null) ? ((Integer)cnParse[1]).intValue() : -1; if (cnParse[2] != null) throw new NumberFormatException(codeName); // Spec vers @@ -350,7 +355,9 @@ if (provide.indexOf(',') != -1) { throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module-Provides: " + provide); // NOI18N } - Dependency.create(Dependency.TYPE_MODULE, provide); + if (verifyCNBs) { + Dependency.create(Dependency.TYPE_MODULE, provide); + } if (provide.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Provides: " + provide); // NOI18N provides[i] = provide; } @@ -382,12 +389,16 @@ String piece = tok.nextToken(); if (piece.endsWith(".*")) { // NOI18N String pkg = piece.substring(0, piece.length() - 2); - Dependency.create(Dependency.TYPE_MODULE, pkg); + if (verifyCNBs) { + Dependency.create(Dependency.TYPE_MODULE, pkg); + } if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N exports.add(new PackageExport(pkg.replace('.', '/') + '/', false)); } else if (piece.endsWith(".**")) { // NOI18N String pkg = piece.substring(0, piece.length() - 3); - Dependency.create(Dependency.TYPE_MODULE, pkg); + if (verifyCNBs) { + Dependency.create(Dependency.TYPE_MODULE, pkg); + } if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N exports.add(new PackageExport(pkg.replace('.', '/') + '/', true)); } else { @@ -414,8 +425,10 @@ if (piece.indexOf('/') != -1) { throw new IllegalArgumentException("May specify only module code name bases in OpenIDE-Module-Friends, not major release versions: " + piece); // NOI18N } - // Indirect way of checking syntax: - Dependency.create(Dependency.TYPE_MODULE, piece); + if (verifyCNBs) { + // Indirect way of checking syntax: + Dependency.create(Dependency.TYPE_MODULE, piece); + } // OK, add it. set.add(piece); } @@ -428,37 +441,7 @@ this.friendNames = set; } } - - - // Dependencies - Set dependencies = new HashSet(20); - // First convert IDE/1 -> org.openide/1, so we never have to deal with - // "IDE deps" internally: - @SuppressWarnings("deprecation") - Set openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N - if (!openideDeps.isEmpty()) { - // If empty, leave it that way; NbInstaller will add it anyway. - Dependency d = openideDeps.iterator().next(); - String name = d.getName(); - if (!name.startsWith("IDE/")) throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N - dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N - if (dependencies.size() != 1) throw new IllegalStateException("Should be singleton: " + dependencies); // NOI18N - - Util.err.warning("the module " + codeNameBase + " uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html"); // NOI18N - } - dependencies.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N - dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N - String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N - if (pkgdeps != null) { - // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies manifest attribute, which is now deprecated: XXX URL TBD"); - dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N - } - dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N - dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N - dependencies.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N - // Permit the concrete installer to make some changes: - mgr.refineDependencies(this, dependencies); - dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]); + initDeps(deps, attr); } catch (IllegalArgumentException iae) { throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N } @@ -632,4 +615,52 @@ } } + /** Initializes dependencies of this module + * + * @param knownDeps Set of this module known from different source, + * can be null + * @param attr attributes in manifest to parse if knownDeps is null + */ + private void initDeps(Set knownDeps, Attributes attr) + throws IllegalStateException, IllegalArgumentException { + if (knownDeps != null) { + dependenciesA = knownDeps.toArray(new Dependency[knownDeps.size()]); + knownDeps = null; + return; + } + + // Dependencies + Set dependencies = new HashSet(20); + // First convert IDE/1 -> org.openide/1, so we never have to deal with + // "IDE deps" internally: + @SuppressWarnings(value = "deprecation") + Set openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N + if (!openideDeps.isEmpty()) { + // If empty, leave it that way; NbInstaller will add it anyway. + Dependency d = openideDeps.iterator().next(); + String name = d.getName(); + if (!name.startsWith("IDE/")) { + throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N + } + dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N + if (dependencies.size() != 1) { + throw new IllegalStateException("Should be singleton: " + dependencies); // NOI18N + } + Util.err.warning("the module " + codeNameBase + " uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html"); // NOI18N + } + dependencies.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N + dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N + String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N + if (pkgdeps != null) { + // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies manifest attribute, which is now deprecated: XXX URL TBD"); + dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N + } + dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N + dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N + dependencies.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N + // Permit the concrete installer to make some changes: + mgr.refineDependencies(this, dependencies); + dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]); + } + } diff -r bae89dd72ba8 o.n.bootstrap/src/org/netbeans/ModuleInstaller.java --- a/o.n.bootstrap/src/org/netbeans/ModuleInstaller.java Fri Apr 03 08:04:47 2009 +0200 +++ b/o.n.bootstrap/src/org/netbeans/ModuleInstaller.java Fri Apr 03 17:39:12 2009 +0200 @@ -203,4 +203,13 @@ return null; } + /** Loades dependencies cached from previous run, if possible. + * @param cnb the code name base of the module to get dependencies for + * @return null or set of dependencies for the module + * @since 2.18 + */ + protected Set loadDependencies(String cnb) { + return null; + } + } diff -r bae89dd72ba8 o.n.bootstrap/src/org/netbeans/ModuleManager.java --- a/o.n.bootstrap/src/org/netbeans/ModuleManager.java Fri Apr 03 08:04:47 2009 +0200 +++ b/o.n.bootstrap/src/org/netbeans/ModuleManager.java Fri Apr 03 17:39:12 2009 +0200 @@ -532,6 +532,9 @@ /** Used by Module to communicate with the ModuleInstaller re. dependencies. */ void refineDependencies(Module m, Set dependencies) { installer.refineDependencies(m, dependencies); + } + Set loadDependencies(String cnb) { + return installer.loadDependencies(cnb); } /** Allows the installer to add provides (used to provide name of platform we run on) */ diff -r bae89dd72ba8 openide.modules/apichanges.xml --- a/openide.modules/apichanges.xml Fri Apr 03 08:04:47 2009 +0200 +++ b/openide.modules/apichanges.xml Fri Apr 03 17:39:12 2009 +0200 @@ -47,6 +47,21 @@ Modules API + + + Dependency class made serializable + + + + + +

+ Dependency now implements Serializable +

+
+ + +
Added annotation @PatchedPublic diff -r bae89dd72ba8 openide.modules/manifest.mf --- a/openide.modules/manifest.mf Fri Apr 03 08:04:47 2009 +0200 +++ b/openide.modules/manifest.mf Fri Apr 03 17:39:12 2009 +0200 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.modules OpenIDE-Module-Localizing-Bundle: org/openide/modules/Bundle.properties -OpenIDE-Module-Specification-Version: 7.9 +OpenIDE-Module-Specification-Version: 7.10 diff -r bae89dd72ba8 openide.modules/src/org/openide/modules/Dependency.java --- a/openide.modules/src/org/openide/modules/Dependency.java Fri Apr 03 08:04:47 2009 +0200 +++ b/openide.modules/src/org/openide/modules/Dependency.java Fri Apr 03 17:39:12 2009 +0200 @@ -41,6 +41,7 @@ package org.openide.modules; +import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -49,11 +50,15 @@ import java.util.StringTokenizer; import org.openide.util.Utilities; -/** A dependency a module can have. +/** A dependency a module can have. Since version 7.10 this class is + * {@link Serializable}. + * * @author Jesse Glick * @since 1.24 */ -public final class Dependency { +public final class Dependency implements Serializable { + static final long serialVersionUID = 9548259318L; + /** Dependency on another module. */ public final static int TYPE_MODULE = 1; @@ -413,6 +418,7 @@ } /** Overridden to compare contents. */ + @Override public boolean equals(Object o) { if (o.getClass() != Dependency.class) { return false; @@ -425,11 +431,13 @@ } /** Overridden to hash by contents. */ + @Override public int hashCode() { return 772067 ^ type ^ name.hashCode(); } /** Unspecified string representation for debugging. */ + @Override public String toString() { StringBuffer buf = new StringBuffer(100);