1 17 package org.apache.tools.ant.taskdefs.optional; 18 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.FileOutputStream ; 22 import java.io.IOException ; 23 import java.io.PrintStream ; 24 import java.util.Date ; 25 import java.util.Properties ; 26 import org.apache.tools.ant.BuildEvent; 27 import org.apache.tools.ant.BuildException; 28 import org.apache.tools.ant.BuildListener; 29 import org.apache.tools.ant.DirectoryScanner; 30 import org.apache.tools.ant.Project; 31 import org.apache.tools.ant.taskdefs.Java; 32 import org.apache.tools.ant.taskdefs.Javac; 33 import org.apache.tools.ant.taskdefs.MatchingTask; 34 import org.apache.tools.ant.taskdefs.Mkdir; 35 import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter; 36 import org.apache.tools.ant.types.Path; 37 import org.apache.tools.ant.types.Reference; 38 39 204 public class IContract extends MatchingTask { 205 206 private static final String ICONTROL_PROPERTIES_HEADER 207 = "You might want to set classRoot to point to your normal " 208 + "compilation class root directory."; 209 210 211 private String icCompiler = "javac"; 212 213 214 private File targets = null; 215 216 220 private boolean dirty = false; 221 222 223 private boolean iContractMissing = false; 224 225 226 private File srcDir = null; 227 228 229 private File instrumentDir = null; 230 231 232 private File buildDir = null; 233 234 235 private File repositoryDir = null; 236 237 238 private File repBuildDir = null; 239 240 241 private Path classpath = null; 242 243 244 private String failThrowable = "java.lang.Error"; 245 246 247 private String verbosity = "error*"; 248 249 250 private boolean quiet = false; 251 252 253 private File controlFile = null; 254 255 256 private boolean pre = true; 257 private boolean preModified = false; 258 259 260 private boolean post = true; 261 private boolean postModified = false; 262 263 264 private boolean invariant = true; 265 private boolean invariantModified = false; 266 267 273 private boolean instrumentall = false; 274 275 279 private boolean updateIcontrol = false; 280 281 282 private File classDir = null; 283 284 289 public void setSrcdir(File srcDir) { 290 this.srcDir = srcDir; 291 } 292 293 294 299 public void setClassdir(File classDir) { 300 this.classDir = classDir; 301 } 302 303 304 309 public void setInstrumentdir(File instrumentDir) { 310 this.instrumentDir = instrumentDir; 311 if (this.buildDir == null) { 312 setBuilddir(instrumentDir); 313 } 314 } 315 316 317 322 public void setBuilddir(File buildDir) { 323 this.buildDir = buildDir; 324 } 325 326 327 332 public void setRepositorydir(File repositoryDir) { 333 this.repositoryDir = repositoryDir; 334 if (this.repBuildDir == null) { 335 setRepbuilddir(repositoryDir); 336 } 337 } 338 339 340 345 public void setRepbuilddir(File repBuildDir) { 346 this.repBuildDir = repBuildDir; 347 } 348 349 350 355 public void setPre(boolean pre) { 356 this.pre = pre; 357 preModified = true; 358 } 359 360 361 366 public void setPost(boolean post) { 367 this.post = post; 368 postModified = true; 369 } 370 371 372 377 public void setInvariant(boolean invariant) { 378 this.invariant = invariant; 379 invariantModified = true; 380 } 381 382 383 388 public void setFailthrowable(String clazz) { 389 this.failThrowable = clazz; 390 } 391 392 393 400 public void setVerbosity(String verbosity) { 401 this.verbosity = verbosity; 402 } 403 404 405 410 public void setQuiet(boolean quiet) { 411 this.quiet = quiet; 412 } 413 414 415 421 public void setTargets(File targets) { 422 this.targets = targets; 423 } 424 425 426 431 public void setControlfile(File controlFile) { 432 if (!controlFile.exists()) { 433 log("WARNING: Control file " + controlFile.getAbsolutePath() 434 + " doesn't exist. iContract will be run " 435 + "without control file."); 436 } 437 this.controlFile = controlFile; 438 } 439 440 441 446 public void setClasspath(Path path) { 447 createClasspath().append(path); 448 } 449 450 451 459 public Path createClasspath() { 460 if (classpath == null) { 461 classpath = new Path(getProject()); 462 } 463 return classpath; 464 } 465 466 467 472 public void setClasspathRef(Reference reference) { 473 createClasspath().setRefid(reference); 474 } 475 476 477 483 public void setUpdateicontrol(boolean updateIcontrol) { 484 this.updateIcontrol = updateIcontrol; 485 } 486 487 488 493 public void execute() throws BuildException { 494 preconditions(); 495 scan(); 496 if (dirty) { 497 498 boolean useControlFile = (controlFile != null) && controlFile.exists(); 500 501 if (useControlFile && !preModified) { 502 pre = false; 503 } 504 if (useControlFile && !postModified) { 505 post = false; 506 } 507 if (useControlFile && !invariantModified) { 508 invariant = false; 509 } 510 if ((pre || post || invariant) && controlFile != null) { 512 log("WARNING: specifying pre,post or invariant will " 513 + "override control file settings"); 514 } 515 516 517 getProject().addBuildListener(new IContractPresenceDetector()); 521 522 Mkdir mkdir = (Mkdir) getProject().createTask("mkdir"); 526 527 mkdir.setDir(instrumentDir); 528 mkdir.execute(); 529 mkdir.setDir(buildDir); 530 mkdir.execute(); 531 mkdir.setDir(repositoryDir); 532 mkdir.execute(); 533 534 Path baseClasspath = createClasspath(); 536 537 String compiler = getProject().getProperty("build.compiler"); 540 ClasspathHelper classpathHelper = new ClasspathHelper(compiler); 541 542 classpathHelper.modify(baseClasspath); 543 544 Path beforeInstrumentationClasspath = ((Path) baseClasspath.clone()); 547 548 beforeInstrumentationClasspath.append(new Path(getProject(), 549 srcDir.getAbsolutePath())); 550 551 Path afterInstrumentationClasspath = ((Path) baseClasspath.clone()); 554 555 afterInstrumentationClasspath.append(new Path(getProject(), 556 instrumentDir.getAbsolutePath())); 557 afterInstrumentationClasspath.append(new Path(getProject(), 558 repositoryDir.getAbsolutePath())); 559 afterInstrumentationClasspath.append(new Path(getProject(), 560 srcDir.getAbsolutePath())); 561 afterInstrumentationClasspath.append(new Path(getProject(), 562 buildDir.getAbsolutePath())); 563 564 Path repositoryClasspath = ((Path) baseClasspath.clone()); 567 568 repositoryClasspath.append(new Path(getProject(), 569 instrumentDir.getAbsolutePath())); 570 repositoryClasspath.append(new Path(getProject(), 571 srcDir.getAbsolutePath())); 572 repositoryClasspath.append(new Path(getProject(), 573 repositoryDir.getAbsolutePath())); 574 repositoryClasspath.append(new Path(getProject(), 575 buildDir.getAbsolutePath())); 576 577 Path iContractClasspath = ((Path) baseClasspath.clone()); 579 580 iContractClasspath.append(new Path(getProject(), 581 System.getProperty("java.home") + File.separator + ".." 582 + File.separator + "lib" + File.separator + "tools.jar")); 583 iContractClasspath.append(new Path(getProject(), 584 srcDir.getAbsolutePath())); 585 iContractClasspath.append(new Path(getProject(), 586 repositoryDir.getAbsolutePath())); 587 iContractClasspath.append(new Path(getProject(), 588 instrumentDir.getAbsolutePath())); 589 iContractClasspath.append(new Path(getProject(), 590 buildDir.getAbsolutePath())); 591 592 Java iContract = (Java) getProject().createTask("java"); 594 595 iContract.setTaskName(getTaskName()); 596 iContract.setFork(true); 597 iContract.setClassname("com.reliablesystems.iContract.Tool"); 598 iContract.setClasspath(iContractClasspath); 599 600 StringBuffer args = new StringBuffer (); 602 603 args.append(directiveString()); 604 args.append("-v").append(verbosity).append(" "); 605 606 args.append("-b").append("\"").append(icCompiler); 607 args.append(" -classpath ").append(beforeInstrumentationClasspath); 608 args.append("\" "); 609 610 args.append("-c").append("\"").append(icCompiler); 611 args.append(" -classpath ").append(afterInstrumentationClasspath); 612 args.append(" -d ").append(buildDir).append("\" "); 613 614 args.append("-n").append("\"").append(icCompiler); 615 args.append(" -classpath ").append(repositoryClasspath); 616 args.append("\" "); 617 618 args.append("-d").append(failThrowable).append(" "); 619 620 args.append("-o").append(instrumentDir).append(File.separator); 621 args.append("@p").append(File.separator).append("@f.@e "); 622 623 args.append("-k").append(repositoryDir).append(File.separator); 624 args.append("@p "); 625 626 args.append(quiet ? "-q " : ""); 627 args.append(instrumentall ? "-a " : ""); 630 args.append("@").append(targets.getAbsolutePath()); 631 iContract.createArg().setLine(args.toString()); 632 633 636 if (updateIcontrol) { 638 Properties iControlProps = new Properties (); 639 640 try { 641 iControlProps.load(new FileInputStream ("icontrol.properties")); 643 } catch (IOException e) { 644 log("File icontrol.properties not found. That's ok. " 645 + "Writing a default one."); 646 } 647 iControlProps.setProperty("sourceRoot", 648 srcDir.getAbsolutePath()); 649 iControlProps.setProperty("classRoot", 650 classDir.getAbsolutePath()); 651 iControlProps.setProperty("classpath", 652 afterInstrumentationClasspath.toString()); 653 iControlProps.setProperty("controlFile", 654 controlFile.getAbsolutePath()); 655 iControlProps.setProperty("targetsFile", 656 targets.getAbsolutePath()); 657 658 try { 659 iControlProps.store(new FileOutputStream ("icontrol.properties"), 661 ICONTROL_PROPERTIES_HEADER); 662 log("Updated icontrol.properties"); 663 } catch (IOException e) { 664 log("Couldn't write icontrol.properties."); 665 } 666 } 667 668 int result = iContract.executeJava(); 670 671 if (result != 0) { 672 if (iContractMissing) { 673 log("iContract can't be found on your classpath. " 674 + "Your classpath is:"); 675 log(classpath.toString()); 676 log("If you don't have the iContract jar, go get it at " 677 + "http://www.reliable-systems.com/tools/"); 678 } 679 throw new BuildException("iContract instrumentation failed. " 680 + "Code = " + result); 681 } 682 } else { 683 } 686 } 687 688 689 690 private void preconditions() throws BuildException { 691 if (srcDir == null) { 692 throw new BuildException("srcdir attribute must be set!", 693 getLocation()); 694 } 695 if (!srcDir.exists()) { 696 throw new BuildException("srcdir \"" + srcDir.getPath() 697 + "\" does not exist!", getLocation()); 698 } 699 if (instrumentDir == null) { 700 throw new BuildException("instrumentdir attribute must be set!", 701 getLocation()); 702 } 703 if (repositoryDir == null) { 704 throw new BuildException("repositorydir attribute must be set!", 705 getLocation()); 706 } 707 if (updateIcontrol && classDir == null) { 708 throw new BuildException("classdir attribute must be specified " 709 + "when updateicontrol=true!", getLocation()); 710 } 711 if (updateIcontrol && controlFile == null) { 712 throw new BuildException("controlfile attribute must be specified " 713 + "when updateicontrol=true!", getLocation()); 714 } 715 } 716 717 718 726 private void scan() throws BuildException { 727 long now = (new Date ()).getTime(); 728 729 DirectoryScanner ds = null; 730 731 ds = getDirectoryScanner(srcDir); 732 733 String [] files = ds.getIncludedFiles(); 734 735 FileOutputStream targetOutputStream = null; 736 PrintStream targetPrinter = null; 737 boolean writeTargets = false; 738 739 try { 740 if (targets == null) { 741 targets = new File ("targets"); 742 log("Warning: targets file not specified. generating file: " 743 + targets.getName()); 744 writeTargets = true; 745 } else if (!targets.exists()) { 746 log("Specified targets file doesn't exist. generating file: " 747 + targets.getName()); 748 writeTargets = true; 749 } 750 if (writeTargets) { 751 log("You should consider using iControl to create a target file."); 752 targetOutputStream = new FileOutputStream (targets); 753 targetPrinter = new PrintStream (targetOutputStream); 754 } 755 for (int i = 0; i < files.length; i++) { 756 File srcFile = new File (srcDir, files[i]); 757 758 if (files[i].endsWith(".java")) { 759 if (targetPrinter != null) { 761 targetPrinter.println(srcFile.getAbsolutePath()); 762 } 763 File classFile 764 = new File (buildDir, files[i].substring(0, files[i].indexOf(".java")) + ".class"); 765 766 if (srcFile.lastModified() > now) { 767 log("Warning: file modified in the future: " 768 + files[i], Project.MSG_WARN); 769 } 770 771 if (!classFile.exists() || srcFile.lastModified() > classFile.lastModified()) { 772 dirty = true; 776 } 777 } 778 } 779 if (targetPrinter != null) { 780 targetPrinter.flush(); 781 targetPrinter.close(); 782 } 783 } catch (IOException e) { 784 throw new BuildException("Could not create target file:" + e.getMessage()); 785 } 786 787 long controlFileTime = -1; 789 790 try { 791 if (controlFile != null) { 792 if (controlFile.exists() && buildDir.exists()) { 793 controlFileTime = controlFile.lastModified(); 794 ds = getDirectoryScanner(buildDir); 795 files = ds.getIncludedFiles(); 796 for (int i = 0; i < files.length; i++) { 797 File srcFile = new File (srcDir, files[i]); 798 799 if (files[i].endsWith(".class")) { 800 if (controlFileTime > srcFile.lastModified()) { 801 if (!dirty) { 802 log("Control file " 803 + controlFile.getAbsolutePath() 804 + " has been updated. " 805 + "Instrumenting all files..."); 806 } 807 dirty = true; 808 instrumentall = true; 809 } 810 } 811 } 812 } 813 } 814 } catch (Throwable t) { 815 throw new BuildException("Got an interesting exception:" 816 + t.getMessage()); 817 } 818 } 819 820 821 825 private final String directiveString() { 826 StringBuffer sb = new StringBuffer (); 827 boolean comma = false; 828 829 boolean useControlFile = (controlFile != null) && controlFile.exists(); 830 831 if (useControlFile || pre || post || invariant) { 832 sb.append("-m"); 833 } 834 if (useControlFile) { 835 sb.append("@").append(controlFile); 836 comma = true; 837 } 838 if (pre) { 839 if (comma) { 840 sb.append(","); 841 } 842 sb.append("pre"); 843 comma = true; 844 } 845 if (post) { 846 if (comma) { 847 sb.append(","); 848 } 849 sb.append("post"); 850 comma = true; 851 } 852 if (invariant) { 853 if (comma) { 854 sb.append(","); 855 } 856 sb.append("inv"); 857 } 858 sb.append(" "); 859 return sb.toString(); 860 } 861 862 863 869 private class IContractPresenceDetector implements BuildListener { 870 public void buildFinished(BuildEvent event) { 871 } 872 873 874 public void buildStarted(BuildEvent event) { 875 } 876 877 878 public void messageLogged(BuildEvent event) { 879 if ("java.lang.NoClassDefFoundError: com/reliablesystems/iContract/Tool".equals(event.getMessage())) { 880 iContractMissing = true; 881 } 882 } 883 884 885 public void targetFinished(BuildEvent event) { 886 } 887 888 889 public void targetStarted(BuildEvent event) { 890 } 891 892 893 public void taskFinished(BuildEvent event) { 894 } 895 896 897 public void taskStarted(BuildEvent event) { 898 } 899 } 900 901 902 908 private class ClasspathHelper extends DefaultCompilerAdapter { 909 private final String compiler; 910 911 912 public ClasspathHelper(String compiler) { 913 super(); 914 this.compiler = compiler; 915 } 916 917 public void modify(Path path) { 919 if ("jikes".equals(compiler)) { 922 icCompiler = compiler; 923 includeJavaRuntime = true; 924 path.append(getCompileClasspath()); 925 } 926 } 927 928 public void setJavac(Javac javac) { 930 } 931 932 933 public boolean execute() { 934 return true; 935 } 936 } 937 } 938 939 | Popular Tags |