KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > apisupport > project > universe > ModuleList


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.apisupport.project.universe;
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Properties JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.StringTokenizer JavaDoc;
36 import java.util.regex.Pattern JavaDoc;
37 import org.netbeans.api.project.ProjectManager;
38 import org.netbeans.modules.apisupport.project.ManifestManager;
39 import org.netbeans.modules.apisupport.project.NbModuleProjectType;
40 import org.netbeans.modules.apisupport.project.ProjectXMLManager;
41 import org.netbeans.modules.apisupport.project.Util;
42 import org.netbeans.spi.project.support.ant.PropertyEvaluator;
43 import org.netbeans.spi.project.support.ant.PropertyProvider;
44 import org.netbeans.spi.project.support.ant.PropertyUtils;
45 import org.openide.ErrorManager;
46 import org.openide.util.Mutex;
47 import org.openide.util.MutexException;
48 import org.openide.util.NbCollections;
49 import org.openide.xml.XMLUtil;
50 import org.w3c.dom.Document JavaDoc;
51 import org.w3c.dom.Element JavaDoc;
52 import org.xml.sax.InputSource JavaDoc;
53 import org.xml.sax.SAXException JavaDoc;
54
55 /**
56  * Represents list of known modules.
57  * @author Jesse Glick
58  */

59 public final class ModuleList {
60     
61     /** for performance measurement from ModuleListTest */
62     static long timeSpentInXmlParsing;
63     static int xmlFilesParsed;
64     static int directoriesChecked;
65     static int jarsOpened;
66     
67     public static final String JavaDoc DEST_DIR_IN_NETBEANS_ORG = "nbbuild" + File.separatorChar + "netbeans"; // NOI18N
68
/** Synch with org.netbeans.nbbuild.ModuleListParser.DEPTH_NB_ALL */
69     public static final int DEPTH_NB_ALL = 3;
70     
71     /**
72      * Cache of source-derived lists, by source root.
73      */

74     private static final Map JavaDoc<File JavaDoc,ModuleList> sourceLists = new HashMap JavaDoc();
75     /**
76      * Cache of binary-derived lists, by binary root (~ dest dir).
77      */

78     private static final Map JavaDoc<File JavaDoc,ModuleList> binaryLists = new HashMap JavaDoc();
79     /**
80      * Map from netbeans.org source roots to cluster.properties loads.
81      */

82     private static final Map JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,String JavaDoc>> clusterPropertiesFiles = new HashMap JavaDoc();
83     /**
84      * Map from netbeans.org source roots, to cluster definitions,
85      * where a cluster definition is from netbeans.org relative source path
86      * to physical cluster directory.
87      */

88     private static final Map JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,String JavaDoc>> clusterLocations = new HashMap JavaDoc();
89     
90     /** All entries known to exist for a given included file path. */
91     private static final Map JavaDoc<File JavaDoc,Set JavaDoc<ModuleEntry>> knownEntries = new HashMap JavaDoc();
92
93     /**
94      * Find the list of modules associated with a project (itself, others in
95      * its suite, others in its platform, or others in netbeans.org). <p>Do not
96      * cache the result; always call this method fresh, in case {@link
97      * #refresh} has been called. This method actually call {@link
98      * #getModuleList(File, File)} with the <code>null</code> for the
99      * <code>customNbDestDir</code> parameter.
100      *
101      * @param basedir the project directory to start in
102      * @return a module list
103      */

104     public static ModuleList getModuleList(File JavaDoc basedir) throws IOException JavaDoc {
105         return getModuleList(basedir, null);
106     }
107     
108     /**
109      * The same as {@link #getModuleList(File)}, but giving chance to specify a
110      * custom NetBeans platform.
111      *
112      * @param basedir the project directory to start in
113      * @param customNbDestDir custom NetBeans platform directory to be used for
114      * searching NB module instead of using the currently set one in a
115      * module's properties. If <code>null</code> is passed the
116      * default(active) platform from module's properties will be used
117      * @return a module list
118      */

119     public static ModuleList getModuleList(final File JavaDoc basedir, final File JavaDoc customNbDestDir) throws IOException JavaDoc {
120         try {
121             return (ModuleList) ProjectManager.mutex().readAccess(new Mutex.ExceptionAction() { // #69971
122
public Object JavaDoc run() throws IOException JavaDoc {
123                     synchronized (binaryLists) { // need to protect caches from race conditions, so this seems OK
124
timeSpentInXmlParsing = 0L;
125         xmlFilesParsed = 0;
126         directoriesChecked = 0;
127         jarsOpened = 0;
128         Element JavaDoc data = parseData(basedir);
129         if (data == null) {
130             throw new IOException JavaDoc("Not an NBM project in " + basedir); // NOI18N
131
}
132         boolean suiteComponent = Util.findElement(data, "suite-component", NbModuleProjectType.NAMESPACE_SHARED) != null; // NOI18N
133
boolean standalone = Util.findElement(data, "standalone", NbModuleProjectType.NAMESPACE_SHARED) != null; // NOI18N
134
assert !(suiteComponent && standalone) : basedir;
135         if (suiteComponent) {
136             PropertyEvaluator eval = parseProperties(basedir, null, true, false, "irrelevant"); // NOI18N
137
String JavaDoc suiteS = eval.getProperty("suite.dir");
138             if (suiteS == null) {
139                 throw new IOException JavaDoc("No suite.dir defined from " + basedir); // NOI18N
140
}
141             File JavaDoc suite = PropertyUtils.resolveFile(basedir, suiteS);
142             return findOrCreateModuleListFromSuite(suite, customNbDestDir);
143         } else if (standalone) {
144             return findOrCreateModuleListFromStandaloneModule(basedir, customNbDestDir);
145         } else {
146             // netbeans.org module.
147
File JavaDoc nbroot = findNetBeansOrg(basedir);
148             if (nbroot == null) {
149                 throw new IOException JavaDoc("Could not find netbeans.org CVS root from " + basedir + "; note that 3rd-level modules (a/b/c) are permitted at the maximum"); // NOI18N
150
}
151             return findOrCreateModuleListFromNetBeansOrgSources(nbroot);
152         }
153                     }
154                 }
155             });
156         } catch (MutexException e) {
157             throw (IOException JavaDoc) e.getException();
158         }
159     }
160     
161     /**
162      * Check to see if there are <em>any</em> known module list entries.
163      * @return false if {@link #getKnownEntries} cannot return a nonempty set at the moment, true if it might
164      */

165     public static boolean existKnownEntries() {
166         synchronized (knownEntries) {
167             return !knownEntries.isEmpty();
168         }
169     }
170     
171     /**
172      * Find the known module entries which build to a given built file path (e.g. module JAR).
173      * Applies to any entries which have been scanned.
174      * @param file some file built as part of the module
175      * @return a set of entries thought to build to this file (may be empty but not null)
176      */

177     public static Set JavaDoc<ModuleEntry> getKnownEntries(File JavaDoc file) {
178         synchronized (knownEntries) {
179             Set JavaDoc<ModuleEntry> entries = (Set JavaDoc) knownEntries.get(file);
180             if (entries != null) {
181                 return new HashSet JavaDoc(entries);
182             } else {
183                 return Collections.EMPTY_SET;
184             }
185         }
186     }
187     
188     private static void registerEntry(ModuleEntry entry, Set JavaDoc<File JavaDoc> files) {
189         synchronized (knownEntries) {
190             Iterator JavaDoc it = files.iterator();
191             while (it.hasNext()) {
192                 File JavaDoc f = (File JavaDoc) it.next();
193                 Set JavaDoc<ModuleEntry> entries = (Set JavaDoc) knownEntries.get(f);
194                 if (entries == null) {
195                     entries = new HashSet JavaDoc();
196                     knownEntries.put(f, entries);
197                 }
198                 entries.add(entry);
199             }
200         }
201     }
202     
203     static ModuleList findOrCreateModuleListFromNetBeansOrgSources(File JavaDoc root) throws IOException JavaDoc {
204         ModuleList list = (ModuleList) sourceLists.get(root);
205         if (list == null) {
206             list = createModuleListFromNetBeansOrgSources(root);
207             sourceLists.put(root, list);
208         }
209         return list;
210     }
211     
212     private static ModuleList createModuleListFromNetBeansOrgSources(File JavaDoc root) throws IOException JavaDoc {
213         Util.err.log("ModuleList.createModuleListFromSources: " + root);
214         File JavaDoc nbdestdir = new File JavaDoc(root, DEST_DIR_IN_NETBEANS_ORG);
215         Map JavaDoc<String JavaDoc,ModuleEntry> entries = new HashMap JavaDoc();
216         scanNetBeansOrgStableSources(entries, root, nbdestdir);
217         return new ModuleList(entries, root, true);
218     }
219     
220     /**
221      * Look just for stable modules in netbeans.org, assuming that this is most commonly what is wanted.
222      * @see "#62221"
223      */

224     private static void scanNetBeansOrgStableSources(Map JavaDoc<String JavaDoc,ModuleEntry> entries, File JavaDoc root, File JavaDoc nbdestdir) throws IOException JavaDoc {
225         Map JavaDoc<String JavaDoc,String JavaDoc> clusterProps = getClusterProperties(root);
226         // Use ${clusters.list}, *not* ${nb.clusters.list}: we do want to include testtools,
227
// since those modules contribute sources for JARs which are used in unit test classpaths for stable modules.
228
String JavaDoc clusterList = (String JavaDoc) clusterProps.get("clusters.list"); // NOI18N
229
if (clusterList == null) {
230             throw new IOException JavaDoc("No ${nb.clusters.list} found in " + root); // NOI18N
231
}
232         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(clusterList, ", "); // NOI18N
233
while (tok.hasMoreTokens()) {
234             String JavaDoc clusterName = tok.nextToken();
235             String JavaDoc moduleList = (String JavaDoc) clusterProps.get(clusterName);
236             if (moduleList == null) {
237                 throw new IOException JavaDoc("No ${" + clusterName + "} found in " + root); // NOI18N
238
}
239             StringTokenizer JavaDoc tok2 = new StringTokenizer JavaDoc(moduleList, ", "); // NOI18N
240
while (tok2.hasMoreTokens()) {
241                 String JavaDoc module = tok2.nextToken();
242                 scanPossibleProject(new File JavaDoc(root, module.replace('/', File.separatorChar)), entries, false, false, root, nbdestdir, module, true);
243             }
244         }
245     }
246     
247     public static final Set JavaDoc<String JavaDoc> EXCLUDED_DIR_NAMES = new HashSet JavaDoc();
248     static {
249         EXCLUDED_DIR_NAMES.add("CVS"); // NOI18N
250
EXCLUDED_DIR_NAMES.add("nbproject"); // NOI18N
251
EXCLUDED_DIR_NAMES.add("www"); // NOI18N
252
EXCLUDED_DIR_NAMES.add("test"); // NOI18N
253
EXCLUDED_DIR_NAMES.add("build"); // NOI18N
254
EXCLUDED_DIR_NAMES.add("src"); // NOI18N
255
EXCLUDED_DIR_NAMES.add("org"); // NOI18N
256
}
257     private static void doScanNetBeansOrgSources(Map JavaDoc<String JavaDoc,ModuleEntry> entries, File JavaDoc dir, int depth,
258             File JavaDoc root, File JavaDoc nbdestdir, String JavaDoc pathPrefix, boolean warnReDuplicates) {
259         File JavaDoc[] kids = dir.listFiles();
260         if (kids == null) {
261             return;
262         }
263         for (int i = 0; i < kids.length; i++) {
264             if (!kids[i].isDirectory()) {
265                 continue;
266             }
267             String JavaDoc name = kids[i].getName();
268             if (EXCLUDED_DIR_NAMES.contains(name)) {
269                 // #61579: known to not be project dirs, so skip to save time.
270
continue;
271             }
272             String JavaDoc newPathPrefix = (pathPrefix != null) ? pathPrefix + "/" + name : name; // NOI18N
273
try {
274                 scanPossibleProject(kids[i], entries, false, false, root, nbdestdir, newPathPrefix, warnReDuplicates);
275             } catch (IOException JavaDoc e) {
276                 // #60295: make it nonfatal.
277
Util.err.annotate(e, ErrorManager.UNKNOWN, "Malformed project metadata in " + kids[i] + ", skipping...", null, null, null); // NOI18N
278
Util.err.notify(ErrorManager.INFORMATIONAL, e);
279             }
280             if (depth > 1) {
281                 doScanNetBeansOrgSources(entries, kids[i], depth - 1, root, nbdestdir, newPathPrefix, warnReDuplicates);
282             }
283         }
284     }
285     
286     private static void scanPossibleProject(File JavaDoc basedir, Map JavaDoc<String JavaDoc,ModuleEntry> entries,
287             boolean suiteComponent, boolean standalone, File JavaDoc root, File JavaDoc nbdestdir, String JavaDoc path, boolean warnReDuplicates) throws IOException JavaDoc {
288         directoriesChecked++;
289         Element JavaDoc data = parseData(basedir);
290         if (data == null) {
291             return;
292         }
293         assert root != null ^ (standalone || suiteComponent);
294         assert path != null ^ (standalone || suiteComponent);
295         String JavaDoc cnb = Util.findText(Util.findElement(data, "code-name-base", NbModuleProjectType.NAMESPACE_SHARED)); // NOI18N
296
PropertyEvaluator eval = parseProperties(basedir, root, suiteComponent, standalone, cnb);
297         String JavaDoc module = eval.getProperty("module.jar"); // NOI18N
298
// Cf. ParseProjectXml.computeClasspath:
299
StringBuffer JavaDoc cpextra = new StringBuffer JavaDoc();
300         Iterator JavaDoc<Element JavaDoc> exts = Util.findSubElements(data).iterator();
301         while (exts.hasNext()) {
302             Element JavaDoc ext = (Element JavaDoc) exts.next();
303             if (!ext.getLocalName().equals("class-path-extension")) { // NOI18N
304
continue;
305             }
306             Element JavaDoc binaryOrigin = Util.findElement(ext, "binary-origin", NbModuleProjectType.NAMESPACE_SHARED); // NOI18N
307
String JavaDoc text;
308             if (binaryOrigin != null) {
309                 text = Util.findText(binaryOrigin);
310             } else {
311                 Element JavaDoc runtimeRelativePath = Util.findElement(ext, "runtime-relative-path", NbModuleProjectType.NAMESPACE_SHARED); // NOI18N
312
assert runtimeRelativePath != null : "Malformed <class-path-extension> in " + basedir;
313                 String JavaDoc reltext = Util.findText(runtimeRelativePath);
314                 // XXX assumes that module.jar is not overridden independently of module.jar.dir:
315
text = "${cluster}/${module.jar.dir}/" + reltext; // NOI18N
316
}
317             String JavaDoc evaluated = eval.evaluate(text);
318             if (evaluated == null) {
319                 continue;
320             }
321             File JavaDoc binary = PropertyUtils.resolveFile(basedir, evaluated);
322             cpextra.append(':');
323             cpextra.append(binary.getAbsolutePath());
324         }
325         File JavaDoc manifest = new File JavaDoc(basedir, "manifest.mf"); // NOI18N
326
ManifestManager mm = (manifest.isFile() ?
327             ManifestManager.getInstance(manifest, false) : ManifestManager.NULL_INSTANCE);
328         File JavaDoc clusterDir = PropertyUtils.resolveFile(basedir, eval.evaluate("${cluster}")); // NOI18N
329
ModuleEntry entry;
330         ManifestManager.PackageExport[] publicPackages = ProjectXMLManager.findPublicPackages(data);
331         String JavaDoc[] friends = ProjectXMLManager.findFriends(data);
332         if (!suiteComponent && !standalone) {
333             entry = new NetBeansOrgEntry(root, cnb, path, clusterDir, module, cpextra.toString(),
334                     mm.getReleaseVersion(), mm.getProvidedTokens(),
335                     publicPackages, friends, mm.isDeprecated());
336         } else {
337             entry = new ExternalEntry(basedir, cnb, clusterDir, PropertyUtils.resolveFile(clusterDir, module),
338                     cpextra.toString(), nbdestdir, mm.getReleaseVersion(),
339                     mm.getProvidedTokens(), publicPackages, friends, mm.isDeprecated());
340         }
341         if (entries.containsKey(cnb)) {
342             if (warnReDuplicates) {
343                 Util.err.log(ErrorManager.WARNING, "Warning: two modules found with the same code name base (" + cnb + "): " + entries.get(cnb) + " and " + entry);
344             }
345         } else {
346             entries.put(cnb, entry);
347         }
348         registerEntry(entry, findSourceNBMFiles(entry, eval));
349     }
350     
351     /**
352      * Look for files to be included in the NBM.
353      * Some stock entries are always present: the module JAR, update_tracking/*.xml, config/Modules/*.xml,
354      * config/ModuleAutoDeps/*.xml, ant/nblib/*.jar, modules/docs/*.jar (cf. common.xml#files-init).
355      * Additionally, ${extra.module.files} if defined is parsed. Literal entries (no wildcards) are
356      * always included; entries with Ant-style wildcards are included if matches can be found on disk.
357      * And anything in the release/ directory is added.
358      */

359     private static Set JavaDoc<File JavaDoc> findSourceNBMFiles(ModuleEntry entry, PropertyEvaluator eval) throws IOException JavaDoc {
360         Set JavaDoc<File JavaDoc> files = new HashSet JavaDoc();
361         files.add(entry.getJarLocation());
362         File JavaDoc cluster = entry.getClusterDirectory();
363         String JavaDoc cnbd = entry.getCodeNameBase().replace('.', '-');
364         String JavaDoc[] STANDARD_FILES = {
365             "update_tracking/*.xml", // NOI18N
366
"config/Modules/*.xml", // NOI18N
367
"config/ModuleAutoDeps/*.xml", // NOI18N
368
"ant/nblib/*.jar", // NOI18N
369
"modules/docs/*.jar", // NOI18N
370
};
371         for (int i = 0; i < STANDARD_FILES.length; i++) {
372             int x = STANDARD_FILES[i].indexOf('*');
373             findSourceNBMFilesMaybeAdd(files, cluster, STANDARD_FILES[i].substring(0, x) + cnbd + STANDARD_FILES[i].substring(x + 1));
374         }
375         String JavaDoc emf = eval.getProperty("extra.module.files"); // NOI18N
376
if (emf != null) {
377             String JavaDoc[] entries = emf.split(" *, *"); // NOI18N
378
for (int i = 0; i < entries.length; i++) {
379                 String JavaDoc pattern = entries[i];
380                 if (pattern.endsWith("/")) { // NOI18N
381
// Shorthand for /**
382
pattern += "**"; // NOI18N
383
}
384                 if (pattern.indexOf('*') == -1) {
385                     // Literal file location relative to cluster dir.
386
findSourceNBMFilesMaybeAdd(files, cluster, pattern);
387                 } else {
388                     // Wildcard. Convert to regexp and do a brute-force search.
389
// Not the most efficient option but should probably suffice.
390
String JavaDoc regex = "\\Q" + pattern.replaceAll("\\*\\*", "__DBLASTERISK__"). // NOI18N
391
replaceAll("\\*", "\\\\E[^/]*\\\\Q"). // NOI18N
392
replaceAll("__DBLASTERISK__", "\\\\E.*\\\\Q") + "\\E"; // NOI18N
393
Pattern JavaDoc regexp = Pattern.compile(regex);
394                     String JavaDoc[] clusterFiles = scanDirForFiles(cluster);
395                     for (int j = 0; j < clusterFiles.length; j++) {
396                         if (regexp.matcher(clusterFiles[j]).matches()) {
397                             findSourceNBMFilesMaybeAdd(files, cluster, clusterFiles[j]);
398                         }
399                     }
400                 }
401             }
402         }
403         File JavaDoc src = entry.getSourceLocation();
404         assert src != null && src.isDirectory() : entry;
405         // XXX handle overrides of release.dir
406
File JavaDoc releaseDir = new File JavaDoc(src, "release"); // NOI18N
407
if (releaseDir.isDirectory()) {
408             String JavaDoc[] releaseFiles = scanDirForFiles(releaseDir);
409             for (int i = 0; i < releaseFiles.length; i++) {
410                 findSourceNBMFilesMaybeAdd(files, cluster, releaseFiles[i]);
411             }
412         }
413         return files;
414     }
415     private static void findSourceNBMFilesMaybeAdd(Set JavaDoc<File JavaDoc> files, File JavaDoc cluster, String JavaDoc path) {
416         File JavaDoc f = new File JavaDoc(cluster, path.replace('/', File.separatorChar));
417         files.add(f);
418     }
419     private static final Map JavaDoc<File JavaDoc,String JavaDoc[]> DIR_SCAN_CACHE = new HashMap JavaDoc();
420     private static String JavaDoc[] scanDirForFiles(File JavaDoc dir) {
421         String JavaDoc[] files = DIR_SCAN_CACHE.get(dir);
422         if (files == null) {
423             List JavaDoc<String JavaDoc> l = new ArrayList JavaDoc(250);
424             doScanDirForFiles(dir, l, "");
425             files = l.toArray(new String JavaDoc[l.size()]);
426         }
427         return files;
428     }
429     private static void doScanDirForFiles(File JavaDoc d, List JavaDoc<String JavaDoc> files, String JavaDoc prefix) {
430         directoriesChecked++;
431         File JavaDoc[] kids = d.listFiles();
432         if (kids != null) {
433             for (int i = 0; i < kids.length; i++) {
434                 File JavaDoc f = kids[i];
435                 if (f.isFile()) {
436                     files.add(prefix + f.getName());
437                 } else if (f.isDirectory()) {
438                     doScanDirForFiles(f, files, prefix + f.getName() + '/');
439                 }
440             }
441         }
442     }
443     
444     public static ModuleList findOrCreateModuleListFromSuite(
445             File JavaDoc root, File JavaDoc customNbDestDir) throws IOException JavaDoc {
446         PropertyEvaluator eval = parseSuiteProperties(root);
447         File JavaDoc nbdestdir;
448         if (customNbDestDir == null) {
449             String JavaDoc nbdestdirS = eval.getProperty("netbeans.dest.dir"); // NOI18N
450
if (nbdestdirS == null) {
451                 throw new IOException JavaDoc("No netbeans.dest.dir defined in " + root); // NOI18N
452
}
453             nbdestdir = PropertyUtils.resolveFile(root, nbdestdirS);
454         } else {
455             nbdestdir = customNbDestDir;
456         }
457         return merge(new ModuleList[] {
458             findOrCreateModuleListFromSuiteWithoutBinaries(root, nbdestdir, eval),
459             findOrCreateModuleListFromBinaries(nbdestdir),
460         }, root);
461     }
462     
463     private static ModuleList findOrCreateModuleListFromSuiteWithoutBinaries(File JavaDoc root, File JavaDoc nbdestdir, PropertyEvaluator eval) throws IOException JavaDoc {
464         ModuleList sources = (ModuleList) sourceLists.get(root);
465         if (sources == null) {
466             Map JavaDoc<String JavaDoc,ModuleEntry> entries = new HashMap JavaDoc();
467             File JavaDoc[] modules = findModulesInSuite(root, eval);
468             for (int i = 0; i < modules.length; i++) {
469                 try {
470                     scanPossibleProject(modules[i], entries, true, false, null, nbdestdir, null, true);
471                 } catch (IOException JavaDoc e) {
472                     Util.err.annotate(e, ErrorManager.UNKNOWN, "Malformed project metadata in " + modules[i] + ", skipping...", null, null, null); // NOI18N
473
Util.err.notify(ErrorManager.INFORMATIONAL, e);
474                 }
475             }
476             sources = new ModuleList(entries, root, false);
477             sourceLists.put(root, sources);
478         }
479         return sources;
480     }
481     
482     static ModuleList findOrCreateModuleListFromSuiteWithoutBinaries(File JavaDoc root) throws IOException JavaDoc {
483         PropertyEvaluator eval = parseSuiteProperties(root);
484         String JavaDoc nbdestdirS = eval.getProperty("netbeans.dest.dir"); // NOI18N
485
if (nbdestdirS == null) {
486             throw new IOException JavaDoc("No netbeans.dest.dir defined in " + root); // NOI18N
487
}
488         File JavaDoc nbdestdir = PropertyUtils.resolveFile(root, nbdestdirS);
489         return findOrCreateModuleListFromSuiteWithoutBinaries(root, nbdestdir, eval);
490     }
491     
492     private static PropertyEvaluator parseSuiteProperties(File JavaDoc root) throws IOException JavaDoc {
493         Map JavaDoc<String JavaDoc,String JavaDoc> predefs = new HashMap JavaDoc(System.getProperties());
494         predefs.put("basedir", root.getAbsolutePath()); // NOI18N
495
PropertyProvider predefsProvider = PropertyUtils.fixedPropertyProvider(predefs);
496         List JavaDoc<PropertyProvider> providers = new ArrayList JavaDoc();
497         providers.add(loadPropertiesFile(new File JavaDoc(root, "nbproject" + File.separatorChar + "private" + File.separatorChar + "platform-private.properties"))); // NOI18N
498
providers.add(loadPropertiesFile(new File JavaDoc(root, "nbproject" + File.separatorChar + "platform.properties"))); // NOI18N
499
PropertyEvaluator eval = PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
500         String JavaDoc buildS = eval.getProperty("user.properties.file"); // NOI18N
501
if (buildS != null) {
502             providers.add(loadPropertiesFile(PropertyUtils.resolveFile(root, buildS)));
503         } else {
504             // Never been opened, perhaps - so fake it.
505
providers.add(PropertyUtils.globalPropertyProvider());
506         }
507         providers.add(loadPropertiesFile(new File JavaDoc(root, "nbproject" + File.separatorChar + "private" + File.separatorChar + "private.properties"))); // NOI18N
508
providers.add(loadPropertiesFile(new File JavaDoc(root, "nbproject" + File.separatorChar + "project.properties"))); // NOI18N
509
eval = PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
510         String JavaDoc platformS = eval.getProperty("nbplatform.active"); // NOI18N
511
if (platformS != null) {
512             providers.add(PropertyUtils.fixedPropertyProvider(Collections.singletonMap("netbeans.dest.dir", "${nbplatform." + platformS + ".netbeans.dest.dir}"))); // NOI18N
513
}
514         return PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
515     }
516     
517     static File JavaDoc[] findModulesInSuite(File JavaDoc root) throws IOException JavaDoc {
518         return findModulesInSuite(root, parseSuiteProperties(root));
519     }
520     
521     private static File JavaDoc[] findModulesInSuite(File JavaDoc root, PropertyEvaluator eval) throws IOException JavaDoc {
522         String JavaDoc modulesS = eval.getProperty("modules"); // NOI18N
523
if (modulesS == null) {
524             modulesS = ""; // NOI18N
525
}
526         String JavaDoc[] modulesA = PropertyUtils.tokenizePath(modulesS);
527         File JavaDoc[] modules = new File JavaDoc[modulesA.length];
528         for (int i = 0; i < modulesA.length; i++) {
529             modules[i] = PropertyUtils.resolveFile(root, modulesA[i]);
530         }
531         return modules;
532     }
533     
534     private static ModuleList findOrCreateModuleListFromStandaloneModule(
535             File JavaDoc basedir, File JavaDoc customNbDestDir) throws IOException JavaDoc {
536         PropertyEvaluator eval = parseProperties(basedir, null, false, true, "irrelevant"); // NOI18N
537
File JavaDoc nbdestdir;
538         if (customNbDestDir == null) {
539             String JavaDoc nbdestdirS = eval.getProperty("netbeans.dest.dir"); // NOI18N
540
if (nbdestdirS == null) {
541                 throw new IOException JavaDoc("No netbeans.dest.dir defined in " + basedir); // NOI18N
542
}
543             if (nbdestdirS.indexOf("${") != -1) { // NOI18N
544
throw new IOException JavaDoc("Unevaluated properties in " + nbdestdirS + " from " + basedir + "; probably means platform definitions not loaded correctly"); // NOI18N
545
}
546             nbdestdir = PropertyUtils.resolveFile(basedir, nbdestdirS);
547         } else {
548             nbdestdir = customNbDestDir;
549         }
550         ModuleList binaries = findOrCreateModuleListFromBinaries(nbdestdir);
551         ModuleList sources = (ModuleList) sourceLists.get(basedir);
552         if (sources == null) {
553             Map JavaDoc<String JavaDoc,ModuleEntry> entries = new HashMap JavaDoc();
554             scanPossibleProject(basedir, entries, false, true, null, nbdestdir, null, true);
555             if (entries.isEmpty()) {
556                 throw new IOException JavaDoc("No module in " + basedir); // NOI18N
557
}
558             sources = new ModuleList(entries, basedir, false);
559             sourceLists.put(basedir, sources);
560         }
561         return merge(new ModuleList[] {sources, binaries}, basedir);
562     }
563     
564     static ModuleList findOrCreateModuleListFromBinaries(File JavaDoc root) throws IOException JavaDoc {
565         ModuleList list = (ModuleList) binaryLists.get(root);
566         if (list == null) {
567             list = createModuleListFromBinaries(root);
568             binaryLists.put(root, list);
569         }
570         return list;
571     }
572     
573     private static final String JavaDoc[] MODULE_DIRS = {
574         "modules", // NOI18N
575
"modules/eager", // NOI18N
576
"modules/autoload", // NOI18N
577
"lib", // NOI18N
578
"core", // NOI18N
579
};
580     private static ModuleList createModuleListFromBinaries(File JavaDoc root) throws IOException JavaDoc {
581         Util.err.log("ModuleList.createModuleListFromBinaries: " + root);
582         // Loosely copied from o.n.nbbuild.ModuleListParser
583
Map JavaDoc<String JavaDoc,ModuleEntry> entries = new HashMap JavaDoc();
584         File JavaDoc[] clusters = root.listFiles();
585         if (clusters == null) {
586             throw new IOException JavaDoc("Cannot examine dir " + root); // NOI18N
587
}
588         for (int i = 0; i < clusters.length; i++) {
589             for (int j = 0; j < MODULE_DIRS.length; j++) {
590                 File JavaDoc dir = new File JavaDoc(clusters[i], MODULE_DIRS[j].replace('/', File.separatorChar));
591                 if (!dir.isDirectory()) {
592                     continue;
593                 }
594                 File JavaDoc[] jars = dir.listFiles();
595                 if (jars == null) {
596                     throw new IOException JavaDoc("Cannot examine dir " + dir); // NOI18N
597
}
598                 for (int k = 0; k < jars.length; k++) {
599                     File JavaDoc m = jars[k];
600                     if (!m.getName().endsWith(".jar")) { // NOI18N
601
continue;
602                     }
603                     jarsOpened++;
604                     ManifestManager mm = ManifestManager.getInstanceFromJAR(m);
605                     String JavaDoc codenamebase = mm.getCodeNameBase();
606                     if (codenamebase == null) {
607                         continue;
608                     }
609                     String JavaDoc cp = mm.getClassPath();
610                     File JavaDoc[] exts;
611                     if (cp == null) {
612                         exts = new File JavaDoc[0];
613                     } else {
614                         String JavaDoc[] pieces = cp.trim().split(" +"); // NOI18N
615
exts = new File JavaDoc[pieces.length];
616                         for (int l = 0; l < pieces.length; l++) {
617                             exts[l] = new File JavaDoc(dir, pieces[l].replace('/', File.separatorChar));
618                         }
619                     }
620                     ModuleEntry entry = new BinaryEntry(codenamebase, m, exts, root, clusters[i],
621                             mm.getReleaseVersion(), mm.getSpecificationVersion(), mm.getProvidedTokens(),
622                             mm.getPublicPackages(), mm.getFriends(), mm.isDeprecated(), mm.getModuleDependencies());
623                     if (entries.containsKey(codenamebase)) {
624                         Util.err.log(ErrorManager.WARNING, "Warning: two modules found with the same code name base (" + codenamebase + "): " + entries.get(codenamebase) + " and " + entry);
625                     } else {
626                         entries.put(codenamebase, entry);
627                     }
628                     registerEntry(entry, findBinaryNBMFiles(clusters[i], codenamebase, m));
629                 }
630             }
631         }
632         return new ModuleList(entries, root, false);
633     }
634     
635     /**
636      * Try to find which files are part of a module's binary build (i.e. slated for NBM).
637      * Tries to scan update tracking for the file, but also always adds in the module JAR
638      * as a fallback (since this is the most important file for various purposes).
639      * Note that update_tracking/*.xml is added as well as files it lists.
640      */

641     private static Set JavaDoc<File JavaDoc> findBinaryNBMFiles(File JavaDoc cluster, String JavaDoc cnb, File JavaDoc jar) throws IOException JavaDoc {
642         Set JavaDoc<File JavaDoc> files = new HashSet JavaDoc();
643         files.add(jar);
644         File JavaDoc tracking = new File JavaDoc(new File JavaDoc(cluster, "update_tracking"), cnb.replace('.', '-') + ".xml"); // NOI18N
645
if (tracking.isFile()) {
646             files.add(tracking);
647             Document JavaDoc doc;
648             try {
649                 xmlFilesParsed++;
650                 timeSpentInXmlParsing -= System.currentTimeMillis();
651                 doc = XMLUtil.parse(new InputSource JavaDoc(tracking.toURI().toString()), false, false, null, null);
652                 timeSpentInXmlParsing += System.currentTimeMillis();
653             } catch (SAXException JavaDoc e) {
654                 throw (IOException JavaDoc) new IOException JavaDoc(e.toString()).initCause(e);
655             }
656             Iterator JavaDoc it = Util.findSubElements(doc.getDocumentElement()).iterator();
657             while (it.hasNext()) {
658                 Element JavaDoc moduleVersion = (Element JavaDoc) it.next();
659                 if (moduleVersion.getTagName().equals("module_version") && moduleVersion.getAttribute("last").equals("true")) { // NOI18N
660
Iterator JavaDoc it2 = Util.findSubElements(moduleVersion).iterator();
661                     while (it2.hasNext()) {
662                         Element JavaDoc fileEl = (Element JavaDoc) it2.next();
663                         if (fileEl.getTagName().equals("file")) { // NOI18N
664
String JavaDoc name = fileEl.getAttribute("name"); // NOI18N
665
File JavaDoc f = new File JavaDoc(cluster, name.replace('/', File.separatorChar));
666                             if (f.isFile()) {
667                                 files.add(f);
668                             }
669                         }
670                     }
671                 }
672             }
673         }
674         return files;
675     }
676     
677     private static final String JavaDoc PROJECT_XML = "nbproject" + File.separatorChar + "project.xml"; // NOI18N
678
/**
679      * Load a project.xml from a project.
680      * @param basedir a putative project base directory
681      * @return its primary configuration data (if there is an NBM project here), else null
682      */

683     static Element JavaDoc parseData(File JavaDoc basedir) throws IOException JavaDoc {
684         File JavaDoc projectXml = new File JavaDoc(basedir, PROJECT_XML);
685         // #61579: tboudreau claims File.exists is much cheaper on some systems
686
//System.err.println("parseData: " + basedir);
687
if (!projectXml.exists() || !projectXml.isFile()) {
688             return null;
689         }
690         Document JavaDoc doc;
691         try {
692             xmlFilesParsed++;
693             timeSpentInXmlParsing -= System.currentTimeMillis();
694             doc = XMLUtil.parse(new InputSource JavaDoc(projectXml.toURI().toString()), false, true, null, null);
695             timeSpentInXmlParsing += System.currentTimeMillis();
696         } catch (SAXException JavaDoc e) {
697             throw (IOException JavaDoc) new IOException JavaDoc(projectXml + ": " + e.toString()).initCause(e); // NOI18N
698
}
699         Element JavaDoc docel = doc.getDocumentElement();
700         Element JavaDoc type = Util.findElement(docel, "type", "http://www.netbeans.org/ns/project/1"); // NOI18N
701
if (!Util.findText(type).equals("org.netbeans.modules.apisupport.project")) { // NOI18N
702
return null;
703         }
704         Element JavaDoc cfg = Util.findElement(docel, "configuration", "http://www.netbeans.org/ns/project/1"); // NOI18N
705
Element JavaDoc data = Util.findElement(cfg, "data", NbModuleProjectType.NAMESPACE_SHARED); // NOI18N
706
if (data != null) {
707             return data;
708         } else {
709             data = Util.findElement(cfg, "data", NbModuleProjectType.NAMESPACE_SHARED_2); // NOI18N
710
if (data != null) {
711                 return Util.translateXML(data, NbModuleProjectType.NAMESPACE_SHARED);
712             } else {
713                 return null;
714             }
715         }
716     }
717     
718     /**
719      * Load properties for a project.
720      * Only deals with certain properties of interest here (all file-type values assumed relative to basedir):
721      * netbeans.dest.dir (file-valued)
722      * module.jar (plain string)
723      * module.jar.dir (plain string)
724      * cluster (file-valued)
725      * suite.dir (file-valued)
726      * @param basedir project basedir
727      * @param root root of sources (netbeans.org only)
728      * @param suiteComponent whether this is an external module in a suite
729      * @param standalone whether this is an external standalone module
730      * @param cnb code name base of this project
731      */

732     static PropertyEvaluator parseProperties(File JavaDoc basedir, File JavaDoc root, boolean suiteComponent, boolean standalone, String JavaDoc cnb) throws IOException JavaDoc {
733         assert !(suiteComponent && standalone) : basedir;
734         Map JavaDoc<String JavaDoc,String JavaDoc> predefs = new HashMap JavaDoc(System.getProperties());
735         predefs.put("basedir", basedir.getAbsolutePath()); // NOI18N
736
PropertyProvider predefsProvider = PropertyUtils.fixedPropertyProvider(predefs);
737         List JavaDoc<PropertyProvider> providers = new ArrayList JavaDoc();
738         if (suiteComponent) {
739             providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "private" + File.separatorChar + "suite-private.properties"))); // NOI18N
740
providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "suite.properties"))); // NOI18N
741
PropertyEvaluator eval = PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
742             String JavaDoc suiteS = eval.getProperty("suite.dir"); // NOI18N
743
if (suiteS != null) {
744                 File JavaDoc suite = PropertyUtils.resolveFile(basedir, suiteS);
745                 providers.add(loadPropertiesFile(new File JavaDoc(suite, "nbproject" + File.separatorChar + "private" + File.separatorChar + "platform-private.properties"))); // NOI18N
746
providers.add(loadPropertiesFile(new File JavaDoc(suite, "nbproject" + File.separatorChar + "platform.properties"))); // NOI18N
747
}
748         } else if (standalone) {
749             providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "private" + File.separatorChar + "platform-private.properties"))); // NOI18N
750
providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "platform.properties"))); // NOI18N
751
}
752         if (suiteComponent || standalone) {
753             PropertyEvaluator eval = PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
754             String JavaDoc buildS = eval.getProperty("user.properties.file"); // NOI18N
755
if (buildS != null) {
756                 providers.add(loadPropertiesFile(PropertyUtils.resolveFile(basedir, buildS)));
757             } else {
758                 providers.add(PropertyUtils.globalPropertyProvider());
759             }
760             eval = PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
761             String JavaDoc platformS = eval.getProperty("nbplatform.active"); // NOI18N
762
if (platformS != null) {
763                 providers.add(PropertyUtils.fixedPropertyProvider(Collections.singletonMap("netbeans.dest.dir", "${nbplatform." + platformS + ".netbeans.dest.dir}"))); // NOI18N
764
}
765         }
766         // private.properties & project.properties.
767
providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "private" + File.separatorChar + "private.properties"))); // NOI18N
768
providers.add(loadPropertiesFile(new File JavaDoc(basedir, "nbproject" + File.separatorChar + "project.properties"))); // NOI18N
769
// Implicit stuff.
770
Map JavaDoc<String JavaDoc,String JavaDoc> defaults = new HashMap JavaDoc();
771         boolean isNetBeansOrg = !suiteComponent && !standalone;
772         if (isNetBeansOrg) {
773             defaults.put("nb_all", root.getAbsolutePath()); // NOI18N
774
defaults.put("netbeans.dest.dir", new File JavaDoc(root, DEST_DIR_IN_NETBEANS_ORG).getAbsolutePath()); // NOI18N
775
}
776         defaults.put("code.name.base.dashes", cnb.replace('.', '-')); // NOI18N
777
defaults.put("module.jar.dir", "modules"); // NOI18N
778
defaults.put("module.jar.basename", "${code.name.base.dashes}.jar"); // NOI18N
779
defaults.put("module.jar", "${module.jar.dir}/${module.jar.basename}"); // NOI18N
780
providers.add(PropertyUtils.fixedPropertyProvider(defaults));
781         if (suiteComponent) {
782             defaults.put("cluster", "${suite.dir}/build/cluster"); // NOI18N
783
} else if (standalone) {
784             defaults.put("cluster", "build/cluster"); // NOI18N
785
} else {
786             // netbeans.org
787
String JavaDoc cluster = findClusterLocation(basedir, root);
788             if (cluster == null) {
789                 cluster = "extra"; // NOI18N
790
}
791             defaults.put("cluster", "${netbeans.dest.dir}/" + cluster); // NOI18N
792
}
793         return PropertyUtils.sequentialPropertyEvaluator(predefsProvider, (PropertyProvider[]) providers.toArray(new PropertyProvider[providers.size()]));
794     }
795     
796     private static PropertyProvider loadPropertiesFile(File JavaDoc f) throws IOException JavaDoc {
797         if (!f.isFile()) {
798             return PropertyUtils.fixedPropertyProvider(Collections.EMPTY_MAP);
799         }
800         Properties JavaDoc p = new Properties JavaDoc();
801         InputStream JavaDoc is = new FileInputStream JavaDoc(f);
802         try {
803             p.load(is);
804         } finally {
805             is.close();
806         }
807         return PropertyUtils.fixedPropertyProvider(NbCollections.checkedMapByFilter(p, String JavaDoc.class, String JavaDoc.class, true));
808     }
809     
810     /**
811      * Refresh any existing lists, e.g. in response to a new module being created.
812      */

813     public static void refresh() {
814         sourceLists.clear();
815         binaryLists.clear();
816         // XXX what about knownEntries?
817
}
818     
819     /**
820      * Refresh cached module list for the given suite. If there is not such a
821      * cached list yet, the method is just no-op.
822      */

823     public static void refreshSuiteModuleList(File JavaDoc suiteDir) {
824         sourceLists.remove(suiteDir);
825     }
826     
827     /**
828      * Whether whether a given dir is root of netbeans.org CVS.
829      */

830     public static boolean isNetBeansOrg(File JavaDoc dir) {
831         return new File JavaDoc(dir, "nbbuild").isDirectory() && // NOI18N
832
new File JavaDoc(dir, "openide").isDirectory(); // NOI18N
833
}
834     
835     /**
836      * Find the root of netbeans.org CVS starting from a project basedir.
837      */

838     public static File JavaDoc findNetBeansOrg(File JavaDoc basedir) {
839         File JavaDoc f = basedir;
840         for (int i = 0; i < DEPTH_NB_ALL; i++) {
841             f = f.getParentFile();
842             if (f == null) {
843                 return null;
844             }
845             if (isNetBeansOrg(f)) {
846                 return f;
847             }
848         }
849         // Not here.
850
return null;
851     }
852     
853     private static Map JavaDoc<String JavaDoc,String JavaDoc> getClusterProperties(File JavaDoc nbroot) throws IOException JavaDoc {
854         Map JavaDoc<String JavaDoc,String JavaDoc> clusterDefs = (Map JavaDoc) clusterPropertiesFiles.get(nbroot);
855         if (clusterDefs == null) {
856             PropertyProvider pp = loadPropertiesFile(new File JavaDoc(nbroot, "nbbuild" + File.separatorChar + "cluster.properties")); // NOI18N
857
PropertyEvaluator clusterEval = PropertyUtils.sequentialPropertyEvaluator(
858                     PropertyUtils.fixedPropertyProvider(Collections.EMPTY_MAP),
859                     new PropertyProvider[] {
860                 pp,
861             });
862             clusterDefs = clusterEval.getProperties();
863             if (clusterDefs == null) {
864                 // Definition failure of some sort.
865
clusterDefs = Collections.EMPTY_MAP;
866             }
867         }
868         return clusterDefs;
869     }
870     
871     /**
872      * Find cluster location of a netbeans.org module.
873      * @param basedir project basedir
874      * @param nbroot location of netbeans.org source root
875      */

876     private static String JavaDoc findClusterLocation(File JavaDoc basedir, File JavaDoc nbroot) throws IOException JavaDoc {
877         String JavaDoc path = PropertyUtils.relativizeFile(nbroot, basedir);
878         assert path.indexOf("..") == -1 : path;
879         Map JavaDoc<String JavaDoc,String JavaDoc> clusterLocationsHere = (Map JavaDoc) clusterLocations.get(nbroot);
880         if (clusterLocationsHere == null) {
881             clusterLocationsHere = new HashMap JavaDoc();
882             Map JavaDoc<String JavaDoc,String JavaDoc> clusterDefs = getClusterProperties(nbroot);
883             Iterator JavaDoc it = clusterDefs.entrySet().iterator();
884             while (it.hasNext()) {
885                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
886                 String JavaDoc key = (String JavaDoc)entry.getKey();
887                 String JavaDoc clusterDir = (String JavaDoc) clusterDefs.get(key + ".dir"); // NOI18N
888
if (clusterDir == null) {
889                     // Not a list of modules.
890
// XXX could also just read clusters.list
891
continue;
892                 }
893                 String JavaDoc val = (String JavaDoc) entry.getValue();
894                 StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(val, ", "); // NOI18N
895
while (tok.hasMoreTokens()) {
896                     String JavaDoc p = tok.nextToken();
897                     clusterLocationsHere.put(p, clusterDir);
898                 }
899             }
900             clusterLocations.put(nbroot, clusterLocationsHere);
901         }
902         return (String JavaDoc) clusterLocationsHere.get(path);
903     }
904     
905     // NONSTATIC PART
906

907     /** all module entries, indexed by cnb */
908     private Map JavaDoc<String JavaDoc,ModuleEntry> entries;
909     
910     /** originally passed top-level dir */
911     private final File JavaDoc home;
912
913     /** whether this list is for netbeans.org and may not yet include experimental modules; cf. #62221 */
914     private boolean lazyNetBeansOrgList;
915     
916     private ModuleList(Map JavaDoc<String JavaDoc,ModuleEntry> entries, File JavaDoc home, boolean lazyNetBeansOrgList) {
917         this.entries = entries;
918         this.home = home;
919         this.lazyNetBeansOrgList = lazyNetBeansOrgList;
920     }
921     
922     public String JavaDoc toString() {
923         return "ModuleList[" + home + "]" + (lazyNetBeansOrgList ? "[lazy]" : "") + entries.values(); // NOI18N
924
}
925     
926     /**
927      * Merge a bunch of module lists into one.
928      * In case of conflict (by CNB), earlier entries take precedence.
929      */

930     private static ModuleList merge(ModuleList[] lists, File JavaDoc home) {
931         Map JavaDoc<String JavaDoc,ModuleEntry> entries = new HashMap JavaDoc();
932         for (int i = 0; i < lists.length; i++) {
933             lists[i].maybeRescanNetBeansOrgSources();
934             Iterator JavaDoc it = lists[i].entries.entrySet().iterator();
935             while (it.hasNext()) {
936                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
937                 String JavaDoc cnb = (String JavaDoc) entry.getKey();
938                 if (!entries.containsKey(cnb)) {
939                     entries.put(cnb, (ModuleEntry) entry.getValue());
940                 }
941             }
942         }
943         return new ModuleList(entries, home, false);
944     }
945     
946     private void maybeRescanNetBeansOrgSources() {
947         if (lazyNetBeansOrgList) {
948             lazyNetBeansOrgList = false;
949             File JavaDoc nbdestdir = new File JavaDoc(home, DEST_DIR_IN_NETBEANS_ORG);
950             Map JavaDoc<String JavaDoc,ModuleEntry> _entries = new HashMap JavaDoc(entries); // #68513: possible race condition
951
doScanNetBeansOrgSources(_entries, home, DEPTH_NB_ALL, home, nbdestdir, null, false);
952             entries = _entries;
953         }
954     }
955     
956     /**
957      * Find an entry by name.
958      * @param codeNameBase code name base of the module
959      * @return the matching module, or null if there is none such
960      */

961     public ModuleEntry getEntry(String JavaDoc codeNameBase) {
962         ModuleEntry e = (ModuleEntry) entries.get(codeNameBase);
963         if (e != null) {
964             return e;
965         } else {
966             maybeRescanNetBeansOrgSources();
967             return (ModuleEntry) entries.get(codeNameBase);
968         }
969     }
970     
971     /**
972      * Get all known entries at once.
973      * @return all known module entries
974      */

975     public Set JavaDoc<ModuleEntry> getAllEntries() {
976         maybeRescanNetBeansOrgSources();
977         return new HashSet JavaDoc(entries.values());
978     }
979     
980     /**
981      * Get all known entries at once, but do not look for experimental netbeans.org modules.
982      * If a previous call to {@link #getAllEntries} or {@link #getEntry} has forced a full
983      * source scan of netbeans.org in order to find experimental modules (i.e. those not in
984      * the standard clusters), then this will be the same as {@link #getAllEntries}. Otherwise
985      * it will include only the stable modules, which may be faster. For module lists that are
986      * not from a netbeans.org source tree, this is the same as {@link #getAllEntries}.
987      * @return all known module entries
988      */

989     public Set JavaDoc<ModuleEntry> getAllEntriesSoft() {
990         return new HashSet JavaDoc(entries.values());
991     }
992     
993     public static LocalizedBundleInfo loadBundleInfo(File JavaDoc projectDir) {
994         LocalizedBundleInfo bundleInfo = Util.findLocalizedBundleInfo(projectDir);
995         return bundleInfo == null ? LocalizedBundleInfo.EMPTY : bundleInfo;
996     }
997
998 }
999
Popular Tags