KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > IContract


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  */

17 package org.apache.tools.ant.taskdefs.optional;
18
19 import java.io.File JavaDoc;
20 import java.io.FileInputStream JavaDoc;
21 import java.io.FileOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.PrintStream JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.Properties JavaDoc;
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 /**
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  */

204 public class IContract extends MatchingTask {
205
206     private static final String JavaDoc 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 JavaDoc icCompiler = "javac";
212
213     /** temporary file with file names of all java files to be instrumented */
214     private File JavaDoc 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 JavaDoc srcDir = null;
227
228     /** instrumentation src root */
229     private File JavaDoc instrumentDir = null;
230
231     /** instrumentation build root */
232     private File JavaDoc buildDir = null;
233
234     /** repository src root */
235     private File JavaDoc repositoryDir = null;
236
237     /** repository build root */
238     private File JavaDoc 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 JavaDoc failThrowable = "java.lang.Error";
245
246     /** The -v option */
247     private String JavaDoc verbosity = "error*";
248
249     /** The -q option */
250     private boolean quiet = false;
251
252     /** The -m option */
253     private File JavaDoc 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 JavaDoc classDir = null;
283
284     /**
285      * Sets the source directory.
286      *
287      * @param srcDir the source directory
288      */

289     public void setSrcdir(File JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc args = new StringBuffer JavaDoc();
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 JavaDoc iControlProps = new Properties JavaDoc();
639
640                 try {
641                     // to read existing propertiesfile
642
iControlProps.load(new FileInputStream JavaDoc("icontrol.properties"));
643                 } catch (IOException JavaDoc 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 JavaDoc("icontrol.properties"),
661                         ICONTROL_PROPERTIES_HEADER);
662                     log("Updated icontrol.properties");
663                 } catch (IOException JavaDoc 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 JavaDoc()).getTime();
728
729         DirectoryScanner ds = null;
730
731         ds = getDirectoryScanner(srcDir);
732
733         String JavaDoc[] files = ds.getIncludedFiles();
734
735         FileOutputStream JavaDoc targetOutputStream = null;
736         PrintStream JavaDoc targetPrinter = null;
737         boolean writeTargets = false;
738
739         try {
740             if (targets == null) {
741                 targets = new File JavaDoc("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 JavaDoc(targets);
753                 targetPrinter = new PrintStream JavaDoc(targetOutputStream);
754             }
755             for (int i = 0; i < files.length; i++) {
756                 File JavaDoc srcFile = new File JavaDoc(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 JavaDoc classFile
764                         = new File JavaDoc(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 JavaDoc 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 JavaDoc srcFile = new File JavaDoc(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 JavaDoc 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 JavaDoc directiveString() {
826         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
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 JavaDoc compiler;
910
911
912         public ClasspathHelper(String JavaDoc 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
939
Popular Tags