Merge with more modern (and hopefully deadlock prone) version of default branch
1.1 --- a/autoupdate.services/nbproject/project.xml Thu Mar 15 16:10:40 2012 +0100
1.2 +++ b/autoupdate.services/nbproject/project.xml Fri Mar 16 08:17:35 2012 +0100
1.3 @@ -29,7 +29,7 @@
1.4 <compile-dependency/>
1.5 <run-dependency>
1.6 <release-version>1</release-version>
1.7 - <specification-version>1.28</specification-version>
1.8 + <specification-version>1.38</specification-version>
1.9 </run-dependency>
1.10 </dependency>
1.11 <dependency>
2.1 --- a/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java Thu Mar 15 16:10:40 2012 +0100
2.2 +++ b/autoupdate.services/src/org/netbeans/modules/autoupdate/services/Utilities.java Fri Mar 16 08:17:35 2012 +0100
2.3 @@ -63,6 +63,7 @@
2.4 import org.netbeans.api.autoupdate.UpdateElement;
2.5 import org.netbeans.api.autoupdate.UpdateManager;
2.6 import org.netbeans.api.autoupdate.UpdateUnit;
2.7 +import org.netbeans.core.startup.Main;
2.8 import org.netbeans.core.startup.TopLogging;
2.9 import org.netbeans.modules.autoupdate.updateprovider.DummyModuleInfo;
2.10 import org.netbeans.modules.autoupdate.updateprovider.InstalledModuleProvider;
2.11 @@ -102,7 +103,6 @@
2.12 public static final String NBM_EXTENTSION = ".nbm";
2.13 public static final String JAR_EXTENSION = ".jar"; //OSGi bundle
2.14 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat ("yyyy/MM/dd"); // NOI18N
2.15 - public static final String ATTR_VISIBLE = "AutoUpdate-Show-In-Client";
2.16 public static final String ATTR_ESSENTIAL = "AutoUpdate-Essential-Module";
2.17
2.18 private static final String[] FIRST_CLASS_MODULES = new String [] {
2.19 @@ -1049,15 +1049,7 @@
2.20 }
2.21
2.22 public static boolean isKitModule (ModuleInfo mi) {
2.23 - // XXX: it test can break simple modules mode
2.24 - // should find corresponing UpdateElement and check its type
2.25 - Object o = mi.getAttribute (ATTR_VISIBLE);
2.26 - if (o != null) {
2.27 - return Boolean.parseBoolean(o.toString());
2.28 - }
2.29 - // OSGi bundles should be considered invisible by default since they are typically autoloads.
2.30 - // (NB modules get AutoUpdate-Show-In-Client inserted into the JAR by the build process.)
2.31 - return mi.getAttribute("Bundle-SymbolicName") == null;
2.32 + return Main.getModuleSystem().isShowInAutoUpdateClient(mi);
2.33 }
2.34
2.35 public static boolean isEssentialModule (ModuleInfo mi) {
3.1 --- a/core.startup/apichanges.xml Thu Mar 15 16:10:40 2012 +0100
3.2 +++ b/core.startup/apichanges.xml Fri Mar 16 08:17:35 2012 +0100
3.3 @@ -56,6 +56,21 @@
3.4 <!-- ACTUAL CHANGES BEGIN HERE: -->
3.5
3.6 <changes>
3.7 + <change id="is.au.visible">
3.8 + <api name="bridge"/>
3.9 + <summary>isShowInAutoUpdateClient</summary>
3.10 + <version major="1" minor="38"/>
3.11 + <date day="21" month="3" year="2012"/>
3.12 + <author login="jtulach"/>
3.13 + <compatibility addition="yes" binary="compatible" semantic="compatible" />
3.14 + <description>
3.15 + <p>
3.16 + Method to allow ergonomics and autoupdate to check if a module
3.17 + is visible in the autoupdate client.
3.18 + </p>
3.19 + </description>
3.20 + <class package="org.netbeans.core.startup" name="ModuleSystem"/>
3.21 + </change>
3.22 <change id="netbeans.productversion">
3.23 <api name="exec-property"/>
3.24 <summary>netbeans.productversion property</summary>
4.1 --- a/core.startup/manifest.mf Thu Mar 15 16:10:40 2012 +0100
4.2 +++ b/core.startup/manifest.mf Fri Mar 16 08:17:35 2012 +0100
4.3 @@ -3,5 +3,5 @@
4.4 OpenIDE-Module-Localizing-Bundle: org/netbeans/core/startup/Bundle.properties
4.5 OpenIDE-Module-Layer: org/netbeans/core/startup/layer.xml
4.6 OpenIDE-Module-Provides: org.openide.modules.InstalledFileLocator
4.7 -OpenIDE-Module-Specification-Version: 1.37
4.8 +OpenIDE-Module-Specification-Version: 1.38
4.9
5.1 --- a/core.startup/nbproject/project.xml Thu Mar 15 16:10:40 2012 +0100
5.2 +++ b/core.startup/nbproject/project.xml Fri Mar 16 08:17:35 2012 +0100
5.3 @@ -55,7 +55,7 @@
5.4 <compile-dependency/>
5.5 <run-dependency>
5.6 <release-version>1</release-version>
5.7 - <specification-version>2.49</specification-version>
5.8 + <specification-version>2.51</specification-version>
5.9 </run-dependency>
5.10 </dependency>
5.11 <dependency>
6.1 --- a/core.startup/src/org/netbeans/core/startup/ModuleList.java Thu Mar 15 16:10:40 2012 +0100
6.2 +++ b/core.startup/src/org/netbeans/core/startup/ModuleList.java Fri Mar 16 08:17:35 2012 +0100
6.3 @@ -880,7 +880,7 @@
6.4 }
6.5 // Newly added modules first.
6.6 for (Module m : mgr.getModules()) {
6.7 - if (m.isFixed() || m.getAllJars().isEmpty()) {
6.8 + if (m.isFixed() || m.getJarFile() == null) {
6.9 // No way, we don't manage these.
6.10 continue;
6.11 }
7.1 --- a/core.startup/src/org/netbeans/core/startup/ModuleSystem.java Thu Mar 15 16:10:40 2012 +0100
7.2 +++ b/core.startup/src/org/netbeans/core/startup/ModuleSystem.java Fri Mar 16 08:17:35 2012 +0100
7.3 @@ -70,6 +70,7 @@
7.4 import org.openide.filesystems.FileObject;
7.5 import org.openide.filesystems.FileSystem;
7.6 import org.openide.filesystems.FileUtil;
7.7 +import org.openide.modules.ModuleInfo;
7.8 import org.openide.util.Exceptions;
7.9
7.10 /** Controller of the IDE's whole module system.
7.11 @@ -459,6 +460,20 @@
7.12 public String getEffectiveClasspath(Module m) {
7.13 return installer.getEffectiveClasspath(m);
7.14 }
7.15 +
7.16 + /** Checks whether the provided module will be visible in autoupdate client.
7.17 + * Seeks for AutoUpdate-Show-In-Client attribute in manifest. The module
7.18 + * is visible if the attribute is missing or if it is set to <code>true</code>.
7.19 + * Uses caches to remember the value between restarts.
7.20 + *
7.21 + * @since 1.38
7.22 + * @param mi the module to test
7.23 + * @return <code>true</code> if the module is supposed to be visible in
7.24 + * autoupdate client
7.25 + */
7.26 + public boolean isShowInAutoUpdateClient(ModuleInfo mi) {
7.27 + return this.installer.isShowInAutoUpdateClient(mi);
7.28 + }
7.29
7.30 /** Dummy event handler that does not print anything.
7.31 * Useful for test scripts where you do not really want to see
8.1 --- a/core.startup/src/org/netbeans/core/startup/NbInstaller.java Thu Mar 15 16:10:40 2012 +0100
8.2 +++ b/core.startup/src/org/netbeans/core/startup/NbInstaller.java Fri Mar 16 08:17:35 2012 +0100
8.3 @@ -44,16 +44,14 @@
8.4
8.5 package org.netbeans.core.startup;
8.6
8.7 -import java.io.ByteArrayInputStream;
8.8 import java.io.DataOutputStream;
8.9 import java.io.File;
8.10 import java.io.IOException;
8.11 +import java.io.InputStream;
8.12 import java.net.URL;
8.13 -import java.nio.ByteBuffer;
8.14 import java.util.ArrayList;
8.15 import java.util.Collection;
8.16 import java.util.Collections;
8.17 -import java.util.Date;
8.18 import java.util.Enumeration;
8.19 import java.util.HashMap;
8.20 import java.util.HashSet;
8.21 @@ -62,6 +60,7 @@
8.22 import java.util.List;
8.23 import java.util.Locale;
8.24 import java.util.Map;
8.25 +import java.util.Properties;
8.26 import java.util.Set;
8.27 import java.util.StringTokenizer;
8.28 import java.util.TreeMap;
8.29 @@ -69,7 +68,6 @@
8.30 import java.util.jar.Attributes;
8.31 import java.util.jar.JarEntry;
8.32 import java.util.jar.JarFile;
8.33 -import java.util.jar.Manifest;
8.34 import java.util.logging.Level;
8.35 import java.util.logging.Logger;
8.36 import org.netbeans.Events;
8.37 @@ -80,16 +78,16 @@
8.38 import org.netbeans.Stamps;
8.39 import org.netbeans.Util;
8.40 import org.netbeans.core.startup.layers.ModuleLayeredFileSystem;
8.41 -import org.netbeans.core.startup.preferences.RelPaths;
8.42 import org.openide.filesystems.FileObject;
8.43 import org.openide.filesystems.FileUtil;
8.44 import org.openide.modules.Dependency;
8.45 +import org.openide.modules.ModuleInfo;
8.46 import org.openide.modules.ModuleInstall;
8.47 import org.openide.modules.SpecificationVersion;
8.48 -import org.openide.util.Exceptions;
8.49 import org.openide.util.NbCollections;
8.50 import org.openide.util.SharedClassObject;
8.51 import org.openide.util.NbBundle;
8.52 +import org.openide.util.Utilities;
8.53 import org.openide.util.lookup.InstanceContent;
8.54 import org.xml.sax.SAXException;
8.55
8.56 @@ -124,6 +122,8 @@
8.57 private final Map<Module,List<Module.PackageExport>> hiddenClasspathPackages = new HashMap<Module,List<Module.PackageExport>>();
8.58 /** #164510: similar to {@link #hiddenClasspathPackages} but backwards for efficiency */
8.59 private final Map<Module.PackageExport,List<Module>> hiddenClasspathPackagesReverse = new HashMap<Module.PackageExport,List<Module>>();
8.60 + /** caches important values from module manifests */
8.61 + private final Cache cache = new Cache();
8.62
8.63 /** Create an NbInstaller.
8.64 * You should also call {@link #registerManager} and if applicable
8.65 @@ -145,12 +145,15 @@
8.66 }
8.67
8.68 // @SuppressWarnings("unchecked")
8.69 + @Override
8.70 public void prepare(Module m) throws InvalidException {
8.71 ev.log(Events.PREPARE, m);
8.72 checkForHiddenPackages(m);
8.73 Set<ManifestSection> mysections = null;
8.74 Class<?> clazz = null;
8.75 - {
8.76 +
8.77 + String processSections = cache.findGlobalProperty("processSections", null, "false"); // NOI18N
8.78 + if (!"false".equals(processSections)) { // NOI18N
8.79 // Find and load manifest sections.
8.80 for (Map.Entry<String,Attributes> entry : m.getManifest().getEntries().entrySet()) {
8.81 ManifestSection section = ManifestSection.create(entry.getKey(), entry.getValue(), m);
8.82 @@ -161,8 +164,11 @@
8.83 mysections.add(section);
8.84 }
8.85 }
8.86 + if (mysections != null) {
8.87 + cache.findGlobalProperty("processSections", "false", "true"); // NOI18N
8.88 + }
8.89 }
8.90 - String installClass = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Install"); // NOI18N
8.91 + String installClass = cache.findProperty(m, "OpenIDE-Module-Install", false); // NOI18N
8.92 if (installClass != null) {
8.93 String installClassName;
8.94 try {
8.95 @@ -216,15 +222,14 @@
8.96 }
8.97 // For layer & help set, validate only that the base-locale resource
8.98 // exists, not its contents or anything.
8.99 - String layerResource = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Layer"); // NOI18N
8.100 - String osgi = m.getManifest().getMainAttributes().getValue("Bundle-SymbolicName"); // NOI18N
8.101 - if (layerResource != null && osgi == null) {
8.102 + String layerResource = cache.findProperty(m, "OpenIDE-Module-Layer", false); // NOI18N
8.103 + if (layerResource != null && !m.isNetigso()) {
8.104 URL layer = m.getClassLoader().getResource(layerResource);
8.105 if (layer == null) throw new InvalidException(m, "Layer not found: " + layerResource); // NOI18N
8.106 }
8.107 - String helpSetName = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Description"); // NOI18N
8.108 + String helpSetName = cache.findProperty(m, "OpenIDE-Module-Description", false); // NOI18N
8.109 if (helpSetName != null) {
8.110 - Util.err.warning("Use of OpenIDE-Module-Description in " + m.getCodeNameBase() + " is deprecated.");
8.111 + Util.err.log(Level.WARNING, "Use of OpenIDE-Module-Description in {0} is deprecated.", m.getCodeNameBase());
8.112 Util.err.warning("(Please install help using an XML layer instead.)");
8.113 }
8.114 // We are OK, commit everything to our cache.
8.115 @@ -236,7 +241,7 @@
8.116 }
8.117 if (layerResource != null) {
8.118 layers.put(m, layerResource);
8.119 - }
8.120 + }
8.121 }
8.122
8.123 private void checkForHiddenPackages(Module m) throws InvalidException {
8.124 @@ -251,7 +256,7 @@
8.125 }
8.126 }
8.127 for (Module _m : mWithDeps) {
8.128 - String hidden = (String) _m.getAttribute("OpenIDE-Module-Hide-Classpath-Packages"); // NOI18N
8.129 + String hidden = cache.findProperty(_m, "OpenIDE-Module-Hide-Classpath-Packages", false); // NOI18N
8.130 if (hidden != null) {
8.131 for (String piece : hidden.trim().split("[ ,]+")) { // NOI18N
8.132 try {
8.133 @@ -610,7 +615,8 @@
8.134 private void checkForDeprecations(List<Module> modules) {
8.135 Map<String,Set<String>> depToUsers = new TreeMap<String,Set<String>>();
8.136 for (Module m : modules) {
8.137 - if (!Boolean.parseBoolean((String) m.getAttribute("OpenIDE-Module-Deprecated"))) { // NOI18N
8.138 + String depr = cache.findProperty(m, "OpenIDE-Module-Deprecated", false); // NOI18N
8.139 + if (!Boolean.parseBoolean(depr)) {
8.140 for (Dependency dep : m.getDependencies()) {
8.141 if (dep.getType() == Dependency.TYPE_MODULE) {
8.142 String cnb = (String) Util.parseCodeName(dep.getName())[0];
8.143 @@ -628,8 +634,9 @@
8.144 String dep = entry.getKey();
8.145 Module o = mgr.get(dep);
8.146 assert o != null : "No such module: " + dep;
8.147 - if (Boolean.parseBoolean((String) o.getAttribute("OpenIDE-Module-Deprecated"))) { // NOI18N
8.148 - String message = (String) o.getLocalizedAttribute("OpenIDE-Module-Deprecation-Message"); // NOI18N
8.149 + String depr = cache.findProperty(o, "OpenIDE-Module-Deprecated", false); // NOI18N
8.150 + if (Boolean.parseBoolean(depr)) {
8.151 + String message = cache.findProperty(o, "OpenIDE-Module-Deprecation-Message", true); // NOI18N
8.152 // XXX use NbEvents? I18N?
8.153 // For now, assume this is a developer-oriented message that need not be localized or displayed in a pretty fashion.
8.154 Set<String> users = entry.getValue();
8.155 @@ -1125,186 +1132,6 @@
8.156 }
8.157 }
8.158
8.159 - // Manifest caching: #26786.
8.160 -
8.161 - private static final Logger MANIFEST_LOG = Logger.getLogger(NbInstaller.class.getName() + ".manifestCache");
8.162 -
8.163 - /** While true, try to use the manifest cache.
8.164 - * So (non-reloadable) JARs scanned during startup will have their manifests cached.
8.165 - * After the primary set of modules has been scanned, this will be set to false.
8.166 - * Initially true, unless -J-Dnetbeans.cache.manifests=false is specified,
8.167 - * or there is no available cache directory.
8.168 - */
8.169 - private boolean usingManifestCache;
8.170 - private final Object MANIFEST_CACHE = new Object();
8.171 -
8.172 - {
8.173 - usingManifestCache = Boolean.valueOf(System.getProperty("netbeans.cache.manifests", "true")).booleanValue();
8.174 - if (!usingManifestCache) {
8.175 - MANIFEST_LOG.fine("Manifest cache disabled");
8.176 - }
8.177 - }
8.178 -
8.179 - /** Cache of known JAR manifests.
8.180 - * Initially null. If the cache is read, it may be used to quickly serve JAR manifests.
8.181 - */
8.182 - private Map<File,DateAndManifest> manifestCache;
8.183 - private static final class DateAndManifest {
8.184 - /** modification date when last read */
8.185 - public final long date;
8.186 - public final Manifest manifest;
8.187 - public DateAndManifest(long date, Manifest manifest) {
8.188 - this.date = date;
8.189 - this.manifest = manifest;
8.190 - }
8.191 - }
8.192 -
8.193 - /** Overrides superclass method to keep a cache of module manifests,
8.194 - * so that their JARs do not have to be opened twice during startup.
8.195 - */
8.196 - public @Override Manifest loadManifest(File jar) throws IOException {
8.197 - if (!usingManifestCache) {
8.198 - return super.loadManifest(jar);
8.199 - }
8.200 - Map<File, DateAndManifest> cache;
8.201 - synchronized (MANIFEST_CACHE) {
8.202 - if (manifestCache == null) {
8.203 - manifestCache = Collections.synchronizedMap(loadManifestCache());
8.204 - }
8.205 - cache = manifestCache;
8.206 - }
8.207 - DateAndManifest entry = cache.get(jar);
8.208 - if (entry != null) {
8.209 - // Cache hit.
8.210 - MANIFEST_LOG.fine("Found manifest for " + jar + " in cache");
8.211 - return entry.manifest;
8.212 - } else {
8.213 - MANIFEST_LOG.fine("No entry for " + jar + " in manifest cache");
8.214 - }
8.215 - // Cache miss.
8.216 - Manifest m = super.loadManifest(jar);
8.217 - // (If that threw IOException, we leave it out of the cache.)
8.218 - cache.put(jar, new DateAndManifest(jar.lastModified(), m));
8.219 - saveManifestCache();
8.220 - return m;
8.221 - }
8.222 -
8.223 - class CacheFlusher implements Stamps.Updater {
8.224 - public void flushCaches(DataOutputStream os) throws IOException {
8.225 - updater = new CacheFlusher();
8.226 -
8.227 - MANIFEST_LOG.fine("Saving manifest cache");
8.228 - HashMap<File, DateAndManifest> m;
8.229 - synchronized (MANIFEST_CACHE) {
8.230 - m = new HashMap<File, DateAndManifest>(manifestCache);
8.231 - }
8.232 - for (Map.Entry<File, DateAndManifest> entry : m.entrySet()) {
8.233 - File jar = entry.getKey();
8.234 - String[] relPath = RelPaths.findRelativePath(jar.getAbsolutePath());
8.235 - assert relPath != null : "Cannot find relative path for " + jar;
8.236 - os.writeUTF(relPath[0]);
8.237 - os.writeUTF(relPath[1]);
8.238 - long time = entry.getValue().date;
8.239 - for (int i = 7; i >= 0; i--) {
8.240 - os.write((int) ((time >> (i * 8)) & 0xFF));
8.241 - }
8.242 - entry.getValue().manifest.write(os);
8.243 - os.write(0);
8.244 - }
8.245 - os.close();
8.246 - MANIFEST_LOG.fine("Saving manifest cache - done");
8.247 - }
8.248 -
8.249 - public void cacheReady() {
8.250 - }
8.251 - }
8.252 - CacheFlusher updater = new CacheFlusher();
8.253 -
8.254 - /** Really save the cache.
8.255 - * @see #manifestCacheFile
8.256 - */
8.257 - private void saveManifestCache() throws IOException {
8.258 - MANIFEST_LOG.fine("Schedule saving manifest cache");
8.259 - Stamps.getModulesJARs().scheduleSave(updater, "all-manifest.dat", false);
8.260 - }
8.261 -
8.262 - /** Load the cache if present.
8.263 - * If not present, or there are problems with it,
8.264 - * just create an empty cache.
8.265 - * @see #manifestCacheFile
8.266 - */
8.267 - private Map<File,DateAndManifest> loadManifestCache() {
8.268 - ev.log(Events.PERF_START, "NbInstaller - loadManifestCache"); // NOI18N
8.269 - ByteBuffer bis = Stamps.getModulesJARs().asByteBuffer("all-manifest.dat"); // NOI18N
8.270 - Map<File,DateAndManifest> m = new HashMap<File,DateAndManifest>(200);
8.271 - try {
8.272 - readManifestCacheEntries(bis, m);
8.273 - } catch (IOException ex) {
8.274 - MANIFEST_LOG.log(Level.WARNING, "Cannot read cache", ex); // NOI18N
8.275 - } finally {
8.276 - ev.log(Events.PERF_END, "NbInstaller - loadManifestCache"); // NOI18N
8.277 - }
8.278 - return m;
8.279 - }
8.280 -
8.281 - private static int findNullByte(ByteBuffer data, int start) {
8.282 - int len = data.limit();
8.283 - for (int i = start; i < len; i++) {
8.284 - if (data.get(i) == 0) {
8.285 - return i;
8.286 - }
8.287 - }
8.288 - return -1;
8.289 - }
8.290 -
8.291 - private static void readManifestCacheEntries(ByteBuffer data, Map<File,DateAndManifest> m) throws IOException {
8.292 - if (data == null) {
8.293 - return;
8.294 - }
8.295 -
8.296 - int pos = 0;
8.297 - while (true) {
8.298 - if (pos == data.limit()) {
8.299 - return;
8.300 - }
8.301 - data.position(pos);
8.302 - File jar = new File(RelPaths.readRelativePath(data)); // NOI18N
8.303 - int end = data.position();
8.304 - long time = 0L;
8.305 - if (end + 8 >= data.limit()) throw new IOException("Ran out of space for timestamp for " + jar); // NOI18N
8.306 - for (int i = 0; i < 8; i++) {
8.307 - long b = data.get(end + i + 1);
8.308 - if (b < 0) b += 256;
8.309 - int exponent = 7 - i;
8.310 - long addin = b << (exponent * 8);
8.311 - time |= addin;
8.312 - //System.err.println("i=" + i + " b=0x" + Long.toHexString(b) + " exponent=" + exponent + " addin=0x" + Long.toHexString(addin) + " time=0x" + Long.toHexString(time));
8.313 - }
8.314 - pos = end + 9;
8.315 - end = findNullByte(data, pos);
8.316 - if (end == -1) throw new IOException("Could not find manifest body for " + jar); // NOI18N
8.317 - Manifest mani;
8.318 - try {
8.319 - mani = new Manifest(new ByteArrayInputStream(toArray(data, pos, end - pos)));
8.320 - } catch (IOException ioe) {
8.321 - Exceptions.attachMessage(ioe, "While in entry for " + jar);
8.322 - throw ioe;
8.323 - }
8.324 - m.put(jar, new DateAndManifest(time, mani));
8.325 - if (MANIFEST_LOG.isLoggable(Level.FINE)) {
8.326 - MANIFEST_LOG.fine("Manifest cache entry: jar=" + jar + " date=" + new Date(time) + " codename=" + mani.getMainAttributes().getValue("OpenIDE-Module"));
8.327 - }
8.328 - pos = end + 1;
8.329 - }
8.330 - }
8.331 -
8.332 - private static byte[] toArray(ByteBuffer bb, int pos, int len) {
8.333 - byte[] manarr = new byte[len];
8.334 - bb.position(pos);
8.335 - bb.get(manarr, 0, len);
8.336 - return manarr;
8.337 - }
8.338 -
8.339 /** Check all module classes to make sure there are no unresolvable compile-time
8.340 * dependencies. Turn on this mode with
8.341 * <code>-J-Dnetbeans.preresolve.classes=true</code>
8.342 @@ -1349,5 +1176,83 @@
8.343 }
8.344 }
8.345 }
8.346 +
8.347 + final boolean isShowInAutoUpdateClient(ModuleInfo m) {
8.348 + String show = cache.findProperty(m, "AutoUpdate-Show-In-Client", false); // NOI18N
8.349 + if (show != null) {
8.350 + return Boolean.parseBoolean(show);
8.351 + }
8.352 + // OSGi bundles should be considered invisible by default since they are typically autoloads.
8.353 + // (NB modules get AutoUpdate-Show-In-Client inserted into the JAR by the build process.)
8.354 + if (m instanceof Module) {
8.355 + return !((Module)m).isNetigso();
8.356 + }
8.357 + return true;
8.358 + }
8.359 +
8.360 + /** Cache important attributes from module manifests */
8.361 + private static class Cache implements Stamps.Updater {
8.362 + private static final String CACHE = "all-installer.dat"; // NOI18N
8.363 + private final boolean modulePropertiesCached;
8.364 + private final Properties moduleProperties;
8.365
8.366 + public Cache() {
8.367 + InputStream is = Stamps.getModulesJARs().asStream(CACHE);
8.368 + IF:
8.369 + if (is != null) {
8.370 + Properties p = new Properties();
8.371 + try {
8.372 + p.load(is);
8.373 + is.close();
8.374 + } catch (IOException ex) {
8.375 + LOG.log(Level.INFO, "Can't load all-installer.dat", ex);
8.376 + break IF;
8.377 + }
8.378 + moduleProperties = p;
8.379 + modulePropertiesCached = true;
8.380 + return;
8.381 + }
8.382 + moduleProperties = new Properties();
8.383 + modulePropertiesCached = false;
8.384 + }
8.385 +
8.386 + final String findProperty(ModuleInfo m, String name, boolean localized) {
8.387 + final String fullName = m.getCodeNameBase() + '.' + name;
8.388 + if (modulePropertiesCached) {
8.389 + return moduleProperties.getProperty(fullName);
8.390 + } else {
8.391 + Object p = localized ? m.getLocalizedAttribute(name) : m.getAttribute(name);
8.392 + String prop = p instanceof String ? (String)p : null;
8.393 + if (prop != null) {
8.394 + moduleProperties.setProperty(fullName, prop);
8.395 + Stamps.getModulesJARs().scheduleSave(this, CACHE, false);
8.396 + }
8.397 + return prop;
8.398 + }
8.399 + }
8.400 +
8.401 + final String findGlobalProperty(String name, String expValue, String replaceValue) {
8.402 + assert name != null;
8.403 + assert replaceValue != null;
8.404 + if (modulePropertiesCached) {
8.405 + return moduleProperties.getProperty(name);
8.406 + } else {
8.407 + final Object prevValue = moduleProperties.get(name);
8.408 + if (Utilities.compareObjects(expValue, prevValue)) {
8.409 + moduleProperties.put(name, replaceValue);
8.410 + }
8.411 + Stamps.getModulesJARs().scheduleSave(this, CACHE, false);
8.412 + return null;
8.413 + }
8.414 + }
8.415 +
8.416 + @Override
8.417 + public void flushCaches(DataOutputStream os) throws IOException {
8.418 + moduleProperties.store(os, null);
8.419 + }
8.420 +
8.421 + @Override
8.422 + public void cacheReady() {
8.423 + }
8.424 + } // end of Cache
8.425 }
9.1 --- a/core.startup/test/unit/src/org/netbeans/core/startup/layers/CachingPreventsFileTouchesTest.java Thu Mar 15 16:10:40 2012 +0100
9.2 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/CachingPreventsFileTouchesTest.java Fri Mar 16 08:17:35 2012 +0100
9.3 @@ -51,7 +51,9 @@
9.4 import java.util.Collections;
9.5 import java.util.HashSet;
9.6 import java.util.Set;
9.7 +import java.util.logging.Handler;
9.8 import java.util.logging.Level;
9.9 +import java.util.logging.LogRecord;
9.10 import java.util.logging.Logger;
9.11 import junit.framework.Test;
9.12 import org.netbeans.junit.NbModuleSuite;
9.13 @@ -61,6 +63,7 @@
9.14 import org.openide.filesystems.FileUtil;
9.15 import org.openide.filesystems.LocalFileSystem;
9.16 import org.openide.modules.InstalledFileLocator;
9.17 +import org.openide.modules.ModuleInfo;
9.18 import org.openide.modules.Places;
9.19 import org.openide.util.Lookup;
9.20
9.21 @@ -69,7 +72,14 @@
9.22 * see details on http://wiki.netbeans.org/FitnessViaWhiteAndBlackList
9.23 */
9.24 public class CachingPreventsFileTouchesTest extends NbTestCase {
9.25 - private static final Logger LOG = Logger.getLogger(CachingPreventsFileTouchesTest.class.getName());
9.26 + static {
9.27 + System.setProperty("java.util.logging.config.class", CaptureLog.class.getName());
9.28 + }
9.29 + private static final Logger LOG;
9.30 + static {
9.31 + LOG = Logger.getLogger(CachingPreventsFileTouchesTest.class.getName());
9.32 + CaptureLog.assertCalled();
9.33 + }
9.34
9.35 private static void initCheckReadAccess() throws IOException {
9.36 Set<String> allowedFiles = new HashSet<String>();
9.37 @@ -82,7 +92,6 @@
9.38
9.39 public static Test suite() throws IOException {
9.40 CountingSecurityManager.initialize("none", CountingSecurityManager.Mode.CHECK_READ, null);
9.41 - System.setProperty("org.netbeans.Stamps.level", "ALL");
9.42
9.43 NbTestSuite suite = new NbTestSuite();
9.44 {
9.45 @@ -106,6 +115,7 @@
9.46 }
9.47
9.48 suite.addTest(new CachingPreventsFileTouchesTest("testCachesDontUseAbsolutePaths"));
9.49 + suite.addTest(new CachingPreventsFileTouchesTest("testDontLoadManifests"));
9.50
9.51 return suite;
9.52 }
9.53 @@ -118,14 +128,19 @@
9.54 LOG.log(Level.FINE, "Can't pre-load JavaHelp", ex);
9.55 }
9.56 FileObject fo = FileUtil.getConfigFile("Services/Browsers");
9.57 - fo.delete();
9.58 - // initializes counting, but waits till netbeans.dirs are provided
9.59 - // by NbModuleSuite
9.60 + if (fo != null) {
9.61 + fo.delete();
9.62 + }
9.63 + assertEnabled("org.netbeans.core.windows");
9.64 + System.setProperty("counting.off", "true");
9.65 initCheckReadAccess();
9.66 }
9.67
9.68 - public void testInMiddle() {
9.69 - LOG.info("First run finished, starting another one");
9.70 + public void testInMiddle() throws IOException {
9.71 + String p = System.getProperty("manifestParsing");
9.72 + assertNotNull("Parsing of manifests during first run is natural", p);
9.73 + System.getProperties().remove("manifestParsing");
9.74 + System.setProperty("counting.off", "false");
9.75 }
9.76
9.77 public void testReadAccess() throws Exception {
9.78 @@ -145,6 +160,7 @@
9.79 e.printStackTrace(getLog("file-reads-report.txt"));
9.80 throw e;
9.81 }
9.82 + assertEnabled("org.netbeans.core.windows");
9.83 }
9.84
9.85 public void testRememberCacheDir() {
9.86 @@ -177,6 +193,13 @@
9.87 }
9.88 assertTrue("Some cache files found", cnt > 4);
9.89 }
9.90 +
9.91 + public void testDontLoadManifests() {
9.92 + String p = System.getProperty("manifestParsing");
9.93 + if (p != null) {
9.94 + fail("No manifest parsing should happen:\n" + p);
9.95 + }
9.96 + }
9.97
9.98 private static void assertFileDoesNotContain(File file, String text) throws IOException, PropertyVetoException {
9.99 LocalFileSystem lfs = new LocalFileSystem();
9.100 @@ -188,4 +211,53 @@
9.101 fail("File " + file + " seems to contain '" + text + "'!");
9.102 }
9.103 }
9.104 +
9.105 + private static void assertEnabled(String cnb) {
9.106 + for (ModuleInfo mi : Lookup.getDefault().lookupAll(ModuleInfo.class)) {
9.107 + if (mi.getCodeNameBase().equals(cnb)) {
9.108 + assertTrue("Is enabled", mi.isEnabled());
9.109 + return;
9.110 + }
9.111 + }
9.112 + fail("Not found " + cnb);
9.113 + }
9.114 +
9.115 + public static final class CaptureLog extends Handler {
9.116 + private static Logger watchOver = Logger.getLogger("org.netbeans.core.modules");
9.117 + private static void assertCalled() {
9.118 + assertEquals("OK", System.getProperty("CaptureLog"));
9.119 + }
9.120 +
9.121 + public CaptureLog() {
9.122 + System.setProperty("CaptureLog", "OK");
9.123 + close();
9.124 + }
9.125 +
9.126 + @Override
9.127 + public void publish(LogRecord record) {
9.128 + final String m = record.getMessage();
9.129 + if (m != null && m.contains("loading manifest")) {
9.130 + String prev = System.getProperty("manifestParsing");
9.131 + if (prev == null) {
9.132 + prev = m;
9.133 + } else {
9.134 + prev = prev + "\n" + m;
9.135 + }
9.136 + System.setProperty("manifestParsing", prev);
9.137 + }
9.138 + }
9.139 +
9.140 + @Override
9.141 + public void flush() {
9.142 + }
9.143 +
9.144 + @Override
9.145 + public void close() throws SecurityException {
9.146 + watchOver.addHandler(this);
9.147 + setLevel(Level.FINE);
9.148 + watchOver.setLevel(Level.FINE);
9.149 +
9.150 + Logger.getLogger("org.netbeans.Stamps").setLevel(Level.ALL);
9.151 + }
9.152 + }
9.153 }
10.1 --- a/core.startup/test/unit/src/org/netbeans/core/startup/layers/CountingSecurityManager.java Thu Mar 15 16:10:40 2012 +0100
10.2 +++ b/core.startup/test/unit/src/org/netbeans/core/startup/layers/CountingSecurityManager.java Fri Mar 16 08:17:35 2012 +0100
10.3 @@ -170,6 +170,11 @@
10.4 @Override
10.5 public void checkRead(String file) {
10.6 if (mode == Mode.CHECK_READ && acceptFileRead(file)) {
10.7 + String off = System.getProperty("counting.off");
10.8 + if ("true".equals(off)) {
10.9 + return;
10.10 + }
10.11 +
10.12 String dirs = System.getProperty("netbeans.dirs");
10.13 if (dirs == null && !acceptAll) {
10.14 // not initialized yet
11.1 --- a/dlight.remote/manifest.mf Thu Mar 15 16:10:40 2012 +0100
11.2 +++ b/dlight.remote/manifest.mf Fri Mar 16 08:17:35 2012 +0100
11.3 @@ -4,3 +4,4 @@
11.4 OpenIDE-Module-Implementation-Version: 1
11.5 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/remote/resources/Bundle.properties
11.6 OpenIDE-Module-Needs: org.netbeans.modules.dlight.remote.spi.RemoteProviderToken
11.7 +OpenIDE-Module-Recommends: org.netbeans.modules.remotefs.versioning
12.1 --- a/hudson.php/manifest.mf Thu Mar 15 16:10:40 2012 +0100
12.2 +++ b/hudson.php/manifest.mf Fri Mar 16 08:17:35 2012 +0100
12.3 @@ -3,3 +3,4 @@
12.4 OpenIDE-Module-Layer: org/netbeans/modules/hudson/php/resources/layer.xml
12.5 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/hudson/php/resources/Bundle.properties
12.6 OpenIDE-Module-Specification-Version: 1.1
12.7 +OpenIDE-Module-Provides: org.netbeans.modules.hudson.php
13.1 --- a/hudson.php/nbproject/project.properties Thu Mar 15 16:10:40 2012 +0100
13.2 +++ b/hudson.php/nbproject/project.properties Fri Mar 16 08:17:35 2012 +0100
13.3 @@ -1,4 +1,4 @@
13.4 -is.eager=true
13.5 +is.autoload=true
13.6 javac.source=1.6
13.7 javac.compilerargs=-Xlint -Xlint:-serial
13.8 release.external/config-4f37f781e487dc957ff09359d8a5cb51e6588ff9.xml=hudson/config.xml
14.1 --- a/ide.ergonomics/nbproject/project.properties Thu Mar 15 16:10:40 2012 +0100
14.2 +++ b/ide.ergonomics/nbproject/project.properties Fri Mar 16 08:17:35 2012 +0100
14.3 @@ -8,7 +8,8 @@
14.4 src-ant.cp=${ant.core.lib}
14.5
14.6 test.config.commit.includes=\
14.7 - org/netbeans/modules/ide/ergonomics/DynamicVerifyTest.class
14.8 + org/netbeans/modules/ide/ergonomics/DynamicVerifyTest.class,\
14.9 + org/netbeans/modules/ide/ergonomics/CachingPreventsLoadingOfModuleManifestsTest.class
14.10
14.11 test.config.stableBTD.includes=**/*Test.class
14.12 test.config.stableBTD.excludes=\
15.1 --- a/ide.ergonomics/nbproject/project.xml Thu Mar 15 16:10:40 2012 +0100
15.2 +++ b/ide.ergonomics/nbproject/project.xml Fri Mar 16 08:17:35 2012 +0100
15.3 @@ -38,7 +38,7 @@
15.4 <compile-dependency/>
15.5 <run-dependency>
15.6 <release-version>1</release-version>
15.7 - <specification-version>1.30</specification-version>
15.8 + <specification-version>1.38</specification-version>
15.9 </run-dependency>
15.10 </dependency>
15.11 <dependency>
16.1 --- a/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java Thu Mar 15 16:10:40 2012 +0100
16.2 +++ b/ide.ergonomics/src/org/netbeans/modules/ide/ergonomics/fod/FeatureManager.java Fri Mar 16 08:17:35 2012 +0100
16.3 @@ -62,6 +62,8 @@
16.4 import javax.swing.event.ChangeListener;
16.5 import org.netbeans.Module;
16.6 import org.netbeans.api.project.Project;
16.7 +import org.netbeans.core.startup.Main;
16.8 +import org.netbeans.core.startup.ModuleSystem;
16.9 import org.openide.filesystems.FileObject;
16.10 import org.openide.filesystems.FileUtil;
16.11 import org.openide.modules.Dependency;
16.12 @@ -122,8 +124,7 @@
16.13 }
16.14
16.15 static boolean showInAU(ModuleInfo mi) {
16.16 - final Object show = mi.getAttribute("AutoUpdate-Show-In-Client"); // NOI18N
16.17 - return show == null || "true".equals(show); // NOI18N
16.18 + return Main.getModuleSystem().isShowInAutoUpdateClient(mi);
16.19 }
16.20
16.21
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/ide.ergonomics/test/unit/src/org/netbeans/modules/ide/ergonomics/CachingPreventsLoadingOfModuleManifestsTest.java Fri Mar 16 08:17:35 2012 +0100
17.3 @@ -0,0 +1,249 @@
17.4 +/*
17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
17.6 + *
17.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
17.8 + *
17.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
17.10 + * Other names may be trademarks of their respective owners.
17.11 + *
17.12 + * The contents of this file are subject to the terms of either the GNU
17.13 + * General Public License Version 2 only ("GPL") or the Common
17.14 + * Development and Distribution License("CDDL") (collectively, the
17.15 + * "License"). You may not use this file except in compliance with the
17.16 + * License. You can obtain a copy of the License at
17.17 + * http://www.netbeans.org/cddl-gplv2.html
17.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
17.19 + * specific language governing permissions and limitations under the
17.20 + * License. When distributing the software, include this License Header
17.21 + * Notice in each file and include the License file at
17.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
17.23 + * particular file as subject to the "Classpath" exception as provided
17.24 + * by Oracle in the GPL Version 2 section of the License file that
17.25 + * accompanied this code. If applicable, add the following below the
17.26 + * License Header, with the fields enclosed by brackets [] replaced by
17.27 + * your own identifying information:
17.28 + * "Portions Copyrighted [year] [name of copyright owner]"
17.29 + *
17.30 + * Contributor(s):
17.31 + *
17.32 + * The Original Software is NetBeans. The Initial Developer of the Original
17.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17.34 + * Microsystems, Inc. All Rights Reserved.
17.35 + *
17.36 + * If you wish your version of this file to be governed by only the CDDL
17.37 + * or only the GPL Version 2, indicate your decision by adding
17.38 + * "[Contributor] elects to include this software in this distribution
17.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
17.40 + * single choice of license, a recipient has the option to distribute
17.41 + * your version of this file under either the CDDL, the GPL Version 2 or
17.42 + * to extend the choice of license to its licensees as provided above.
17.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
17.44 + * Version 2 license, then the option applies only if the new code is
17.45 + * made subject to such option by the copyright holder.
17.46 + */
17.47 +
17.48 +package org.netbeans.modules.ide.ergonomics;
17.49 +
17.50 +import java.io.File;
17.51 +import java.io.IOException;
17.52 +import java.io.PrintWriter;
17.53 +import java.io.StringWriter;
17.54 +import java.util.Arrays;
17.55 +import java.util.logging.Handler;
17.56 +import java.util.logging.Level;
17.57 +import java.util.logging.LogRecord;
17.58 +import java.util.logging.Logger;
17.59 +import junit.framework.Test;
17.60 +import org.netbeans.junit.NbModuleSuite;
17.61 +import org.netbeans.junit.NbTestCase;
17.62 +import org.netbeans.junit.NbTestSuite;
17.63 +import org.openide.filesystems.FileObject;
17.64 +import org.openide.filesystems.FileUtil;
17.65 +import org.openide.modules.ModuleInfo;
17.66 +import org.openide.util.Lookup;
17.67 +
17.68 +/**
17.69 + * Verifies that modules outside of platform,ide,nb and ergonomics clusters
17.70 + * are not initialized - e.g. their manifests are not parsed. This is done
17.71 + * by a "logging" contract from ModuleManager caches. As soon as module
17.72 + * manifest is loaded, the test verifies that the file is in one of
17.73 + * allowed clusters.
17.74 + */
17.75 +public class CachingPreventsLoadingOfModuleManifestsTest extends NbTestCase {
17.76 + static {
17.77 + System.setProperty("java.util.logging.config.class", CaptureLog.class.getName());
17.78 + }
17.79 + private static final Logger LOG;
17.80 + static {
17.81 + LOG = Logger.getLogger(CachingPreventsLoadingOfModuleManifestsTest.class.getName());
17.82 + CaptureLog.assertCalled();
17.83 + }
17.84 +
17.85 + public CachingPreventsLoadingOfModuleManifestsTest(String name) {
17.86 + super(name);
17.87 + }
17.88 +
17.89 + public static Test suite() throws IOException {
17.90 + NbModuleSuite.Configuration base = NbModuleSuite.createConfiguration(
17.91 + CachingPreventsLoadingOfModuleManifestsTest.class
17.92 + ).
17.93 + gui(false).
17.94 + clusters("ergonomics.*").
17.95 + clusters(".*").
17.96 + enableModules("ide[0-9]*", ".*").
17.97 + enableClasspathModules(false).
17.98 + honorAutoloadEager(true);
17.99 +
17.100 + System.setProperty("counting.off", "false");
17.101 + System.setProperty("no.stacks", "true");
17.102 + NbTestSuite suite = new NbTestSuite();
17.103 + suite.addTest(base.reuseUserDir(false).addTest("testInitUserDir").suite());
17.104 +
17.105 + suite.addTest(new CachingPreventsLoadingOfModuleManifestsTest("testInMiddle"));
17.106 +
17.107 + suite.addTest(
17.108 + base.reuseUserDir(true).addTest("testEnabledWindows").suite()
17.109 + );
17.110 + suite.addTest(new CachingPreventsLoadingOfModuleManifestsTest("testDontLoadManifests"));
17.111 +
17.112 + return suite;
17.113 + }
17.114 +
17.115 + public void testInitUserDir() throws Exception {
17.116 + ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
17.117 + try {
17.118 + Class<?> c = Class.forName("javax.help.HelpSet", true, l);
17.119 + } catch (ClassNotFoundException ex) {
17.120 + LOG.log(Level.FINE, "Can't pre-load JavaHelp", ex);
17.121 + }
17.122 + FileObject fo = FileUtil.getConfigFile("Services/Browsers");
17.123 + if (fo != null) {
17.124 + fo.delete();
17.125 + }
17.126 + assertEnabled("org.netbeans.core.windows");
17.127 + System.setProperty("counting.off", "true");
17.128 + }
17.129 +
17.130 + public void testInMiddle() throws IOException {
17.131 + String p = System.getProperty("manifestParsing");
17.132 + assertNotNull("Parsing of manifests during first run is natural", p);
17.133 + System.getProperties().remove("manifestParsing");
17.134 + System.setProperty("no.stacks", "false");
17.135 + System.setProperty("counting.off", "false");
17.136 + }
17.137 +
17.138 + public void testEnabledWindows() throws Exception {
17.139 + assertEnabled("org.netbeans.core.windows");
17.140 + }
17.141 +
17.142 + public void testDontLoadManifests() {
17.143 + String p = System.getProperty("manifestParsing");
17.144 + if (p != null) {
17.145 + fail("No manifest parsing should happen:\n" + p);
17.146 + }
17.147 + }
17.148 +
17.149 + private static void assertEnabled(String cnb) {
17.150 + for (ModuleInfo mi : Lookup.getDefault().lookupAll(ModuleInfo.class)) {
17.151 + if (mi.getCodeNameBase().equals(cnb)) {
17.152 + assertTrue("Is enabled", mi.isEnabled());
17.153 + return;
17.154 + }
17.155 + }
17.156 + fail("Not found " + cnb);
17.157 + }
17.158 +
17.159 + public static final class CaptureLog extends Handler {
17.160 + private static Logger watchOver = Logger.getLogger("org.netbeans.core.modules");
17.161 + private static void assertCalled() {
17.162 + assertEquals("OK", System.getProperty("CaptureLog"));
17.163 + }
17.164 +
17.165 + public CaptureLog() {
17.166 + System.setProperty("CaptureLog", "OK");
17.167 + close();
17.168 + }
17.169 +
17.170 + @Override
17.171 + public void publish(LogRecord record) {
17.172 + if (Boolean.getBoolean("counting.off")) {
17.173 + return;
17.174 + }
17.175 + final String m = record.getMessage();
17.176 + if (m != null && m.startsWith("Initialize data")) {
17.177 + Object[] params = record.getParameters();
17.178 + assertNotNull("There are parameters", params);
17.179 + assertEquals("There is just one parameter: " + Arrays.toString(params), 1, params.length);
17.180 + if (params[0] == null) {
17.181 + // fixed modules are OK
17.182 + return;
17.183 + }
17.184 + if (isPlatformOrIde((File)params[0])) {
17.185 + return;
17.186 + }
17.187 +
17.188 + String prev = System.getProperty("manifestParsing");
17.189 + StringWriter sw = new StringWriter();
17.190 + PrintWriter pw = new PrintWriter(sw);
17.191 + if (prev != null) {
17.192 + pw.append(prev).append("\n");
17.193 + }
17.194 + final String msg = m + ": " + params[0];
17.195 + if (Boolean.getBoolean("no.stacks")) {
17.196 + pw.print(msg);
17.197 + } else {
17.198 + new Exception(msg).printStackTrace(pw);
17.199 + }
17.200 + pw.flush();
17.201 + System.setProperty("manifestParsing", sw.toString());
17.202 + }
17.203 + }
17.204 +
17.205 + @Override
17.206 + public void flush() {
17.207 + }
17.208 +
17.209 + @Override
17.210 + public void close() throws SecurityException {
17.211 + watchOver.addHandler(this);
17.212 + setLevel(Level.FINE);
17.213 + watchOver.setLevel(Level.FINE);
17.214 +
17.215 + Logger.getLogger("org.netbeans.core.modules").setLevel(Level.ALL);
17.216 + }
17.217 +
17.218 + private boolean isPlatformOrIde(File file) {
17.219 + String path = file.getPath();
17.220 + final String platform = System.getProperty("netbeans.home");
17.221 + if (platform != null && path.startsWith(platform)) {
17.222 + return true;
17.223 + }
17.224 + final String dirs = System.getProperty("netbeans.dirs");
17.225 + if (dirs != null) {
17.226 + for (String s : dirs.split(File.pathSeparator)) {
17.227 + if (s.endsWith(File.separator + "ide")) {
17.228 + if (path.startsWith(s)) {
17.229 + return true;
17.230 + }
17.231 + }
17.232 + if (s.endsWith(File.separator + "ergonomics")) {
17.233 + if (path.startsWith(s)) {
17.234 + return true;
17.235 + }
17.236 + }
17.237 + if (s.endsWith(File.separator + "nb")) {
17.238 + if (path.startsWith(s)) {
17.239 + return true;
17.240 + }
17.241 + }
17.242 + if (s.endsWith(File.separator + "webcommon")) {
17.243 + if (path.startsWith(s)) {
17.244 + return true;
17.245 + }
17.246 + }
17.247 + }
17.248 + }
17.249 + return false;
17.250 + }
17.251 + }
17.252 +}
18.1 --- a/netbinox/test/unit/src/org/netbeans/modules/netbinox/CachingPreventsFileTouchesTest.java Thu Mar 15 16:10:40 2012 +0100
18.2 +++ b/netbinox/test/unit/src/org/netbeans/modules/netbinox/CachingPreventsFileTouchesTest.java Fri Mar 16 08:17:35 2012 +0100
18.3 @@ -89,7 +89,7 @@
18.4 NbTestSuite suite = new NbTestSuite();
18.5 Compile compile = new Compile("testCompile");
18.6 suite.addTest(compile);
18.7 - NbModuleSuite.Configuration common = NbModuleSuite.emptyConfiguration().clusters(".*").enableClasspathModules(false)
18.8 + NbModuleSuite.Configuration common = NbModuleSuite.emptyConfiguration().clusters("(?!ergonomics).*").enableClasspathModules(false)
18.9 .gui(false).honorAutoloadEager(true);
18.10 {
18.11 NbModuleSuite.Configuration conf = common.reuseUserDir(false).addTest(CachingPreventsFileTouchesTest.class, "testInitUserDir");
18.12 @@ -175,6 +175,13 @@
18.13
18.14 public void testStartAgain() throws Exception {
18.15 CachingAndExternalPathsTest.doNecessarySetup();
18.16 + final String dirs = System.getProperty("netbeans.dirs");
18.17 + for (String s : dirs.split(File.pathSeparator)) {
18.18 + if (s.endsWith("ergonomics")) {
18.19 + fail("There should be no ergonomics cluster in netbeans.dirs: " + dirs);
18.20 + }
18.21 + }
18.22 +
18.23 // will be reset next time the system starts
18.24 System.getProperties().remove("netbeans.dirs");
18.25 // initializes counting, but waits till netbeans.dirs are provided
19.1 --- a/o.n.bootstrap/manifest.mf Thu Mar 15 16:10:40 2012 +0100
19.2 +++ b/o.n.bootstrap/manifest.mf Fri Mar 16 08:17:35 2012 +0100
19.3 @@ -1,6 +1,6 @@
19.4 Manifest-Version: 1.0
19.5 OpenIDE-Module: org.netbeans.bootstrap/1
19.6 -OpenIDE-Module-Specification-Version: 2.50
19.7 +OpenIDE-Module-Specification-Version: 2.51
19.8 OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
19.9 OpenIDE-Module-Recommends: org.netbeans.NetigsoFramework
19.10
20.1 --- a/o.n.bootstrap/src/org/netbeans/JarClassLoader.java Thu Mar 15 16:10:40 2012 +0100
20.2 +++ b/o.n.bootstrap/src/org/netbeans/JarClassLoader.java Fri Mar 16 08:17:35 2012 +0100
20.3 @@ -82,7 +82,6 @@
20.4 import java.util.concurrent.Future;
20.5 import java.util.concurrent.FutureTask;
20.6 import java.util.jar.Attributes;
20.7 -import java.util.jar.Attributes.Name;
20.8 import java.util.jar.JarEntry;
20.9 import java.util.jar.JarFile;
20.10 import java.util.jar.Manifest;
20.11 @@ -104,6 +103,7 @@
20.12 static void initializeCache() {
20.13 cache = Stamps.getModulesJARs();
20.14 archive = new Archive(cache);
20.15 + PackageAttrsCache.initialize();
20.16 }
20.17
20.18 /**
20.19 @@ -186,36 +186,18 @@
20.20
20.21
20.22 protected Package definePackage(String name, Manifest man, URL url)
20.23 - throws IllegalArgumentException
20.24 - {
20.25 - if (man == null ) {
20.26 + throws IllegalArgumentException {
20.27 + if (man == null) {
20.28 return definePackage(name, null, null, null, null, null, null, null);
20.29 }
20.30 -
20.31 - String path = name.replace('.', '/').concat("/"); // NOI18N
20.32 - Attributes spec = man.getAttributes(path);
20.33 - Attributes main = man.getMainAttributes();
20.34 -
20.35 - String specTitle = getAttr(spec, main, Name.SPECIFICATION_TITLE);
20.36 - String implTitle = getAttr(spec, main, Name.IMPLEMENTATION_TITLE);
20.37 - String specVersion = getAttr(spec, main, Name.SPECIFICATION_VERSION);
20.38 - String implVersion = getAttr(spec, main, Name.IMPLEMENTATION_VERSION);
20.39 - String specVendor = getAttr(spec, main, Name.SPECIFICATION_VENDOR);
20.40 - String implVendor = getAttr(spec, main, Name.IMPLEMENTATION_VENDOR);
20.41 - String sealed = getAttr(spec, main, Name.SEALED);
20.42
20.43 - URL sealBase = "true".equalsIgnoreCase(sealed) ? url : null; // NOI18N
20.44 - return definePackage(name, specTitle, specVersion, specVendor,
20.45 - implTitle, implVersion, implVendor, sealBase);
20.46 + String path = name.replace('.', '/').concat("/"); // NOI18N
20.47 + String[] arr = PackageAttrsCache.findPackageAttrs(url, man, path);
20.48 + URL sealBase = "true".equalsIgnoreCase(arr[6]) ? url : null; // NOI18N
20.49 + return definePackage(name, arr[0], arr[1], arr[2],
20.50 + arr[3], arr[4], arr[5], sealBase);
20.51 }
20.52 -
20.53 - private static String getAttr(Attributes spec, Attributes main, Name name) {
20.54 - String val = null;
20.55 - if (spec != null) val = spec.getValue (name);
20.56 - if (val == null && main != null) val = main.getValue (name);
20.57 - return val;
20.58 - }
20.59 -
20.60 +
20.61 private Boolean patchingBytecode;
20.62 @Override
20.63 protected Class doLoadClass(String pkgName, String name) {
20.64 @@ -223,7 +205,7 @@
20.65
20.66 // look up the Sources and return a class based on their content
20.67 for( int i=0; i<sources.length; i++ ) {
20.68 - Source src = sources[i];
20.69 + final Source src = sources[i];
20.70 byte[] data = src.getClassData(path);
20.71 if (data == null) continue;
20.72
20.73 @@ -254,7 +236,32 @@
20.74 // XXX full sealing check, URLClassLoader does something more
20.75 if (pkg.isSealed() && !pkg.isSealed(src.getURL())) throw new SecurityException("sealing violation"); // NOI18N
20.76 } else {
20.77 - Manifest man = module == null || src != sources[0] ? src.getManifest() : module.getManifest();
20.78 + class DelayedManifest extends Manifest {
20.79 + private Manifest delegate;
20.80 +
20.81 + private Manifest delegate() {
20.82 + if (delegate == null) {
20.83 + delegate = module == null || src != sources[0] ? src.getManifest() : module.getManifest();
20.84 + }
20.85 + return delegate;
20.86 + }
20.87 +
20.88 + @Override
20.89 + public Attributes getMainAttributes() {
20.90 + return delegate().getMainAttributes();
20.91 + }
20.92 +
20.93 + @Override
20.94 + public Attributes getAttributes(String name) {
20.95 + return delegate().getAttributes(name);
20.96 + }
20.97 +
20.98 + @Override
20.99 + public Map<String, Attributes> getEntries() {
20.100 + return delegate().getEntries();
20.101 + }
20.102 + }
20.103 + Manifest man = new DelayedManifest();
20.104 try {
20.105 definePackage(pkgName, man, src.getURL());
20.106 } catch (IllegalArgumentException x) {
20.107 @@ -863,13 +870,21 @@
20.108 }
20.109
20.110 private static Iterable<String> getCoveredPackages(Module mod, Source[] sources) {
20.111 + if (mod != null) {
20.112 + Set<String> ret = mod.getCoveredPackages();
20.113 + if (ret != null) {
20.114 + return ret;
20.115 + }
20.116 + }
20.117 +
20.118 Set<String> known = new HashSet<String>();
20.119 Manifest m = mod == null ? null : mod.getManifest();
20.120 if (m != null) {
20.121 Attributes attr = m.getMainAttributes();
20.122 - String pack = attr.getValue("Covered-Packages");
20.123 + String pack = attr.getValue("Covered-Packages"); // NOI18N
20.124 if (pack != null) {
20.125 known.addAll(Arrays.asList(pack.split(",", -1)));
20.126 + mod.registerCoveredPackages(known);
20.127 return known;
20.128 }
20.129 }
20.130 @@ -879,9 +894,8 @@
20.131 for (Source s : sources) s.listCoveredPackages(known, save);
20.132
20.133 if (save.length() > 0) save.setLength(save.length()-1);
20.134 - if (m != null) {
20.135 - Attributes attr = m.getMainAttributes();
20.136 - attr.putValue("Covered-Packages", save.toString());
20.137 + if (mod != null) {
20.138 + mod.registerCoveredPackages(known);
20.139 }
20.140 return known;
20.141 }
21.1 --- a/o.n.bootstrap/src/org/netbeans/Module.java Thu Mar 15 16:10:40 2012 +0100
21.2 +++ b/o.n.bootstrap/src/org/netbeans/Module.java Fri Mar 16 08:17:35 2012 +0100
21.3 @@ -44,14 +44,18 @@
21.4
21.5 package org.netbeans;
21.6
21.7 +import java.io.DataInput;
21.8 +import java.io.DataOutput;
21.9 import java.io.File;
21.10 import java.io.IOException;
21.11 import java.io.InputStream;
21.12 +import java.io.ObjectInput;
21.13 +import java.io.ObjectInputStream;
21.14 +import java.io.ObjectOutput;
21.15 import java.lang.reflect.Method;
21.16 import java.net.URL;
21.17 import java.security.CodeSource;
21.18 import java.util.*;
21.19 -import java.util.jar.Attributes;
21.20 import java.util.jar.Manifest;
21.21 import java.util.logging.Level;
21.22 import java.util.logging.Logger;
21.23 @@ -60,7 +64,6 @@
21.24 import org.openide.modules.SpecificationVersion;
21.25 import org.openide.util.Enumerations;
21.26 import org.openide.util.Exceptions;
21.27 -import org.openide.util.NbBundle;
21.28 import org.openide.util.Union2;
21.29
21.30 /** Object representing one module, possibly installed.
21.31 @@ -96,28 +99,13 @@
21.32 protected boolean reloadable;
21.33 /** if true, this module is eagerly turned on whenever it can be */
21.34 private final boolean eager;
21.35 - /** code name base (no slash) */
21.36 - private String codeNameBase;
21.37 - /** code name release, or -1 if undefined */
21.38 - private int codeNameRelease;
21.39 - /** full code name */
21.40 - private String codeName;
21.41 - /** provided tokens */
21.42 - private String[] provides;
21.43 - /** set of dependencies parsed from manifest */
21.44 - private Dependency[] dependenciesA;
21.45 - /** specification version parsed from manifest, or null */
21.46 - private SpecificationVersion specVers;
21.47 /** currently active module classloader */
21.48 - protected ClassLoader classloader = null;
21.49 - /** public packages, may be null */
21.50 - private PackageExport[] publicPackages;
21.51 - /** Set<String> of CNBs of friend modules or null */
21.52 - private Set/*<String>*/ friendNames;
21.53 + protected ClassLoader classloader;
21.54
21.55 - private final static PackageExport[] ZERO_PACKAGE_ARRAY = new PackageExport[0];
21.56 - private final static String[] ZERO_STRING_ARRAY = new String[0];
21.57 + private ModuleData data;
21.58 +
21.59 private static Method findResources;
21.60 + private static final Object DATA_LOCK = new Object();
21.61
21.62 /** Use ModuleManager.create as a factory. */
21.63 protected Module(ModuleManager mgr, Events ev, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException {
21.64 @@ -128,14 +116,14 @@
21.65 this.reloadable = reloadable;
21.66 this.autoload = autoload;
21.67 this.eager = eager;
21.68 - enabled = false;
21.69 + this.enabled = false;
21.70 }
21.71
21.72 /** Create a special-purpose "fixed" JAR. */
21.73 protected Module(ModuleManager mgr, Events ev, Object history, ClassLoader classloader) throws InvalidException {
21.74 this(mgr, ev, history, classloader, false, false);
21.75 }
21.76 -
21.77 +
21.78 /**
21.79 * Create a special-purpose "fixed" JAR which may nonetheless be marked eager or autoload.
21.80 * @since 2.7
21.81 @@ -152,6 +140,63 @@
21.82 enabled = false;
21.83 }
21.84
21.85 + ModuleData createData(ObjectInput in, Manifest mf) throws IOException {
21.86 + if (in != null) {
21.87 + return new ModuleData(in);
21.88 + } else {
21.89 + return new ModuleData(mf, this);
21.90 + }
21.91 + }
21.92 +
21.93 + final void writeData(ObjectOutput out) throws IOException {
21.94 + data().write(out);
21.95 + }
21.96 +
21.97 + final ModuleData data() {
21.98 + try {
21.99 + return dataWithCheck();
21.100 + } catch (InvalidException ex) {
21.101 + throw new IllegalStateException(ex);
21.102 + }
21.103 + }
21.104 +
21.105 + final ModuleData dataWithCheck() throws InvalidException {
21.106 + synchronized (DATA_LOCK) {
21.107 + if (data != null) {
21.108 + return data;
21.109 + }
21.110 + Util.err.log(Level.FINE, "Initialize data {0}", getJarFile()); // NOI18N
21.111 + InputStream is = mgr.dataFor(getJarFile());
21.112 + if (is != null) {
21.113 + try {
21.114 + ObjectInputStream ois = new ObjectInputStream(is);
21.115 + ModuleData mine = createData(ois, null);
21.116 + ois.close();
21.117 + assert data == null;
21.118 + data = mine;
21.119 + return mine;
21.120 + } catch (IOException ex) {
21.121 + Util.err.log(Level.INFO, "Cannot read cache for " + getJarFile(), ex); // NOI18N
21.122 + }
21.123 + }
21.124 + try {
21.125 + ModuleData mine = createData(null, getManifest());
21.126 + assert mine == data;
21.127 + return mine;
21.128 + } catch (InvalidException ex) {
21.129 + throw ex;
21.130 + } catch (IOException ex) {
21.131 + // no I/O needed when reading from manifest
21.132 + throw new IllegalStateException(ex);
21.133 + }
21.134 + }
21.135 + }
21.136 +
21.137 + final void assignData(ModuleData data) {
21.138 + assert Thread.holdsLock(DATA_LOCK);
21.139 + this.data = data;
21.140 + }
21.141 +
21.142 /** Get the associated module manager. */
21.143 public ModuleManager getManager() {
21.144 return mgr;
21.145 @@ -215,26 +260,31 @@
21.146
21.147 @Override
21.148 public String getCodeName() {
21.149 - return codeName;
21.150 + return data().getCodeName();
21.151 }
21.152
21.153 @Override
21.154 public String getCodeNameBase() {
21.155 - return codeNameBase;
21.156 + String cnb = mgr.cnbFor(getJarFile());
21.157 + if (cnb != null) {
21.158 + return cnb;
21.159 + }
21.160 + return data().getCodeNameBase();
21.161 }
21.162
21.163 @Override
21.164 public int getCodeNameRelease() {
21.165 - return codeNameRelease;
21.166 + return data().getCodeNameRelease();
21.167 }
21.168
21.169 public @Override String[] getProvides() {
21.170 - return provides;
21.171 + return data().getProvides();
21.172 }
21.173 /** Test whether the module provides a given token or not.
21.174 * @since JST-PENDING again used from NbProblemDisplayer
21.175 */
21.176 public final boolean provides(String token) {
21.177 + String[] provides = getProvides();
21.178 if (provides == null) {
21.179 return false;
21.180 }
21.181 @@ -250,14 +300,32 @@
21.182 public Set<Dependency> getDependencies() {
21.183 return new HashSet<Dependency>(Arrays.asList(getDependenciesArray()));
21.184 }
21.185 - public final Dependency[] getDependenciesArray() {
21.186 + public final Dependency[] getDependenciesArray() {
21.187 + Dependency[] dependenciesA;
21.188 + try {
21.189 + dependenciesA = data().getDependencies();
21.190 + } catch (IllegalStateException ex) {
21.191 + dependenciesA = null;
21.192 + }
21.193 return dependenciesA == null ? new Dependency[0] : dependenciesA;
21.194 }
21.195
21.196 @Override
21.197 public SpecificationVersion getSpecificationVersion() {
21.198 - return specVers;
21.199 + return data().getSpecificationVersion();
21.200 }
21.201 +
21.202 + @Override
21.203 + public String getImplementationVersion() {
21.204 + return data.getImplementationVersion();
21.205 + }
21.206 +
21.207 + @Override
21.208 + public String getBuildVersion() {
21.209 + return data.getBuildVersion();
21.210 + }
21.211 +
21.212 +
21.213
21.214 public @Override boolean owns(Class<?> clazz) {
21.215 ClassLoader cl = clazz.getClassLoader();
21.216 @@ -269,7 +337,7 @@
21.217 }
21.218 String _codeName = findClasspathModuleCodeName(clazz);
21.219 if (_codeName != null) {
21.220 - return _codeName.equals(codeName);
21.221 + return _codeName.equals(getCodeName());
21.222 }
21.223 return true; // not sure...
21.224 }
21.225 @@ -304,13 +372,14 @@
21.226 * @see "#19621"
21.227 */
21.228 public PackageExport[] getPublicPackages() {
21.229 - return publicPackages;
21.230 + return data().getPublicPackages();
21.231 }
21.232
21.233 /** Checks whether we use friends attribute and if so, then
21.234 * whether the name of module is listed there.
21.235 */
21.236 boolean isDeclaredAsFriend (Module module) {
21.237 + Set<String> friendNames = data().getFriendNames();
21.238 if (friendNames == null) {
21.239 return true;
21.240 }
21.241 @@ -323,151 +392,9 @@
21.242 * some kind of description of the problem.
21.243 */
21.244 protected void parseManifest() throws InvalidException {
21.245 - Attributes attr = getManifest().getMainAttributes();
21.246 -
21.247 - // Code name
21.248 - codeName = attr.getValue("OpenIDE-Module"); // NOI18N
21.249 - if (codeName == null) {
21.250 - InvalidException e = new InvalidException("Not a module: no OpenIDE-Module tag in manifest of " + /* #17629: important! */this, getManifest()); // NOI18N
21.251 - // #29393: plausible user mistake, deal with it politely.
21.252 - Exceptions.attachLocalizedMessage(e,
21.253 - NbBundle.getMessage(Module.class,
21.254 - "EXC_not_a_module",
21.255 - this.toString()));
21.256 - throw e;
21.257 - }
21.258 - try {
21.259 - // This has the side effect of checking syntax:
21.260 - if (codeName.indexOf(',') != -1) {
21.261 - throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N
21.262 - }
21.263 - Object[] cnParse = Util.parseCodeName(codeName);
21.264 - codeNameBase = (String)cnParse[0];
21.265 - Set<?> deps = mgr.loadDependencies(codeNameBase);
21.266 - boolean verifyCNBs = deps == null;
21.267 - if (verifyCNBs) {
21.268 - Dependency.create(Dependency.TYPE_MODULE, codeName);
21.269 - }
21.270 - codeNameRelease = (cnParse[1] != null) ? ((Integer)cnParse[1]).intValue() : -1;
21.271 - if (cnParse[2] != null) throw new NumberFormatException(codeName);
21.272 - // Spec vers
21.273 - String specVersS = attr.getValue("OpenIDE-Module-Specification-Version"); // NOI18N
21.274 - if (specVersS != null) {
21.275 - try {
21.276 - specVers = new SpecificationVersion(specVersS);
21.277 - } catch (NumberFormatException nfe) {
21.278 - throw (InvalidException)new InvalidException("While parsing OpenIDE-Module-Specification-Version: " + nfe.toString()).initCause(nfe); // NOI18N
21.279 - }
21.280 - } else {
21.281 - specVers = null;
21.282 - }
21.283 - computeProvides(attr, verifyCNBs);
21.284 -
21.285 - // Exports
21.286 - String exportsS = attr.getValue("OpenIDE-Module-Public-Packages"); // NOI18N
21.287 - if (exportsS != null) {
21.288 - if (exportsS.trim().equals("-")) { // NOI18N
21.289 - publicPackages = ZERO_PACKAGE_ARRAY;
21.290 - } else {
21.291 - StringTokenizer tok = new StringTokenizer(exportsS, ", "); // NOI18N
21.292 - List<PackageExport> exports = new ArrayList<PackageExport>(Math.max(tok.countTokens(), 1));
21.293 - while (tok.hasMoreTokens()) {
21.294 - String piece = tok.nextToken();
21.295 - if (piece.endsWith(".*")) { // NOI18N
21.296 - String pkg = piece.substring(0, piece.length() - 2);
21.297 - if (verifyCNBs) {
21.298 - Dependency.create(Dependency.TYPE_MODULE, pkg);
21.299 - }
21.300 - if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
21.301 - exports.add(new PackageExport(pkg.replace('.', '/') + '/', false));
21.302 - } else if (piece.endsWith(".**")) { // NOI18N
21.303 - String pkg = piece.substring(0, piece.length() - 3);
21.304 - if (verifyCNBs) {
21.305 - Dependency.create(Dependency.TYPE_MODULE, pkg);
21.306 - }
21.307 - if (pkg.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
21.308 - exports.add(new PackageExport(pkg.replace('.', '/') + '/', true));
21.309 - } else {
21.310 - throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
21.311 - }
21.312 - }
21.313 - if (exports.isEmpty()) throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
21.314 - publicPackages = exports.toArray(new PackageExport[exports.size()]);
21.315 - }
21.316 - } else {
21.317 - // XXX new link?
21.318 - Util.err.log(Level.WARNING, "module {0} does not declare OpenIDE-Module-Public-Packages in its manifest, so all packages are considered public by default: http://www.netbeans.org/download/dev/javadoc/OpenAPIs/org/openide/doc-files/upgrade.html#3.4-public-packages", codeNameBase);
21.319 - publicPackages = null;
21.320 - }
21.321 -
21.322 - {
21.323 - // friends
21.324 - String friends = attr.getValue("OpenIDE-Module-Friends"); // NOI18N
21.325 - if (friends != null) {
21.326 - StringTokenizer tok = new StringTokenizer(friends, ", "); // NOI18N
21.327 - HashSet<String> set = new HashSet<String> ();
21.328 - while (tok.hasMoreTokens()) {
21.329 - String piece = tok.nextToken();
21.330 - if (piece.indexOf('/') != -1) {
21.331 - throw new IllegalArgumentException("May specify only module code name bases in OpenIDE-Module-Friends, not major release versions: " + piece); // NOI18N
21.332 - }
21.333 - if (verifyCNBs) {
21.334 - // Indirect way of checking syntax:
21.335 - Dependency.create(Dependency.TYPE_MODULE, piece);
21.336 - }
21.337 - // OK, add it.
21.338 - set.add(piece);
21.339 - }
21.340 - if (set.isEmpty()) {
21.341 - throw new IllegalArgumentException("Empty OpenIDE-Module-Friends: " + friends); // NOI18N
21.342 - }
21.343 - if (publicPackages == null || publicPackages.length == 0) {
21.344 - throw new IllegalArgumentException("No use specifying OpenIDE-Module-Friends without any public packages: " + friends); // NOI18N
21.345 - }
21.346 - this.friendNames = set;
21.347 - }
21.348 - }
21.349 - initDeps(deps, attr);
21.350 - } catch (IllegalArgumentException iae) {
21.351 - throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N
21.352 - }
21.353 + data();
21.354 }
21.355
21.356 - final void computeProvides(Attributes attr, boolean verifyCNBs) throws InvalidException, IllegalArgumentException {
21.357 - // Token provides
21.358 - String providesS = attr.getValue("OpenIDE-Module-Provides"); // NOI18N
21.359 - if (providesS == null) {
21.360 - provides = ZERO_STRING_ARRAY;
21.361 - } else {
21.362 - StringTokenizer tok = new StringTokenizer(providesS, ", "); // NOI18N
21.363 - provides = new String[tok.countTokens()];
21.364 - for (int i = 0; i < provides.length; i++) {
21.365 - String provide = tok.nextToken();
21.366 - if (provide.indexOf(',') != -1) {
21.367 - throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module-Provides: " + provide); // NOI18N
21.368 - }
21.369 - if (verifyCNBs) {
21.370 - Dependency.create(Dependency.TYPE_MODULE, provide);
21.371 - }
21.372 - if (provide.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Provides: " + provide); // NOI18N
21.373 - provides[i] = provide;
21.374 - }
21.375 - if (new HashSet<String>(Arrays.asList(provides)).size() < provides.length) {
21.376 - throw new IllegalArgumentException("Duplicate entries in OpenIDE-Module-Provides: " + providesS); // NOI18N
21.377 - }
21.378 - }
21.379 - String[] additionalProvides = mgr.refineProvides (this);
21.380 - if (additionalProvides != null) {
21.381 - if (provides == null) {
21.382 - provides = additionalProvides;
21.383 - } else {
21.384 - ArrayList<String> l = new ArrayList<String> ();
21.385 - l.addAll (Arrays.asList (provides));
21.386 - l.addAll (Arrays.asList (additionalProvides));
21.387 - provides = l.toArray (provides);
21.388 - }
21.389 - }
21.390 - }
21.391
21.392 /** Get all JARs loaded by this module.
21.393 * Includes the module itself, any locale variants of the module,
21.394 @@ -511,7 +438,7 @@
21.395 // impl of ModuleInfo method
21.396 public @Override ClassLoader getClassLoader() throws IllegalArgumentException {
21.397 if (!enabled) {
21.398 - throw new IllegalArgumentException("Not enabled: " + codeNameBase); // NOI18N
21.399 + throw new IllegalArgumentException("Not enabled: " + getCodeNameBase()); // NOI18N
21.400 }
21.401 assert classloader != null : "Should have had a non-null loader for " + this;
21.402 return classloader;
21.403 @@ -658,6 +585,32 @@
21.404 }
21.405 }
21.406
21.407 + /** To be overriden to empty in FixedModule & co. */
21.408 + void refineDependencies(Set<Dependency> dependencies) {
21.409 + // Permit the concrete installer to make some changes:
21.410 + mgr.refineDependencies(this, dependencies);
21.411 + }
21.412 +
21.413 + void registerCoveredPackages(Set<String> known) {
21.414 + data().registerCoveredPackages(known);
21.415 + }
21.416 +
21.417 + Set<String> getCoveredPackages() {
21.418 + return data().getCoveredPackages();
21.419 + }
21.420 +
21.421 + /** Is this module a wrapper around OSGi?
21.422 + * @return true, if the module is build around OSGi
21.423 + * @since 2.51
21.424 + */
21.425 + public final boolean isNetigso() {
21.426 + return isNetigsoImpl();
21.427 + }
21.428 +
21.429 + boolean isNetigsoImpl() {
21.430 + return false;
21.431 + }
21.432 +
21.433 /** Struct representing a package exported from a module.
21.434 * @since org.netbeans.core/1 > 1.4
21.435 * @see Module#getPublicPackages
21.436 @@ -685,58 +638,31 @@
21.437 public @Override int hashCode() {
21.438 return pkg.hashCode();
21.439 }
21.440 +
21.441 + static void write(DataOutput dos, PackageExport[] arr) throws IOException {
21.442 + if (arr == null) {
21.443 + dos.writeInt(0);
21.444 + return;
21.445 + }
21.446 + dos.writeInt(arr.length);
21.447 + for (PackageExport pe : arr) {
21.448 + dos.writeUTF(pe.pkg);
21.449 + dos.writeBoolean(pe.recursive);
21.450 + }
21.451 + }
21.452 +
21.453 + static PackageExport[] read(DataInput is) throws IOException {
21.454 + int cnt = is.readInt();
21.455 + if (cnt == 0) {
21.456 + return null;
21.457 + }
21.458 + PackageExport[] arr = new PackageExport[cnt];
21.459 + for (int i = 0; i < cnt; i++) {
21.460 + String pkg = is.readUTF();
21.461 + boolean recursive = is.readBoolean();
21.462 + arr[i] = new PackageExport(pkg, recursive);
21.463 + }
21.464 + return arr;
21.465 + }
21.466 }
21.467 -
21.468 - /** Initializes dependencies of this module
21.469 - *
21.470 - * @param knownDeps Set<Dependency> of this module known from different source,
21.471 - * can be null
21.472 - * @param attr attributes in manifest to parse if knownDeps is null
21.473 - */
21.474 - private void initDeps(Set<?> knownDeps, Attributes attr)
21.475 - throws IllegalStateException, IllegalArgumentException {
21.476 - if (knownDeps != null) {
21.477 - dependenciesA = knownDeps.toArray(new Dependency[knownDeps.size()]);
21.478 - knownDeps = null;
21.479 - return;
21.480 - }
21.481 -
21.482 - // Dependencies
21.483 - Set<Dependency> dependencies = new HashSet<Dependency>(20);
21.484 - // First convert IDE/1 -> org.openide/1, so we never have to deal with
21.485 - // "IDE deps" internally:
21.486 - @SuppressWarnings(value = "deprecation")
21.487 - Set<Dependency> openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N
21.488 - if (!openideDeps.isEmpty()) {
21.489 - // If empty, leave it that way; NbInstaller will add it anyway.
21.490 - Dependency d = openideDeps.iterator().next();
21.491 - String name = d.getName();
21.492 - if (!name.startsWith("IDE/")) {
21.493 - throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N
21.494 - }
21.495 - dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N
21.496 - if (dependencies.size() != 1) {
21.497 - throw new IllegalStateException("Should be singleton: " + dependencies); // NOI18N
21.498 - }
21.499 - Util.err.log(Level.WARNING, "the module {0} uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html", codeNameBase); // NOI18N
21.500 - }
21.501 - dependencies.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N
21.502 - dependencies.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N
21.503 - String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N
21.504 - if (pkgdeps != null) {
21.505 - // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies manifest attribute, which is now deprecated: XXX URL TBD");
21.506 - dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
21.507 - }
21.508 - dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
21.509 - dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N
21.510 - dependencies.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N
21.511 - refineDependencies(dependencies);
21.512 - dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]);
21.513 - }
21.514 -
21.515 - void refineDependencies(Set<Dependency> dependencies) {
21.516 - // Permit the concrete installer to make some changes:
21.517 - mgr.refineDependencies(this, dependencies);
21.518 - }
21.519 -
21.520 }
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/o.n.bootstrap/src/org/netbeans/ModuleData.java Fri Mar 16 08:17:35 2012 +0100
22.3 @@ -0,0 +1,466 @@
22.4 +/*
22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
22.6 + *
22.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
22.8 + *
22.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
22.10 + * Other names may be trademarks of their respective owners.
22.11 + *
22.12 + * The contents of this file are subject to the terms of either the GNU
22.13 + * General Public License Version 2 only ("GPL") or the Common
22.14 + * Development and Distribution License("CDDL") (collectively, the
22.15 + * "License"). You may not use this file except in compliance with the
22.16 + * License. You can obtain a copy of the License at
22.17 + * http://www.netbeans.org/cddl-gplv2.html
22.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
22.19 + * specific language governing permissions and limitations under the
22.20 + * License. When distributing the software, include this License Header
22.21 + * Notice in each file and include the License file at
22.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
22.23 + * particular file as subject to the "Classpath" exception as provided
22.24 + * by Oracle in the GPL Version 2 section of the License file that
22.25 + * accompanied this code. If applicable, add the following below the
22.26 + * License Header, with the fields enclosed by brackets [] replaced by
22.27 + * your own identifying information:
22.28 + * "Portions Copyrighted [year] [name of copyright owner]"
22.29 + *
22.30 + * If you wish your version of this file to be governed by only the CDDL
22.31 + * or only the GPL Version 2, indicate your decision by adding
22.32 + * "[Contributor] elects to include this software in this distribution
22.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
22.34 + * single choice of license, a recipient has the option to distribute
22.35 + * your version of this file under either the CDDL, the GPL Version 2 or
22.36 + * to extend the choice of license to its licensees as provided above.
22.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
22.38 + * Version 2 license, then the option applies only if the new code is
22.39 + * made subject to such option by the copyright holder.
22.40 + *
22.41 + * Contributor(s):
22.42 + *
22.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
22.44 + */
22.45 +package org.netbeans;
22.46 +
22.47 +import java.io.DataInput;
22.48 +import java.io.DataOutput;
22.49 +import java.io.IOException;
22.50 +import java.io.ObjectInput;
22.51 +import java.io.ObjectOutput;
22.52 +import java.util.ArrayList;
22.53 +import java.util.Arrays;
22.54 +import java.util.Collection;
22.55 +import java.util.Collections;
22.56 +import java.util.HashSet;
22.57 +import java.util.List;
22.58 +import java.util.Set;
22.59 +import java.util.StringTokenizer;
22.60 +import java.util.jar.Attributes;
22.61 +import java.util.jar.Manifest;
22.62 +import java.util.logging.Level;
22.63 +import org.netbeans.Module.PackageExport;
22.64 +import org.openide.modules.Dependency;
22.65 +import org.openide.modules.SpecificationVersion;
22.66 +import org.openide.util.Exceptions;
22.67 +import org.openide.util.NbBundle;
22.68 +
22.69 +/** Information about essential properties of a module.
22.70 + *
22.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
22.72 + */
22.73 +class ModuleData {
22.74 + private final static PackageExport[] ZERO_PACKAGE_ARRAY = new PackageExport[0];
22.75 + private final static String[] ZERO_STRING_ARRAY = new String[0];
22.76 +
22.77 + private final String codeName;
22.78 + private final String codeNameBase;
22.79 + private final int codeNameRelease;
22.80 + private final String implVersion;
22.81 + private final String buildVersion;
22.82 + private final Set<String> friendNames;
22.83 + private final SpecificationVersion specVers;
22.84 + private final PackageExport[] publicPackages;
22.85 + private final String[] provides;
22.86 + private final Dependency[] dependencies;
22.87 + private final Set<String> coveredPackages;
22.88 +
22.89 +
22.90 + ModuleData(Manifest mf, Module forModule) throws InvalidException {
22.91 + Attributes attr = mf.getMainAttributes();
22.92 + // Code name
22.93 + codeName = attr.getValue("OpenIDE-Module"); // NOI18N
22.94 + if (codeName == null) {
22.95 + InvalidException e = new InvalidException("Not a module: no OpenIDE-Module tag in manifest of " + /* #17629: important! */ this, mf); // NOI18N
22.96 + // #29393: plausible user mistake, deal with it politely.
22.97 + Exceptions.attachLocalizedMessage(e,
22.98 + NbBundle.getMessage(Module.class,
22.99 + "EXC_not_a_module",
22.100 + this.toString()));
22.101 + throw e;
22.102 + }
22.103 + forModule.assignData(this);
22.104 + try {
22.105 + // This has the side effect of checking syntax:
22.106 + if (codeName.indexOf(',') != -1) {
22.107 + throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module: " + codeName); // NOI18N
22.108 + }
22.109 + Object[] cnParse = Util.parseCodeName(codeName);
22.110 + codeNameBase = (String) cnParse[0];
22.111 + Set<?> deps = forModule.getManager().loadDependencies(codeNameBase);
22.112 + boolean verifyCNBs = deps == null;
22.113 + if (verifyCNBs) {
22.114 + Dependency.create(Dependency.TYPE_MODULE, codeName);
22.115 + }
22.116 + codeNameRelease = (cnParse[1] != null) ? ((Integer) cnParse[1]).intValue() : -1;
22.117 + if (cnParse[2] != null) {
22.118 + throw new NumberFormatException(codeName);
22.119 + }
22.120 + // Spec vers
22.121 + String specVersS = attr.getValue("OpenIDE-Module-Specification-Version"); // NOI18N
22.122 + if (specVersS != null) {
22.123 + try {
22.124 + specVers = new SpecificationVersion(specVersS);
22.125 + } catch (NumberFormatException nfe) {
22.126 + throw (InvalidException) new InvalidException("While parsing OpenIDE-Module-Specification-Version: " + nfe.toString()).initCause(nfe); // NOI18N
22.127 + }
22.128 + } else {
22.129 + specVers = null;
22.130 + }
22.131 + String iv = attr.getValue("OpenIDE-Module-Implementation-Version"); // NOI18N
22.132 + implVersion = iv == null ? "" : iv;
22.133 + String bld = attr.getValue("OpenIDE-Module-Build-Version"); // NOI18N
22.134 + buildVersion = bld == null ? implVersion : bld;
22.135 +
22.136 + this.provides = computeProvides(forModule, attr, verifyCNBs);
22.137 +
22.138 + // Exports
22.139 + String exportsS = attr.getValue("OpenIDE-Module-Public-Packages"); // NOI18N
22.140 + if (exportsS != null) {
22.141 + if (exportsS.trim().equals("-")) { // NOI18N
22.142 + publicPackages = ZERO_PACKAGE_ARRAY;
22.143 + } else {
22.144 + StringTokenizer tok = new StringTokenizer(exportsS, ", "); // NOI18N
22.145 + List<Module.PackageExport> exports = new ArrayList<Module.PackageExport>(Math.max(tok.countTokens(), 1));
22.146 + while (tok.hasMoreTokens()) {
22.147 + String piece = tok.nextToken();
22.148 + if (piece.endsWith(".*")) { // NOI18N
22.149 + String pkg = piece.substring(0, piece.length() - 2);
22.150 + if (verifyCNBs) {
22.151 + Dependency.create(Dependency.TYPE_MODULE, pkg);
22.152 + }
22.153 + if (pkg.lastIndexOf('/') != -1) {
22.154 + throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
22.155 + }
22.156 + exports.add(new Module.PackageExport(pkg.replace('.', '/') + '/', false));
22.157 + } else if (piece.endsWith(".**")) { // NOI18N
22.158 + String pkg = piece.substring(0, piece.length() - 3);
22.159 + if (verifyCNBs) {
22.160 + Dependency.create(Dependency.TYPE_MODULE, pkg);
22.161 + }
22.162 + if (pkg.lastIndexOf('/') != -1) {
22.163 + throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
22.164 + }
22.165 + exports.add(new Module.PackageExport(pkg.replace('.', '/') + '/', true));
22.166 + } else {
22.167 + throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
22.168 + }
22.169 + }
22.170 + if (exports.isEmpty()) {
22.171 + throw new IllegalArgumentException("Illegal OpenIDE-Module-Public-Packages: " + exportsS); // NOI18N
22.172 + }
22.173 + publicPackages = exports.toArray(new Module.PackageExport[exports.size()]);
22.174 + }
22.175 + } else {
22.176 + // XXX new link?
22.177 + Util.err.log(Level.WARNING, "module {0} does not declare OpenIDE-Module-Public-Packages in its manifest, so all packages are considered public by default: http://www.netbeans.org/download/dev/javadoc/OpenAPIs/org/openide/doc-files/upgrade.html#3.4-public-packages", codeNameBase);
22.178 + publicPackages = null;
22.179 + }
22.180 +
22.181 + {
22.182 + HashSet<String> set = null;
22.183 + // friends
22.184 + String friends = attr.getValue("OpenIDE-Module-Friends"); // NOI18N
22.185 + if (friends != null) {
22.186 + StringTokenizer tok = new StringTokenizer(friends, ", "); // NOI18N
22.187 + set = new HashSet<String>();
22.188 + while (tok.hasMoreTokens()) {
22.189 + String piece = tok.nextToken();
22.190 + if (piece.indexOf('/') != -1) {
22.191 + throw new IllegalArgumentException("May specify only module code name bases in OpenIDE-Module-Friends, not major release versions: " + piece); // NOI18N
22.192 + }
22.193 + if (verifyCNBs) {
22.194 + // Indirect way of checking syntax:
22.195 + Dependency.create(Dependency.TYPE_MODULE, piece);
22.196 + }
22.197 + // OK, add it.
22.198 + set.add(piece);
22.199 + }
22.200 + if (set.isEmpty()) {
22.201 + throw new IllegalArgumentException("Empty OpenIDE-Module-Friends: " + friends); // NOI18N
22.202 + }
22.203 + if (publicPackages == null || publicPackages.length == 0) {
22.204 + throw new IllegalArgumentException("No use specifying OpenIDE-Module-Friends without any public packages: " + friends); // NOI18N
22.205 + }
22.206 + }
22.207 + this.friendNames = set;
22.208 + }
22.209 + this.dependencies = initDeps(forModule, deps, attr);
22.210 + } catch (IllegalArgumentException iae) {
22.211 + throw (InvalidException) new InvalidException("While parsing " + codeName + " a dependency attribute: " + iae.toString()).initCause(iae); // NOI18N
22.212 + }
22.213 + this.coveredPackages = new HashSet<String>();
22.214 + }
22.215 +
22.216 + ModuleData(Manifest mf, NetigsoModule m) throws InvalidException {
22.217 + final String symbName = getMainAttribute(mf, "Bundle-SymbolicName"); // NOI18N
22.218 + if (symbName == null) {
22.219 + throw new InvalidException("Not an OSGi bundle: " + m);
22.220 + }
22.221 + m.assignData(this);
22.222 + this.codeName = symbName.replace('-', '_');
22.223 + int slash = codeName.lastIndexOf('/');
22.224 + if (slash != -1) {
22.225 + this.codeNameRelease = Integer.parseInt(symbName.substring(slash + 1));
22.226 + } else {
22.227 + this.codeNameRelease = -1;
22.228 + }
22.229 + String v = getMainAttribute(mf, "Bundle-Version"); // NOI18N
22.230 + if (v == null) {
22.231 + NetigsoModule.LOG.log(Level.WARNING, "No Bundle-Version for {0}", m);
22.232 + this.specVers = new SpecificationVersion(v = "0.0");
22.233 + } else {
22.234 + this.specVers = computeVersion(v);
22.235 + }
22.236 + this.codeNameBase = codeName;
22.237 + String iv = getMainAttribute(mf, "OpenIDE-Module-Implementation-Version"); // NOI18N
22.238 + this.implVersion = iv == null ? v : iv;
22.239 + String bld = getMainAttribute(mf, "OpenIDE-Module-Build-Version"); // NOI18N
22.240 + this.buildVersion = bld == null ? implVersion : bld;
22.241 + this.friendNames = Collections.emptySet();
22.242 + this.publicPackages = null;
22.243 + this.provides = computeProvides(m, mf.getMainAttributes(), false);
22.244 + this.dependencies = null;
22.245 + this.coveredPackages = new HashSet<String>();
22.246 + }
22.247 +
22.248 + ModuleData(ObjectInput dis) throws IOException {
22.249 + try {
22.250 + this.codeName = dis.readUTF();
22.251 + this.codeNameBase = dis.readUTF();
22.252 + this.codeNameRelease = dis.readInt();
22.253 + this.coveredPackages = readStrings(dis, new HashSet<String>(), true);
22.254 + this.dependencies = (Dependency[]) dis.readObject();
22.255 + this.implVersion = dis.readUTF();
22.256 + this.buildVersion = dis.readUTF();
22.257 + this.provides = readStrings(dis);
22.258 + this.friendNames = readStrings(dis, new HashSet<String>(), false);
22.259 + this.specVers = new SpecificationVersion(dis.readUTF());
22.260 + this.publicPackages = Module.PackageExport.read(dis);
22.261 + } catch (ClassNotFoundException cnfe) {
22.262 + throw new IOException(cnfe);
22.263 + }
22.264 + }
22.265 +
22.266 + void write(ObjectOutput dos) throws IOException {
22.267 + dos.writeUTF(codeName);
22.268 + dos.writeUTF(codeNameBase);
22.269 + dos.writeInt(codeNameRelease);
22.270 + writeStrings(dos, coveredPackages);
22.271 + dos.writeObject(dependencies);
22.272 + dos.writeUTF(implVersion);
22.273 + dos.writeUTF(buildVersion);
22.274 + writeStrings(dos, provides);
22.275 + writeStrings(dos, friendNames);
22.276 + dos.writeUTF(specVers.toString());
22.277 + Module.PackageExport.write(dos, publicPackages);
22.278 + }
22.279 +
22.280 + private String[] computeProvides(Module forModule, Attributes attr, boolean verifyCNBs) throws InvalidException, IllegalArgumentException {
22.281 + String[] arr;
22.282 + // Token provides
22.283 + String providesS = attr.getValue("OpenIDE-Module-Provides"); // NOI18N
22.284 + if (providesS == null) {
22.285 + arr = ZERO_STRING_ARRAY;
22.286 + } else {
22.287 + StringTokenizer tok = new StringTokenizer(providesS, ", "); // NOI18N
22.288 + arr = new String[tok.countTokens()];
22.289 + for (int i = 0; i < arr.length; i++) {
22.290 + String provide = tok.nextToken();
22.291 + if (provide.indexOf(',') != -1) {
22.292 + throw new InvalidException("Illegal code name syntax parsing OpenIDE-Module-Provides: " + provide); // NOI18N
22.293 + }
22.294 + if (verifyCNBs) {
22.295 + Dependency.create(Dependency.TYPE_MODULE, provide);
22.296 + }
22.297 + if (provide.lastIndexOf('/') != -1) throw new IllegalArgumentException("Illegal OpenIDE-Module-Provides: " + provide); // NOI18N
22.298 + arr[i] = provide;
22.299 + }
22.300 + if (new HashSet<String>(Arrays.asList(arr)).size() < arr.length) {
22.301 + throw new IllegalArgumentException("Duplicate entries in OpenIDE-Module-Provides: " + providesS); // NOI18N
22.302 + }
22.303 + }
22.304 + String[] additionalProvides = forModule.getManager().refineProvides (forModule);
22.305 + if (additionalProvides != null) {
22.306 + if (arr == null) {
22.307 + arr = additionalProvides;
22.308 + } else {
22.309 + ArrayList<String> l = new ArrayList<String> ();
22.310 + l.addAll (Arrays.asList (arr));
22.311 + l.addAll (Arrays.asList (additionalProvides));
22.312 + arr = l.toArray (arr);
22.313 + }
22.314 + }
22.315 + return arr;
22.316 + }
22.317 +
22.318 + /**
22.319 + * Initializes dependencies of this module
22.320 + *
22.321 + * @param knownDeps Set<Dependency> of this module known from different
22.322 + * source, can be null
22.323 + * @param attr attributes in manifest to parse if knownDeps is null
22.324 + */
22.325 + private Dependency[] initDeps(Module forModule, Set<?> knownDeps, Attributes attr)
22.326 + throws IllegalStateException, IllegalArgumentException {
22.327 + if (knownDeps != null) {
22.328 + return knownDeps.toArray(new Dependency[knownDeps.size()]);
22.329 + }
22.330 +
22.331 + // deps
22.332 + Set<Dependency> deps = new HashSet<Dependency>(20);
22.333 + // First convert IDE/1 -> org.openide/1, so we never have to deal with
22.334 + // "IDE deps" internally:
22.335 + @SuppressWarnings(value = "deprecation")
22.336 + Set<Dependency> openideDeps = Dependency.create(Dependency.TYPE_IDE, attr.getValue("OpenIDE-Module-IDE-Dependencies")); // NOI18N
22.337 + if (!openideDeps.isEmpty()) {
22.338 + // If empty, leave it that way; NbInstaller will add it anyway.
22.339 + Dependency d = openideDeps.iterator().next();
22.340 + String name = d.getName();
22.341 + if (!name.startsWith("IDE/")) {
22.342 + throw new IllegalStateException("Weird IDE dep: " + name); // NOI18N
22.343 + }
22.344 + deps.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/" + name.substring(4) + " > " + d.getVersion())); // NOI18N
22.345 + if (deps.size() != 1) {
22.346 + throw new IllegalStateException("Should be singleton: " + deps); // NOI18N
22.347 + }
22.348 + Util.err.log(Level.WARNING, "the module {0} uses OpenIDE-Module-IDE-Dependencies which is deprecated. See http://openide.netbeans.org/proposals/arch/modularize.html", codeNameBase); // NOI18N
22.349 + }
22.350 + deps.addAll(Dependency.create(Dependency.TYPE_JAVA, attr.getValue("OpenIDE-Module-Java-Dependencies"))); // NOI18N
22.351 + deps.addAll(Dependency.create(Dependency.TYPE_MODULE, attr.getValue("OpenIDE-Module-Module-Dependencies"))); // NOI18N
22.352 + String pkgdeps = attr.getValue("OpenIDE-Module-Package-Dependencies"); // NOI18N
22.353 + if (pkgdeps != null) {
22.354 + // XXX: Util.err.log(ErrorManager.WARNING, "Warning: module " + codeNameBase + " uses the OpenIDE-Module-Package-Dependencies
22.355 + // manifest attribute, which is now deprecated: XXX URL TBD");
22.356 + deps.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
22.357 + }
22.358 + deps.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
22.359 + deps.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N
22.360 + deps.addAll(Dependency.create(Dependency.TYPE_RECOMMENDS, attr.getValue("OpenIDE-Module-Recommends"))); // NOI18N
22.361 + forModule.refineDependencies(deps);
22.362 + return deps.toArray(new Dependency[0]);
22.363 + }
22.364 +
22.365 + final String getCodeName() {
22.366 + return codeName;
22.367 + }
22.368 +
22.369 + final String getCodeNameBase() {
22.370 + return codeNameBase;
22.371 + }
22.372 +
22.373 + final int getCodeNameRelease() {
22.374 + return codeNameRelease;
22.375 + }
22.376 +
22.377 + final String[] getProvides() {
22.378 + return provides;
22.379 + }
22.380 +
22.381 + final SpecificationVersion getSpecificationVersion() {
22.382 + return specVers;
22.383 + }
22.384 +
22.385 + final PackageExport[] getPublicPackages() {
22.386 + return publicPackages;
22.387 + }
22.388 +
22.389 + final Set<String> getFriendNames() {
22.390 + return friendNames;
22.391 + }
22.392 +
22.393 + final Dependency[] getDependencies() {
22.394 + return dependencies;
22.395 + }
22.396 +
22.397 + final String getBuildVersion() {
22.398 + return buildVersion.isEmpty() ? null : buildVersion;
22.399 + }
22.400 +
22.401 + final String getImplementationVersion() {
22.402 + return implVersion.isEmpty() ? null : implVersion;
22.403 + }
22.404 +
22.405 + void registerCoveredPackages(Set<String> known) {
22.406 + assert coveredPackages.isEmpty();
22.407 + coveredPackages.addAll(known);
22.408 + }
22.409 +
22.410 + Set<String> getCoveredPackages() {
22.411 + return coveredPackages.isEmpty() ? null : coveredPackages;
22.412 + }
22.413 +
22.414 + private <T extends Collection<String>> T readStrings(
22.415 + DataInput dis, T set, boolean returnEmpty
22.416 + ) throws IOException {
22.417 + int cnt = dis.readInt();
22.418 + if (!returnEmpty && cnt == 0) {
22.419 + return null;
22.420 + }
22.421 + while (cnt-- > 0) {
22.422 + set.add(dis.readUTF());
22.423 + }
22.424 + return set;
22.425 + }
22.426 + private String[] readStrings(ObjectInput dis) throws IOException {
22.427 + List<String> arr = new ArrayList<String>();
22.428 + readStrings(dis, arr, false);
22.429 + return arr.toArray(new String[0]);
22.430 + }
22.431 + private void writeStrings(DataOutput dos, Collection<String> set)
22.432 + throws IOException {
22.433 + if (set == null) {
22.434 + dos.writeInt(0);
22.435 + return;
22.436 + }
22.437 + dos.writeInt(set.size());
22.438 + for (String s : set) {
22.439 + dos.writeUTF(s);
22.440 + }
22.441 + }
22.442 + private void writeStrings(ObjectOutput dos, String[] provides) throws IOException {
22.443 + writeStrings(dos, Arrays.asList(provides));
22.444 + }
22.445 +
22.446 + private static String getMainAttribute(Manifest manifest, String attr) {
22.447 + String s = manifest.getMainAttributes().getValue(attr);
22.448 + if (s == null) {
22.449 + return null;
22.450 + }
22.451 + int semicolon = s.indexOf(';');
22.452 + if (semicolon == -1) {
22.453 + return s;
22.454 + } else {
22.455 + return s.substring(0, semicolon);
22.456 + }
22.457 + }
22.458 + private static SpecificationVersion computeVersion(String v) {
22.459 + int pos = -1;
22.460 + for (int i = 0; i < 3; i++) {
22.461 + pos = v.indexOf('.', pos + 1);
22.462 + if (pos == -1) {
22.463 + return new SpecificationVersion(v);
22.464 + }
22.465 + }
22.466 + return new SpecificationVersion(v.substring(0, pos));
22.467 + }
22.468 +
22.469 +}
23.1 --- a/o.n.bootstrap/src/org/netbeans/ModuleFactory.java Thu Mar 15 16:10:40 2012 +0100
23.2 +++ b/o.n.bootstrap/src/org/netbeans/ModuleFactory.java Fri Mar 16 08:17:35 2012 +0100
23.3 @@ -65,9 +65,16 @@
23.4 public Module create(File jar, Object history, boolean reloadable,
23.5 boolean autoload, boolean eager, ModuleManager mgr, Events ev)
23.6 throws IOException {
23.7 + final Boolean osgiStatus = mgr.isOSGi(jar);
23.8 + if (Boolean.TRUE.equals(osgiStatus)) {
23.9 + return new NetigsoModule(null, jar, mgr, ev, history, reloadable, autoload, eager);
23.10 + }
23.11 + Module m;
23.12 try {
23.13 - StandardModule m = new StandardModule(mgr, ev, jar, history, reloadable, autoload, eager);
23.14 - return m;
23.15 + m = new StandardModule(mgr, ev, jar, history, reloadable, autoload, eager);
23.16 + if (osgiStatus == null) {
23.17 + m.dataWithCheck();
23.18 + }
23.19 } catch (InvalidException ex) {
23.20 Manifest mani = ex.getManifest();
23.21 if (mani != null) {
23.22 @@ -75,10 +82,15 @@
23.23 if (name == null) {
23.24 throw ex;
23.25 }
23.26 - return new NetigsoModule(mani, jar, mgr, ev, history, reloadable, autoload, eager);
23.27 + m = new NetigsoModule(mani, jar, mgr, ev, history, reloadable, autoload, eager);
23.28 + if (osgiStatus == null) {
23.29 + m.dataWithCheck();
23.30 + }
23.31 + } else {
23.32 + throw ex;
23.33 }
23.34 - throw ex;
23.35 }
23.36 + return m;
23.37 }
23.38
23.39 /**
24.1 --- a/o.n.bootstrap/src/org/netbeans/ModuleManager.java Thu Mar 15 16:10:40 2012 +0100
24.2 +++ b/o.n.bootstrap/src/org/netbeans/ModuleManager.java Fri Mar 16 08:17:35 2012 +0100
24.3 @@ -47,9 +47,13 @@
24.4 import java.beans.PropertyChangeListener;
24.5 import java.beans.PropertyChangeSupport;
24.6 import java.io.ByteArrayInputStream;
24.7 +import java.io.ByteArrayOutputStream;
24.8 +import java.io.DataInputStream;
24.9 +import java.io.DataOutputStream;
24.10 import java.io.File;
24.11 import java.io.IOException;
24.12 import java.io.InputStream;
24.13 +import java.io.ObjectOutputStream;
24.14 import java.net.URL;
24.15 import java.security.AllPermission;
24.16 import java.security.CodeSource;
24.17 @@ -57,6 +61,7 @@
24.18 import java.security.Permissions;
24.19 import java.util.ArrayList;
24.20 import java.util.Arrays;
24.21 +import java.util.Collection;
24.22 import java.util.Collections;
24.23 import java.util.Comparator;
24.24 import java.util.Enumeration;
24.25 @@ -112,7 +117,7 @@
24.26 private static final Set<Union2<Dependency,InvalidException>> EMPTY_COLLECTION = Collections.<Union2<Dependency, InvalidException>>emptySet();
24.27
24.28 // modules providing a given requires token; set may never be empty
24.29 - private final Map<String,Set<Module>> providersOf = new HashMap<String,Set<Module>>(25);
24.30 + private final ProvidersOf providersOf = new ProvidersOf();
24.31
24.32 private final ModuleInstaller installer;
24.33 private ModuleFactory moduleFactory;
24.34 @@ -122,6 +127,7 @@
24.35 private final Object classLoaderLock = new String("ModuleManager.classLoaderLock"); // NOI18N
24.36
24.37 private final Events ev;
24.38 + private final ModuleDataCache mdc = new ModuleDataCache();
24.39
24.40 /** Create a manager, initially with no managed modules.
24.41 * The handler for installing modules is given.
24.42 @@ -308,6 +314,10 @@
24.43 return new HashSet<Module>(modules);
24.44 }
24.45
24.46 + final int getModuleCount() {
24.47 + return modules.size();
24.48 + }
24.49 +
24.50 /** Get a set of modules managed which are currently enabled.
24.51 * Convenience method only.
24.52 * @see #PROP_ENABLED_MODULES
24.53 @@ -348,7 +358,7 @@
24.54 */
24.55 @Deprecated
24.56 public Set<Module> getModuleInterdependencies(Module m, boolean reverse, boolean transitive) {
24.57 - return Util.moduleInterdependencies(m, reverse, transitive, true, modules, modulesByName, providersOf);
24.58 + return Util.moduleInterdependencies(m, reverse, transitive, true, modules, modulesByName, getProvidersOf());
24.59 }
24.60
24.61 /**
24.62 @@ -367,7 +377,7 @@
24.63 * @since org.netbeans.bootstrap/1 > 2.48
24.64 */
24.65 public Set<Module> getModuleInterdependencies(Module m, boolean reverse, boolean transitive, boolean considerNeeds) {
24.66 - return Util.moduleInterdependencies(m, reverse, transitive, considerNeeds, modules, modulesByName, providersOf);
24.67 + return Util.moduleInterdependencies(m, reverse, transitive, considerNeeds, modules, modulesByName, getProvidersOf());
24.68 }
24.69
24.70 /** Get a classloader capable of loading from any
24.71 @@ -499,6 +509,91 @@
24.72 return cnt;
24.73 }
24.74
24.75 + /** Checks whether the module is supposed be OSGi or not
24.76 + * @return null if it is not known
24.77 + */
24.78 + final Boolean isOSGi(File jar) {
24.79 + return mdc.isOSGi(jar.getPath());
24.80 + }
24.81 +
24.82 + /** Obtains (and destroys) data for given JAR file.
24.83 + * @return stream with data or null if not found in cache
24.84 + */
24.85 + final InputStream dataFor(File jar) {
24.86 + if (jar == null) {
24.87 + return null;
24.88 + }
24.89 + byte[] arr = mdc.getModuleState(jar.getPath());
24.90 + return arr == null ? null : new ByteArrayInputStream(arr);
24.91 + }
24.92 + /** Obtains cnb for given JAR file.
24.93 + * @return stream with data or null if not found in cache
24.94 + */
24.95 + final String cnbFor(File jar) {
24.96 + if (jar == null) {
24.97 + return null;
24.98 + }
24.99 + return mdc.getCnb(jar.getPath());
24.100 + }
24.101 +
24.102 + private Map<String, Set<Module>> getProvidersOf() {
24.103 + return providersOf.getProvidersOf();
24.104 + }
24.105 +
24.106 + static void registerProviders(Module m, Map<String, Set<Module>> po) {
24.107 + String[] provides = m.getProvides();
24.108 + for (int i = 0; i < provides.length; i++) {
24.109 + Set<Module> providing = po.get(provides[i]);
24.110 + if (providing == null) {
24.111 + providing = new HashSet<Module>(16);
24.112 + po.put(provides[i], providing);
24.113 + }
24.114 + providing.add(m);
24.115 + }
24.116 + }
24.117 +
24.118 + private class ProvidersOf {
24.119 + private Map<String,Set<Module>> providersOf;
24.120 +
24.121 + public ProvidersOf() {
24.122 + }
24.123 +
24.124 + final synchronized Map<String, Set<Module>> getProvidersOf() {
24.125 + if (providersOf == null) {
24.126 + providersOf = new HashMap<String, Set<Module>>();
24.127 + for (Module m : modules) {
24.128 + possibleProviderAdded(m);
24.129 + }
24.130 + }
24.131 + return providersOf;
24.132 + }
24.133 +
24.134 + final synchronized void possibleProviderAdded(Module m) {
24.135 + if (providersOf == null) {
24.136 + return;
24.137 + }
24.138 + registerProviders(m, providersOf);
24.139 + }
24.140 +
24.141 + final synchronized void possibleProviderRemoved(Module m) {
24.142 + if (providersOf == null) {
24.143 + return;
24.144 + }
24.145 + for (String token : m.getProvides()) {
24.146 + Set<Module> providing = providersOf.get(token);
24.147 + if (providing != null) {
24.148 + providing.remove(m);
24.149 + if (providing.isEmpty()) {
24.150 + providersOf.remove(token);
24.151 + }
24.152 + } else {
24.153 + // Else we called reload and m.reload threw IOException, so
24.154 + // it has already removed its provider list
24.155 + }
24.156 + }
24.157 + }
24.158 + }
24.159 +
24.160 /** A classloader giving access to all the module classloaders at once. */
24.161 private final class SystemClassLoader extends JarClassLoader {
24.162
24.163 @@ -769,14 +864,13 @@
24.164 }
24.165
24.166 private void subCreate(Module m) throws DuplicateException {
24.167 - Util.err.log(Level.FINE, "created: {0}", m);
24.168 Module old = get(m.getCodeNameBase());
24.169 if (old != null) {
24.170 throw new DuplicateException(old, m);
24.171 }
24.172 modules.add(m);
24.173 modulesByName.put(m.getCodeNameBase(), m);
24.174 - possibleProviderAdded(m);
24.175 + providersOf.possibleProviderAdded(m);
24.176 lookup.add(m);
24.177 firer.created(m);
24.178 firer.change(new ChangeFirer.Change(this, PROP_MODULES, null, null));
24.179 @@ -787,17 +881,6 @@
24.180 clearProblemCache();
24.181 firer.fire();
24.182 }
24.183 - private void possibleProviderAdded(Module m) {
24.184 - String[] provides = m.getProvides();
24.185 - for (int i = 0; i < provides.length; i++) {
24.186 - Set<Module> providing = providersOf.get(provides[i]);
24.187 - if (providing == null) {
24.188 - providing = new HashSet<Module>(16);
24.189 - providersOf.put(provides[i], providing);
24.190 - }
24.191 - providing.add(m);
24.192 - }
24.193 - }
24.194
24.195 /** Remove a module from the managed set.
24.196 * Must be disabled first.
24.197 @@ -810,7 +893,7 @@
24.198 ev.log(Events.DELETE_MODULE, m);
24.199 modules.remove(m);
24.200 modulesByName.remove(m.getCodeNameBase());
24.201 - possibleProviderRemoved(m);
24.202 + providersOf.possibleProviderRemoved(m);
24.203 lookup.remove(m);
24.204 firer.deleted(m);
24.205 firer.change(new ChangeFirer.Change(this, PROP_MODULES, null, null));
24.206 @@ -820,20 +903,6 @@
24.207 m.destroy();
24.208 firer.fire();
24.209 }
24.210 - private void possibleProviderRemoved(Module m) {
24.211 - for (String token : m.getProvides()) {
24.212 - Set<Module> providing = providersOf.get(token);
24.213 - if (providing != null) {
24.214 - providing.remove(m);
24.215 - if (providing.isEmpty()) {
24.216 - providersOf.remove(token);
24.217 - }
24.218 - } else {
24.219 - // Else we called reload and m.reload threw IOException, so
24.220 - // it has already removed its provider list
24.221 - }
24.222 - }
24.223 - }
24.224
24.225 /** Reload a module.
24.226 * This could make a fresh copy of its JAR file preparing
24.227 @@ -854,7 +923,7 @@
24.228 Util.err.fine("reload: " + m);
24.229 if (m.isFixed()) throw new IllegalArgumentException("reload fixed module: " + m); // NOI18N
24.230 if (m.isEnabled()) throw new IllegalArgumentException("reload enabled module: " + m); // NOI18N
24.231 - possibleProviderRemoved(m);
24.232 + providersOf.possibleProviderRemoved(m);
24.233 try {
24.234 m.reload();
24.235 } catch (IOException ioe) {
24.236 @@ -862,7 +931,7 @@
24.237 delete(m);
24.238 throw ioe;
24.239 }
24.240 - possibleProviderAdded(m);
24.241 + providersOf.possibleProviderAdded(m);
24.242 firer.change(new ChangeFirer.Change(m, Module.PROP_MANIFEST, null, null));
24.243 // Some problem with this module may now have gone away. In turn, some
24.244 // other modules may now no longer have problems. So clear the cache
24.245 @@ -966,25 +1035,9 @@
24.246 }
24.247 fallback.addFirst(m);
24.248 Util.err.fine("enable: bringing up: " + m);
24.249 - ev.log(Events.PERF_START, "bringing up classloader on " + m.getCodeName() ); // NOI18N
24.250 + ev.log(Events.PERF_START, "bringing up classloader on " + m.getCodeNameBase()); // NOI18N
24.251 try {
24.252 - // Calculate the parents to initialize the classloader with.
24.253 - Dependency[] dependencies = m.getDependenciesArray();
24.254 - Set<Module> parents = new HashSet<Module>(dependencies.length * 4 / 3 + 1);
24.255 - for (int i = 0; i < dependencies.length; i++) {
24.256 - Dependency dep = dependencies[i];
24.257 - if (dep.getType() != Dependency.TYPE_MODULE) {
24.258 - // Token providers do *not* go into the parent classloader
24.259 - // list. The providing module must have been turned on first.
24.260 - // But you cannot automatically access classes from it.
24.261 - continue;
24.262 - }
24.263 - String name = (String)Util.parseCodeName(dep.getName())[0];
24.264 - Module parent = get(name);
24.265 - // Should not happen:
24.266 - if (parent == null) throw new IOException("Parent " + name + " not found!"); // NOI18N
24.267 - parents.add(parent);
24.268 - }
24.269 + Set<Module> parents = calculateParents(m);
24.270 m.classLoaderUp(parents);
24.271 } catch (IOException ioe) {
24.272 tryingClassLoaderUp = true;
24.273 @@ -993,7 +1046,7 @@
24.274 throw ie;
24.275 }
24.276 m.setEnabled(true);
24.277 - ev.log(Events.PERF_END, "bringing up classloader on " + m.getCodeName() ); // NOI18N
24.278 + ev.log(Events.PERF_END, "bringing up classloader on " + m.getCodeNameBase() ); // NOI18N
24.279 // Check package dependencies.
24.280 // ev.log(Events.PERF_START, "package dependency check on " + m.getCodeName() ); // NOI18N
24.281 Util.err.fine("enable: checking package dependencies for " + m);
24.282 @@ -1187,6 +1240,30 @@
24.283 return m1.getCodeNameBase().compareTo(m2.getCodeNameBase());
24.284 }
24.285 }
24.286 +
24.287 + private final Set<Module> calculateParents(Module m) throws NumberFormatException, IOException {
24.288 + // Calculate the parents to initialize the classloader with.
24.289 + Dependency[] dependencies = m.getDependenciesArray();
24.290 + Set<Module> res = new HashSet<Module>(dependencies.length * 4 / 3 + 1);
24.291 + for (int i = 0; i < dependencies.length; i++) {
24.292 + Dependency dep = dependencies[i];
24.293 + if (dep.getType() != Dependency.TYPE_MODULE) {
24.294 + // Token providers do *not* go into the parent classloader
24.295 + // list. The providing module must have been turned on first.
24.296 + // But you cannot automatically access classes from it.
24.297 + continue;
24.298 + }
24.299 + String name = (String) Util.parseCodeName(dep.getName())[0];
24.300 + Module parent = get(name);
24.301 + // Should not happen:
24.302 + if (parent == null) {
24.303 + throw new IOException("Parent " + name + " not found!"); // NOI18N
24.304 + }
24.305 + res.add(parent);
24.306 + }
24.307 + return res;
24.308 + }
24.309 +
24.310
24.311 /** Simulate what would happen if a set of modules were to be enabled.
24.312 * None of the listed modules may be autoload modules, nor eager, nor currently enabled,
24.313 @@ -1221,6 +1298,15 @@
24.314 return simulateEnable(modules, true);
24.315 }
24.316 final List<Module> simulateEnable(Set<Module> modules, boolean honorAutoloadEager) throws IllegalArgumentException {
24.317 + List<String> cnbs = mdc.simulateEnable(modules);
24.318 + if (cnbs != null) {
24.319 + List<Module> arr = new ArrayList<Module>(cnbs.size());
24.320 + for (String cnb : cnbs) {
24.321 + arr.add(get(cnb));
24.322 + }
24.323 + assert !arr.contains(null) : arr;
24.324 + return arr;
24.325 + }
24.326 /* Not quite, eager modules may change this:
24.327 if (modules.isEmpty()) {
24.328 return Collections.EMPTY_LIST;
24.329 @@ -1247,10 +1333,11 @@
24.330 }
24.331 }
24.332 while (searchForPossibleEager(willEnable, stillDisabled, modules)) {/* search again */}
24.333 - Map<Module,List<Module>> deps = Util.moduleDependencies(willEnable, modulesByName, providersOf);
24.334 + Map<Module,List<Module>> deps = Util.moduleDependencies(willEnable, modulesByName, getProvidersOf());
24.335 try {
24.336 List<Module> l = Utilities.topologicalSort(willEnable, deps);
24.337 Collections.reverse(l);
24.338 + mdc.registerEnable(modules, l);
24.339 return l;
24.340 } catch (TopologicalSortException ex) {
24.341 // Some kind of cycle involving prov-req deps. Should be extremely rare.
24.342 @@ -1297,7 +1384,7 @@
24.343 dep.getType() == Dependency.TYPE_NEEDS ||
24.344 dep.getType() == Dependency.TYPE_RECOMMENDS
24.345 ) {
24.346 - Set<Module> providers = providersOf.get(dep.getName());
24.347 + Set<Module> providers = getProvidersOf().get(dep.getName());
24.348 if (providers == null) {
24.349 assert dep.getType() == Dependency.TYPE_RECOMMENDS : "Should have found a provider of " + dep;
24.350 continue;
24.351 @@ -1382,7 +1469,7 @@
24.352 if (other == null) throw new IllegalStateException("Should have found module: " + codeNameBase); // NOI18N
24.353 if (!couldBeEnabledWithEagers(other, willEnable, recursion)) return false;
24.354 } else if (dep.getType() == Dependency.TYPE_REQUIRES || dep.getType() == Dependency.TYPE_NEEDS) {
24.355 - Set<Module> providers = providersOf.get(dep.getName());
24.356 + Set<Module> providers = getProvidersOf().get(dep.getName());
24.357 if (providers == null) throw new IllegalStateException("Should have found a provider of: " + dep.getName()); // NOI18N
24.358 // Just need *one* to match.
24.359 boolean foundOne = false;
24.360 @@ -1403,7 +1490,7 @@
24.361 public List<Module> simulateJaveleonReload(Module moduleToReload) throws IllegalArgumentException {
24.362 Set<Module> transitiveDependents = new HashSet<Module>(20);
24.363 addToJaveleonDisableList(transitiveDependents, moduleToReload);
24.364 - Map<Module,List<Module>> deps = Util.moduleDependencies(transitiveDependents, modulesByName, providersOf);
24.365 + Map<Module,List<Module>> deps = Util.moduleDependencies(transitiveDependents, modulesByName, getProvidersOf());
24.366 try {
24.367 LinkedList<Module> orderedForEnabling = new LinkedList<Module>();
24.368 for (Module m : Utilities.topologicalSort(transitiveDependents, deps)) {
24.369 @@ -1468,7 +1555,7 @@
24.370 Set<Module> stillEnabled = new HashSet<Module>(getEnabledModules());
24.371 stillEnabled.removeAll(willDisable);
24.372 while (searchForUnusedAutoloads(willDisable, stillEnabled)) {/* search again */}
24.373 - Map<Module,List<Module>> deps = Util.moduleDependencies(willDisable, modulesByName, providersOf);
24.374 + Map<Module,List<Module>> deps = Util.moduleDependencies(willDisable, modulesByName, getProvidersOf());
24.375 try {
24.376 return Utilities.topologicalSort(willDisable, deps);
24.377 } catch (TopologicalSortException ex) {
24.378 @@ -1688,7 +1775,7 @@
24.379 // Works much like a regular module dependency. However it only
24.380 // fails if there are no satisfying modules with no problems.
24.381 String token = dep.getName();
24.382 - Set<Module> providers = providersOf.get(token);
24.383 + Set<Module> providers = getProvidersOf().get(token);
24.384 if (providers == null) {
24.385 // Nobody provides it. This dep failed.
24.386 probs.add(Union2.<Dependency,InvalidException>createFirst(dep));
24.387 @@ -1811,7 +1898,11 @@
24.388 public boolean shutDown(Runnable midHook) {
24.389 assertWritable();
24.390 Set<Module> unorderedModules = getEnabledModules();
24.391 - Map<Module,List<Module>> deps = Util.moduleDependencies(unorderedModules, modulesByName, providersOf);
24.392 + Map<String, Set<Module>> providersMap = new HashMap<String, Set<Module>>();
24.393 + for (Module m : unorderedModules) {
24.394 + registerProviders(m, providersMap);
24.395 + }
24.396 + Map<Module,List<Module>> deps = Util.moduleDependencies(unorderedModules, modulesByName, providersMap);
24.397 List<Module> sortedModules;
24.398 try {
24.399 sortedModules = Utilities.topologicalSort(unorderedModules, deps);
24.400 @@ -1849,4 +1940,177 @@
24.401 }
24.402 });
24.403 }
24.404 + private class ModuleDataCache implements Stamps.Updater {
24.405 + private static final String CACHE = "all-manifests.dat";
24.406 + private final Map<String,byte[]> path2Data;
24.407 + private final Map<String,Boolean> path2OSGi;
24.408 + private final Map<String,String> path2Cnb;
24.409 + private final int moduleCount;
24.410 + private Set<String> toEnable;
24.411 + private List<String> willEnable;
24.412 +
24.413 + public ModuleDataCache() {
24.414 + InputStream is = Stamps.getModulesJARs().asStream(CACHE);
24.415 + Map<String,byte[]> map = null;
24.416 + Map<String,Boolean> osgi = null;
24.417 + Map<String,String> cnbs = null;
24.418 + Set<String> toEn = null;
24.419 + List<String> toWi = null;
24.420 + int cnt = -1;
24.421 + if (is != null) try {
24.422 + DataInputStream dis = new DataInputStream(is);
24.423 + map = new HashMap<String, byte[]>();
24.424 + osgi = new HashMap<String, Boolean>();
24.425 + cnbs = new HashMap<String, String>();
24.426 + cnt = dis.readInt();
24.427 + for (;;) {
24.428 + String path = Stamps.readRelativePath(dis);
24.429 + if (path.isEmpty()) {
24.430 + break;
24.431 + }
24.432 + boolean isOSGi = dis.readBoolean();
24.433 + osgi.put(path, isOSGi);
24.434 + cnbs.put(path, dis.readUTF());
24.435 + int len = dis.readInt();
24.436 + byte[] data = new byte[len];
24.437 + dis.readFully(data);
24.438 + map.put(path, data);
24.439 + }
24.440 + toEn = readCnbs(dis, new HashSet<String>());
24.441 + toWi = readCnbs(dis, new ArrayList<String>());
24.442 + dis.close();
24.443 + } catch (IOException ex) {
24.444 + Util.err.log(Level.INFO, "Cannot read all-modules.dat", ex);
24.445 + map = null;
24.446 + osgi = null;
24.447 + cnbs = null;
24.448 + toEn = null;
24.449 + toWi = null;
24.450 + }
24.451 + path2Data = map;
24.452 + path2OSGi = osgi;
24.453 + path2Cnb = cnbs;
24.454 + toEnable = toEn;
24.455 + willEnable = toWi;
24.456 + moduleCount = cnt;
24.457 + if (map == null) {
24.458 + reset();
24.459 + }
24.460 + }
24.461 +
24.462 + public Boolean isOSGi(String path) {
24.463 + if (path2OSGi == null) {
24.464 + return null;
24.465 + }
24.466 + return path2OSGi.get(path);
24.467 + }
24.468 +
24.469 + public synchronized byte[] getModuleState(String path) {
24.470 + byte[] res = null;
24.471 + if (path2Data != null) {
24.472 + res = path2Data.remove(path);
24.473 + }
24.474 + if (res == null) {
24.475 + reset();
24.476 + }
24.477 + return res;
24.478 + }
24.479 + final String getCnb(String path) {
24.480 + return path2Cnb == null ? null : path2Cnb.get(path);
24.481 + }
24.482 +
24.483 + @Override
24.484 + public void flushCaches(DataOutputStream os) throws IOException {
24.485 + Set<Module> store = getModules();
24.486 + os.writeInt(store.size());
24.487 + for (Module m : store) {
24.488 + final File path = m.getJarFile();
24.489 + if (path == null) {
24.490 + assert m instanceof FixedModule : "Only fixed modules are excluded from caches " + m;
24.491 + continue;
24.492 + }
24.493 + Stamps.writeRelativePath(path.getPath(), os);
24.494 + os.writeBoolean(m.isNetigso());
24.495 + os.writeUTF(m.getCodeNameBase());
24.496 +
24.497 + ByteArrayOutputStream data = new ByteArrayOutputStream();
24.498 + ObjectOutputStream dos = new ObjectOutputStream(data);
24.499 + m.writeData(dos);
24.500 + dos.close();
24.501 +
24.502 + byte[] arr = data.toByteArray();
24.503 + os.writeInt(arr.length);
24.504 + os.write(arr);
24.505 + }
24.506 + Stamps.writeRelativePath("", os);
24.507 + synchronized (this) {
24.508 + writeCnbs(os, toEnable);
24.509 + writeCnbs(os, willEnable);
24.510 + }
24.511 + }
24.512 + @Override
24.513 + public void cacheReady() {
24.514 + }
24.515 +
24.516 + private synchronized void reset() {
24.517 + toEnable = null;
24.518 + willEnable = null;
24.519 + }
24.520 +
24.521 + synchronized final void registerEnable(Set<Module> modules, List<Module> l) {
24.522 + toEnable = new HashSet<String>();
24.523 + for (Module m : modules) {
24.524 + toEnable.add(m.getCodeNameBase());
24.525 + }
24.526 + List<String> arr = new ArrayList<String>(l.size());
24.527 + for (Module m : l) {
24.528 + arr.add(m.getCodeNameBase());
24.529 + }
24.530 + willEnable = Collections.unmodifiableList(arr);
24.531 + Stamps.getModulesJARs().scheduleSave(this, CACHE, false);
24.532 + }
24.533 +
24.534 + synchronized final List<String> simulateEnable(Set<Module> modules) {
24.535 + if (
24.536 + toEnable != null &&
24.537 + modules.size() == toEnable.size() &&
24.538 + moduleCount == getModuleCount()
24.539 + ) {
24.540 + Set<String> clone = new HashSet<String>(toEnable);
24.541 + for (Module m : modules) {
24.542 + if (!clone.remove(m.getCodeNameBase())) {
24.543 + return null;
24.544 + }
24.545 + }
24.546 + if (clone.isEmpty()) {
24.547 + return willEnable;
24.548 + }
24.549 + }
24.550 + return null;
24.551 + }
24.552 +
24.553 + private <T extends Collection<String>> T readCnbs(DataInputStream dis, T fill) throws IOException {
24.554 + int size = dis.readInt();
24.555 + if (size == -1) {
24.556 + return null;
24.557 + }
24.558 +
24.559 + while (size-- > 0) {
24.560 + fill.add(dis.readUTF());
24.561 + }
24.562 + return fill;
24.563 + }
24.564 +
24.565 + private void writeCnbs(DataOutputStream os, Collection<String> cnbs) throws IOException {
24.566 + if (cnbs == null) {
24.567 + os.writeInt(-1);
24.568 + return;
24.569 + }
24.570 +
24.571 + os.writeInt(cnbs.size());
24.572 + for (String s : cnbs) {
24.573 + os.writeUTF(s);
24.574 + }
24.575 + }
24.576 + }
24.577 }
25.1 --- a/o.n.bootstrap/src/org/netbeans/NetigsoModule.java Thu Mar 15 16:10:40 2012 +0100
25.2 +++ b/o.n.bootstrap/src/org/netbeans/NetigsoModule.java Fri Mar 16 08:17:35 2012 +0100
25.3 @@ -46,6 +46,7 @@
25.4
25.5 import java.io.File;
25.6 import java.io.IOException;
25.7 +import java.io.ObjectInput;
25.8 import java.net.URL;
25.9 import java.util.Collections;
25.10 import java.util.Enumeration;
25.11 @@ -54,7 +55,6 @@
25.12 import java.util.jar.Manifest;
25.13 import java.util.logging.Level;
25.14 import java.util.logging.Logger;
25.15 -import org.openide.modules.SpecificationVersion;
25.16 import org.openide.util.Exceptions;
25.17
25.18 /** Special module for representing OSGi bundles
25.19 @@ -66,58 +66,26 @@
25.20 private final File jar;
25.21 private final Manifest manifest;
25.22 private int startLevel = -1;
25.23 - private final String codeName;
25.24 - private final int release;
25.25 - private final SpecificationVersion version;
25.26 private InvalidException problem;
25.27
25.28 public NetigsoModule(Manifest mani, File jar, ModuleManager mgr, Events ev, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException {
25.29 super(mgr, ev, history, reloadable, autoload, eager);
25.30 this.jar = jar;
25.31 this.manifest = mani;
25.32 - final String symbName = getMainAttribute("Bundle-SymbolicName");
25.33 - this.codeName = symbName.replace('-', '_');
25.34 - int slash = codeName.lastIndexOf('/');
25.35 - if (slash != -1) {
25.36 - this.release = Integer.parseInt(symbName.substring(slash + 1));
25.37 - } else {
25.38 - this.release = -1;
25.39 - }
25.40 - String v = getMainAttribute("Bundle-Version"); // NOI18N
25.41 - if (v == null) {
25.42 - NetigsoModule.LOG.log(Level.WARNING, "No Bundle-Version for {0}", jar);
25.43 - this.version = new SpecificationVersion("0.0");
25.44 - } else {
25.45 - this.version = computeVersion(v);
25.46 - }
25.47 -
25.48 - computeProvides(mani.getMainAttributes(), false);
25.49 }
25.50
25.51 @Override
25.52 - public String getCodeName() {
25.53 - return getCodeNameBase();
25.54 + ModuleData createData(ObjectInput in, Manifest mf) throws IOException {
25.55 + if (in != null) {
25.56 + return new ModuleData(in);
25.57 + } else {
25.58 + return new ModuleData(mf, this);
25.59 + }
25.60 }
25.61
25.62 @Override
25.63 - public String getCodeNameBase() {
25.64 - return codeName;
25.65 - }
25.66 -
25.67 - @Override
25.68 - public int getCodeNameRelease() {
25.69 - return release;
25.70 - }
25.71 -
25.72 - @Override
25.73 - public SpecificationVersion getSpecificationVersion() {
25.74 - return version;
25.75 - }
25.76 -
25.77 - @Override
25.78 - public String getImplementationVersion() {
25.79 - String explicit = super.getImplementationVersion(); // OIDE-M-I-V/-B-V added by NB build harness
25.80 - return explicit != null ? explicit : getMainAttribute("Bundle-Version"); // NOI18N
25.81 + boolean isNetigsoImpl() {
25.82 + return true;
25.83 }
25.84
25.85 @Override
25.86 @@ -236,19 +204,6 @@
25.87 return "Netigso: " + jar;
25.88 }
25.89
25.90 - private String getMainAttribute(String attr) {
25.91 - String s = manifest.getMainAttributes().getValue(attr);
25.92 - if (s == null) {
25.93 - return null;
25.94 - }
25.95 - int semicolon = s.indexOf(';');
25.96 - if (semicolon == -1) {
25.97 - return s;
25.98 - } else {
25.99 - return s.substring(0, semicolon);
25.100 - }
25.101 - }
25.102 -
25.103 @Override
25.104 final int getStartLevelImpl() {
25.105 return startLevel;
25.106 @@ -258,17 +213,6 @@
25.107 this.startLevel = startLevel;
25.108 }
25.109
25.110 - private static SpecificationVersion computeVersion(String v) {
25.111 - int pos = -1;
25.112 - for (int i = 0; i < 3; i++) {
25.113 - pos = v.indexOf('.', pos + 1);
25.114 - if (pos == -1) {
25.115 - return new SpecificationVersion(v);
25.116 - }
25.117 - }
25.118 - return new SpecificationVersion(v.substring(0, pos));
25.119 - }
25.120 -
25.121 private final class DelegateCL extends ProxyClassLoader
25.122 implements Util.ModuleProvider {
25.123 public DelegateCL() {
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/o.n.bootstrap/src/org/netbeans/PackageAttrsCache.java Fri Mar 16 08:17:35 2012 +0100
26.3 @@ -0,0 +1,176 @@
26.4 +/*
26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.6 + *
26.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
26.8 + *
26.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
26.10 + * Other names may be trademarks of their respective owners.
26.11 + *
26.12 + * The contents of this file are subject to the terms of either the GNU
26.13 + * General Public License Version 2 only ("GPL") or the Common
26.14 + * Development and Distribution License("CDDL") (collectively, the
26.15 + * "License"). You may not use this file except in compliance with the
26.16 + * License. You can obtain a copy of the License at
26.17 + * http://www.netbeans.org/cddl-gplv2.html
26.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.19 + * specific language governing permissions and limitations under the
26.20 + * License. When distributing the software, include this License Header
26.21 + * Notice in each file and include the License file at
26.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
26.23 + * particular file as subject to the "Classpath" exception as provided
26.24 + * by Oracle in the GPL Version 2 section of the License file that
26.25 + * accompanied this code. If applicable, add the following below the
26.26 + * License Header, with the fields enclosed by brackets [] replaced by
26.27 + * your own identifying information:
26.28 + * "Portions Copyrighted [year] [name of copyright owner]"
26.29 + *
26.30 + * If you wish your version of this file to be governed by only the CDDL
26.31 + * or only the GPL Version 2, indicate your decision by adding
26.32 + * "[Contributor] elects to include this software in this distribution
26.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
26.34 + * single choice of license, a recipient has the option to distribute
26.35 + * your version of this file under either the CDDL, the GPL Version 2 or
26.36 + * to extend the choice of license to its licensees as provided above.
26.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
26.38 + * Version 2 license, then the option applies only if the new code is
26.39 + * made subject to such option by the copyright holder.
26.40 + *
26.41 + * Contributor(s):
26.42 + *
26.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
26.44 + */
26.45 +package org.netbeans;
26.46 +
26.47 +import java.io.DataInputStream;
26.48 +import java.io.DataOutputStream;
26.49 +import java.io.IOException;
26.50 +import java.io.InputStream;
26.51 +import java.net.URL;
26.52 +import java.util.Collections;
26.53 +import java.util.HashMap;
26.54 +import java.util.HashSet;
26.55 +import java.util.Map;
26.56 +import java.util.jar.Attributes;
26.57 +import java.util.jar.Manifest;
26.58 +import java.util.logging.Level;
26.59 +import java.util.logging.Logger;
26.60 +
26.61 +/** Cache of various attributes of packages (vendor, spec & impl version, etc.)
26.62 + *
26.63 + * @author Jaroslav Tulach <jtulach@netbeans.org>
26.64 + */
26.65 +final class PackageAttrsCache implements Stamps.Updater {
26.66 + private static final String CACHE = "package-attrs.dat"; // NOI18N
26.67 + private static final String[] EMPTY = new String[7];
26.68 + private static final Logger LOG = Logger.getLogger(PackageAttrsCache.class.getName());
26.69 + private static PackageAttrsCache packages;
26.70 +
26.71 + static void initialize() {
26.72 + packages = new PackageAttrsCache();
26.73 + }
26.74 +
26.75 + private final Map<String,String[]> cache;
26.76 + PackageAttrsCache() {
26.77 + InputStream is = Stamps.getModulesJARs().asStream(CACHE);
26.78 + Map<String,String[]> tmp = null;
26.79 + if (is != null) {
26.80 + try {
26.81 + tmp = new HashMap<String, String[]>();
26.82 + DataInputStream dis = new DataInputStream(is);
26.83 + for (;;) {
26.84 + String key = Stamps.readRelativePath(dis);
26.85 + if (key.isEmpty()) {
26.86 + break;
26.87 + }
26.88 + String[] arr = new String[7];
26.89 + for (int i = 0; i < 7; i++) {
26.90 + arr[i] = dis.readUTF();
26.91 + }
26.92 + tmp.put(key, arr);
26.93 + }
26.94 + } catch (IOException ex) {
26.95 + LOG.log(Level.INFO, "Cannot read " + CACHE, ex);
26.96 + tmp = null;
26.97 + }
26.98 + }
26.99 + if (tmp == null) {
26.100 + cache = new HashMap<String,String[]>();
26.101 + Stamps.getModulesJARs().scheduleSave(this, CACHE, false);
26.102 + } else {
26.103 + cache = Collections.unmodifiableMap(tmp);
26.104 + }
26.105 + }
26.106 +
26.107 + static String[] findPackageAttrs(URL src, Manifest man, String path) {
26.108 + PackageAttrsCache p = packages;
26.109 + return p == null ? extractFromManifest(man, path) : p.findImpl(src, man, path);
26.110 + }
26.111 +
26.112 + final String[] findImpl(URL src, Manifest man, String path) {
26.113 + String key = src.toExternalForm() + "!/" + path;
26.114 + String[] arr;
26.115 + if (cache instanceof HashSet) {
26.116 + arr = extractFromManifest(man, path);
26.117 + if (isEmpty(arr)) {
26.118 + arr = EMPTY;
26.119 + } else {
26.120 + cache.put(key, arr);
26.121 + }
26.122 + } else {
26.123 + arr = cache.get(key);
26.124 + if (arr == null) {
26.125 + arr = EMPTY;
26.126 + }
26.127 + }
26.128 + return arr;
26.129 + }
26.130 +
26.131 +
26.132 + @Override
26.133 + public void flushCaches(DataOutputStream os) throws IOException {
26.134 + for (Map.Entry<String, String[]> entry : cache.entrySet()) {
26.135 + Stamps.writeRelativePath(entry.getKey(), os);
26.136 + for (String s : entry.getValue()) {
26.137 + os.writeUTF(s);
26.138 + }
26.139 + }
26.140 + Stamps.writeRelativePath("", os);
26.141 + }
26.142 +
26.143 + @Override
26.144 + public void cacheReady() {
26.145 + }
26.146 +
26.147 + private static String getAttr(Attributes spec, Attributes main, Attributes.Name name) {
26.148 + String val = null;
26.149 + if (spec != null) val = spec.getValue (name);
26.150 + if (val == null && main != null) val = main.getValue (name);
26.151 + return val;
26.152 + }
26.153 +
26.154 + private static String[] extractFromManifest(Manifest man, String path) {
26.155 + Attributes spec = man.getAttributes(path);
26.156 + Attributes main = man.getMainAttributes();
26.157 + String[] arr = new String[7];
26.158 + arr[0] = getAttr(spec, main, Attributes.Name.SPECIFICATION_TITLE);
26.159 + arr[1] = getAttr(spec, main, Attributes.Name.SPECIFICATION_VERSION);
26.160 + arr[2] = getAttr(spec, main, Attributes.Name.SPECIFICATION_VENDOR);
26.161 + arr[3] = getAttr(spec, main, Attributes.Name.IMPLEMENTATION_TITLE);
26.162 + arr[4] = getAttr(spec, main, Attributes.Name.IMPLEMENTATION_VERSION);
26.163 + arr[5] = getAttr(spec, main, Attributes.Name.IMPLEMENTATION_VENDOR);
26.164 + arr[6] = getAttr(spec, main, Attributes.Name.SEALED);
26.165 + return arr;
26.166 + }
26.167 +
26.168 + private static boolean isEmpty(String[] arr) {
26.169 + if (arr == EMPTY) {
26.170 + return true;
26.171 + }
26.172 + for (String s : arr) {
26.173 + if (s != null) {
26.174 + return false;
26.175 + }
26.176 + }
26.177 + return true;
26.178 + }
26.179 +}
27.1 --- a/o.n.bootstrap/src/org/netbeans/Stamps.java Thu Mar 15 16:10:40 2012 +0100
27.2 +++ b/o.n.bootstrap/src/org/netbeans/Stamps.java Fri Mar 16 08:17:35 2012 +0100
27.3 @@ -44,7 +44,7 @@
27.4
27.5 import java.io.BufferedOutputStream;
27.6 import java.io.ByteArrayInputStream;
27.7 -import java.io.DataInputStream;
27.8 +import java.io.DataInput;
27.9 import java.io.DataOutput;
27.10 import java.io.DataOutputStream;
27.11 import java.io.File;
27.12 @@ -810,7 +810,7 @@
27.13 return cluster.getName().replaceAll("\\.\\.", "__");
27.14 }
27.15
27.16 - static String readRelativePath(DataInputStream dis) throws IOException {
27.17 + static String readRelativePath(DataInput dis) throws IOException {
27.18 String index = dis.readUTF();
27.19 if (index.isEmpty()) {
27.20 return index;
28.1 --- a/o.n.bootstrap/src/org/netbeans/StandardModule.java Thu Mar 15 16:10:40 2012 +0100
28.2 +++ b/o.n.bootstrap/src/org/netbeans/StandardModule.java Fri Mar 16 08:17:35 2012 +0100
28.3 @@ -52,17 +52,16 @@
28.4 import java.io.File;
28.5 import java.io.IOException;
28.6 import java.io.InputStream;
28.7 +import java.io.ObjectInput;
28.8 import java.security.AllPermission;
28.9 import java.security.CodeSource;
28.10 import java.security.PermissionCollection;
28.11 import java.security.Permissions;
28.12 import java.util.ArrayList;
28.13 import java.util.Collections;
28.14 -import java.util.HashMap;
28.15 import java.util.HashSet;
28.16 import java.util.List;
28.17 import java.util.Locale;
28.18 -import java.util.Map;
28.19 import java.util.MissingResourceException;
28.20 import java.util.Properties;
28.21 import java.util.ResourceBundle;
28.22 @@ -92,38 +91,19 @@
28.23 /** JAR file holding the module */
28.24 private final File jar;
28.25 /** if reloadable, temporary JAR file actually loaded from */
28.26 - private File physicalJar = null;
28.27 + private File physicalJar;
28.28 private Manifest manifest;
28.29
28.30 - /** Map from extension JARs to sets of JAR that load them via Class-Path.
28.31 - * Used only for debugging purposes, so that a warning is printed if two
28.32 - * different modules try to load the same extension (which would cause them
28.33 - * to both load their own private copy, which may not be intended).
28.34 - */
28.35 - private static final Map<File,Set<File>> extensionOwners = new HashMap<File,Set<File>>();
28.36 /** Simple registry of JAR files used as modules.
28.37 * Used only for debugging purposes, so that we can be sure
28.38 * that no one is using Class-Path to refer to other modules.
28.39 */
28.40 private static final Set<File> moduleJARs = new HashSet<File>();
28.41
28.42 - /** Set of locale-variants JARs for this module (or null).
28.43 - * Added explicitly to classloader, and can be used by execution engine.
28.44 - */
28.45 - private Set<File> localeVariants = null;
28.46 - /** Set of extension JARs that this module loads via Class-Path (or null).
28.47 - * Can be used e.g. by execution engine. (#9617)
28.48 - */
28.49 - private Set<File> plainExtensions = null;
28.50 - /** Set of localized extension JARs derived from plainExtensions (or null).
28.51 - * Used to add these to the classloader. (#9348)
28.52 - * Can be used e.g. by execution engine.
28.53 - */
28.54 - private Set<File> localeExtensions = null;
28.55 /** Patches added at the front of the classloader (or null).
28.56 * Files are assumed to be JARs; directories are themselves.
28.57 */
28.58 - private Set<File> patches = null;
28.59 + private Set<File> patches;
28.60
28.61 /** localized properties, only non-null if requested from disabled module */
28.62 private Properties localizedProps;
28.63 @@ -132,16 +112,16 @@
28.64 public StandardModule(ModuleManager mgr, Events ev, File jar, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException {
28.65 super(mgr, ev, history, JaveleonModule.isJaveleonPresent || reloadable, autoload, eager);
28.66 this.jar = jar;
28.67 - loadManifest();
28.68 - parseManifest();
28.69 - findExtensionsAndVariants(manifest);
28.70 - // Check if some other module already listed this one in Class-Path.
28.71 - // For the chronologically reverse case, see findExtensionsAndVariants().
28.72 - Set<File> bogoOwners = extensionOwners.get(jar);
28.73 - if (bogoOwners != null) {
28.74 - Util.err.warning("module " + jar + " was incorrectly placed in the Class-Path of other JARs " + bogoOwners + "; please use OpenIDE-Module-Module-Dependencies instead");
28.75 + moduleJARs.add(jar);
28.76 + }
28.77 +
28.78 + @Override
28.79 + ModuleData createData(ObjectInput in, Manifest mf) throws IOException {
28.80 + if (in != null) {
28.81 + return new StandardModuleData(in);
28.82 + } else {
28.83 + return new StandardModuleData(mf, this);
28.84 }
28.85 - moduleJARs.add(jar);
28.86 }
28.87
28.88 public @Override Manifest getManifest() {
28.89 @@ -315,109 +295,57 @@
28.90 }
28.91 }
28.92
28.93 - /** Find any extensions loaded by the module, as well as any localized
28.94 - * variants of the module or its extensions.
28.95 - */
28.96 - private void findExtensionsAndVariants(Manifest m) {
28.97 - assert jar != null : "Cannot load extensions from classpath module " + getCodeNameBase();
28.98 - localeVariants = null;
28.99 - List<File> l = LocaleVariants.findLocaleVariantsOf(jar, getCodeNameBase());
28.100 - if (!l.isEmpty()) {
28.101 - localeVariants = new HashSet<File>(l);
28.102 - }
28.103 - plainExtensions = null;
28.104 - localeExtensions = null;
28.105 - String classPath = m.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
28.106 - if (classPath != null) {
28.107 - StringTokenizer tok = new StringTokenizer(classPath);
28.108 - while (tok.hasMoreTokens()) {
28.109 - String ext = tok.nextToken();
28.110 - if (new File(ext).isAbsolute()) { // NOI18N
28.111 - Util.err.log(Level.WARNING, "Class-Path value {0} from {1} is illegal according to the Java Extension Mechanism: must be relative", new Object[] {ext, jar});
28.112 - }
28.113 - File base = jar.getParentFile();
28.114 - while (ext.startsWith("../")) {
28.115 - // cannot access FileUtil.normalizeFile from here, and URI.normalize might be unsafe for UNC paths
28.116 - ext = ext.substring(3);
28.117 - base = base.getParentFile();
28.118 - }
28.119 - File extfile = new File(base, ext.replace('/', File.separatorChar));
28.120 - //No need to sync on extensionOwners - we are in write mutex
28.121 - Set<File> owners = extensionOwners.get(extfile);
28.122 - if (owners == null) {
28.123 - owners = new HashSet<File>(2);
28.124 - owners.add(jar);
28.125 - extensionOwners.put(extfile, owners);
28.126 - } else if (! owners.contains(jar)) {
28.127 - owners.add(jar);
28.128 - events.log(Events.EXTENSION_MULTIPLY_LOADED, extfile, owners);
28.129 - } // else already know about it (OK or warned)
28.130 - // Also check to make sure it is not a module JAR! See constructor for the reverse case.
28.131 - if (moduleJARs.contains(extfile)) {
28.132 - Util.err.warning("Class-Path value " + ext + " from " + jar + " illegally refers to another module; use OpenIDE-Module-Module-Dependencies instead");
28.133 - }
28.134 - if (plainExtensions == null) plainExtensions = new HashSet<File>();
28.135 - plainExtensions.add(extfile);
28.136 - l = LocaleVariants.findLocaleVariantsOf(extfile, getCodeNameBase());
28.137 - if (!l.isEmpty()) {
28.138 - if (localeExtensions == null) {
28.139 - localeExtensions = new HashSet<File>();
28.140 + private Set<File> findPatches() {
28.141 + if (patches == null) {
28.142 + // #9273: load any modules/patches/this-code-name/*.jar files first:
28.143 + File patchdir = new File(new File(jar.getParentFile(), "patches"), // NOI18N
28.144 + getCodeNameBase().replace('.', '-')); // NOI18N
28.145 + if (patchdir.isDirectory()) {
28.146 + File[] jars = patchdir.listFiles(Util.jarFilter());
28.147 + if (jars != null) {
28.148 + for (File patchJar : jars) {
28.149 + if (patches == null) {
28.150 + patches = new HashSet<File>(5);
28.151 + }
28.152 + patches.add(patchJar);
28.153 }
28.154 - localeExtensions.addAll(l);
28.155 + } else {
28.156 + Util.err.warning("Could not search for patches in " + patchdir);
28.157 }
28.158 }
28.159 - }
28.160 - // #9273: load any modules/patches/this-code-name/*.jar files first:
28.161 - File patchdir = new File(new File(jar.getParentFile(), "patches"), // NOI18N
28.162 - getCodeNameBase().replace('.', '-')); // NOI18N
28.163 - scanForPatches(patchdir);
28.164 - // Use of the following system property is not supported, but is used
28.165 - // by e.g. XTest to influence installed modules without changing the build.
28.166 - // Format is -Dnetbeans.patches.org.nb.mods.foo=/path/to.file.jar:/path/to/dir
28.167 - String patchesClassPath = System.getProperty("netbeans.patches." + getCodeNameBase()); // NOI18N
28.168 - if (patchesClassPath != null) {
28.169 - StringTokenizer tokenizer = new StringTokenizer(patchesClassPath, File.pathSeparator);
28.170 - while (tokenizer.hasMoreTokens()) {
28.171 - String element = tokenizer.nextToken();
28.172 - File fileElement = new File(element);
28.173 - if (fileElement.exists()) {
28.174 - if (patches == null) {
28.175 - patches = new HashSet<File>(15);
28.176 + // Use of the following system property is not supported, but is used
28.177 + // by e.g. XTest to influence installed modules without changing the build.
28.178 + // Format is -Dnetbeans.patches.org.nb.mods.foo=/path/to.file.jar:/path/to/dir
28.179 + String patchesClassPath = System.getProperty("netbeans.patches." + getCodeNameBase()); // NOI18N
28.180 + if (patchesClassPath != null) {
28.181 + StringTokenizer tokenizer = new StringTokenizer(patchesClassPath, File.pathSeparator);
28.182 + while (tokenizer.hasMoreTokens()) {
28.183 + String element = tokenizer.nextToken();
28.184 + File fileElement = new File(element);
28.185 + if (fileElement.exists()) {
28.186 + if (patches == null) {
28.187 + patches = new HashSet<File>(15);
28.188 + }
28.189 + patches.add(fileElement);
28.190 }
28.191 - patches.add(fileElement);
28.192 }
28.193 }
28.194 - }
28.195 - if (Util.err.isLoggable(Level.FINE)) {
28.196 - Util.err.fine("localeVariants of " + jar + ": " + localeVariants);
28.197 - Util.err.fine("plainExtensions of " + jar + ": " + plainExtensions);
28.198 - Util.err.fine("localeExtensions of " + jar + ": " + localeExtensions);
28.199 - Util.err.fine("patches of " + jar + ": " + patches);
28.200 - }
28.201 - if (patches != null) {
28.202 - for (File patch : patches) {
28.203 - events.log(Events.PATCH, patch);
28.204 + if (Util.err.isLoggable(Level.FINE)) {
28.205 + Util.err.log(Level.FINE, "patches of {0}: {1}", new Object[]{jar, patches});
28.206 + }
28.207 + if (patches != null) {
28.208 + for (File patch : patches) {
28.209 + events.log(Events.PATCH, patch);
28.210 + }
28.211 + }
28.212 + if (patches == null) {
28.213 + patches = Collections.emptySet();
28.214 }
28.215 }
28.216 +
28.217 + return patches;
28.218 }
28.219
28.220 - /** Scans a directory for possible patch JARs. */
28.221 - private void scanForPatches(File patchdir) {
28.222 - if (!patchdir.isDirectory()) {
28.223 - return;
28.224 - }
28.225 - File[] jars = patchdir.listFiles(Util.jarFilter());
28.226 - if (jars != null) {
28.227 - for (File patchJar : jars) {
28.228 - if (patches == null) {
28.229 - patches = new HashSet<File>(5);
28.230 - }
28.231 - patches.add(patchJar);
28.232 - }
28.233 - } else {
28.234 - Util.err.warning("Could not search for patches in " + patchdir);
28.235 - }
28.236 - }
28.237
28.238 /** Check if there is any need to load localized properties.
28.239 * If so, try to load them. Throw an exception if they cannot
28.240 @@ -508,17 +436,17 @@
28.241 * JARs already present in the classpath are <em>not</em> listed.
28.242 * @return a <code>List<File></code> of JARs
28.243 */
28.244 + @Override
28.245 public List<File> getAllJars() {
28.246 List<File> l = new ArrayList<File>();
28.247 - if (patches != null) l.addAll(patches);
28.248 + Set<File> ptchs = findPatches();
28.249 + if (ptchs != null) l.addAll(ptchs);
28.250 if (physicalJar != null) {
28.251 l.add(physicalJar);
28.252 } else if (jar != null) {
28.253 l.add(jar);
28.254 }
28.255 - if (plainExtensions != null) l.addAll (plainExtensions);
28.256 - if (localeVariants != null) l.addAll (localeVariants);
28.257 - if (localeExtensions != null) l.addAll (localeExtensions);
28.258 + ((StandardModuleData)data()).addCp(l);
28.259 return l;
28.260 }
28.261
28.262 @@ -548,7 +476,8 @@
28.263 localizedProps = null;
28.264 loadManifest();
28.265 parseManifest();
28.266 - findExtensionsAndVariants(manifest);
28.267 + // JST: reload not solved yet
28.268 + // JST findExtensionsAndVariants(manifest);
28.269 String codeNameBase2 = getCodeNameBase();
28.270 if (! codeNameBase1.equals(codeNameBase2)) {
28.271 throw new InvalidException("Code name base changed during reload: " + codeNameBase1 + " -> " + codeNameBase2); // NOI18N
28.272 @@ -596,7 +525,8 @@
28.273 loaders.add(l);
28.274 }
28.275 List<File> classp = new ArrayList<File>(3);
28.276 - if (patches != null) classp.addAll(patches);
28.277 + Set<File> ptchs = findPatches();
28.278 + if (ptchs != null) classp.addAll(ptchs);
28.279
28.280 if (reloadable) {
28.281 ensurePhysicalJar();
28.282 @@ -607,12 +537,8 @@
28.283 } else {
28.284 classp.add(jar);
28.285 }
28.286 - // URLClassLoader would not otherwise find these, so:
28.287 - if (localeVariants != null) classp.addAll(localeVariants);
28.288 -
28.289 - if (localeExtensions != null) classp.addAll(localeExtensions);
28.290 -
28.291 - if (plainExtensions != null) classp.addAll(plainExtensions);
28.292 +
28.293 + ((StandardModuleData)data()).addCp(classp);
28.294
28.295 // #27853:
28.296 getManager().refineClassLoader(this, loaders);
28.297 @@ -675,6 +601,10 @@
28.298 }
28.299 return modulePermissions;
28.300 }
28.301 +
28.302 + static boolean isModuleJar(File f) {
28.303 + return moduleJARs.contains(f);
28.304 + }
28.305
28.306 /** Class loader to load a single module.
28.307 * Auto-localizing, multi-parented, permission-granting, the works.
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/o.n.bootstrap/src/org/netbeans/StandardModuleData.java Fri Mar 16 08:17:35 2012 +0100
29.3 @@ -0,0 +1,215 @@
29.4 +/*
29.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.6 + *
29.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
29.8 + *
29.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
29.10 + * Other names may be trademarks of their respective owners.
29.11 + *
29.12 + * The contents of this file are subject to the terms of either the GNU
29.13 + * General Public License Version 2 only ("GPL") or the Common
29.14 + * Development and Distribution License("CDDL") (collectively, the
29.15 + * "License"). You may not use this file except in compliance with the
29.16 + * License. You can obtain a copy of the License at
29.17 + * http://www.netbeans.org/cddl-gplv2.html
29.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.19 + * specific language governing permissions and limitations under the
29.20 + * License. When distributing the software, include this License Header
29.21 + * Notice in each file and include the License file at
29.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
29.23 + * particular file as subject to the "Classpath" exception as provided
29.24 + * by Oracle in the GPL Version 2 section of the License file that
29.25 + * accompanied this code. If applicable, add the following below the
29.26 + * License Header, with the fields enclosed by brackets [] replaced by
29.27 + * your own identifying information:
29.28 + * "Portions Copyrighted [year] [name of copyright owner]"
29.29 + *
29.30 + * If you wish your version of this file to be governed by only the CDDL
29.31 + * or only the GPL Version 2, indicate your decision by adding
29.32 + * "[Contributor] elects to include this software in this distribution
29.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
29.34 + * single choice of license, a recipient has the option to distribute
29.35 + * your version of this file under either the CDDL, the GPL Version 2 or
29.36 + * to extend the choice of license to its licensees as provided above.
29.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
29.38 + * Version 2 license, then the option applies only if the new code is
29.39 + * made subject to such option by the copyright holder.
29.40 + *
29.41 + * Contributor(s):
29.42 + *
29.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
29.44 + */
29.45 +package org.netbeans;
29.46 +
29.47 +import java.io.DataInput;
29.48 +import java.io.DataOutput;
29.49 +import java.io.File;
29.50 +import java.io.IOException;
29.51 +import java.io.ObjectInput;
29.52 +import java.io.ObjectOutput;
29.53 +import java.util.HashMap;
29.54 +import java.util.HashSet;
29.55 +import java.util.List;
29.56 +import java.util.Map;
29.57 +import java.util.Set;
29.58 +import java.util.StringTokenizer;
29.59 +import java.util.jar.Attributes;
29.60 +import java.util.jar.Manifest;
29.61 +import java.util.logging.Level;
29.62 +
29.63 +/**
29.64 + *
29.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
29.66 + */
29.67 +final class StandardModuleData extends ModuleData {
29.68 + /**
29.69 + * Map from extension JARs to sets of JAR that load them via Class-Path.
29.70 + * Used only for debugging purposes, so that a warning is printed if two
29.71 + * different modules try to load the same extension (which would cause them
29.72 + * to both load their own private copy, which may not be intended).
29.73 + */
29.74 + private static final Map<File, Set<File>> extensionOwners = new HashMap<File, Set<File>>();
29.75 + /** Set of locale-variants JARs for this module (or null).
29.76 + * Added explicitly to classloader, and can be used by execution engine.
29.77 + */
29.78 + private final Set<File> localeVariants;
29.79 + /** Set of extension JARs that this module loads via Class-Path (or null).
29.80 + * Can be used e.g. by execution engine. (#9617)
29.81 + */
29.82 + private final Set<File> plainExtensions;
29.83 + /** Set of localized extension JARs derived from plainExtensions (or null).
29.84 + * Used to add these to the classloader. (#9348)
29.85 + * Can be used e.g. by execution engine.
29.86 + */
29.87 + private final Set<File> localeExtensions;
29.88 +
29.89 +
29.90 + public StandardModuleData(Manifest mf, StandardModule forModule) throws InvalidException {
29.91 + super(mf, forModule);
29.92 + assert forModule instanceof StandardModule;
29.93 + final File jar = forModule.getJarFile();
29.94 + assert jar != null : "Cannot load extensions from classpath module " + getCodeNameBase();
29.95 + List<File> l = LocaleVariants.findLocaleVariantsOf(jar, getCodeNameBase());
29.96 + if (!l.isEmpty()) {
29.97 + localeVariants = new HashSet<File>(l);
29.98 + } else {
29.99 + localeVariants = null;
29.100 + }
29.101 + Set<File> pe = null;
29.102 + Set<File> le = null;
29.103 + String classPath = mf.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
29.104 + if (classPath != null) {
29.105 + StringTokenizer tok = new StringTokenizer(classPath);
29.106 + while (tok.hasMoreTokens()) {
29.107 + String ext = tok.nextToken();
29.108 + if (new File(ext).isAbsolute()) { // NOI18N
29.109 + Util.err.log(Level.WARNING, "Class-Path value {0} from {1} is illegal according to the Java Extension Mechanism: must be relative", new Object[]{ext, jar});
29.110 + }
29.111 + File base = jar.getParentFile();
29.112 + while (ext.startsWith("../")) {
29.113 + // cannot access FileUtil.normalizeFile from here, and URI.normalize might be unsafe for UNC paths
29.114 + ext = ext.substring(3);
29.115 + base = base.getParentFile();
29.116 + }
29.117 + File extfile = new File(base, ext.replace('/', File.separatorChar));
29.118 + //No need to sync on extensionOwners - we are in write mutex
29.119 + Set<File> owners = extensionOwners.get(extfile);
29.120 + if (owners == null) {
29.121 + owners = new HashSet<File>(2);
29.122 + owners.add(jar);
29.123 + extensionOwners.put(extfile, owners);
29.124 + } else if (!owners.contains(jar)) {
29.125 + owners.add(jar);
29.126 + forModule.getManager().getEvents().log(Events.EXTENSION_MULTIPLY_LOADED, extfile, owners);
29.127 + } // else already know about it (OK or warned)
29.128 + // Also check to make sure it is not a module JAR! See constructor for the reverse case.
29.129 + if (StandardModule.isModuleJar(extfile)) {
29.130 + Util.err.log(Level.WARNING,
29.131 + "Class-Path value {0} from {1} illegally refers to another module; use OpenIDE-Module-Module-Dependencies instead",
29.132 + new Object[]{ext, jar}
29.133 + );
29.134 + }
29.135 + if (pe == null) {
29.136 + pe = new HashSet<File>();
29.137 + }
29.138 + pe.add(extfile);
29.139 + l = LocaleVariants.findLocaleVariantsOf(extfile, getCodeNameBase());
29.140 + if (!l.isEmpty()) {
29.141 + if (le == null) {
29.142 + le = new HashSet<File>();
29.143 + }
29.144 + le.addAll(l);
29.145 + }
29.146 + }
29.147 + }
29.148 + localeExtensions = le;
29.149 + plainExtensions = pe;
29.150 +
29.151 +
29.152 + if (Util.err.isLoggable(Level.FINE)) {
29.153 + Util.err.log(Level.FINE, "localeVariants of {0}: {1}", new Object[]{jar, localeVariants});
29.154 + Util.err.log(Level.FINE, "plainExtensions of {0}: {1}", new Object[]{jar, plainExtensions});
29.155 + Util.err.log(Level.FINE, "localeExtensions of {0}: {1}", new Object[]{jar, localeExtensions});
29.156 + }
29.157 + // For the chronologically reverse case, see findExtensionsAndVariants().
29.158 + Set<File> bogoOwners = extensionOwners.get(jar);
29.159 + if (bogoOwners != null) {
29.160 + Util.err.log(Level.WARNING,
29.161 + "module {0} was incorrectly placed in the Class-Path of other JARs {1}; please use OpenIDE-Module-Module-Dependencies instead",
29.162 + new Object[]{jar, bogoOwners}
29.163 + );
29.164 + }
29.165 + }
29.166 +
29.167 + public StandardModuleData(ObjectInput dis) throws IOException {
29.168 + super(dis);
29.169 + localeVariants = readFiles(dis);
29.170 + localeExtensions = readFiles(dis);
29.171 + plainExtensions = readFiles(dis);
29.172 + }
29.173 +
29.174 + @Override
29.175 + void write(ObjectOutput dos) throws IOException {
29.176 + super.write(dos);
29.177 + writeFiles(dos, localeVariants);
29.178 + writeFiles(dos, localeExtensions);
29.179 + writeFiles(dos, plainExtensions);
29.180 + }
29.181 +
29.182 + private static Set<File> readFiles(DataInput is) throws IOException {
29.183 + int size = is.readInt();
29.184 + Set<File> set = new HashSet<File>();
29.185 + while (size-- > 0) {
29.186 + set.add(new File(Stamps.readRelativePath(is)));
29.187 + }
29.188 + return set;
29.189 + }
29.190 +
29.191 + private static void writeFiles(DataOutput os, Set<File> files) throws IOException {
29.192 + if (files == null) {
29.193 + os.writeInt(0);
29.194 + return;
29.195 + }
29.196 + os.writeInt(files.size());
29.197 + for (File f : files) {
29.198 + Stamps.writeRelativePath(f.getPath(), os);
29.199 + }
29.200 + }
29.201 +
29.202 + final void addCp(List<File> classp) {
29.203 + // URLClassLoader would not otherwise find these, so:
29.204 + if (localeVariants != null) {
29.205 + classp.addAll(localeVariants);
29.206 + }
29.207 +
29.208 + if (localeExtensions != null) {
29.209 + classp.addAll(localeExtensions);
29.210 + }
29.211 +
29.212 + if (plainExtensions != null) {
29.213 + classp.addAll(plainExtensions);
29.214 + }
29.215 +
29.216 + }
29.217 +
29.218 +}
30.1 --- a/o.n.bootstrap/test/unit/src/org/netbeans/JarClassLoaderTest.java Thu Mar 15 16:10:40 2012 +0100
30.2 +++ b/o.n.bootstrap/test/unit/src/org/netbeans/JarClassLoaderTest.java Fri Mar 16 08:17:35 2012 +0100
30.3 @@ -170,9 +170,15 @@
30.4
30.5 private void doCanLoadCached(String covPkg) throws Exception {
30.6 final File jar = new File(getWorkDir(), "default-package-resource-cached.jar");
30.7 - TestFileUtils.writeZipFile(jar, "resource.txt:content", "package/resource.txt:content", "META-INF/MANIFEST.MF:Covered-Packages: " + covPkg + ",\n");
30.8 + TestFileUtils.writeZipFile(jar, "resource.txt:content", "package/resource.txt:content",
30.9 + "META-INF/MANIFEST.MF:OpenIDE-Module: x.y.z\nCovered-Packages: " + covPkg + ",\n"
30.10 + );
30.11
30.12 - Module fake = new Module(null, null, null, null) {
30.13 + MockModuleInstaller inst = new MockModuleInstaller();
30.14 + MockEvents ev = new MockEvents();
30.15 + ModuleManager mm = new ModuleManager(inst, ev);
30.16 +
30.17 + Module fake = new Module(mm, null, null, null) {
30.18 public List<File> getAllJars() {throw new UnsupportedOperationException();}
30.19 public void setReloadable(boolean r) { throw new UnsupportedOperationException();}
30.20 public void reload() throws IOException { throw new UnsupportedOperationException();}
31.1 --- a/php.kit/manifest.mf Thu Mar 15 16:10:40 2012 +0100
31.2 +++ b/php.kit/manifest.mf Fri Mar 16 08:17:35 2012 +0100
31.3 @@ -2,4 +2,4 @@
31.4 OpenIDE-Module: org.netbeans.modules.php.kit
31.5 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/php/kit/Bundle.properties
31.6 OpenIDE-Module-Specification-Version: 1.36
31.7 -OpenIDE-Module-Recommends: org.netbeans.modules.web.client.tools.kit
31.8 +OpenIDE-Module-Recommends: org.netbeans.modules.web.client.tools.kit,org.netbeans.modules.hudson.php
32.1 --- a/remotefs.versioning/manifest.mf Thu Mar 15 16:10:40 2012 +0100
32.2 +++ b/remotefs.versioning/manifest.mf Fri Mar 16 08:17:35 2012 +0100
32.3 @@ -2,4 +2,5 @@
32.4 OpenIDE-Module: org.netbeans.modules.remotefs.versioning
32.5 OpenIDE-Module-Implementation-Version: 1
32.6 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/remotefs/versioning/Bundle.properties
32.7 +OpenIDE-Module-Provides: org.netbeans.modules.remotefs.versioning
32.8
33.1 --- a/remotefs.versioning/nbproject/project.properties Thu Mar 15 16:10:40 2012 +0100
33.2 +++ b/remotefs.versioning/nbproject/project.properties Fri Mar 16 08:17:35 2012 +0100
33.3 @@ -1,4 +1,4 @@
33.4 -is.eager=true
33.5 +is.autoload=true
33.6 javac.source=1.6
33.7 javac.compilerargs=-Xlint -Xlint:-serial
33.8 spec.version.base=1.0