KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > nbbuild > ModuleListParser


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.nbbuild;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34 import java.util.jar.Attributes JavaDoc;
35 import java.util.jar.JarFile JavaDoc;
36 import org.apache.tools.ant.BuildListener;
37 import org.apache.tools.ant.Project;
38 import org.apache.tools.ant.taskdefs.Property;
39 import org.apache.tools.ant.types.Path;
40 import org.apache.tools.ant.util.FileUtils;
41 import org.w3c.dom.Document JavaDoc;
42 import org.w3c.dom.Element JavaDoc;
43 import org.xml.sax.InputSource JavaDoc;
44
45 /**
46  * Scans for known modules.
47  * Precise algorithm summarized in issue #42681 and issue #58966.
48  * @author Jesse Glick
49  */

50 final class ModuleListParser {
51
52     /** Synch with org.netbeans.modules.apisupport.project.ModuleList.DEPTH_NB_ALL */
53     private static final int DEPTH_NB_ALL = 3;
54     
55     private static Map JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>> SOURCE_SCAN_CACHE = new HashMap JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>>();
56     private static Map JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>> SUITE_SCAN_CACHE = new HashMap JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>>();
57     private static Map JavaDoc<File JavaDoc,Entry> STANDALONE_SCAN_CACHE = new HashMap JavaDoc<File JavaDoc,Entry>();
58     private static Map JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>> BINARY_SCAN_CACHE = new HashMap JavaDoc<File JavaDoc,Map JavaDoc<String JavaDoc,Entry>>();
59     
60     /** Clear caches. Cf. #71130. */
61     public static void resetCaches() {
62         SOURCE_SCAN_CACHE.clear();
63         SUITE_SCAN_CACHE.clear();
64         STANDALONE_SCAN_CACHE.clear();
65         BINARY_SCAN_CACHE.clear();
66     }
67     
68     /**
69      * Find all NBM projects in a root, possibly from cache.
70      */

71     private static Map JavaDoc<String JavaDoc,Entry> scanNetBeansOrgSources(File JavaDoc root, Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, Project project) throws IOException JavaDoc {
72         Map JavaDoc<String JavaDoc,Entry> entries = SOURCE_SCAN_CACHE.get(root);
73         if (entries == null) {
74             entries = new HashMap JavaDoc<String JavaDoc,Entry>();
75             // Similar to #62221: if just invoked from a module in standard clusters, only scan those clusters (faster):
76
Set JavaDoc<String JavaDoc> standardModules = new HashSet JavaDoc<String JavaDoc>();
77             boolean doFastScan = false;
78             String JavaDoc basedir = properties.get("basedir");
79             if (basedir != null) {
80                 File JavaDoc basedirF = new File JavaDoc(basedir);
81                 String JavaDoc clusterList = properties.get("nb.clusters.list");
82                 if (clusterList != null) {
83                     StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(clusterList, ", ");
84                     while (tok.hasMoreTokens()) {
85                         String JavaDoc clusterName = tok.nextToken();
86                         String JavaDoc moduleList = properties.get(clusterName);
87                         if (moduleList != null) {
88                             StringTokenizer JavaDoc tok2 = new StringTokenizer JavaDoc(moduleList, ", ");
89                             while (tok2.hasMoreTokens()) {
90                                 String JavaDoc module = tok2.nextToken();
91                                 standardModules.add(module);
92                                 doFastScan |= new File JavaDoc(root, module.replace('/', File.separatorChar)).equals(basedirF);
93                             }
94                         }
95                     }
96                 }
97             }
98             if (doFastScan) {
99                 if (project != null) {
100                     project.log("Scanning for modules in " + root + " among standard clusters");
101                 }
102                 Iterator JavaDoc it = standardModules.iterator();
103                 while (it.hasNext()) {
104                     String JavaDoc module = (String JavaDoc) it.next();
105                     scanPossibleProject(new File JavaDoc(root, module.replace('/', File.separatorChar)), entries, properties, module, ParseProjectXml.TYPE_NB_ORG, project);
106                 }
107             } else {
108                 // Might be an extra module (e.g. something in contrib); need to scan everything.
109
if (project != null) {
110                     project.log("Scanning for modules in " + root);
111                     project.log("Quick scan mode disabled since " + basedir + " not among standard modules of " + root + " which are " + standardModules, project.MSG_VERBOSE);
112                 }
113                 doScanNetBeansOrgSources(entries, root, DEPTH_NB_ALL, properties, null, project);
114             }
115             if (project != null) {
116                 project.log("Found modules: " + entries.keySet(), Project.MSG_VERBOSE);
117             }
118             SOURCE_SCAN_CACHE.put(root, entries);
119         }
120         return entries;
121     }
122     
123     /** Borrowed from org.netbeans.modules.apisupport.project.universe.ModuleList; cf. #61579 */
124     private static final String JavaDoc[] EXCLUDED_DIR_NAMES = {
125         "CVS", // NOI18N
126
"nbproject", // NOI18N
127
"www", // NOI18N
128
"test", // NOI18N
129
"build", // NOI18N
130
"src", // NOI18N
131
"org", // NOI18N
132
};
133     /**
134      * Scan a root for all NBM projects.
135      */

136     private static void doScanNetBeansOrgSources(Map JavaDoc<String JavaDoc,Entry> entries, File JavaDoc dir, int depth, Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, String JavaDoc pathPrefix, Project project) throws IOException JavaDoc {
137         if (depth == 0) {
138             return;
139         }
140         File JavaDoc[] kids = dir.listFiles();
141         if (kids == null) {
142             return;
143         }
144         KIDS: for (File JavaDoc kid : kids) {
145             if (!kid.isDirectory()) {
146                 continue;
147             }
148             String JavaDoc name = kid.getName();
149             for (String JavaDoc n : EXCLUDED_DIR_NAMES) {
150                 if (name.equals(n)) {
151                     continue KIDS;
152                 }
153             }
154             String JavaDoc newPathPrefix = (pathPrefix != null) ? pathPrefix + "/" + name : name;
155             scanPossibleProject(kid, entries, properties, newPathPrefix, ParseProjectXml.TYPE_NB_ORG, project);
156             doScanNetBeansOrgSources(entries, kid, depth - 1, properties, newPathPrefix, project);
157         }
158     }
159     
160     /**
161      * Check a single dir to see if it is an NBM project, and if so, register it.
162      */

163     private static boolean scanPossibleProject(File JavaDoc dir, Map JavaDoc<String JavaDoc,Entry> entries, Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, String JavaDoc path, int moduleType, Project project) throws IOException JavaDoc {
164         File JavaDoc nbproject = new File JavaDoc(dir, "nbproject");
165         File JavaDoc projectxml = new File JavaDoc(nbproject, "project.xml");
166         if (!projectxml.isFile()) {
167             return false;
168         }
169         Document JavaDoc doc;
170         try {
171             doc = XMLUtil.parse(new InputSource JavaDoc(projectxml.toURI().toString()),
172                                      false, true, /*XXX*/null, null);
173         } catch (Exception JavaDoc e) { // SAXException, IOException (#60295: e.g. encoding problem in XML)
174
// Include \n so that following line can be hyperlinked
175
throw (IOException JavaDoc) new IOException JavaDoc("Error parsing project file\n" + projectxml + ": " + e.getMessage()).initCause(e);
176         }
177         Element JavaDoc typeEl = XMLUtil.findElement(doc.getDocumentElement(), "type", ParseProjectXml.PROJECT_NS);
178         if (!XMLUtil.findText(typeEl).equals("org.netbeans.modules.apisupport.project")) {
179             return false;
180         }
181         Element JavaDoc configEl = XMLUtil.findElement(doc.getDocumentElement(), "configuration", ParseProjectXml.PROJECT_NS);
182         Element JavaDoc dataEl = ParseProjectXml.findNBMElement(configEl, "data");
183         if (dataEl == null) {
184             if (project != null) {
185                 project.log(projectxml.toString() + ": warning: module claims to be a NBM project but is missing <data xmlns=\"" + ParseProjectXml.NBM_NS3 + "\">; maybe an old NB 4.[01] project?", Project.MSG_WARN);
186             }
187             return false;
188         }
189         Element JavaDoc cnbEl = ParseProjectXml.findNBMElement(dataEl, "code-name-base");
190         String JavaDoc cnb = XMLUtil.findText(cnbEl);
191         // Clumsy but the best way I know of to evaluate properties.
192
Project fakeproj = new Project();
193         if (project != null) {
194             // Try to debug any problems in the following definitions (cf. #59849).
195
Iterator JavaDoc it = project.getBuildListeners().iterator();
196             while (it.hasNext()) {
197                 fakeproj.addBuildListener((BuildListener) it.next());
198             }
199         }
200         fakeproj.setBaseDir(dir); // in case ${basedir} is used somewhere
201
Property faketask = new Property();
202         faketask.setProject(fakeproj);
203         switch (moduleType) {
204         case ParseProjectXml.TYPE_NB_ORG:
205             // do nothing here
206
break;
207         case ParseProjectXml.TYPE_SUITE:
208             faketask.setFile(new File JavaDoc(nbproject, "private/suite-private.properties"));
209             faketask.execute();
210             faketask.setFile(new File JavaDoc(nbproject, "suite.properties"));
211             faketask.execute();
212             faketask.setFile(new File JavaDoc(fakeproj.replaceProperties("${suite.dir}/nbproject/private/platform-private.properties")));
213             faketask.execute();
214             faketask.setFile(new File JavaDoc(fakeproj.replaceProperties("${suite.dir}/nbproject/platform.properties")));
215             faketask.execute();
216             break;
217         case ParseProjectXml.TYPE_STANDALONE:
218             faketask.setFile(new File JavaDoc(nbproject, "private/platform-private.properties"));
219             faketask.execute();
220             faketask.setFile(new File JavaDoc(nbproject, "platform.properties"));
221             faketask.execute();
222             break;
223         default:
224             assert false : moduleType;
225         }
226         faketask.setFile(new File JavaDoc(nbproject, "private/private.properties".replace('/', File.separatorChar)));
227         faketask.execute();
228         faketask.setFile(new File JavaDoc(nbproject, "project.properties"));
229         faketask.execute();
230         faketask.setFile(null);
231         faketask.setName("module.jar.dir");
232         faketask.setValue("modules");
233         faketask.execute();
234         assert fakeproj.getProperty("module.jar.dir") != null : fakeproj.getProperties();
235         faketask.setName("module.jar.basename");
236         faketask.setValue(cnb.replace('.', '-') + ".jar");
237         faketask.execute();
238         faketask.setName("module.jar");
239         faketask.setValue(fakeproj.replaceProperties("${module.jar.dir}/${module.jar.basename}"));
240         faketask.execute();
241         switch (moduleType) {
242         case ParseProjectXml.TYPE_NB_ORG:
243             assert path != null;
244             // Find the associated cluster.
245
for (Map.Entry JavaDoc<String JavaDoc,String JavaDoc> entry : properties.entrySet()) {
246                 String JavaDoc val = entry.getValue();
247                 String JavaDoc[] modules = val.split(", *");
248                 if (Arrays.asList(modules).contains(path)) {
249                     String JavaDoc key = entry.getKey();
250                     String JavaDoc clusterDir = properties.get(key + ".dir");
251                     if (clusterDir != null) {
252                         faketask.setName("cluster.dir");
253                         faketask.setValue(clusterDir);
254                         faketask.execute();
255                         break;
256                     }
257                 }
258             }
259             faketask.setName("cluster.dir");
260             faketask.setValue("extra"); // fallback
261
faketask.execute();
262             faketask.setName("netbeans.dest.dir");
263             faketask.setValue(properties.get("netbeans.dest.dir"));
264             faketask.execute();
265             faketask.setName("cluster");
266             faketask.setValue(fakeproj.replaceProperties("${netbeans.dest.dir}/${cluster.dir}"));
267             faketask.execute();
268             break;
269         case ParseProjectXml.TYPE_SUITE:
270             assert path == null;
271             faketask.setName("suite.dir");
272             faketask.setValue(properties.get("suite.dir"));
273             faketask.execute();
274             faketask.setName("cluster");
275             faketask.setValue(fakeproj.replaceProperties("${suite.dir}/build/cluster"));
276             faketask.execute();
277             break;
278         case ParseProjectXml.TYPE_STANDALONE:
279             assert path == null;
280             faketask.setName("cluster");
281             faketask.setValue(fakeproj.replaceProperties("${basedir}/build/cluster"));
282             faketask.execute();
283             break;
284         default:
285             assert false : moduleType;
286         }
287         File JavaDoc jar = fakeproj.resolveFile(fakeproj.replaceProperties("${cluster}/${module.jar}"));
288         List JavaDoc<File JavaDoc> exts = new ArrayList JavaDoc<File JavaDoc>();
289         for (Element JavaDoc ext : XMLUtil.findSubElements(dataEl)) {
290             if (!ext.getLocalName().equals("class-path-extension")) {
291                 continue;
292             }
293             Element JavaDoc binaryOrigin = ParseProjectXml.findNBMElement(ext, "binary-origin");
294             File JavaDoc origBin = null;
295             if (binaryOrigin != null) {
296                 String JavaDoc reltext = XMLUtil.findText(binaryOrigin);
297                 String JavaDoc nball = properties.get("nb_all");
298                 if (nball != null) {
299                     faketask.setName("nb_all");
300                     faketask.setValue(nball);
301                     faketask.execute();
302                 }
303                 fakeproj.setBaseDir(dir);
304                 origBin = fakeproj.resolveFile(fakeproj.replaceProperties(reltext));
305             }
306
307             File JavaDoc resultBin = null;
308             if (origBin == null || !origBin.exists()) {
309                 Element JavaDoc runtimeRelativePath = ParseProjectXml.findNBMElement(ext, "runtime-relative-path");
310                 if (runtimeRelativePath == null) {
311                     throw new IOException JavaDoc("Have malformed <class-path-extension> in " + projectxml);
312                 }
313                 String JavaDoc reltext = XMLUtil.findText(runtimeRelativePath);
314                 // No need to evaluate property refs in it - it is *not* substitutable-text in the schema.
315
resultBin = new File JavaDoc(jar.getParentFile(), reltext.replace('/', File.separatorChar));
316             }
317
318             if (origBin != null) {
319                 exts.add(origBin);
320             }
321
322             if (resultBin != null) {
323                 exts.add(resultBin);
324             }
325         }
326         List JavaDoc<String JavaDoc> prereqs = new ArrayList JavaDoc<String JavaDoc>();
327         List JavaDoc<String JavaDoc> rundeps = new ArrayList JavaDoc<String JavaDoc>();
328         Element JavaDoc depsEl = ParseProjectXml.findNBMElement(dataEl, "module-dependencies");
329         if (depsEl == null) {
330             throw new IOException JavaDoc("Malformed project file " + projectxml);
331         }
332         for (Element JavaDoc dep : XMLUtil.findSubElements(depsEl)) {
333             Element JavaDoc cnbEl2 = ParseProjectXml.findNBMElement(dep, "code-name-base");
334             if (cnbEl2 == null) {
335                 throw new IOException JavaDoc("Malformed project file " + projectxml);
336             }
337             String JavaDoc cnb2 = XMLUtil.findText(cnbEl2);
338             rundeps.add(cnb2);
339             if (ParseProjectXml.findNBMElement(dep, "build-prerequisite") == null) {
340                 continue;
341             }
342             prereqs.add(cnb2);
343         }
344         String JavaDoc cluster = fakeproj.getProperty("cluster.dir"); // may be null
345
Entry entry = new Entry(cnb, jar, exts.toArray(new File JavaDoc[exts.size()]), dir, path,
346                 prereqs.toArray(new String JavaDoc[prereqs.size()]), cluster, rundeps.toArray(new String JavaDoc[rundeps.size()]));
347         if (entries.containsKey(cnb)) {
348             throw new IOException JavaDoc("Duplicated module " + cnb + ": found in " + entries.get(cnb) + " and " + entry);
349         } else {
350             entries.put(cnb, entry);
351         }
352         return true;
353     }
354     
355     /**
356      * Find all modules in a binary build, possibly from cache.
357      */

358     private static Map JavaDoc<String JavaDoc,Entry> scanBinaries(Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, Project project) throws IOException JavaDoc {
359         String JavaDoc buildS = properties.get("netbeans.dest.dir");
360         File JavaDoc basedir = new File JavaDoc(properties.get("basedir"));
361         if (buildS == null) {
362             throw new IOException JavaDoc("No definition of netbeans.dest.dir in " + basedir);
363         }
364         // Resolve against basedir, and normalize ../ sequences and so on in case they are used.
365
// Neither operation is likely to be needed, but just in case.
366
File JavaDoc build = FileUtils.getFileUtils().normalize(FileUtils.getFileUtils().resolveFile(basedir, buildS).getAbsolutePath());
367         if (!build.isDirectory()) {
368             throw new IOException JavaDoc("No such netbeans.dest.dir: " + build);
369         }
370         Map JavaDoc<String JavaDoc,Entry> entries = BINARY_SCAN_CACHE.get(build);
371         if (entries == null) {
372             if (project != null) {
373                 project.log("Scanning for modules in " + build);
374             }
375             entries = new HashMap JavaDoc<String JavaDoc,Entry>();
376             doScanBinaries(build, entries);
377             if (project != null) {
378                 project.log("Found modules: " + entries.keySet(), Project.MSG_VERBOSE);
379             }
380             BINARY_SCAN_CACHE.put(build, entries);
381         }
382         return entries;
383     }
384     
385     private static final String JavaDoc[] MODULE_DIRS = {
386         "modules",
387         "modules/eager",
388         "modules/autoload",
389         "lib",
390         "core",
391     };
392     /**
393      * Look for all possible modules in a NB build.
394      * Checks modules/{,autoload/,eager/}*.jar as well as well-known core/*.jar and lib/boot.jar in each cluster.
395      * XXX would be slightly more precise to check config/Modules/*.xml rather than scan for module JARs.
396      */

397     private static void doScanBinaries(File JavaDoc build, Map JavaDoc<String JavaDoc,Entry> entries) throws IOException JavaDoc {
398         File JavaDoc[] clusters = build.listFiles();
399         if (clusters == null) {
400             throw new IOException JavaDoc("Cannot examine dir " + build);
401         }
402         for (int i = 0; i < clusters.length; i++) {
403             for (int j = 0; j < MODULE_DIRS.length; j++) {
404                 File JavaDoc dir = new File JavaDoc(clusters[i], MODULE_DIRS[j].replace('/', File.separatorChar));
405                 if (!dir.isDirectory()) {
406                     continue;
407                 }
408                 File JavaDoc[] jars = dir.listFiles();
409                 if (jars == null) {
410                     throw new IOException JavaDoc("Cannot examine dir " + dir);
411                 }
412                 for (int k = 0; k < jars.length; k++) {
413                     File JavaDoc m = jars[k];
414                     if (!m.getName().endsWith(".jar")) {
415                         continue;
416                     }
417                     JarFile JavaDoc jf = new JarFile JavaDoc(m);
418                     try {
419                         Attributes JavaDoc attr = jf.getManifest().getMainAttributes();
420                         String JavaDoc codename = attr.getValue("OpenIDE-Module");
421                         if (codename == null) {
422                             continue;
423                         }
424                         String JavaDoc codenamebase;
425                         int slash = codename.lastIndexOf('/');
426                         if (slash == -1) {
427                             codenamebase = codename;
428                         } else {
429                             codenamebase = codename.substring(0, slash);
430                         }
431                         
432                         String JavaDoc cp = attr.getValue("Class-Path");
433                         File JavaDoc[] exts;
434                         if (cp == null) {
435                             exts = new File JavaDoc[0];
436                         } else {
437                             String JavaDoc[] pieces = cp.split(" +");
438                             exts = new File JavaDoc[pieces.length];
439                             for (int l = 0; l < pieces.length; l++) {
440                                 exts[l] = new File JavaDoc(dir, pieces[l].replace('/', File.separatorChar));
441                             }
442                         }
443                         String JavaDoc moduleDependencies = attr.getValue("OpenIDE-Module-Module-Dependencies");
444                         
445                         
446                         Entry entry = new Entry(codenamebase, m, exts,dir, null, null, clusters[i].getName(),parseRuntimeDependencies(moduleDependencies));
447                         if (entries.containsKey(codenamebase)) {
448                             throw new IOException JavaDoc("Duplicated module " + codenamebase + ": found in " + entries.get(codenamebase) + " and " + entry);
449                         } else {
450                             entries.put(codenamebase, entry);
451                         }
452                     } finally {
453                         jf.close();
454                     }
455                 }
456             }
457         }
458     }
459     
460     private static Map JavaDoc<String JavaDoc,Entry> scanSuiteSources(Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, Project project) throws IOException JavaDoc {
461         File JavaDoc basedir = new File JavaDoc(properties.get("basedir"));
462         String JavaDoc suiteDir = properties.get("suite.dir");
463         if (suiteDir == null) {
464             throw new IOException JavaDoc("No definition of suite.dir in " + basedir);
465         }
466         File JavaDoc suite = FileUtils.getFileUtils().resolveFile(basedir, suiteDir);
467         if (!suite.isDirectory()) {
468             throw new IOException JavaDoc("No such suite " + suite);
469         }
470         Map JavaDoc<String JavaDoc,Entry> entries = SUITE_SCAN_CACHE.get(suite);
471         if (entries == null) {
472             if (project != null) {
473                 project.log("Scanning for modules in suite " + suite);
474             }
475             entries = new HashMap JavaDoc<String JavaDoc,Entry>();
476             doScanSuite(entries, suite, properties, project);
477             if (project != null) {
478                 project.log("Found modules: " + entries.keySet(), Project.MSG_VERBOSE);
479             }
480             SUITE_SCAN_CACHE.put(suite, entries);
481         }
482         return entries;
483     }
484     
485     private static void doScanSuite(Map JavaDoc<String JavaDoc,Entry> entries, File JavaDoc suite, Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, Project project) throws IOException JavaDoc {
486         Project fakeproj = new Project();
487         fakeproj.setBaseDir(suite); // in case ${basedir} is used somewhere
488
Property faketask = new Property();
489         faketask.setProject(fakeproj);
490         faketask.setFile(new File JavaDoc(suite, "nbproject/private/private.properties".replace('/', File.separatorChar)));
491         faketask.execute();
492         faketask.setFile(new File JavaDoc(suite, "nbproject/project.properties".replace('/', File.separatorChar)));
493         faketask.execute();
494         String JavaDoc modulesS = fakeproj.getProperty("modules");
495         if (modulesS == null) {
496             throw new IOException JavaDoc("No definition of modules in " + suite);
497         }
498         String JavaDoc[] modules = Path.translatePath(fakeproj, modulesS);
499         for (int i = 0; i < modules.length; i++) {
500             File JavaDoc module = new File JavaDoc(modules[i]);
501             if (!module.isDirectory()) {
502                 throw new IOException JavaDoc("No such module " + module + " referred to from " + suite);
503             }
504             if (!scanPossibleProject(module, entries, properties, null, ParseProjectXml.TYPE_SUITE, project)) {
505                 throw new IOException JavaDoc("No valid module found in " + module + " referred to from " + suite);
506             }
507         }
508     }
509     
510     private static Entry scanStandaloneSource(Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, Project project) throws IOException JavaDoc {
511         File JavaDoc basedir = new File JavaDoc(properties.get("project"));
512         Entry entry = STANDALONE_SCAN_CACHE.get(basedir);
513         if (entry == null) {
514             Map JavaDoc<String JavaDoc,Entry> entries = new HashMap JavaDoc<String JavaDoc,Entry>();
515             if (!scanPossibleProject(basedir, entries, properties, null, ParseProjectXml.TYPE_STANDALONE, project)) {
516                 throw new IOException JavaDoc("No valid module found in " + basedir);
517             }
518             assert entries.size() == 1;
519             entry = entries.values().iterator().next();
520             STANDALONE_SCAN_CACHE.put(basedir, entry);
521         }
522         return entry;
523     }
524     
525     /** all module entries, indexed by cnb */
526     private final Map JavaDoc<String JavaDoc,Entry> entries;
527     
528     /**
529      * Initiates scan if not already parsed.
530      * Properties interpreted:
531      * <ol>
532      * <li> ${nb_all} - location of NB sources (used only for netbeans.org modules)
533      * <li> ${netbeans.dest.dir} - location of NB build
534      * <li> ${basedir} - directory of this project (used only for standalone modules)
535      * <li> ${suite.dir} - directory of the suite (used only for suite modules)
536      * <li> ${nb.cluster.TOKEN} - list of module paths included in cluster TOKEN (comma-separated) (used only for netbeans.org modules)
537      * <li> ${nb.cluster.TOKEN.dir} - directory in ${netbeans.dest.dir} where cluster TOKEN is built (used only for netbeans.org modules)
538      * <li> ${project} - basedir for standalone modules
539      * </ol>
540      * @param properties some properties to be used (see above)
541      * @param type the type of project
542      * @param project a project ref, only for logging (may be null with no loss of semantics)
543      */

544     public ModuleListParser(Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties, int type, Project project) throws IOException JavaDoc {
545         String JavaDoc nball = properties.get("nb_all");
546         if (type != ParseProjectXml.TYPE_NB_ORG) {
547             // External module.
548
File JavaDoc basedir = new File JavaDoc(properties.get("basedir"));
549             if (nball != null) {
550                 throw new IOException JavaDoc("You must *not* declare <suite-component/> or <standalone/> for a netbeans.org module in " + basedir + "; fix project.xml to use the /2 schema");
551             }
552             entries = scanBinaries(properties, project);
553             if (type == ParseProjectXml.TYPE_SUITE) {
554                 entries.putAll(scanSuiteSources(properties, project));
555             } else {
556                 assert type == ParseProjectXml.TYPE_STANDALONE;
557                 Entry e = scanStandaloneSource(properties, project);
558                 entries.put(e.getCnb(), e);
559             }
560         } else {
561             // netbeans.org module.
562
if (nball == null) {
563                 throw new IOException JavaDoc("You must declare either <suite-component/> or <standalone/> for an external module in " + new File JavaDoc(properties.get("basedir")));
564             }
565             // If scan.binaries property is set or it runs from tests we scan binaries otherwise sources.
566
boolean xtest = properties.get("xtest.home") != null && properties.get("xtest.testtype") != null;
567             if (properties.get("scan.binaries") != null || xtest) {
568                 entries = scanBinaries(properties, project);
569                 // module itself has to be added because it doesn't have to be in binaries
570
Entry e = scanStandaloneSource(properties, project);
571                     // xtest gets module jar and cluster from binaries
572
if (e.clusterName == null && xtest) {
573                          Entry oldEntry = entries.get(e.getCnb());
574                          if (oldEntry != null) {
575                              e = new Entry(e.getCnb(),oldEntry.getJar(),
576                                           e.getClassPathExtensions(),e.sourceLocation,
577                                           e.netbeansOrgPath,e.buildPrerequisites,
578                                           oldEntry.getClusterName(),
579                                           e.runtimeDependencies);
580                          }
581                     }
582                     entries.put(e.getCnb(), e);
583             } else {
584                 entries = scanNetBeansOrgSources(new File JavaDoc(nball), properties, project);
585             }
586         }
587     }
588     /**
589      * Find all entries in this list.
590      * @return a set of all known entries
591      */

592     public Set JavaDoc<Entry> findAll() {
593         return new HashSet JavaDoc<Entry>(entries.values());
594     }
595     
596     /**
597      * Find one entry by code name base.
598      * @param cnb the desired code name base
599      * @return the matching entry or null
600      */

601     public Entry findByCodeNameBase(String JavaDoc cnb) {
602         return entries.get(cnb);
603     }
604
605     
606     /** parse Openide-Module-Module-Dependencies entry
607      * @return array of code name bases
608      */

609     private static String JavaDoc[] parseRuntimeDependencies(String JavaDoc moduleDependencies) {
610         if (moduleDependencies == null) {
611             return new String JavaDoc[0];
612         }
613         List JavaDoc<String JavaDoc> cnds = new ArrayList JavaDoc<String JavaDoc>();
614         StringTokenizer JavaDoc toks = new StringTokenizer JavaDoc(moduleDependencies,",");
615         while (toks.hasMoreTokens()) {
616             String JavaDoc token = toks.nextToken().trim();
617             // substring cnd/x
618
int slIdx = token.indexOf('/');
619             if (slIdx != -1) {
620                 token = token.substring(0,slIdx);
621             }
622             // substring cnd' 'xx
623
slIdx = token.indexOf(' ');
624             if (slIdx != -1) {
625                 token = token.substring(0,slIdx);
626             }
627             // substring cnd >
628
slIdx = token.indexOf('>');
629             if (slIdx != -1) {
630                 token = token.substring(0,slIdx);
631             }
632             token = token.trim();
633             if (token.length() > 0) {
634                cnds.add(token);
635             }
636         }
637         return cnds.toArray(new String JavaDoc[cnds.size()]);
638     }
639     
640     /**
641      * One entry in the file.
642      */

643     public static final class Entry {
644         
645         private final String JavaDoc cnb;
646         private final File JavaDoc jar;
647         private final File JavaDoc[] classPathExtensions;
648         private final File JavaDoc sourceLocation;
649         private final String JavaDoc netbeansOrgPath;
650         private final String JavaDoc[] buildPrerequisites;
651         private final String JavaDoc clusterName;
652         private final String JavaDoc[] runtimeDependencies;
653         
654         Entry(String JavaDoc cnb, File JavaDoc jar, File JavaDoc[] classPathExtensions, File JavaDoc sourceLocation, String JavaDoc netbeansOrgPath, String JavaDoc[] buildPrerequisites, String JavaDoc clusterName,String JavaDoc[] runtimeDependencies) {
655             this.cnb = cnb;
656             this.jar = jar;
657             this.classPathExtensions = classPathExtensions;
658             this.sourceLocation = sourceLocation;
659             this.netbeansOrgPath = netbeansOrgPath;
660             this.buildPrerequisites = buildPrerequisites;
661             this.clusterName = clusterName;
662             this.runtimeDependencies = runtimeDependencies;
663         }
664         
665         /**
666          * Get the code name base, e.g. org.netbeans.modules.ant.grammar.
667          */

668         public String JavaDoc getCnb() {
669             return cnb;
670         }
671         
672         /**
673          * Get the absolute JAR location, e.g. .../ide5/modules/org-netbeans-modules-ant-grammar.jar.
674          */

675         public File JavaDoc getJar() {
676             return jar;
677         }
678         
679         /**
680          * Get a list of extensions to the class path of this module (may be empty).
681          */

682         public File JavaDoc[] getClassPathExtensions() {
683             return classPathExtensions;
684         }
685         
686         /**
687          * Get the path within netbeans.org, if this is a netbeans.org module (else null).
688          */

689         public String JavaDoc getNetbeansOrgPath() {
690             return netbeansOrgPath;
691         }
692         
693         /**
694          * Get a list of declared build prerequisites (or null for sourceless entries).
695          * Each entry is a code name base.
696          */

697         public String JavaDoc[] getBuildPrerequisites() {
698             return buildPrerequisites;
699         }
700         /** Get runtime dependencies, OpenIDE-Module-Dependencies entry.
701          */

702         public String JavaDoc[] getRuntimeDependencies() {
703             return runtimeDependencies;
704         }
705         
706         /**
707          * Return the name of the cluster in which this module resides.
708          * If this entry represents an external module in source form,
709          * then the cluster will be null. If the module represents a netbeans.org
710          * module or a binary module in a platform, then the cluster name will
711          * be the (base) name of the directory containing the "modules" subdirectory
712          * (sometimes "lib" or "core") where the JAR is.
713          */

714         public String JavaDoc getClusterName() {
715             return clusterName;
716         }
717         
718         public String JavaDoc toString() {
719             return (sourceLocation != null ? sourceLocation : jar).getAbsolutePath();
720         }
721         
722     }
723
724 }
725
Popular Tags