1 19 20 import java.io.ByteArrayOutputStream ; 21 import java.io.File ; 22 import java.io.FileInputStream ; 23 import java.io.FileOutputStream ; 24 import java.io.FilenameFilter ; 25 import java.io.InputStream ; 26 import java.io.IOException ; 27 import java.io.OutputStream ; 28 import java.io.PrintWriter ; 29 import java.util.Comparator ; 30 import java.util.Enumeration ; 31 import java.util.HashSet ; 32 import java.util.Iterator ; 33 import java.util.Locale ; 34 import java.util.Map ; 35 import java.util.Set ; 36 import java.util.StringTokenizer ; 37 import java.util.TreeMap ; 38 import java.util.TreeSet ; 39 import java.util.jar.Attributes ; 40 import java.util.jar.Manifest ; 41 import javax.xml.parsers.DocumentBuilder ; 42 import javax.xml.parsers.DocumentBuilderFactory ; 43 import javax.xml.parsers.ParserConfigurationException ; 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 ; 51 import org.w3c.dom.Element ; 52 import org.w3c.dom.NodeList ; 53 import org.xml.sax.SAXException ; 54 55 59 public class ConvertToNbmProjectTask extends Task { 60 61 private static final String NS_PROJECT = "http://www.netbeans.org/ns/project/1"; 62 private static final String NS_NBMPROJECT = "http://www.netbeans.org/ns/nb-module-project/3"; 63 private static final String 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 TYPE = "org.netbeans.modules.apisupport.project"; 65 66 private File nbroot; 67 public void setNbroot(File r) { 68 nbroot = r; 69 } 70 71 private String path; 72 public void setPath(String p) { 73 path = p; 74 } 75 76 public void execute() throws BuildException { 77 File dir = new File (nbroot, path.replace('/', File.separatorChar)); 78 if (!dir.exists()) { 79 throw new BuildException("No such dir " + dir); 80 } 81 File nbprojectDir = new File (dir, "nbproject"); 82 if (nbprojectDir.exists()) { 83 throw new BuildException("Some project already defined in " + dir); 84 } 85 File buildXml = new File (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 e.printStackTrace(); 99 } 100 { 101 Document testDoc = XMLUtil.createDocument("foo", "urn:testns", null, null); 104 OutputStream testOs = new ByteArrayOutputStream (); 105 try { 106 XMLUtil.write(testDoc, testOs, "UTF-8"); 107 } catch (Exception e) { 108 throw new BuildException(e); 109 } 110 } 111 File manifest = new File (dir, "manifest.mf"); 112 if (!manifest.isFile()) { 113 throw new BuildException("No such file " + manifest, getLocation()); 114 } 115 String cnb; 116 String moduleDeps; 117 String openideDeps; 118 String pkgs; 119 String implVers; 120 Set packagesWithClasses = new TreeSet (); 121 try { 122 InputStream is = new FileInputStream (manifest); 123 try { 124 Manifest mani = new Manifest (is); 125 Attributes attr = mani.getMainAttributes(); 126 String 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 src = new File (dir, "src"); 144 scanForClasses(src, "", packagesWithClasses); 145 log("Found packages with classes in them: " + packagesWithClasses, Project.MSG_VERBOSE); 146 } catch (IOException e) { 147 throw new BuildException(e); 148 } 149 DocumentBuilder db; 150 try { 151 db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 152 } catch (ParserConfigurationException e) { 153 throw new BuildException(e); 154 } 155 Map javadocProperties = new TreeMap (); 156 try { 157 Document doc = db.parse(buildXml); 158 NodeList nl = doc.getElementsByTagName("target"); 159 for (int i = 0; i < nl.getLength(); i++) { 160 Element targetEl = (Element )nl.item(i); 161 String name = targetEl.getAttribute("name"); 162 if (name.equals("javadoc")) { 163 NodeList nl2 = targetEl.getElementsByTagName("ant"); 165 if (nl2.getLength() == 1) { 166 Element antEl = (Element )nl2.item(0); 167 NodeList nl3 = antEl.getElementsByTagName("property"); 168 for (int j = 0; j < nl3.getLength(); j++) { 169 Element propEl = (Element )nl3.item(j); 170 String 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 continue; 176 } 177 String value = propEl.getAttribute("value"); 178 if (!value.equals("")) { 179 javadocProperties.put(propName, value); 180 } else { 181 String 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 e) { 196 throw new BuildException(e); 197 } catch (SAXException e) { 198 throw new BuildException(e); 199 } 200 Set deps = new TreeSet (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 deps.addAll(Dependency.create(Dependency.TYPE_MODULE, "org.openide/1 > 4.23")); 209 } 210 Set packages = new TreeSet (); 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 _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 tok = new StringTokenizer (_pkgs, ", "); 222 while (tok.hasMoreTokens()) { 223 String piece = tok.nextToken(); 224 if (piece.endsWith(".*")) { String pkg = piece.substring(0, piece.length() - 2); 226 packages.add(pkg); 227 } else if (piece.endsWith(".**")) { String pkg = piece.substring(0, piece.length() - 3); 229 if (packagesWithClasses.contains(pkg)) { 230 packages.add(pkg); 231 } 232 String prefix = piece.substring(0, piece.length() - 2); 233 Iterator it = packagesWithClasses.iterator(); 234 while (it.hasNext()) { 235 String knownPkg = (String )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 doc = db.getDOMImplementation().createDocument(NS_PROJECT, "project", null); 246 Element projectEl = doc.getDocumentElement(); 247 doc.insertBefore(doc.createComment("\n" + CDDL_COMMENT + "\n"), projectEl); 248 Element typeEl = doc.createElementNS(NS_PROJECT, "type"); 249 typeEl.appendChild(doc.createTextNode(TYPE)); 250 projectEl.appendChild(typeEl); 251 Element configEl = doc.createElementNS(NS_PROJECT, "configuration"); 252 Element dataEl = doc.createElementNS(NS_NBMPROJECT, "data"); 253 Element nameEl = doc.createElementNS(NS_NBMPROJECT, "code-name-base"); 254 nameEl.appendChild(doc.createTextNode(cnb)); 255 dataEl.appendChild(nameEl); 256 Element modDepsEl = doc.createElementNS(NS_NBMPROJECT, "module-dependencies"); 257 Iterator 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 pubPkgsEl = doc.createElementNS(NS_NBMPROJECT, "public-packages"); 264 it = packages.iterator(); 265 while (it.hasNext()) { 266 Element packageEl = doc.createElementNS(NS_NBMPROJECT, "package"); 267 packageEl.appendChild(doc.createTextNode((String )it.next())); 268 pubPkgsEl.appendChild(packageEl); 269 } 270 dataEl.appendChild(pubPkgsEl); 271 configEl.appendChild(dataEl); 272 projectEl.appendChild(configEl); 273 nbprojectDir.mkdir(); 274 File projectXml = new File (nbprojectDir, "project.xml"); 275 try { 276 OutputStream os = new FileOutputStream (projectXml); 277 try { 278 XMLUtil.write(doc, os, "UTF-8"); 279 } finally { 280 os.close(); 281 } 282 } catch (IOException e) { 283 throw new BuildException(e); 284 } 285 File projectProps = new File (nbprojectDir, "project.properties"); 287 try { 288 OutputStream os = new FileOutputStream (projectProps); 289 try { 290 PrintWriter w = new PrintWriter (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 entry = (Map.Entry )it.next(); 299 String name = (String )entry.getKey(); 300 String value = (String )entry.getValue(); 301 w.println(name + "=" + value); 302 } 303 w.flush(); 304 } finally { 305 os.close(); 306 } 307 } catch (IOException 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 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 (dir, ".cvsignore") + ": no more 'manifest-subst.mf' (or 'netbeans' or 'Info'); add 'build'."); 331 log("(Usually need just 'build'.)"); 332 if (new File (new File (new File (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 (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 } 343 344 private static void scanForClasses(File dir, String prefix, Set pkgs) throws IOException { 345 File [] kids = dir.listFiles(); 346 if (kids == null) { 347 throw new IOException ("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 { 359 360 public int compare(Object o1, Object o2) { 361 Dependency d1 = (Dependency)o1; 362 Dependency d2 = (Dependency)o2; 363 return trimRelVers(d1.getName()).compareTo(trimRelVers(d2.getName())); 365 } 366 367 private static String trimRelVers(String 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 dependencyToXml(Dependency d, Document doc) throws BuildException { 379 assert d.getType() == Dependency.TYPE_MODULE : d; 380 String name = d.getName(); 381 int slash = name.indexOf('/'); 382 String 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 depEl = doc.createElementNS(NS_NBMPROJECT, "dependency"); 391 Element cnbEl = doc.createElementNS(NS_NBMPROJECT, "code-name-base"); 392 cnbEl.appendChild(doc.createTextNode(cnb)); 393 depEl.appendChild(cnbEl); 394 Element buildEl = doc.createElementNS(NS_NBMPROJECT, "build-prerequisite"); 395 depEl.appendChild(buildEl); 396 Element compileEl = doc.createElementNS(NS_NBMPROJECT, "compile-dependency"); 397 depEl.appendChild(compileEl); 398 Element runEl = doc.createElementNS(NS_NBMPROJECT, "run-dependency"); 399 if (relvers != null) { 400 Element 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 break; 408 case Dependency.COMPARE_SPEC: 409 Element 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 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
|