KickJava   Java API By Example, From Geeks To Geeks.

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


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.ByteArrayOutputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.HashSet JavaDoc;
33 import java.util.Hashtable JavaDoc;
34 import java.util.LinkedList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38 import java.util.StringTokenizer JavaDoc;
39 import java.util.jar.Attributes JavaDoc;
40 import java.util.jar.JarFile JavaDoc;
41 import java.util.regex.Pattern JavaDoc;
42 import java.util.zip.CRC32 JavaDoc;
43 import java.util.zip.ZipEntry JavaDoc;
44 import java.util.zip.ZipInputStream JavaDoc;
45 import java.util.zip.ZipOutputStream JavaDoc;
46 import org.apache.tools.ant.BuildException;
47 import org.apache.tools.ant.Project;
48 import org.apache.tools.ant.Task;
49 import org.w3c.dom.Document JavaDoc;
50 import org.w3c.dom.Element JavaDoc;
51 import org.xml.sax.InputSource JavaDoc;
52 import org.xml.sax.SAXException JavaDoc;
53
54 /**
55  * Parse a projectized module's <code>nbproject/project.xml</code> and
56  * define various useful Ant properties based on the result.
57  * @author Jesse Glick
58  */

59 public final class ParseProjectXml extends Task {
60
61     static final String JavaDoc PROJECT_NS = "http://www.netbeans.org/ns/project/1";
62     static final String JavaDoc NBM_NS2 = "http://www.netbeans.org/ns/nb-module-project/2";
63     static final String JavaDoc NBM_NS3 = "http://www.netbeans.org/ns/nb-module-project/3";
64     
65     static final int TYPE_NB_ORG = 0;
66     static final int TYPE_SUITE = 1;
67     static final int TYPE_STANDALONE = 2;
68
69     private File JavaDoc project;
70     /**
71      * Set the NetBeans module project to work on.
72      */

73     public void setProject(File JavaDoc f) {
74         project = f;
75     }
76     private File JavaDoc projectFile;
77     /**
78      * Another option is to directly point to project file.
79      * Used only in unit testing.
80      */

81     public void setProjectFile (File JavaDoc f) {
82         projectFile = f;
83     }
84     private File JavaDoc getProjectFile () {
85         if (projectFile != null) {
86             return projectFile;
87         }
88         return new File JavaDoc(new File JavaDoc(project, "nbproject"), "project.xml");
89     }
90
91     private String JavaDoc publicPackagesProperty;
92     /**
93      * Set the property to set a list of
94      * OpenIDE-Module-Public-Packages to.
95      */

96     public void setPublicPackagesProperty(String JavaDoc s) {
97         publicPackagesProperty = s;
98     }
99     
100     private String JavaDoc friendsProperty;
101     /**
102      * Set the property to set a list of
103      * OpenIDE-Module-Friends to.
104      */

105     public void setFriendsProperty(String JavaDoc s) {
106         friendsProperty = s;
107     }
108
109     private String JavaDoc javadocPackagesProperty;
110     /**
111      * Set the property to set a list of public packages for Javadoc
112      * to.
113      */

114     public void setJavadocPackagesProperty(String JavaDoc s) {
115         javadocPackagesProperty = s;
116     }
117
118     private String JavaDoc moduleDependenciesProperty;
119     /**
120      * Set the property to set a list of
121      * OpenIDE-Module-Module-Dependencies to, based on the list of
122      * stated run-time dependencies.
123      */

124     public void setModuleDependenciesProperty(String JavaDoc s) {
125         moduleDependenciesProperty = s;
126     }
127
128     private String JavaDoc codeNameBaseDashesProperty;
129     /**
130      * Set the property to set the module code name base (separated by
131      * dashes not dots) to.
132      */

133     public void setCodeNameBaseDashesProperty(String JavaDoc s) {
134         codeNameBaseDashesProperty = s;
135     }
136
137     private String JavaDoc codeNameBaseSlashesProperty;
138     /**
139      * Set the property to set the module code name base (separated by
140      * slashes not dots) to.
141      */

142     public void setCodeNameBaseSlashesProperty(String JavaDoc s) {
143         codeNameBaseSlashesProperty = s;
144     }
145
146     private String JavaDoc domainProperty;
147     /**
148      * Set the property to set the module's netbeans.org domain to.
149      * Only applicable to modules in netbeans.org (i.e. no <path>).
150      */

151     public void setDomainProperty(String JavaDoc s) {
152         domainProperty = s;
153     }
154
155     private String JavaDoc moduleClassPathProperty;
156     /**
157      * Set the property to set the computed module class path to,
158      * based on the list of stated compile-time dependencies.
159      */

160     public void setModuleClassPathProperty(String JavaDoc s) {
161         moduleClassPathProperty = s;
162     }
163
164     private String JavaDoc moduleRunClassPathProperty;
165     /**
166      * Set the property to set the computed module runtime class path to.
167      * Currently identical to the regular class path with the exception
168      * that original JARs are used, never public-package-only JARs.
169      * XXX In the future should however reflect &lt;run-dependency/&gt;
170      * rather than &lt;compile-dependency/&gt; and should also include
171      * transitive dependencies.
172      */

173     public void setModuleRunClassPathProperty(String JavaDoc s) {
174         moduleRunClassPathProperty = s;
175     }
176     
177     private File JavaDoc publicPackageJarDir;
178     /**
179      * Set the location of a directory in which to look for and create
180      * JARs containing just the public packages of appropriate
181      * compile-time dependencies.
182      */

183     public void setPublicPackageJarDir(File JavaDoc d) {
184         publicPackageJarDir = d;
185     }
186     
187     private String JavaDoc classPathExtensionsProperty;
188     /**
189      * Set the property to set the declared Class-Path attribute to.
190      */

191     public void setClassPathExtensionsProperty(String JavaDoc s) {
192         classPathExtensionsProperty = s;
193     }
194
195     // test distribution path
196
public static String JavaDoc testDistLocation;
197
198     public static class TestType {
199         private String JavaDoc name;
200         private String JavaDoc folder;
201         private String JavaDoc runtimeCP;
202         private String JavaDoc compileCP;
203
204         public TestType() {}
205         public String JavaDoc getName() {
206             return name;
207         }
208
209         public void setName(String JavaDoc name) {
210             this.name = name;
211         }
212
213         public String JavaDoc getFolder() {
214             return folder;
215         }
216
217         public void setFolder(String JavaDoc folder) {
218             this.folder = folder;
219         }
220
221         public String JavaDoc getRuntimeCP() {
222             return runtimeCP;
223         }
224
225         public void setRuntimeCP(String JavaDoc runtimeCP) {
226             this.runtimeCP = runtimeCP;
227         }
228
229         public String JavaDoc getCompileCP() {
230             return compileCP;
231         }
232
233         public void setCompileCP(String JavaDoc compileCP) {
234             this.compileCP = compileCP;
235         }
236         
237     }
238       List JavaDoc<TestType> testTypes = new LinkedList JavaDoc<TestType>();
239       
240       public void addTestType(TestType testType) {
241           testTypes.add(testType);
242       }
243       public void add(TestType testType) {
244           testTypes.add(testType);
245       }
246   
247       
248       private TestType getTestType(String JavaDoc name) {
249           for (TestType testType : testTypes) {
250               if (testType.getName().equals(name)) {
251                   return testType;
252               }
253           }
254           return null;
255       }
256  
257  
258     private void define(String JavaDoc prop, String JavaDoc val) {
259         log("Setting " + prop + "=" + val, Project.MSG_VERBOSE);
260         String JavaDoc old = getProject().getProperty(prop);
261         if (old != null && !old.equals(val)) {
262             getProject().log("Warning: " + prop + " was already set to " + old, Project.MSG_WARN);
263         }
264         getProject().setNewProperty(prop, val);
265     }
266     
267     
268     public void execute() throws BuildException {
269         try {
270             if (getProjectFile() == null) {
271                 throw new BuildException("You must set 'project' or 'projectfile'", getLocation());
272             }
273             // XXX validate against nbm-project{,2}.xsd; does this require JDK 1.5?
274
// Cf.: ant/project/eg/ValidateAllBySchema.java
275
// XXX share parse w/ ModuleListParser
276
Document JavaDoc pDoc = XMLUtil.parse(new InputSource JavaDoc(getProjectFile ().toURI().toString()),
277                                           false, true, /*XXX*/null, null);
278             if (publicPackagesProperty != null || javadocPackagesProperty != null) {
279                 PublicPackage[] pkgs = getPublicPackages(pDoc);
280                 if (publicPackagesProperty != null) {
281                     String JavaDoc val;
282                     if (pkgs.length > 0) {
283                         String JavaDoc sep = "";
284                         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
285                         for (PublicPackage p : pkgs) {
286                             b.append(sep);
287                             
288                             String JavaDoc name = p.name;
289                             if (name.indexOf (',') >= 0) {
290                                 throw new BuildException ("Package name cannot contain ',' as " + p, getLocation ());
291                             }
292                             if (name.indexOf ('*') >= 0) {
293                                 throw new BuildException ("Package name cannot contain '*' as " + p, getLocation ());
294                             }
295                             
296                             b.append(name);
297                             if (p.subpackages) {
298                                 b.append (".**");
299                             } else {
300                                 b.append(".*");
301                             }
302                             sep = ", ";
303                         }
304                         val = b.toString();
305                     } else {
306                         val = "-";
307                     }
308                     define(publicPackagesProperty, val);
309                 }
310                 NO_JAVA_DOC_PROPERTY_SET: if (javadocPackagesProperty != null) {
311                     if (pkgs.length > 0) {
312                         String JavaDoc sep = "";
313                         StringBuffer JavaDoc b = new StringBuffer JavaDoc();
314                         for (PublicPackage p : pkgs) {
315                             b.append(sep);
316                             if (p.subpackages) {
317                                 if (getProject().getProperty(javadocPackagesProperty) == null) {
318                                     String JavaDoc msg = javadocPackagesProperty + " cannot be set as <subpackages> does not work for Javadoc (see <subpackages>" + p.name + "</subpackages> tag in " + getProjectFile () + "). Set the property in project.properties if you want to build Javadoc.";
319                                     // #52135: do not halt the build, just leave it.
320
getProject().log("Warning: " + msg, Project.MSG_WARN);
321                                 }
322                                 break NO_JAVA_DOC_PROPERTY_SET;
323                             }
324                             b.append(p.name);
325                             sep = ", ";
326                         }
327                         define(javadocPackagesProperty, b.toString());
328                     }
329                 }
330             }
331             if (friendsProperty != null) {
332                 String JavaDoc[] friends = getFriends(pDoc);
333                 if (friends != null) {
334                     StringBuffer JavaDoc b = new StringBuffer JavaDoc();
335                     for (String JavaDoc f : friends) {
336                         if (b.length() > 0) {
337                             b.append(", ");
338                         }
339                         b.append(f);
340                     }
341                     define(friendsProperty, b.toString());
342                 }
343             }
344             ModuleListParser modules = null;
345             Dep[] deps = null;
346             if (moduleDependenciesProperty != null ||
347                     moduleClassPathProperty != null ||
348                     moduleRunClassPathProperty != null ||
349                     testTypes.size() > 0) {
350                 @SuppressWarnings JavaDoc("unchecked")
351                 Hashtable JavaDoc<String JavaDoc,String JavaDoc> properties = getProject().getProperties();
352                 properties.put("project", project.getAbsolutePath());
353                 modules = new ModuleListParser(properties, getModuleType(pDoc), getProject());
354                 ModuleListParser.Entry myself = modules.findByCodeNameBase(getCodeNameBase(pDoc));
355                 if (myself == null) { // #71130
356
ModuleListParser.resetCaches();
357                     modules = new ModuleListParser(properties, getModuleType(pDoc), getProject());
358                     myself = modules.findByCodeNameBase(getCodeNameBase(pDoc));
359                     assert myself != null;
360                 }
361                 deps = getDeps(pDoc, modules);
362             }
363             if (moduleDependenciesProperty != null) {
364                 if (moduleDependenciesProperty != null) {
365                     StringBuffer JavaDoc b = new StringBuffer JavaDoc();
366                     for (Dep d : deps) {
367                         if (!d.run) {
368                             continue;
369                         }
370                         if (b.length() > 0) {
371                             b.append(", ");
372                         }
373                         b.append(d);
374                     }
375                     if (b.length() > 0) {
376                         define(moduleDependenciesProperty, b.toString());
377                     }
378                 }
379             }
380             if (codeNameBaseDashesProperty != null) {
381                 String JavaDoc cnb = getCodeNameBase(pDoc);
382                 define(codeNameBaseDashesProperty, cnb.replace('.', '-'));
383             }
384             if (codeNameBaseSlashesProperty != null) {
385                 String JavaDoc cnb = getCodeNameBase(pDoc);
386                 define(codeNameBaseSlashesProperty, cnb.replace('.', '/'));
387             }
388             if (moduleClassPathProperty != null) {
389                 String JavaDoc cp = computeClasspath(pDoc, modules, deps, false);
390                 define(moduleClassPathProperty, cp);
391             }
392             if (moduleRunClassPathProperty != null) {
393                 String JavaDoc cp = computeClasspath(pDoc, modules, deps, true);
394                 define(moduleRunClassPathProperty, cp);
395             }
396             if (domainProperty != null) {
397                 if (getModuleType(pDoc) != TYPE_NB_ORG) {
398                     throw new BuildException("Cannot set " + domainProperty + " for a non-netbeans.org module", getLocation());
399                 }
400                 File JavaDoc nball = new File JavaDoc(getProject().getProperty("nb_all"));
401                 File JavaDoc basedir = getProject().getBaseDir();
402                 File JavaDoc dir = basedir;
403                 while (true) {
404                     File JavaDoc parent = dir.getParentFile();
405                     if (parent == null) {
406                         throw new BuildException("Could not find " + basedir + " inside " + nball + " for purposes of defining " + domainProperty);
407                     }
408                     if (parent.equals(nball)) {
409                         define(domainProperty, dir.getName());
410                         break;
411                     }
412                     dir = parent;
413                 }
414             }
415             if (classPathExtensionsProperty != null) {
416                 String JavaDoc val = computeClassPathExtensions(pDoc);
417                 if (val != null) {
418                     define(classPathExtensionsProperty, val);
419                 }
420             }
421             
422             // Test dependecies
423
//
424
if (modules != null) {
425                String JavaDoc testDistLocation = getProject().getProperty(TestDeps.TEST_DIST_VAR);
426                if (testDistLocation == null) {
427                    testDistLocation = "${" + TestDeps.TEST_DIST_VAR + "}";
428                }
429                ParseProjectXml.testDistLocation = testDistLocation;
430                
431                for (TestDeps td : getTestDeps(pDoc, modules, getCodeNameBase(pDoc))) {
432                    // unit tests
433
TestType testType = getTestType(td.testtype);
434                    if (testType!= null ) {
435                        if (testType.getFolder() != null) {
436                            define(testType.getFolder(),td.getTestFolder());
437                        }
438                        if (testType.getCompileCP() != null && td.getCompileClassPath() != null && td.getCompileClassPath().trim().length() > 0) {
439                            define(testType.getCompileCP(),td.getCompileClassPath());
440                        }
441                        if (testType.getRuntimeCP() != null && td.getRuntimeClassPath() != null && td.getRuntimeClassPath().trim().length() > 0) {
442                            define(testType.getRuntimeCP(),td.getRuntimeClassPath());
443                        }
444                    }
445                }
446             }
447         } catch (BuildException e) {
448             throw e;
449         } catch (Exception JavaDoc e) {
450             throw new BuildException(e, getLocation());
451         }
452     }
453
454     private Element JavaDoc getConfig(Document JavaDoc pDoc) throws BuildException {
455         Element JavaDoc e = pDoc.getDocumentElement();
456         Element JavaDoc c = XMLUtil.findElement(e, "configuration", PROJECT_NS);
457         if (c == null) {
458             throw new BuildException("No <configuration>", getLocation());
459         }
460         Element JavaDoc d = findNBMElement(c, "data");
461         if (d == null) {
462             throw new BuildException("No <data> in " + getProjectFile(), getLocation());
463         }
464         return d;
465     }
466     
467     private static final class PublicPackage extends Object JavaDoc {
468         public final String JavaDoc name;
469         public boolean subpackages;
470         
471         public PublicPackage (String JavaDoc name, boolean subpackages) {
472             this.name = name;
473             this.subpackages = subpackages;
474         }
475     }
476
477     private PublicPackage[] getPublicPackages(Document JavaDoc d) throws BuildException {
478         Element JavaDoc cfg = getConfig(d);
479         Element JavaDoc pp = findNBMElement(cfg, "public-packages");
480         if (pp == null) {
481             pp = findNBMElement(cfg, "friend-packages");
482         }
483         if (pp == null) {
484             throw new BuildException("No <public-packages>", getLocation());
485         }
486         List JavaDoc<PublicPackage> pkgs = new ArrayList JavaDoc<PublicPackage>();
487         for (Element JavaDoc p : XMLUtil.findSubElements(pp)) {
488             boolean sub = false;
489             if ("friend".equals(p.getNodeName())) {
490                 continue;
491             }
492             if (!"package".equals (p.getNodeName ())) {
493                 if (!("subpackages".equals (p.getNodeName ()))) {
494                     throw new BuildException ("Strange element name, should be package or subpackages: " + p.getNodeName (), getLocation ());
495                 }
496                 sub = true;
497             }
498             
499             String JavaDoc t = XMLUtil.findText(p);
500             if (t == null) {
501                 throw new BuildException("No text in <package>", getLocation());
502             }
503             pkgs.add(new PublicPackage(t, sub));
504         }
505         return pkgs.toArray(new PublicPackage[pkgs.size()]);
506     }
507     
508     private String JavaDoc[] getFriends(Document JavaDoc d) throws BuildException {
509         Element JavaDoc cfg = getConfig(d);
510         Element JavaDoc pp = findNBMElement(cfg, "friend-packages");
511         if (pp == null) {
512             return null;
513         }
514         List JavaDoc<String JavaDoc> friends = new ArrayList JavaDoc<String JavaDoc>();
515         boolean other = false;
516         for (Element JavaDoc p : XMLUtil.findSubElements(pp)) {
517             if ("friend".equals(p.getNodeName())) {
518                 String JavaDoc t = XMLUtil.findText(p);
519                 if (t == null) {
520                     throw new BuildException("No text in <friend>", getLocation());
521                 }
522                 friends.add(t);
523             } else {
524                 other = true;
525             }
526         }
527         if (friends.isEmpty()) {
528             throw new BuildException("Must have at least one <friend> in <friend-packages>", getLocation());
529         }
530         if (!other) {
531             throw new BuildException("Must have at least one <package> in <friend-packages>", getLocation());
532         }
533         return friends.toArray(new String JavaDoc[friends.size()]);
534     }
535
536     private final class Dep {
537         private final ModuleListParser modules;
538         /** will be e.g. org.netbeans.modules.form */
539         public String JavaDoc codenamebase;
540         public String JavaDoc release = null;
541         public String JavaDoc spec = null;
542         public boolean impl = false;
543         public boolean compile = false;
544         public boolean run = false;
545         
546         public Dep(ModuleListParser modules) {
547             this.modules = modules;
548         }
549         
550         public String JavaDoc toString() throws BuildException {
551             StringBuffer JavaDoc b = new StringBuffer JavaDoc(codenamebase);
552             if (release != null) {
553                 b.append('/');
554                 b.append(release);
555             }
556             if (spec != null) {
557                 b.append(" > ");
558                 b.append(spec);
559                 assert !impl;
560             }
561             if (impl) {
562                 b.append(" = "); // NO18N
563
String JavaDoc implVers = implementationVersionOf(modules, codenamebase);
564                 if (implVers == null) {
565                     throw new BuildException("No OpenIDE-Module-Implementation-Version found in " + codenamebase);
566                 }
567                 b.append(implVers);
568             }
569             return b.toString();
570         }
571         
572         private String JavaDoc implementationVersionOf(ModuleListParser modules, String JavaDoc cnb) throws BuildException {
573             File JavaDoc jar = computeClasspathModuleLocation(modules, cnb, null, null, null);
574             if (!jar.isFile()) {
575                 throw new BuildException("No such classpath entry: " + jar, getLocation());
576             }
577             try {
578                 JarFile JavaDoc jarFile = new JarFile JavaDoc(jar, false);
579                 try {
580                     return jarFile.getManifest().getMainAttributes().getValue("OpenIDE-Module-Implementation-Version");
581                 } finally {
582                     jarFile.close();
583                 }
584             } catch (IOException JavaDoc e) {
585                 throw new BuildException(e, getLocation());
586             }
587         }
588
589         private boolean matches(Attributes JavaDoc attr) {
590             if (release != null) {
591                 String JavaDoc givenCodeName = attr.getValue("OpenIDE-Module");
592                 int slash = givenCodeName.indexOf('/');
593                 int givenRelease = -1;
594                 if (slash != -1) {
595                     assert codenamebase.equals(givenCodeName.substring(0, slash));
596                     givenRelease = Integer.parseInt(givenCodeName.substring(slash + 1));
597                 }
598                 int dash = release.indexOf('-');
599                 if (dash == -1) {
600                     if (Integer.parseInt(release) != givenRelease) {
601                         return false;
602                     }
603                 } else {
604                     int lower = Integer.parseInt(release.substring(0, dash));
605                     int upper = Integer.parseInt(release.substring(dash + 1));
606                     if (givenRelease < lower || givenRelease > upper) {
607                         return false;
608                     }
609                 }
610             }
611             if (spec != null) {
612                 String JavaDoc givenSpec = attr.getValue("OpenIDE-Module-Specification-Version");
613                 if (givenSpec == null) {
614                     return false;
615                 }
616                 // XXX cannot use org.openide.modules.SpecificationVersion from here
617
int[] specVals = digitize(spec);
618                 int[] givenSpecVals = digitize(givenSpec);
619                 int len1 = specVals.length;
620                 int len2 = givenSpecVals.length;
621                 int max = Math.max(len1, len2);
622                 for (int i = 0; i < max; i++) {
623                     int d1 = ((i < len1) ? specVals[i] : 0);
624                     int d2 = ((i < len2) ? givenSpecVals[i] : 0);
625                     if (d1 < d2) {
626                         break;
627                     } else if (d1 > d2) {
628                         return false;
629                     }
630                 }
631             }
632             if (impl) {
633                 if (attr.getValue("OpenIDE-Module-Implementation-Version") == null) {
634                     return false;
635                 }
636             }
637             return true;
638         }
639         private int[] digitize(String JavaDoc spec) throws NumberFormatException JavaDoc {
640             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(spec, ".");
641             int len = tok.countTokens();
642             int[] digits = new int[len];
643             for (int i = 0; i < len; i++) {
644                 digits[i] = Integer.parseInt(tok.nextToken());
645             }
646             return digits;
647         }
648         
649     }
650
651     private Dep[] getDeps(Document JavaDoc pDoc, ModuleListParser modules) throws BuildException {
652         Element JavaDoc cfg = getConfig(pDoc);
653         Element JavaDoc md = findNBMElement(cfg, "module-dependencies");
654         if (md == null) {
655             throw new BuildException("No <module-dependencies>", getLocation());
656         }
657         List JavaDoc<Dep> deps = new ArrayList JavaDoc<Dep>();
658         for (Element JavaDoc dep : XMLUtil.findSubElements(md)) {
659             Dep d = new Dep(modules);
660             Element JavaDoc cnb = findNBMElement(dep, "code-name-base");
661             if (cnb == null) {
662                 throw new BuildException("No <code-name-base>", getLocation());
663             }
664             String JavaDoc t = XMLUtil.findText(cnb);
665             if (t == null) {
666                 throw new BuildException("No text in <code-name-base>", getLocation());
667             }
668             d.codenamebase = t;
669             Element JavaDoc rd = findNBMElement(dep, "run-dependency");
670             if (rd != null) {
671                 d.run = true;
672                 Element JavaDoc rv = findNBMElement(rd, "release-version");
673                 if (rv != null) {
674                     t = XMLUtil.findText(rv);
675                     if (t == null) {
676                         throw new BuildException("No text in <release-version>", getLocation());
677                     }
678                     d.release = t;
679                 }
680                 Element JavaDoc sv = findNBMElement(rd, "specification-version");
681                 if (sv != null) {
682                     t = XMLUtil.findText(sv);
683                     if (t == null) {
684                         throw new BuildException("No text in <specification-version>", getLocation());
685                     }
686                     d.spec = t;
687                 }
688                 Element JavaDoc iv = findNBMElement(rd, "implementation-version");
689                 if (iv != null) {
690                     d.impl = true;
691                 }
692             }
693             d.compile = findNBMElement(dep, "compile-dependency") != null;
694             deps.add(d);
695         }
696         return deps.toArray(new Dep[deps.size()]);
697     }
698
699     private String JavaDoc getCodeNameBase(Document JavaDoc d) throws BuildException {
700         Element JavaDoc data = getConfig(d);
701         Element JavaDoc name = findNBMElement(data, "code-name-base");
702         if (name == null) {
703             throw new BuildException("No <code-name-base>", getLocation());
704         }
705         String JavaDoc t = XMLUtil.findText(name);
706         if (t == null) {
707             throw new BuildException("No text in <code-name-base>", getLocation());
708         }
709         return t;
710     }
711
712     private int getModuleType(Document JavaDoc d) throws BuildException {
713         Element JavaDoc data = getConfig(d);
714         if (findNBMElement(data, "suite-component") != null) {
715             return TYPE_SUITE;
716         } else if (findNBMElement(data, "standalone") != null) {
717             return TYPE_STANDALONE;
718         } else {
719             return TYPE_NB_ORG;
720         }
721     }
722
723     private String JavaDoc computeClasspath(Document JavaDoc pDoc, ModuleListParser modules, Dep[] deps, boolean runtime) throws BuildException, IOException JavaDoc, SAXException JavaDoc {
724         String JavaDoc myCnb = getCodeNameBase(pDoc);
725         StringBuffer JavaDoc cp = new StringBuffer JavaDoc();
726         String JavaDoc includedClustersProp = getProject().getProperty("enabled.clusters");
727         Set JavaDoc<String JavaDoc> includedClusters = includedClustersProp != null ?
728             new HashSet JavaDoc<String JavaDoc>(Arrays.asList(includedClustersProp.split(" *, *"))) :
729             null;
730         // Compatibility:
731
String JavaDoc excludedClustersProp = getProject().getProperty("disabled.clusters");
732         Set JavaDoc<String JavaDoc> excludedClusters = excludedClustersProp != null ?
733             new HashSet JavaDoc<String JavaDoc>(Arrays.asList(excludedClustersProp.split(" *, *"))) :
734             null;
735         String JavaDoc excludedModulesProp = getProject().getProperty("disabled.modules");
736         Set JavaDoc<String JavaDoc> excludedModules = excludedModulesProp != null ?
737             new HashSet JavaDoc<String JavaDoc>(Arrays.asList(excludedModulesProp.split(" *, *"))) :
738             null;
739         for (Dep dep : deps) { // XXX should operative transitively if runtime
740
if (!dep.compile) { // XXX should be sensitive to runtime
741
continue;
742             }
743             String JavaDoc cnb = dep.codenamebase;
744             File JavaDoc depJar = computeClasspathModuleLocation(modules, cnb, includedClusters, excludedClusters, excludedModules);
745             
746             Attributes JavaDoc attr;
747             if (!depJar.isFile()) {
748                 throw new BuildException("No such classpath entry: " + depJar, getLocation());
749             }
750             JarFile JavaDoc jarFile = new JarFile JavaDoc(depJar, false);
751             try {
752                 attr = jarFile.getManifest().getMainAttributes();
753             } finally {
754                 jarFile.close();
755             }
756             
757             if (!dep.matches(attr)) { // #68631
758
throw new BuildException("Cannot compile against a module: " + depJar + " because of dependency: " + dep, getLocation());
759             }
760
761             if (!runtime && Boolean.parseBoolean(attr.getValue("OpenIDE-Module-Deprecated"))) {
762                 log("The module " + cnb + " has been deprecated", Project.MSG_WARN);
763             }
764
765             List JavaDoc<File JavaDoc> additions = new ArrayList JavaDoc<File JavaDoc>();
766             additions.add(depJar);
767             // #52354: look for <class-path-extension>s in dependent modules.
768
ModuleListParser.Entry entry = modules.findByCodeNameBase(cnb);
769             if (entry != null) {
770                 additions.addAll(Arrays.asList(entry.getClassPathExtensions()));
771             }
772             
773             if (!dep.impl && /* #71807 */ dep.run) {
774                 String JavaDoc friends = attr.getValue("OpenIDE-Module-Friends");
775                 if (friends != null && !Arrays.asList(friends.split(" *, *")).contains(myCnb)) {
776                     throw new BuildException("The module " + myCnb + " is not a friend of " + depJar, getLocation());
777                 }
778                 String JavaDoc pubpkgs = attr.getValue("OpenIDE-Module-Public-Packages");
779                 if ("-".equals(pubpkgs)) {
780                     throw new BuildException("The module " + depJar + " has no public packages and so cannot be compiled against", getLocation());
781                 } else if (pubpkgs != null && !runtime && publicPackageJarDir != null) {
782                     File JavaDoc splitJar = createPublicPackageJar(additions, pubpkgs, publicPackageJarDir, cnb);
783                     additions.clear();
784                     additions.add(splitJar);
785                 }
786             }
787             
788             for (File JavaDoc f : additions) {
789                 if (cp.length() > 0) {
790                     cp.append(':');
791                 }
792                 cp.append(f.getAbsolutePath());
793             }
794         }
795         // Also look for <class-path-extension>s for myself and put them in my own classpath.
796
ModuleListParser.Entry entry = modules.findByCodeNameBase(myCnb);
797         assert entry != null;
798         for (File JavaDoc f : entry.getClassPathExtensions()) {
799             cp.append(':');
800             cp.append(f.getAbsolutePath());
801         }
802         return cp.toString();
803     }
804     
805     private File JavaDoc computeClasspathModuleLocation(ModuleListParser modules, String JavaDoc cnb,
806             Set JavaDoc<String JavaDoc> includedClusters, Set JavaDoc<String JavaDoc> excludedClusters, Set JavaDoc<String JavaDoc> excludedModules) throws BuildException {
807         ModuleListParser.Entry module = modules.findByCodeNameBase(cnb);
808         if (module == null) {
809             throw new BuildException("No dependent module " + cnb, getLocation());
810         }
811         String JavaDoc cluster = module.getClusterName();
812         if (cluster != null) { // #68716
813
if (includedClusters != null && !includedClusters.isEmpty() && !includedClusters.contains(cluster)) {
814                 throw new BuildException("Module " + cnb + " part of cluster " + cluster + " which is excluded from the target platform", getLocation());
815             }
816             if ((includedClusters == null || includedClusters.isEmpty()) && excludedClusters != null && excludedClusters.contains(cluster)) {
817                 throw new BuildException("Module " + cnb + " part of cluster " + cluster + " which is excluded from the target platform", getLocation());
818             }
819             if (excludedModules != null && excludedModules.contains(cnb)) { // again #68716
820
throw new BuildException("Module " + cnb + " excluded from the target platform", getLocation());
821             }
822         }
823         return module.getJar();
824     }
825  
826   final class TestDeps {
827       public static final String JavaDoc UNIT = "unit";
828       public static final String JavaDoc QA_FUNCTIONAL = "qa-functional";
829       // unit, qa-functional, performance
830
final String JavaDoc testtype;
831       // all dependecies for the testtype
832
final List JavaDoc<TestDep> dependencies = new ArrayList JavaDoc<TestDep>();
833       // code name base of tested module
834
final String JavaDoc cnb;
835       final ModuleListParser modulesParser;
836
837       public static final String JavaDoc TEST_DIST_VAR = "test.dist.dir";
838       public TestDeps(String JavaDoc testtype,String JavaDoc cnb,ModuleListParser modulesParser) {
839           assert modulesParser != null;
840           this.testtype = testtype;
841           this.cnb = cnb;
842           this.modulesParser = modulesParser;
843       }
844       
845       public List JavaDoc<String JavaDoc> getFiles(boolean compile) {
846           List JavaDoc<String JavaDoc> files = new ArrayList JavaDoc<String JavaDoc>();
847           for (TestDep d : dependencies) {
848               files.addAll(d.getFiles(compile));
849           }
850           return files;
851       }
852       public void addDepenency(TestDep dep) {
853           dependencies.add(dep);
854       }
855
856         private String JavaDoc getTestFolder() {
857             ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnb);
858             String JavaDoc sep = "/";
859             
860             String JavaDoc cluster = entry.getClusterName();
861             if (cluster == null) {
862                 // no cluster name is specified for standalone or module in module suite
863
cluster = "cluster";
864             }
865             return ParseProjectXml.testDistLocation + sep + testtype + sep + cluster + sep + cnb.replace('.','-');
866         }
867
868         String JavaDoc getCompileClassPath() {
869             return getPath(getFiles(true));
870         }
871         private String JavaDoc getPath(List JavaDoc<String JavaDoc> files) {
872             StringBuffer JavaDoc path = new StringBuffer JavaDoc();
873             Set JavaDoc<String JavaDoc> filesSet = new HashSet JavaDoc<String JavaDoc>();
874             for (String JavaDoc filePath : files) {
875                 if (!filesSet.contains(filePath)) {
876                     if (path.length() > 0) {
877                         path.append(File.pathSeparatorChar);
878                     }
879                     filesSet.add(filePath);
880                     path.append(filePath);
881                 }
882             }
883             return path.toString().replace(File.separatorChar,'/');
884         }
885
886         String JavaDoc getRuntimeClassPath() {
887             return getPath(getFiles(false));
888         }
889         
890
891   }
892    /** Test dependency for module and type
893     */

894    final class TestDep {
895        final ModuleListParser modulesParser;
896        // code name base
897
final String JavaDoc cnb;
898        // dependencies on tests of modules
899
final boolean recursive;
900        final boolean test;
901        // runtime classpath
902
final boolean compile;
903        TestDeps testDeps;
904        
905        TestDep (String JavaDoc cnb,ModuleListParser modules, boolean recursive,boolean test, boolean compile,TestDeps testDeps) {
906            this.modulesParser = modules;
907            this.cnb = cnb;
908            this.recursive = recursive;
909            this.test = test;
910            this.testDeps = testDeps;
911            this.compile = compile;
912        }
913        /* get modules dependecies
914         */

915        List JavaDoc<ModuleListParser.Entry> getModules() {
916            List JavaDoc<ModuleListParser.Entry> entries = new ArrayList JavaDoc<ModuleListParser.Entry>();
917            if (recursive ) {
918                Map JavaDoc<String JavaDoc,ModuleListParser.Entry> entriesMap = new HashMap JavaDoc<String JavaDoc,ModuleListParser.Entry>();
919                addRecursiveModules(cnb,entriesMap);
920                entries.addAll(entriesMap.values());
921            } else {
922                ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnb);
923                if (entry == null) {
924                    throw new BuildException("Module " + cnb + " doesn't exist.");
925                }
926                entries.add(modulesParser.findByCodeNameBase(cnb));
927            }
928            return entries;
929            
930        }
931        
932        private void addRecursiveModules(String JavaDoc cnd, Map JavaDoc<String JavaDoc,ModuleListParser.Entry> entriesMap) {
933            if (!entriesMap.containsKey(cnd)) {
934                ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnd);
935                if (entry == null) {
936                    throw new BuildException("Module " + cnd + " doesn't exist.");
937                }
938                entriesMap.put(cnd,entry);
939                String JavaDoc cnds[] = entry.getRuntimeDependencies();
940                // cnds can be null
941
if (cnds != null) {
942                    for (String JavaDoc c : cnds) {
943                        addRecursiveModules(c, entriesMap);
944                    }
945                }
946            }
947        }
948        List JavaDoc<String JavaDoc> getFiles(boolean compile) {
949            List JavaDoc<String JavaDoc> files = new ArrayList JavaDoc<String JavaDoc>();
950            if (!compile || ( compile && this.compile)) {
951                List JavaDoc<ModuleListParser.Entry> modules = getModules();
952                for (ModuleListParser.Entry entry : getModules()) {
953                    if (entry != null) {
954                        files.add(entry.getJar().getAbsolutePath());
955                    } else {
956                        log("Entry doesn't exist.");
957                    }
958                }
959                // get tests files
960
if (test) {
961                    // get test folder
962
ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnb);
963                    String JavaDoc sep = File.separator;
964                    String JavaDoc cluster = entry.getClusterName();
965                    if (cluster == null) {
966                        cluster = "cluster";
967                    }
968                    String JavaDoc jarPath = ParseProjectXml.testDistLocation + sep + testDeps.testtype + sep + cluster + sep + cnb.replace('.','-') + sep + "tests.jar";
969                    files.add(jarPath);
970                }
971            }
972            return files;
973        }
974    }
975     private String JavaDoc computeClassPathExtensions(Document JavaDoc pDoc) {
976         Element JavaDoc data = getConfig(pDoc);
977         StringBuffer JavaDoc list = null;
978         for (Element JavaDoc ext : XMLUtil.findSubElements(data)) {
979             if (!ext.getLocalName().equals("class-path-extension")) {
980                 continue;
981             }
982             Element JavaDoc runtimeRelativePath = findNBMElement(ext, "runtime-relative-path");
983             if (runtimeRelativePath == null) {
984                 throw new BuildException("Have malformed <class-path-extension> in " + getProjectFile(), getLocation());
985             }
986             String JavaDoc reltext = XMLUtil.findText(runtimeRelativePath);
987             if (list == null) {
988                 list = new StringBuffer JavaDoc();
989             } else {
990                 list.append(' ');
991             }
992             list.append(reltext);
993         }
994         return list != null ? list.toString() : null;
995     }
996
997     /**
998      * Create a compact JAR containing only classes in public packages.
999      * Forces the compiler to honor public package restrictions.
1000     * @see "#59792"
1001     */

1002    private File JavaDoc createPublicPackageJar(List JavaDoc<File JavaDoc> jars, String JavaDoc pubpkgs, File JavaDoc dir, String JavaDoc cnb) throws IOException JavaDoc {
1003        if (!dir.isDirectory()) {
1004            throw new IOException JavaDoc("No such directory " + dir);
1005        }
1006        File JavaDoc ppjar = new File JavaDoc(dir, cnb.replace('.', '-') + ".jar");
1007        if (ppjar.exists()) {
1008            // Check if it is up to date first. Must be as new as any input JAR.
1009
boolean uptodate = true;
1010            long stamp = ppjar.lastModified();
1011            for (File JavaDoc jar : jars) {
1012                if (jar.lastModified() > stamp) {
1013                    uptodate = false;
1014                    break;
1015                }
1016            }
1017            if (uptodate) {
1018                log("Distilled " + ppjar + " was already up to date", Project.MSG_VERBOSE);
1019                return ppjar;
1020            }
1021        }
1022        log("Distilling " + ppjar + " from " + jars);
1023        String JavaDoc corePattern = pubpkgs.
1024                replaceAll(" +", "").
1025                replaceAll("\\.", "/").
1026                replaceAll(",", "|").
1027                replaceAll("\\*\\*", "(.+/)?").
1028                replaceAll("\\*", "");
1029        Pattern JavaDoc p = Pattern.compile("(" + corePattern + ")[^/]+\\.class");
1030        // E.g.: (org/netbeans/api/foo/|org/netbeans/spi/foo/)[^/]+\.class
1031
OutputStream JavaDoc os = new FileOutputStream JavaDoc(ppjar);
1032        try {
1033            ZipOutputStream JavaDoc zos = new ZipOutputStream JavaDoc(os);
1034            Set JavaDoc<String JavaDoc> addedPaths = new HashSet JavaDoc<String JavaDoc>();
1035            for (File JavaDoc jar : jars) {
1036                if (!jar.isFile()) {
1037                    log("Classpath entry " + jar + " does not exist; skipping", Project.MSG_WARN);
1038                }
1039                InputStream JavaDoc is = new FileInputStream JavaDoc(jar);
1040                try {
1041                    ZipInputStream JavaDoc zis = new ZipInputStream JavaDoc(is);
1042                    ZipEntry JavaDoc inEntry;
1043                    while ((inEntry = zis.getNextEntry()) != null) {
1044                        String JavaDoc path = inEntry.getName();
1045                        if (!addedPaths.add(path)) {
1046                            continue;
1047                        }
1048                        if (!p.matcher(path).matches()) {
1049                            continue;
1050                        }
1051                        ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
1052                        byte[] buf = new byte[4096];
1053                        int read;
1054                        while ((read = zis.read(buf)) != -1) {
1055                            baos.write(buf, 0, read);
1056                        }
1057                        byte[] data = baos.toByteArray();
1058                        ZipEntry JavaDoc outEntry = new ZipEntry JavaDoc(path);
1059                        outEntry.setSize(data.length);
1060                        CRC32 JavaDoc crc = new CRC32 JavaDoc();
1061                        crc.update(data);
1062                        outEntry.setCrc(crc.getValue());
1063                        zos.putNextEntry(outEntry);
1064                        zos.write(data);
1065                    }
1066                } finally {
1067                    is.close();
1068                }
1069            }
1070            zos.close();
1071        } finally {
1072            os.close();
1073        }
1074        return ppjar;
1075    }
1076
1077    private TestDeps[] getTestDeps(Document JavaDoc pDoc,ModuleListParser modules,String JavaDoc testCnb) {
1078        assert modules != null;
1079        Element JavaDoc cfg = getConfig(pDoc);
1080        List JavaDoc<TestDeps> testDepsList = new ArrayList JavaDoc<TestDeps>();
1081        Element JavaDoc pp = findNBMElement(cfg, "test-dependencies");
1082        boolean existsUnitTests = false;
1083        boolean existsQaFunctionalTests = false;
1084        if (pp != null) {
1085            for (Element JavaDoc depssEl : XMLUtil.findSubElements(pp)) {
1086                String JavaDoc testType = findTextOrNull(depssEl,"name");
1087                if (testType == null) {
1088                    testType = TestDeps.UNIT; // default variant
1089
existsUnitTests = true;
1090                } else if (testType.equals(TestDeps.UNIT)) {
1091                    existsUnitTests = true;
1092                } else if (testType.equals(TestDeps.QA_FUNCTIONAL)) {
1093                    existsQaFunctionalTests = true;
1094                }
1095                TestDeps testDeps = new TestDeps(testType,testCnb,modules);
1096                testDepsList.add(testDeps);
1097                for (Element JavaDoc el : XMLUtil.findSubElements(depssEl)) {
1098                    if (el.getTagName().equals("test-dependency")) {
1099                        // parse test dep
1100
boolean test = (findNBMElement(el,"test") != null);
1101                        String JavaDoc cnb = findTextOrNull(el,"code-name-base");
1102                        boolean recursive = (findNBMElement(el,"recursive") != null);
1103                        boolean compile = (findNBMElement(el,"compile-dependency") != null);
1104                        testDeps.addDepenency(new TestDep(cnb,
1105                                                         modules,
1106                                                         recursive,
1107                                                         test,
1108                                                         compile,
1109                                                         testDeps));
1110                    }
1111
1112                }
1113            }
1114        }
1115        // #82204 intialize default testtypes when are not in project.xml
1116
if (!existsUnitTests) {
1117            log("Default TestDeps for unit", Project.MSG_VERBOSE);
1118            testDepsList.add(new TestDeps(TestDeps.UNIT,testCnb,modules));
1119        }
1120        if (!existsQaFunctionalTests) {
1121            log("Default TestDeps for qa-functional", Project.MSG_VERBOSE);
1122            testDepsList.add(new TestDeps(TestDeps.QA_FUNCTIONAL,testCnb,modules));
1123        }
1124        return testDepsList.toArray(new TestDeps[testDepsList.size()]);
1125    }
1126    private static String JavaDoc findTextOrNull(Element JavaDoc parentElement,String JavaDoc elementName) {
1127        Element JavaDoc el = findNBMElement(parentElement,elementName);
1128        return (el == null) ? null :
1129                              XMLUtil.findText(el);
1130                
1131    }
1132    private static String JavaDoc NBM_NS_CACHE = NBM_NS3;
1133    static Element JavaDoc findNBMElement(Element JavaDoc el,String JavaDoc name) {
1134        Element JavaDoc retEl = XMLUtil.findElement(el,name,NBM_NS_CACHE) ;
1135        if (retEl == null) {
1136            NBM_NS_CACHE = (NBM_NS_CACHE == NBM_NS3) ? NBM_NS2 :NBM_NS3;
1137            retEl = XMLUtil.findElement(el,name,NBM_NS_CACHE) ;
1138        }
1139        return retEl;
1140    }
1141 
1142}
1143
Popular Tags