KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ConvertToNbmProjectTask


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 import java.io.ByteArrayOutputStream JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.FilenameFilter JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.OutputStream JavaDoc;
28 import java.io.PrintWriter JavaDoc;
29 import java.util.Comparator JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.Locale JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37 import java.util.TreeMap JavaDoc;
38 import java.util.TreeSet JavaDoc;
39 import java.util.jar.Attributes JavaDoc;
40 import java.util.jar.Manifest JavaDoc;
41 import javax.xml.parsers.DocumentBuilder JavaDoc;
42 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
43 import javax.xml.parsers.ParserConfigurationException JavaDoc;
44 import org.apache.tools.ant.Task;
45 import org.apache.tools.ant.BuildException;
46 import org.apache.tools.ant.Project;
47 import org.apache.tools.ant.taskdefs.Ant;
48 import org.openide.modules.Dependency;
49 import org.openide.xml.XMLUtil;
50 import org.w3c.dom.Document JavaDoc;
51 import org.w3c.dom.Element JavaDoc;
52 import org.w3c.dom.NodeList JavaDoc;
53 import org.xml.sax.SAXException JavaDoc;
54
55 /**
56  * Try to convert an existing NetBeans source module to a project.
57  * @author Jesse Glick
58  */

59 public class ConvertToNbmProjectTask extends Task {
60     
61     private static final String JavaDoc NS_PROJECT = "http://www.netbeans.org/ns/project/1";
62     private static final String JavaDoc NS_NBMPROJECT = "http://www.netbeans.org/ns/nb-module-project/3";
63     private static final String JavaDoc CDDL_COMMENT = "The contents of this file are subject to the terms of the Common Development\nand Distribution License (the License). You may not use this file except in\ncompliance with the License.\n\nYou can obtain a copy of the License at http://www.netbeans.org/cddl.html\nor http://www.netbeans.org/cddl.txt.\n\nWhen distributing Covered Code, include this CDDL Header Notice in each file\nand include the License file at http://www.netbeans.org/cddl.txt.\nIf applicable, add the following below the CDDL Header, with the fields\nenclosed by brackets [] replaced by your own identifying information:\n\"Portions Copyrighted [year] [name of copyright owner]\"\n\nThe Original Software is NetBeans. The Initial Developer of the Original\nSoftware is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun\nMicrosystems, Inc. All Rights Reserved.";
64     private static final String JavaDoc TYPE = "org.netbeans.modules.apisupport.project";
65     
66     private File JavaDoc nbroot;
67     public void setNbroot(File JavaDoc r) {
68         nbroot = r;
69     }
70     
71     private String JavaDoc path;
72     public void setPath(String JavaDoc p) {
73         path = p;
74     }
75     
76     public void execute() throws BuildException {
77         File JavaDoc dir = new File JavaDoc(nbroot, path.replace('/', File.separatorChar));
78         if (!dir.exists()) {
79             throw new BuildException("No such dir " + dir);
80         }
81         File JavaDoc nbprojectDir = new File JavaDoc(dir, "nbproject");
82         if (nbprojectDir.exists()) {
83             throw new BuildException("Some project already defined in " + dir);
84         }
85         File JavaDoc buildXml = new File JavaDoc(dir, "build.xml");
86         if (!buildXml.isFile()) {
87             throw new BuildException("No such " + buildXml);
88         }
89         Ant ant = (Ant)getProject().createTask("ant");
90         ant.setDir(dir);
91         ant.setTarget("clean");
92         ant.setLocation(getLocation());
93         ant.init();
94         try {
95             ant.execute();
96         } catch (BuildException e) {
97             // Probably not fatal.
98
e.printStackTrace();
99         }
100         {
101             // Make sure DOM serialization is functional before we go any further
102
// and start touching files on disk.
103
Document JavaDoc testDoc = XMLUtil.createDocument("foo", "urn:testns", null, null);
104             OutputStream JavaDoc testOs = new ByteArrayOutputStream JavaDoc();
105             try {
106                 XMLUtil.write(testDoc, testOs, "UTF-8");
107             } catch (Exception JavaDoc e) {
108                 throw new BuildException(e);
109             }
110         }
111         File JavaDoc manifest = new File JavaDoc(dir, "manifest.mf");
112         if (!manifest.isFile()) {
113             throw new BuildException("No such file " + manifest, getLocation());
114         }
115         String JavaDoc cnb;
116         String JavaDoc moduleDeps;
117         String JavaDoc openideDeps;
118         String JavaDoc pkgs;
119         String JavaDoc implVers;
120         Set JavaDoc/*<String>*/ packagesWithClasses = new TreeSet JavaDoc();
121         try {
122             InputStream JavaDoc is = new FileInputStream JavaDoc(manifest);
123             try {
124                 Manifest JavaDoc mani = new Manifest JavaDoc(is);
125                 Attributes JavaDoc attr = mani.getMainAttributes();
126                 String JavaDoc cnbr = attr.getValue("OpenIDE-Module");
127                 if (cnbr == null) {
128                     throw new BuildException("No OpenIDE-Module found in " + manifest);
129                 }
130                 int idx = cnbr.lastIndexOf('/');
131                 if (idx == -1) {
132                     cnb = cnbr;
133                 } else {
134                     cnb = cnbr.substring(0, idx);
135                 }
136                 moduleDeps = attr.getValue("OpenIDE-Module-Module-Dependencies");
137                 openideDeps = attr.getValue("OpenIDE-Module-IDE-Dependencies");
138                 pkgs = attr.getValue("OpenIDE-Module-Public-Packages");
139                 implVers = attr.getValue("OpenIDE-Module-Implementation-Version");
140             } finally {
141                 is.close();
142             }
143             File JavaDoc src = new File JavaDoc(dir, "src");
144             scanForClasses(src, "", packagesWithClasses);
145             log("Found packages with classes in them: " + packagesWithClasses, Project.MSG_VERBOSE);
146         } catch (IOException JavaDoc e) {
147             throw new BuildException(e);
148         }
149         DocumentBuilder JavaDoc db;
150         try {
151             db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
152         } catch (ParserConfigurationException JavaDoc e) {
153             throw new BuildException(e);
154         }
155         Map JavaDoc/*<String,String>*/ javadocProperties = new TreeMap JavaDoc();
156         try {
157             Document JavaDoc doc = db.parse(buildXml);
158             NodeList JavaDoc nl = doc.getElementsByTagName("target");
159             for (int i = 0; i < nl.getLength(); i++) {
160                 Element JavaDoc targetEl = (Element JavaDoc)nl.item(i);
161                 String JavaDoc name = targetEl.getAttribute("name");
162                 if (name.equals("javadoc")) {
163                     // Try to look for defined properties too.
164
NodeList JavaDoc nl2 = targetEl.getElementsByTagName("ant");
165                     if (nl2.getLength() == 1) {
166                         Element JavaDoc antEl = (Element JavaDoc)nl2.item(0);
167                         NodeList JavaDoc nl3 = antEl.getElementsByTagName("property");
168                         for (int j = 0; j < nl3.getLength(); j++) {
169                             Element JavaDoc propEl = (Element JavaDoc)nl3.item(j);
170                             String JavaDoc propName = propEl.getAttribute("name");
171                             if (propName.equals("javadoc.base") || propName.equals("javadoc.packages") ||
172                                     propName.equals("javadoc.name") ||
173                                     propName.equals("javadoc.classpath") || propName.equals("javadoc.manifest")) {
174                                 // projectized.xml defines these.
175
continue;
176                             }
177                             String JavaDoc value = propEl.getAttribute("value");
178                             if (!value.equals("")) {
179                                 javadocProperties.put(propName, value);
180                             } else {
181                                 String JavaDoc location = propEl.getAttribute("location");
182                                 if (!location.equals("")) {
183                                     javadocProperties.put(propName, "${basedir}/" + location);
184                                 } else {
185                                     log("Warning: do not grok <property> with name " + propName + "in javadoc target in " + buildXml, Project.MSG_WARN);
186                                 }
187                             }
188                         }
189                     } else {
190                         log("Warning: do not grok javadoc target in " + buildXml, Project.MSG_WARN);
191                     }
192                     break;
193                 }
194             }
195         } catch (IOException JavaDoc e) {
196             throw new BuildException(e);
197         } catch (SAXException JavaDoc e) {
198             throw new BuildException(e);
199         }
200         Set JavaDoc/*<Dependency>*/ deps = new TreeSet JavaDoc(new DependencyComparator());
201         if (moduleDeps != null) {
202             deps.addAll(Dependency.create(Dependency.TYPE_MODULE, moduleDeps));
203         }
204         if (openideDeps != null) {
205             deps.addAll(Dependency.create(Dependency.TYPE_MODULE, openideDeps.replaceFirst("IDE/", "org.openide/")));
206         } else {
207             // fallback - latest in effect at time of writing
208
deps.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/1 > 4.23"));
209         }
210         Set JavaDoc/*<String>*/ packages = new TreeSet JavaDoc();
211         if (pkgs == null) {
212             log("Warning - no OpenIDE-Module-Public-Packages declaration found; so assuming only standard package names are public", Project.MSG_WARN);
213         }
214         if (pkgs == null || !pkgs.equals("-")) {
215             String JavaDoc _pkgs;
216             if (pkgs != null) {
217                 _pkgs = pkgs;
218             } else {
219                 _pkgs = "org.netbeans.api.**, org.netbeans.spi.**, org.openide.**, org.openidex.**";
220             }
221             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(_pkgs, ", ");
222             while (tok.hasMoreTokens()) {
223                 String JavaDoc piece = tok.nextToken();
224                 if (piece.endsWith(".*")) { // NOI18N
225
String JavaDoc pkg = piece.substring(0, piece.length() - 2);
226                     packages.add(pkg);
227                 } else if (piece.endsWith(".**")) { // NOI18N
228
String JavaDoc pkg = piece.substring(0, piece.length() - 3);
229                     if (packagesWithClasses.contains(pkg)) {
230                         packages.add(pkg);
231                     }
232                     String JavaDoc prefix = piece.substring(0, piece.length() - 2);
233                     Iterator JavaDoc it = packagesWithClasses.iterator();
234                     while (it.hasNext()) {
235                         String JavaDoc knownPkg = (String JavaDoc)it.next();
236                         if (knownPkg.startsWith(prefix)) {
237                             packages.add(knownPkg);
238                         }
239                     }
240                 } else {
241                     throw new BuildException("Illegal OpenIDE-Module-Public-Packages: " + pkgs);
242                 }
243             }
244         }
245         Document JavaDoc doc = db.getDOMImplementation().createDocument(NS_PROJECT, "project", null);
246         Element JavaDoc projectEl = doc.getDocumentElement();
247         doc.insertBefore(doc.createComment("\n" + CDDL_COMMENT + "\n"), projectEl);
248         Element JavaDoc typeEl = doc.createElementNS(NS_PROJECT, "type");
249         typeEl.appendChild(doc.createTextNode(TYPE));
250         projectEl.appendChild(typeEl);
251         Element JavaDoc configEl = doc.createElementNS(NS_PROJECT, "configuration");
252         Element JavaDoc dataEl = doc.createElementNS(NS_NBMPROJECT, "data");
253         Element JavaDoc nameEl = doc.createElementNS(NS_NBMPROJECT, "code-name-base");
254         nameEl.appendChild(doc.createTextNode(cnb));
255         dataEl.appendChild(nameEl);
256         Element JavaDoc modDepsEl = doc.createElementNS(NS_NBMPROJECT, "module-dependencies");
257         Iterator JavaDoc it = deps.iterator();
258         while (it.hasNext()) {
259             Dependency d = (Dependency)it.next();
260             modDepsEl.appendChild(dependencyToXml(d, doc));
261         }
262         dataEl.appendChild(modDepsEl);
263         Element JavaDoc pubPkgsEl = doc.createElementNS(NS_NBMPROJECT, "public-packages");
264         it = packages.iterator();
265         while (it.hasNext()) {
266             Element JavaDoc packageEl = doc.createElementNS(NS_NBMPROJECT, "package");
267             packageEl.appendChild(doc.createTextNode((String JavaDoc)it.next()));
268             pubPkgsEl.appendChild(packageEl);
269         }
270         dataEl.appendChild(pubPkgsEl);
271         configEl.appendChild(dataEl);
272         projectEl.appendChild(configEl);
273         nbprojectDir.mkdir();
274         File JavaDoc projectXml = new File JavaDoc(nbprojectDir, "project.xml");
275         try {
276             OutputStream JavaDoc os = new FileOutputStream JavaDoc(projectXml);
277             try {
278                 XMLUtil.write(doc, os, "UTF-8");
279             } finally {
280                 os.close();
281             }
282         } catch (IOException JavaDoc e) {
283             throw new BuildException(e);
284         }
285         // XXX would be nice to validate project.xml now against the schema...
286
File JavaDoc projectProps = new File JavaDoc(nbprojectDir, "project.properties");
287         try {
288             OutputStream JavaDoc os = new FileOutputStream JavaDoc(projectProps);
289             try {
290                 PrintWriter JavaDoc w = new PrintWriter JavaDoc(os);
291                 w.print("# ");
292                 w.println(CDDL_COMMENT.replaceAll("\n", "\n# "));
293                 it = javadocProperties.entrySet().iterator();
294                 if (it.hasNext()) {
295                     w.println();
296                 }
297                 while (it.hasNext()) {
298                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
299                     String JavaDoc name = (String JavaDoc)entry.getKey();
300                     String JavaDoc value = (String JavaDoc)entry.getValue();
301                     w.println(name + "=" + value);
302                 }
303                 w.flush();
304             } finally {
305                 os.close();
306             }
307         } catch (IOException JavaDoc e) {
308             throw new BuildException(e);
309         }
310         log("All done; inspect " + projectXml + " and " + projectProps + " for accuracy.");
311         log("(You may need to add is.autoload=true or is.eager=true as this is not currently autodetected.)");
312         log("Many modules forgot to declare a dep on org.openide.loaders in their manifests - check if you need to add this to project.xml.");
313         log("Add <class-path-extension>s to " + projectXml + " if there are extra JARs on the module's compilation classpath.");
314         log("Add some <extra-compilation-unit>s to " + projectXml + " if you have something like libsrc or antsrc.");
315         String JavaDoc dots = path.replaceAll("[^/]+", "..");
316         log("Edit build.xml to contain just <import file=\"" + dots + "/nbbuild/templates/projectized.xml\"/> and maybe other stuff as needed.");
317         log("You need to remove some entries from " + manifest + ":");
318         if (moduleDeps != null) {
319             log(" OpenIDE-Module-Module-Dependencies: " + moduleDeps);
320         }
321         if (openideDeps != null) {
322             log(" OpenIDE-Module-IDE-Dependencies: " + openideDeps);
323         }
324         if (pkgs != null) {
325             log(" OpenIDE-Module-Public-Packages: " + pkgs);
326         }
327         if (implVers != null) {
328             log(" OpenIDE-Module-Implementation-Version: " + implVers);
329         }
330         log("Don't forget to update " + new File JavaDoc(dir, ".cvsignore") + ": no more 'manifest-subst.mf' (or 'netbeans' or 'Info'); add 'build'.");
331         log("(Usually need just 'build'.)");
332         if (new File JavaDoc(new File JavaDoc(new File JavaDoc(dir, "test"), "unit"), "src").isDirectory()) {
333             log("Delete or projectize any test/build.xml and test/build-unit.xml and define test.unit.cp.extra and/or test.unit.run.cp.extra in " + projectProps + " as needed.");
334         }
335         if (new File JavaDoc(dir, "javahelp").exists()) {
336             log("You appear to have some JavaHelp. This should be built automatically.");
337         }
338         log("(If any unprojectized modules build against this one, edit their build.xml to use ${" + path + ".dir}/modules/" + cnb.replace('.', '-') + ".jar instead of the current JAR path.)");
339         // XXX some info about which of -Spec-Vers and -Impl-Vers to keep in manifest
340
// XXX create nbproject/.cvsignore: "private"
341
// XXX delete Class-Path
342
}
343
344     private static void scanForClasses(File JavaDoc dir, String JavaDoc prefix, Set JavaDoc/*<String>*/ pkgs) throws IOException JavaDoc {
345         File JavaDoc[] kids = dir.listFiles();
346         if (kids == null) {
347             throw new IOException JavaDoc("Could not list " + dir);
348         }
349         for (int i = 0; i < kids.length; i++) {
350             if (kids[i].isDirectory()) {
351                 scanForClasses(kids[i], prefix + kids[i].getName() + '/', pkgs);
352             } else if (kids[i].getName().endsWith(".java") && prefix.length() > 0) {
353                 pkgs.add(prefix.substring(0, prefix.length() - 1).replace('/', '.'));
354             }
355         }
356     }
357     
358     private static final class DependencyComparator implements Comparator JavaDoc {
359         
360         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
361             Dependency d1 = (Dependency)o1;
362             Dependency d2 = (Dependency)o2;
363             // Trim release version so org.openide/1 sorts before org.openide.loaders:
364
return trimRelVers(d1.getName()).compareTo(trimRelVers(d2.getName()));
365         }
366         
367         private static String JavaDoc trimRelVers(String JavaDoc s) {
368             int i = s.indexOf('/');
369             if (i != -1) {
370                 return s.substring(0, i);
371             } else {
372                 return s;
373             }
374         }
375         
376     }
377     
378     private Element JavaDoc dependencyToXml(Dependency d, Document JavaDoc doc) throws BuildException {
379         assert d.getType() == Dependency.TYPE_MODULE : d;
380         String JavaDoc name = d.getName();
381         int slash = name.indexOf('/');
382         String JavaDoc cnb, relvers;
383         if (slash != -1) {
384             cnb = name.substring(0, slash);
385             relvers = name.substring(slash + 1);
386         } else {
387             cnb = name;
388             relvers = null;
389         }
390         Element JavaDoc depEl = doc.createElementNS(NS_NBMPROJECT, "dependency");
391         Element JavaDoc cnbEl = doc.createElementNS(NS_NBMPROJECT, "code-name-base");
392         cnbEl.appendChild(doc.createTextNode(cnb));
393         depEl.appendChild(cnbEl);
394         Element JavaDoc buildEl = doc.createElementNS(NS_NBMPROJECT, "build-prerequisite");
395         depEl.appendChild(buildEl);
396         Element JavaDoc compileEl = doc.createElementNS(NS_NBMPROJECT, "compile-dependency");
397         depEl.appendChild(compileEl);
398         Element JavaDoc runEl = doc.createElementNS(NS_NBMPROJECT, "run-dependency");
399         if (relvers != null) {
400             Element JavaDoc releaseEl = doc.createElementNS(NS_NBMPROJECT, "release-version");
401             releaseEl.appendChild(doc.createTextNode(relvers));
402             runEl.appendChild(releaseEl);
403         }
404         switch (d.getComparison()) {
405         case Dependency.COMPARE_ANY:
406             // Nothing more needed.
407
break;
408         case Dependency.COMPARE_SPEC:
409             Element JavaDoc specEl = doc.createElementNS(NS_NBMPROJECT, "specification-version");
410             specEl.appendChild(doc.createTextNode(d.getVersion()));
411             runEl.appendChild(specEl);
412             break;
413         case Dependency.COMPARE_IMPL:
414             Element JavaDoc implEl = doc.createElementNS(NS_NBMPROJECT, "implementation-version");
415             runEl.appendChild(implEl);
416             break;
417         default:
418             assert false : d;
419         }
420         depEl.appendChild(runEl);
421         return depEl;
422     }
423     
424 }
425
Popular Tags