source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/IContract.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 32.5 KB
Line 
1/*
2 * Copyright 2001-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs.optional;
18
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.io.PrintStream;
24import java.util.Date;
25import java.util.Properties;
26import org.apache.tools.ant.BuildEvent;
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.BuildListener;
29import org.apache.tools.ant.DirectoryScanner;
30import org.apache.tools.ant.Project;
31import org.apache.tools.ant.taskdefs.Java;
32import org.apache.tools.ant.taskdefs.Javac;
33import org.apache.tools.ant.taskdefs.MatchingTask;
34import org.apache.tools.ant.taskdefs.Mkdir;
35import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
36import org.apache.tools.ant.types.Path;
37import org.apache.tools.ant.types.Reference;
38
39/**
40 * Instruments Java classes with iContract DBC preprocessor.
41 * <br/>
42 * The task can generate a properties file for
43 * <a href="http://hjem.sol.no/hellesoy/icontrol.html">iControl</a>,
44 * a graphical user interface that lets you turn on/off assertions.
45 * iControl generates a control file that you can refer to
46 * from this task using the controlfile attribute.
47 * iContract is at
48 * <a href="http://www.reliable-systems.com/tools/">
49 * http://www.reliable-systems.com/tools/</a>
50 * <p/>
51 * Thanks to Rainer Schmitz for enhancements and comments.
52 *
53 *
54 * <p/>
55 * <table border="1" cellpadding="2" cellspacing="0">
56 * <tr>
57 * <td valign="top"><b>Attribute</b></td>
58 * <td valign="top"><b>Description</b></td>
59 * <td align="center" valign="top"><b>Required</b></td>
60 * </tr>
61 * <tr>
62 * <td valign="top">srcdir</td>
63 * <td valign="top">Location of the java files.</td>
64 * <td valign="top" align="center">Yes</td>
65 * </tr>
66 * <tr>
67 * <td valign="top">instrumentdir</td>
68 * <td valign="top">Indicates where the instrumented source
69 * files should go.</td>
70 * <td valign="top" align="center">Yes</td>
71 * </tr>
72 * <tr>
73 * <td valign="top">repositorydir</td>
74 * <td valign="top">Indicates where the repository source
75 * files should go.</td>
76 * <td valign="top" align="center">Yes</td>
77 * </tr>
78 * <tr>
79 * <td valign="top">builddir</td>
80 * <td valign="top">Indicates where the compiled instrumented
81 * classes should go. Defaults to the value of
82 * instrumentdir.
83 * </p>
84 * <em>NOTE:</em> Don't use the same directory for compiled
85 * instrumented classes and uninstrumented classes. It will break the
86 * dependency checking. (Classes will not be reinstrumented if you
87 * change them).</td>
88 * <td valign="top" align="center">No</td>
89 * </tr>
90 * <tr>
91 * <td valign="top">repbuilddir</td>
92 * <td valign="top">Indicates where the compiled repository classes
93 * should go. Defaults to the value of repositorydir.</td>
94 * <td valign="top" align="center">No</td>
95 * </tr>
96 * <tr>
97 * <td valign="top">pre</td>
98 * <td valign="top">Indicates whether or not to instrument for
99 * preconditions. Defaults to <code>true</code> unless
100 * controlfile is specified, in which case it defaults
101 * to <code>false</code>.</td>
102 * <td valign="top" align="center">No</td>
103 * </tr>
104 * <tr>
105 * <td valign="top">post</td>
106 * <td valign="top">Indicates whether or not to instrument for
107 * postconditions. Defaults to <code>true</code> unless
108 * controlfile is specified, in which case it defaults
109 * to <code>false</code>.</td>
110 * <td valign="top" align="center">No</td>
111 * </tr>
112 * <tr>
113 * <td valign="top">invariant</td>
114 * <td valign="top">Indicates whether or not to instrument for invariants.
115 * Defaults to <code>true</code> unless controlfile is
116 * specified, in which case it defaults to
117 * <code>false</code>.</td>
118 * <td valign="top" align="center">No</td>
119 * </tr>
120 * <tr>
121 * <td valign="top">failthrowable</td>
122 * <td valign="top">The full name of the Throwable (Exception) that
123 * should be thrown when an assertion is violated.
124 * Defaults to <code>java.lang.Error</code></td>
125 * <td valign="top" align="center">No</td>
126 * </tr>
127 * <tr>
128 * <td valign="top">verbosity</td>
129 * <td valign="top">Indicates the verbosity level of iContract.
130 * Any combination of
131 * <code>error*,warning*,note*,info*,progress*,debug*</code>
132 * (comma separated) can be used. Defaults to <code>error*</code></td>
133 * <td valign="top" align="center">No</td>
134 * </tr>
135 * <tr>
136 * <td valign="top">quiet</td>
137 * <td valign="top">Indicates if iContract should be quiet. Turn it off
138 * if many your classes extend uninstrumented classes and you don't
139 * want warnings about this. Defaults to <code>false</code></td>
140 * <td valign="top" align="center">No</td>
141 * </tr>
142 * <tr>
143 * <td valign="top">updateicontrol</td>
144 * <td valign="top">If set to true, it indicates that the properties
145 * file for iControl in the current directory should be updated
146 * (or created if it doesn't exist). Defaults to <code>false</code>.
147 * </td>
148 * <td valign="top" align="center">No</td>
149 * </tr>
150 * <tr>
151 * <td valign="top">controlfile</td>
152 * <td valign="top">The name of the control file to pass to iContract.
153 * Consider using iControl to generate the file.
154 * Default is not to pass a file. </td>
155 * <td valign="top" align="center">
156 * Only if <code>updateicontrol=true</code></td>
157 * </tr>
158 * <tr>
159 * <td valign="top">classdir</td>
160 * <td valign="top">Indicates where compiled (unistrumented) classes are
161 * located. This is required in order to properly update
162 * the icontrol.properties file, not for instrumentation.
163 * </td>
164 * <td valign="top" align="center">Only if
165 * <code>updateicontrol=true</code></td>
166 * </tr>
167 * <tr>
168 * <td valign="top">targets</td>
169 * <td valign="top">Name of the file that will be generated by this task,
170 * which lists all the classes that iContract will
171 * instrument. If specified, the file will not be deleted
172 * after execution. If not specified, a file will still
173 * be created, but it will be deleted after execution.</td>
174 * <td valign="top" align="center">No</td>
175 * </tr>
176 * </table>
177 *
178 * <p/>
179 * <b>Note:</b> iContract will use the java compiler indicated by the project's
180 * <code>build.compiler</code> property. See documentation of the Javac task for
181 * more information.
182 * <p/>
183 * Nested includes and excludes are also supported.
184 *
185 * <p><b>Example:</b></p>
186 * <pre>
187 * &lt;icontract
188 * srcdir="${build.src}"
189 * instrumentdir="${build.instrument}"
190 * repositorydir="${build.repository}"
191 * builddir="${build.instrclasses}"
192 * updateicontrol="true"
193 * classdir="${build.classes}"
194 * controlfile="control"
195 * targets="targets"
196 * verbosity="error*,warning*"
197 * quiet="true"
198 * >
199 * &lt;classpath refid="compile-classpath"/>
200 * &lt;/icontract>
201 * </pre>
202 *
203 */
204public 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 /** compiler to use for instrumenation */
211 private String icCompiler = "javac";
212
213 /** temporary file with file names of all java files to be instrumented */
214 private File targets = null;
215
216 /**
217 * will be set to true if any of the source files are newer than the
218 * instrumented files
219 */
220 private boolean dirty = false;
221
222 /** set to true if the iContract jar is missing */
223 private boolean iContractMissing = false;
224
225 /** source file root */
226 private File srcDir = null;
227
228 /** instrumentation src root */
229 private File instrumentDir = null;
230
231 /** instrumentation build root */
232 private File buildDir = null;
233
234 /** repository src root */
235 private File repositoryDir = null;
236
237 /** repository build root */
238 private File repBuildDir = null;
239
240 /** classpath */
241 private Path classpath = null;
242
243 /** The class of the Throwable to be thrown on failed assertions */
244 private String failThrowable = "java.lang.Error";
245
246 /** The -v option */
247 private String verbosity = "error*";
248
249 /** The -q option */
250 private boolean quiet = false;
251
252 /** The -m option */
253 private File controlFile = null;
254
255 /** Indicates whether or not to instrument for preconditions */
256 private boolean pre = true;
257 private boolean preModified = false;
258
259 /** Indicates whether or not to instrument for postconditions */
260 private boolean post = true;
261 private boolean postModified = false;
262
263 /** Indicates whether or not to instrument for invariants */
264 private boolean invariant = true;
265 private boolean invariantModified = false;
266
267 /**
268 * Indicates whether or not to instrument all files regardless of timestamp
269 *
270 * Can't be explicitly set, is set if control file exists and is newer
271 * than any source file
272 */
273 private boolean instrumentall = false;
274
275 /**
276 * Indicates the name of a properties file (intentionally for iControl)
277 * where the classpath property should be updated.
278 */
279 private boolean updateIcontrol = false;
280
281 /** Regular compilation class root */
282 private File classDir = null;
283
284 /**
285 * Sets the source directory.
286 *
287 * @param srcDir the source directory
288 */
289 public void setSrcdir(File srcDir) {
290 this.srcDir = srcDir;
291 }
292
293
294 /**
295 * Sets the class directory (uninstrumented classes).
296 *
297 * @param classDir the source directory
298 */
299 public void setClassdir(File classDir) {
300 this.classDir = classDir;
301 }
302
303
304 /**
305 * Sets the instrumentation directory.
306 *
307 * @param instrumentDir the source directory
308 */
309 public void setInstrumentdir(File instrumentDir) {
310 this.instrumentDir = instrumentDir;
311 if (this.buildDir == null) {
312 setBuilddir(instrumentDir);
313 }
314 }
315
316
317 /**
318 * Sets the build directory for instrumented classes.
319 *
320 * @param buildDir the build directory
321 */
322 public void setBuilddir(File buildDir) {
323 this.buildDir = buildDir;
324 }
325
326
327 /**
328 * Sets the build directory for repository classes.
329 *
330 * @param repositoryDir the source directory
331 */
332 public void setRepositorydir(File repositoryDir) {
333 this.repositoryDir = repositoryDir;
334 if (this.repBuildDir == null) {
335 setRepbuilddir(repositoryDir);
336 }
337 }
338
339
340 /**
341 * Sets the build directory for instrumented classes.
342 *
343 * @param repBuildDir the build directory
344 */
345 public void setRepbuilddir(File repBuildDir) {
346 this.repBuildDir = repBuildDir;
347 }
348
349
350 /**
351 * Turns on/off precondition instrumentation.
352 *
353 * @param pre true turns it on
354 */
355 public void setPre(boolean pre) {
356 this.pre = pre;
357 preModified = true;
358 }
359
360
361 /**
362 * Turns on/off postcondition instrumentation.
363 *
364 * @param post true turns it on
365 */
366 public void setPost(boolean post) {
367 this.post = post;
368 postModified = true;
369 }
370
371
372 /**
373 * Turns on/off invariant instrumentation.
374 *
375 * @param invariant true turns it on
376 */
377 public void setInvariant(boolean invariant) {
378 this.invariant = invariant;
379 invariantModified = true;
380 }
381
382
383 /**
384 * Sets the Throwable (Exception) to be thrown on assertion violation.
385 *
386 * @param clazz the fully qualified Throwable class name
387 */
388 public void setFailthrowable(String clazz) {
389 this.failThrowable = clazz;
390 }
391
392
393 /**
394 * Sets the verbosity level of iContract. Any combination of
395 * error*,warning*,note*,info*,progress*,debug* (comma separated) can be
396 * used. Defaults to error*,warning*
397 *
398 * @param verbosity verbosity level
399 */
400 public void setVerbosity(String verbosity) {
401 this.verbosity = verbosity;
402 }
403
404
405 /**
406 * Tells iContract to be quiet.
407 *
408 * @param quiet true if iContract should be quiet.
409 */
410 public void setQuiet(boolean quiet) {
411 this.quiet = quiet;
412 }
413
414
415 /**
416 * Sets the name of the file where targets will be written. That is the
417 * file that tells iContract what files to process.
418 *
419 * @param targets the targets file name
420 */
421 public void setTargets(File targets) {
422 this.targets = targets;
423 }
424
425
426 /**
427 * Sets the control file to pass to iContract.
428 *
429 * @param controlFile the control file
430 */
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 /**
442 * Sets the classpath to be used for invocation of iContract.
443 *
444 * @param path the classpath
445 */
446 public void setClasspath(Path path) {
447 createClasspath().append(path);
448 }
449
450
451 /**
452 * Sets the classpath.
453 *
454 * @return the nested classpath element
455 * @todo this overwrites the classpath so only one
456 * effective classpath element would work. This
457 * is not how we do this elsewhere.
458 */
459 public Path createClasspath() {
460 if (classpath == null) {
461 classpath = new Path(getProject());
462 }
463 return classpath;
464 }
465
466
467 /**
468 * Adds a reference to a classpath defined elsewhere.
469 *
470 * @param reference referenced classpath
471 */
472 public void setClasspathRef(Reference reference) {
473 createClasspath().setRefid(reference);
474 }
475
476
477 /**
478 * If true, updates iControl properties file
479 *
480 * @param updateIcontrol true if iControl properties file should be
481 * updated
482 */
483 public void setUpdateicontrol(boolean updateIcontrol) {
484 this.updateIcontrol = updateIcontrol;
485 }
486
487
488 /**
489 * Executes the task
490 *
491 * @exception BuildException if the instrumentation fails
492 */
493 public void execute() throws BuildException {
494 preconditions();
495 scan();
496 if (dirty) {
497
498 // turn off assertions if we're using controlfile, unless they are not explicitly set.
499 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 // issue warning if pre,post or invariant is used together with controlfile
511 if ((pre || post || invariant) && controlFile != null) {
512 log("WARNING: specifying pre,post or invariant will "
513 + "override control file settings");
514 }
515
516
517 // We want to be notified if iContract jar is missing.
518 // This makes life easier for the user who didn't understand
519 // that iContract is a separate library (duh!)
520 getProject().addBuildListener(new IContractPresenceDetector());
521
522 // Prepare the directories for iContract. iContract will make
523 // them if they don't exist, but for some reason I don't know,
524 // it will complain about the REP files afterwards
525 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 // Set the classpath that is needed for regular Javac compilation
535 Path baseClasspath = createClasspath();
536
537 // Might need to add the core classes if we're not using
538 // Sun's Javac (like Jikes)
539 String compiler = getProject().getProperty("build.compiler");
540 ClasspathHelper classpathHelper = new ClasspathHelper(compiler);
541
542 classpathHelper.modify(baseClasspath);
543
544 // Create the classpath required to compile the sourcefiles
545 // BEFORE instrumentation
546 Path beforeInstrumentationClasspath = ((Path) baseClasspath.clone());
547
548 beforeInstrumentationClasspath.append(new Path(getProject(),
549 srcDir.getAbsolutePath()));
550
551 // Create the classpath required to compile the sourcefiles
552 // AFTER instrumentation
553 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 // Create the classpath required to automatically compile the
565 // repository files
566 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 // Create the classpath required for iContract itself
578 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 // Create a forked java process
593 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 // Build the arguments to iContract
601 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 // reinstrument everything if controlFile exists and is newer
628 // than any class
629 args.append(instrumentall ? "-a " : "");
630 args.append("@").append(targets.getAbsolutePath());
631 iContract.createArg().setLine(args.toString());
632
633 //System.out.println( "JAVA -classpath " + iContractClasspath
634 // + " com.reliablesystems.iContract.Tool " + args.toString() );
635
636 // update iControlProperties if it's set.
637 if (updateIcontrol) {
638 Properties iControlProps = new Properties();
639
640 try {
641 // to read existing propertiesfile
642 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 // to read existing propertiesfile
660 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 // do it!
669 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 // not dirty
684 //log( "Nothing to do. Everything up to date." );
685 }
686 }
687
688
689 /** Checks that the required attributes are set. */
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 /**
719 * Verifies whether any of the source files have changed. Done by
720 * comparing date of source/class files. The whole lot is "dirty" if at
721 * least one source file or the control file is newer than the
722 * instrumented files. If not dirty, iContract will not be executed. <br/>
723 * Also creates a temporary file with a list of the source files, that
724 * will be deleted upon exit.
725 */
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 // print the target, while we're at here. (Only if generatetarget=true).
760 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 //log( "Found a file newer than the instrumentDir class file: "
773 // + srcFile.getPath() + " newer than " + classFile.getPath()
774 // + ". Running iContract again..." );
775 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 // also, check controlFile timestamp
788 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 /**
822 * Creates the -m option based on the values of controlFile, pre, post and
823 * invariant.
824 */
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 /**
864 * BuildListener that sets the iContractMissing flag to true if a message
865 * about missing iContract is missing. Used to indicate a more verbose
866 * error to the user, with advice about how to solve the problem
867 *
868 */
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 /**
903 * This class is a helper to set correct classpath for other compilers,
904 * like Jikes. It reuses the logic from DefaultCompilerAdapter, which is
905 * protected, so we have to subclass it.
906 *
907 */
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 // make it public
918 public void modify(Path path) {
919 // depending on what compiler to use, set the
920 // includeJavaRuntime flag
921 if ("jikes".equals(compiler)) {
922 icCompiler = compiler;
923 includeJavaRuntime = true;
924 path.append(getCompileClasspath());
925 }
926 }
927
928 // dummy implementation. Never called
929 public void setJavac(Javac javac) {
930 }
931
932
933 public boolean execute() {
934 return true;
935 }
936 }
937}
938
Note: See TracBrowser for help on using the repository browser.