--- a/core.startup/src/org/netbeans/core/startup/ModuleList.java Fri Apr 03 08:04:47 2009 +0200 +++ a/core.startup/src/org/netbeans/core/startup/ModuleList.java Fri Apr 03 14:08:11 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; @@ -287,7 +290,10 @@ // Quasi-prop which is stored separately. props.put("installerState", buf); // NOI18N } + Module.deps = props.get("deps"); Module m = mgr.create(jarFile, history, reloadable, autoload, eager); + Module.deps = null; + read.add(m); DiskStatus status = new DiskStatus(); status.module = m; @@ -787,48 +793,49 @@ * @see "#26786" */ 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 +848,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 +874,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 +897,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; @@ -947,33 +952,45 @@ 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 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()); } } --- a/o.n.bootstrap/src/org/netbeans/Module.java Fri Apr 03 08:04:47 2009 +0200 +++ a/o.n.bootstrap/src/org/netbeans/Module.java Fri Apr 03 14:08:11 2009 +0200 @@ -80,7 +80,8 @@ public static final String PROP_MANIFEST = "manifest"; // NOI18N public static final String PROP_VALID = "valid"; // NOI18N public static final String PROP_PROBLEMS = "problems"; // NOI18N - + public static Object deps; + /** manager which owns this module */ protected final ModuleManager mgr; /** event logging (should not be much here) */ @@ -305,6 +306,8 @@ * some kind of description of the problem. */ protected void parseManifest() throws InvalidException { + boolean verifyCNBs = Module.deps == null; + Attributes attr = getManifest().getMainAttributes(); // Code name codeName = attr.getValue("OpenIDE-Module"); // NOI18N @@ -322,7 +325,9 @@ if (codeName.indexOf(',') != -1) { throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N } - Dependency.create(Dependency.TYPE_MODULE, codeName); + if (verifyCNBs) { + Dependency.create(Dependency.TYPE_MODULE, codeName); + } Object[] cnParse = Util.parseCodeName(codeName); codeNameBase = (String)cnParse[0]; codeNameRelease = (cnParse[1] != null) ? ((Integer)cnParse[1]).intValue() : -1; @@ -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,8 @@ 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(attr); } catch (IllegalArgumentException iae) { throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N } @@ -632,4 +616,46 @@ } } + private void initDeps(Attributes attr) throws IllegalStateException, IllegalArgumentException { + if (deps instanceof Set) { + Set s = (Set)deps; + dependenciesA = s.toArray(new Dependency[s.size()]); + deps = 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()]); + } + } --- a/openide.modules/src/org/openide/modules/Dependency.java Fri Apr 03 08:04:47 2009 +0200 +++ a/openide.modules/src/org/openide/modules/Dependency.java Fri Apr 03 14:08:11 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; @@ -53,7 +54,7 @@ * @author Jesse Glick * @since 1.24 */ -public final class Dependency { +public final class Dependency implements Serializable { /** Dependency on another module. */ public final static int TYPE_MODULE = 1; @@ -413,6 +414,7 @@ } /** Overridden to compare contents. */ + @Override public boolean equals(Object o) { if (o.getClass() != Dependency.class) { return false; @@ -425,11 +427,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);