1 19 20 package org.netbeans.nbbuild; 21 22 import java.io.ByteArrayOutputStream ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.OutputStream ; 29 import java.util.ArrayList ; 30 import java.util.Arrays ; 31 import java.util.HashMap ; 32 import java.util.HashSet ; 33 import java.util.Hashtable ; 34 import java.util.LinkedList ; 35 import java.util.List ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.StringTokenizer ; 39 import java.util.jar.Attributes ; 40 import java.util.jar.JarFile ; 41 import java.util.regex.Pattern ; 42 import java.util.zip.CRC32 ; 43 import java.util.zip.ZipEntry ; 44 import java.util.zip.ZipInputStream ; 45 import java.util.zip.ZipOutputStream ; 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 ; 50 import org.w3c.dom.Element ; 51 import org.xml.sax.InputSource ; 52 import org.xml.sax.SAXException ; 53 54 59 public final class ParseProjectXml extends Task { 60 61 static final String PROJECT_NS = "http://www.netbeans.org/ns/project/1"; 62 static final String NBM_NS2 = "http://www.netbeans.org/ns/nb-module-project/2"; 63 static final String 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 project; 70 73 public void setProject(File f) { 74 project = f; 75 } 76 private File projectFile; 77 81 public void setProjectFile (File f) { 82 projectFile = f; 83 } 84 private File getProjectFile () { 85 if (projectFile != null) { 86 return projectFile; 87 } 88 return new File (new File (project, "nbproject"), "project.xml"); 89 } 90 91 private String publicPackagesProperty; 92 96 public void setPublicPackagesProperty(String s) { 97 publicPackagesProperty = s; 98 } 99 100 private String friendsProperty; 101 105 public void setFriendsProperty(String s) { 106 friendsProperty = s; 107 } 108 109 private String javadocPackagesProperty; 110 114 public void setJavadocPackagesProperty(String s) { 115 javadocPackagesProperty = s; 116 } 117 118 private String moduleDependenciesProperty; 119 124 public void setModuleDependenciesProperty(String s) { 125 moduleDependenciesProperty = s; 126 } 127 128 private String codeNameBaseDashesProperty; 129 133 public void setCodeNameBaseDashesProperty(String s) { 134 codeNameBaseDashesProperty = s; 135 } 136 137 private String codeNameBaseSlashesProperty; 138 142 public void setCodeNameBaseSlashesProperty(String s) { 143 codeNameBaseSlashesProperty = s; 144 } 145 146 private String domainProperty; 147 151 public void setDomainProperty(String s) { 152 domainProperty = s; 153 } 154 155 private String moduleClassPathProperty; 156 160 public void setModuleClassPathProperty(String s) { 161 moduleClassPathProperty = s; 162 } 163 164 private String moduleRunClassPathProperty; 165 173 public void setModuleRunClassPathProperty(String s) { 174 moduleRunClassPathProperty = s; 175 } 176 177 private File publicPackageJarDir; 178 183 public void setPublicPackageJarDir(File d) { 184 publicPackageJarDir = d; 185 } 186 187 private String classPathExtensionsProperty; 188 191 public void setClassPathExtensionsProperty(String s) { 192 classPathExtensionsProperty = s; 193 } 194 195 public static String testDistLocation; 197 198 public static class TestType { 199 private String name; 200 private String folder; 201 private String runtimeCP; 202 private String compileCP; 203 204 public TestType() {} 205 public String getName() { 206 return name; 207 } 208 209 public void setName(String name) { 210 this.name = name; 211 } 212 213 public String getFolder() { 214 return folder; 215 } 216 217 public void setFolder(String folder) { 218 this.folder = folder; 219 } 220 221 public String getRuntimeCP() { 222 return runtimeCP; 223 } 224 225 public void setRuntimeCP(String runtimeCP) { 226 this.runtimeCP = runtimeCP; 227 } 228 229 public String getCompileCP() { 230 return compileCP; 231 } 232 233 public void setCompileCP(String compileCP) { 234 this.compileCP = compileCP; 235 } 236 237 } 238 List <TestType> testTypes = new LinkedList <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 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 prop, String val) { 259 log("Setting " + prop + "=" + val, Project.MSG_VERBOSE); 260 String 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 Document pDoc = XMLUtil.parse(new InputSource (getProjectFile ().toURI().toString()), 277 false, true, null, null); 278 if (publicPackagesProperty != null || javadocPackagesProperty != null) { 279 PublicPackage[] pkgs = getPublicPackages(pDoc); 280 if (publicPackagesProperty != null) { 281 String val; 282 if (pkgs.length > 0) { 283 String sep = ""; 284 StringBuffer b = new StringBuffer (); 285 for (PublicPackage p : pkgs) { 286 b.append(sep); 287 288 String 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 sep = ""; 313 StringBuffer b = new StringBuffer (); 314 for (PublicPackage p : pkgs) { 315 b.append(sep); 316 if (p.subpackages) { 317 if (getProject().getProperty(javadocPackagesProperty) == null) { 318 String 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 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 [] friends = getFriends(pDoc); 333 if (friends != null) { 334 StringBuffer b = new StringBuffer (); 335 for (String 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 ("unchecked") 351 Hashtable <String ,String > 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) { 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 b = new StringBuffer (); 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 cnb = getCodeNameBase(pDoc); 382 define(codeNameBaseDashesProperty, cnb.replace('.', '-')); 383 } 384 if (codeNameBaseSlashesProperty != null) { 385 String cnb = getCodeNameBase(pDoc); 386 define(codeNameBaseSlashesProperty, cnb.replace('.', '/')); 387 } 388 if (moduleClassPathProperty != null) { 389 String cp = computeClasspath(pDoc, modules, deps, false); 390 define(moduleClassPathProperty, cp); 391 } 392 if (moduleRunClassPathProperty != null) { 393 String 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 nball = new File (getProject().getProperty("nb_all")); 401 File basedir = getProject().getBaseDir(); 402 File dir = basedir; 403 while (true) { 404 File 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 val = computeClassPathExtensions(pDoc); 417 if (val != null) { 418 define(classPathExtensionsProperty, val); 419 } 420 } 421 422 if (modules != null) { 425 String 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 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 e) { 450 throw new BuildException(e, getLocation()); 451 } 452 } 453 454 private Element getConfig(Document pDoc) throws BuildException { 455 Element e = pDoc.getDocumentElement(); 456 Element c = XMLUtil.findElement(e, "configuration", PROJECT_NS); 457 if (c == null) { 458 throw new BuildException("No <configuration>", getLocation()); 459 } 460 Element 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 { 468 public final String name; 469 public boolean subpackages; 470 471 public PublicPackage (String name, boolean subpackages) { 472 this.name = name; 473 this.subpackages = subpackages; 474 } 475 } 476 477 private PublicPackage[] getPublicPackages(Document d) throws BuildException { 478 Element cfg = getConfig(d); 479 Element 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 <PublicPackage> pkgs = new ArrayList <PublicPackage>(); 487 for (Element 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 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 [] getFriends(Document d) throws BuildException { 509 Element cfg = getConfig(d); 510 Element pp = findNBMElement(cfg, "friend-packages"); 511 if (pp == null) { 512 return null; 513 } 514 List <String > friends = new ArrayList <String >(); 515 boolean other = false; 516 for (Element p : XMLUtil.findSubElements(pp)) { 517 if ("friend".equals(p.getNodeName())) { 518 String 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 [friends.size()]); 534 } 535 536 private final class Dep { 537 private final ModuleListParser modules; 538 539 public String codenamebase; 540 public String release = null; 541 public String 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 toString() throws BuildException { 551 StringBuffer b = new StringBuffer (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(" = "); String 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 implementationVersionOf(ModuleListParser modules, String cnb) throws BuildException { 573 File 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 jarFile = new JarFile (jar, false); 579 try { 580 return jarFile.getManifest().getMainAttributes().getValue("OpenIDE-Module-Implementation-Version"); 581 } finally { 582 jarFile.close(); 583 } 584 } catch (IOException e) { 585 throw new BuildException(e, getLocation()); 586 } 587 } 588 589 private boolean matches(Attributes attr) { 590 if (release != null) { 591 String 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 givenSpec = attr.getValue("OpenIDE-Module-Specification-Version"); 613 if (givenSpec == null) { 614 return false; 615 } 616 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 spec) throws NumberFormatException { 640 StringTokenizer tok = new StringTokenizer (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 pDoc, ModuleListParser modules) throws BuildException { 652 Element cfg = getConfig(pDoc); 653 Element md = findNBMElement(cfg, "module-dependencies"); 654 if (md == null) { 655 throw new BuildException("No <module-dependencies>", getLocation()); 656 } 657 List <Dep> deps = new ArrayList <Dep>(); 658 for (Element dep : XMLUtil.findSubElements(md)) { 659 Dep d = new Dep(modules); 660 Element cnb = findNBMElement(dep, "code-name-base"); 661 if (cnb == null) { 662 throw new BuildException("No <code-name-base>", getLocation()); 663 } 664 String 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 rd = findNBMElement(dep, "run-dependency"); 670 if (rd != null) { 671 d.run = true; 672 Element 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 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 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 getCodeNameBase(Document d) throws BuildException { 700 Element data = getConfig(d); 701 Element name = findNBMElement(data, "code-name-base"); 702 if (name == null) { 703 throw new BuildException("No <code-name-base>", getLocation()); 704 } 705 String 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 d) throws BuildException { 713 Element 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 computeClasspath(Document pDoc, ModuleListParser modules, Dep[] deps, boolean runtime) throws BuildException, IOException , SAXException { 724 String myCnb = getCodeNameBase(pDoc); 725 StringBuffer cp = new StringBuffer (); 726 String includedClustersProp = getProject().getProperty("enabled.clusters"); 727 Set <String > includedClusters = includedClustersProp != null ? 728 new HashSet <String >(Arrays.asList(includedClustersProp.split(" *, *"))) : 729 null; 730 String excludedClustersProp = getProject().getProperty("disabled.clusters"); 732 Set <String > excludedClusters = excludedClustersProp != null ? 733 new HashSet <String >(Arrays.asList(excludedClustersProp.split(" *, *"))) : 734 null; 735 String excludedModulesProp = getProject().getProperty("disabled.modules"); 736 Set <String > excludedModules = excludedModulesProp != null ? 737 new HashSet <String >(Arrays.asList(excludedModulesProp.split(" *, *"))) : 738 null; 739 for (Dep dep : deps) { if (!dep.compile) { continue; 742 } 743 String cnb = dep.codenamebase; 744 File depJar = computeClasspathModuleLocation(modules, cnb, includedClusters, excludedClusters, excludedModules); 745 746 Attributes attr; 747 if (!depJar.isFile()) { 748 throw new BuildException("No such classpath entry: " + depJar, getLocation()); 749 } 750 JarFile jarFile = new JarFile (depJar, false); 751 try { 752 attr = jarFile.getManifest().getMainAttributes(); 753 } finally { 754 jarFile.close(); 755 } 756 757 if (!dep.matches(attr)) { 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 <File > additions = new ArrayList <File >(); 766 additions.add(depJar); 767 ModuleListParser.Entry entry = modules.findByCodeNameBase(cnb); 769 if (entry != null) { 770 additions.addAll(Arrays.asList(entry.getClassPathExtensions())); 771 } 772 773 if (!dep.impl && dep.run) { 774 String 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 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 splitJar = createPublicPackageJar(additions, pubpkgs, publicPackageJarDir, cnb); 783 additions.clear(); 784 additions.add(splitJar); 785 } 786 } 787 788 for (File f : additions) { 789 if (cp.length() > 0) { 790 cp.append(':'); 791 } 792 cp.append(f.getAbsolutePath()); 793 } 794 } 795 ModuleListParser.Entry entry = modules.findByCodeNameBase(myCnb); 797 assert entry != null; 798 for (File f : entry.getClassPathExtensions()) { 799 cp.append(':'); 800 cp.append(f.getAbsolutePath()); 801 } 802 return cp.toString(); 803 } 804 805 private File computeClasspathModuleLocation(ModuleListParser modules, String cnb, 806 Set <String > includedClusters, Set <String > excludedClusters, Set <String > 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 cluster = module.getClusterName(); 812 if (cluster != null) { 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)) { 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 UNIT = "unit"; 828 public static final String QA_FUNCTIONAL = "qa-functional"; 829 final String testtype; 831 final List <TestDep> dependencies = new ArrayList <TestDep>(); 833 final String cnb; 835 final ModuleListParser modulesParser; 836 837 public static final String TEST_DIST_VAR = "test.dist.dir"; 838 public TestDeps(String testtype,String cnb,ModuleListParser modulesParser) { 839 assert modulesParser != null; 840 this.testtype = testtype; 841 this.cnb = cnb; 842 this.modulesParser = modulesParser; 843 } 844 845 public List <String > getFiles(boolean compile) { 846 List <String > files = new ArrayList <String >(); 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 getTestFolder() { 857 ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnb); 858 String sep = "/"; 859 860 String cluster = entry.getClusterName(); 861 if (cluster == null) { 862 cluster = "cluster"; 864 } 865 return ParseProjectXml.testDistLocation + sep + testtype + sep + cluster + sep + cnb.replace('.','-'); 866 } 867 868 String getCompileClassPath() { 869 return getPath(getFiles(true)); 870 } 871 private String getPath(List <String > files) { 872 StringBuffer path = new StringBuffer (); 873 Set <String > filesSet = new HashSet <String >(); 874 for (String 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 getRuntimeClassPath() { 887 return getPath(getFiles(false)); 888 } 889 890 891 } 892 894 final class TestDep { 895 final ModuleListParser modulesParser; 896 final String cnb; 898 final boolean recursive; 900 final boolean test; 901 final boolean compile; 903 TestDeps testDeps; 904 905 TestDep (String 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 915 List <ModuleListParser.Entry> getModules() { 916 List <ModuleListParser.Entry> entries = new ArrayList <ModuleListParser.Entry>(); 917 if (recursive ) { 918 Map <String ,ModuleListParser.Entry> entriesMap = new HashMap <String ,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 cnd, Map <String ,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 cnds[] = entry.getRuntimeDependencies(); 940 if (cnds != null) { 942 for (String c : cnds) { 943 addRecursiveModules(c, entriesMap); 944 } 945 } 946 } 947 } 948 List <String > getFiles(boolean compile) { 949 List <String > files = new ArrayList <String >(); 950 if (!compile || ( compile && this.compile)) { 951 List <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 if (test) { 961 ModuleListParser.Entry entry = modulesParser.findByCodeNameBase(cnb); 963 String sep = File.separator; 964 String cluster = entry.getClusterName(); 965 if (cluster == null) { 966 cluster = "cluster"; 967 } 968 String 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 computeClassPathExtensions(Document pDoc) { 976 Element data = getConfig(pDoc); 977 StringBuffer list = null; 978 for (Element ext : XMLUtil.findSubElements(data)) { 979 if (!ext.getLocalName().equals("class-path-extension")) { 980 continue; 981 } 982 Element 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 reltext = XMLUtil.findText(runtimeRelativePath); 987 if (list == null) { 988 list = new StringBuffer (); 989 } else { 990 list.append(' '); 991 } 992 list.append(reltext); 993 } 994 return list != null ? list.toString() : null; 995 } 996 997 1002 private File createPublicPackageJar(List <File > jars, String pubpkgs, File dir, String cnb) throws IOException { 1003 if (!dir.isDirectory()) { 1004 throw new IOException ("No such directory " + dir); 1005 } 1006 File ppjar = new File (dir, cnb.replace('.', '-') + ".jar"); 1007 if (ppjar.exists()) { 1008 boolean uptodate = true; 1010 long stamp = ppjar.lastModified(); 1011 for (File 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 corePattern = pubpkgs. 1024 replaceAll(" +", ""). 1025 replaceAll("\\.", "/"). 1026 replaceAll(",", "|"). 1027 replaceAll("\\*\\*", "(.+/)?"). 1028 replaceAll("\\*", ""); 1029 Pattern p = Pattern.compile("(" + corePattern + ")[^/]+\\.class"); 1030 OutputStream os = new FileOutputStream (ppjar); 1032 try { 1033 ZipOutputStream zos = new ZipOutputStream (os); 1034 Set <String > addedPaths = new HashSet <String >(); 1035 for (File jar : jars) { 1036 if (!jar.isFile()) { 1037 log("Classpath entry " + jar + " does not exist; skipping", Project.MSG_WARN); 1038 } 1039 InputStream is = new FileInputStream (jar); 1040 try { 1041 ZipInputStream zis = new ZipInputStream (is); 1042 ZipEntry inEntry; 1043 while ((inEntry = zis.getNextEntry()) != null) { 1044 String path = inEntry.getName(); 1045 if (!addedPaths.add(path)) { 1046 continue; 1047 } 1048 if (!p.matcher(path).matches()) { 1049 continue; 1050 } 1051 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 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 outEntry = new ZipEntry (path); 1059 outEntry.setSize(data.length); 1060 CRC32 crc = new CRC32 (); 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 pDoc,ModuleListParser modules,String testCnb) { 1078 assert modules != null; 1079 Element cfg = getConfig(pDoc); 1080 List <TestDeps> testDepsList = new ArrayList <TestDeps>(); 1081 Element pp = findNBMElement(cfg, "test-dependencies"); 1082 boolean existsUnitTests = false; 1083 boolean existsQaFunctionalTests = false; 1084 if (pp != null) { 1085 for (Element depssEl : XMLUtil.findSubElements(pp)) { 1086 String testType = findTextOrNull(depssEl,"name"); 1087 if (testType == null) { 1088 testType = TestDeps.UNIT; 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 el : XMLUtil.findSubElements(depssEl)) { 1098 if (el.getTagName().equals("test-dependency")) { 1099 boolean test = (findNBMElement(el,"test") != null); 1101 String 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 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 findTextOrNull(Element parentElement,String elementName) { 1127 Element el = findNBMElement(parentElement,elementName); 1128 return (el == null) ? null : 1129 XMLUtil.findText(el); 1130 1131 } 1132 private static String NBM_NS_CACHE = NBM_NS3; 1133 static Element findNBMElement(Element el,String name) { 1134 Element 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 |