donaldp 01/04/09 22:06:47
Modified: docs/manual/OptionalTasks icontract.html
src/main/org/apache/tools/ant/taskdefs/optional
IContract.java
Log:
Updated icontract task
Submitted By: [EMAIL PROTECTED]
Revision Changes Path
1.4 +94 -35 jakarta-ant/docs/manual/OptionalTasks/icontract.html
Index: icontract.html
===================================================================
RCS file: /home/cvs/jakarta-ant/docs/manual/OptionalTasks/icontract.html,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- icontract.html 2001/02/25 05:31:47 1.3
+++ icontract.html 2001/04/10 05:06:46 1.4
@@ -9,11 +9,18 @@
<h2><a name="icontract">icontract</a></h2>
<h3>Description</h3>
-<p>Instruments Java classes with <a
href="http://www.reliable-systems.com/tools/">iContract</a>
-DBC preprocessor.
+<P>
+Instruments Java classes with <a
href="http://www.reliable-systems.com/tools/">iContract</a>
+ DBC preprocessor.<br>
+ The task can generate a properties file for <a
href="http://home.sol.no/~hellesoy/icplus.html">iControl</a>,
+ a graphical user interface that lets you turn on/off assertions. iControl
generates a control file that you can refer to
+ from this task using the controlfile attribute.
+ <p/>
+
+
<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
+ <table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
@@ -21,37 +28,54 @@
</tr>
<tr>
<td valign="top">srcdir</td>
- <td valign="top">Location of the java files</td>
+ <td valign="top">Location of the java files.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">instrumentdir</td>
- <td valign="top">Indicates where the instrumented java and class files
- should go</td>
+ <td valign="top">Indicates where the instrumented source files should
go.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">repositorydir</td>
- <td valign="top">Indicates where the repository java and class files
should
- go</td>
+ <td valign="top">Indicates where the repository source files should
go.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
+ <td valign="top">builddir</td>
+ <td valign="top">Indicates where the compiled instrumented classes
should go.
+ Defaults to the value of instrumentdir.
+ </p>
+ <em>NOTE:</em> Don't use the same directory for compiled instrumented
classes
+ and uninstrumented classes. It will break the dependency checking.
(Classes will
+ not be reinstrumented if you change them).</td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">repositorybuilddir</td>
+ <td valign="top">Indicates where the compiled repository classes should
go.
+ Defaults to the value of repositorydir.</td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
<td valign="top">pre</td>
<td valign="top">Indicates whether or not to instrument for
preconditions.
- Defaults to <code>true</code></td>
+ Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ defaults to <code>false</code>.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">post</td>
<td valign="top">Indicates whether or not to instrument for
postconditions.
- Defaults to <code>true</code></td>
+ Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ defaults to <code>false</code>.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">invariant</td>
<td valign="top">Indicates whether or not to instrument for invariants.
- Defaults to <code>true</code></td>
+ Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ defaults to <code>false</code>.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
@@ -61,44 +85,79 @@
<td valign="top" align="center">No</td>
</tr>
<tr>
- <td valign="top">controlfile</td>
- <td valign="top">The name of the control file to pass to iContract.
Default
- is to not pass a file</td>
+ <td valign="top">verbosity</td>
+ <td valign="top">Indicates the verbosity level of iContract. Any
combination
+ of <code>error*,warning*,note*,info*,progress*,debug*</code> (comma
separated) can be
+ used. Defaults to <code>error*</code></td>
<td valign="top" align="center">No</td>
</tr>
<tr>
- <td valign="top">verbosity</td>
- <td valign="top">Indicates the verbosity level of iContract. Any
combination
- of error*,warning*,note*,info*,progress*,debug* (comma separated) can
be
- used. Defaults to <code>error*,warning*</code></td>
+ <td valign="top">quiet</td>
+ <td valign="top">Indicates if iContract should be quiet. Turn it off if
many your classes extend uninstrumented classes
+ and you don't want warnings about this. Defaults to
<code>false</code></td>
<td valign="top" align="center">No</td>
</tr>
+ <tr>
+ <td valign="top">updateicontrol</td>
+ <td valign="top">If set to true, it indicates that the properties file
for
+ iControl in the current directory should be updated (or created if it
doesn't exist).
+ Defaults to <code>false</code>.</td>
+ <td valign="top" align="center">No</td>
+ </tr>
+ <tr>
+ <td valign="top">controlfile</td>
+ <td valign="top">The name of the control file to pass to iContract.
Consider using iControl to generate the file.
+ Default is not to pass a file. </td>
+ <td valign="top" align="center">Only if
<code>updateicontrol=true</code></td>
+ </tr>
+ <tr>
+ <td valign="top">classdir</td>
+ <td valign="top">Indicates where compiled (unistrumented) classes are
located.
+ This is required in order to properly update the icontrol.properties
file, not
+ for instrumentation.</td>
+ <td valign="top" align="center">Only if
<code>updateicontrol=true</code></td>
+ </tr>
+ <tr>
+ <td valign="top">targets</td>
+ <td valign="top">Name of the file that will be generated by this task,
which lists all the
+ classes that iContract will instrument. If specified, the file will
not be deleted after execution.
+ If not specified, a file will still be created, but it will be
deleted after execution.</td>
+ <td valign="top" align="center">No</td>
+ </tr>
</table>
+<p>
+ <b>Note:</b> iContract will use the java compiler indicated by the project's
+ <code>build.compiler</code> property. See documentation of the Javac task
for
+ more information. Nested includes and excludes are also supported.</p>
+
+ <p><b>Example:</b></p>
+
<p/>
<b>Note:</b> iContract will use the java compiler indicated by the project's
- <code>build.compiler</code> property. See documentation for the Javac task
for
+ <code>build.compiler</code> property. See documentation of the Javac task
for
more information.
+ <p/>
+ Nested includes and excludes can be done very much the same way as any
subclass
+ of MatchingTask.
<p><b>Example:</b></p>
<pre>
- <!-- ===================================================================
-->
- <!-- Instruments source codes with iContract
-->
- <!-- ===================================================================
-->
- <target name="instrument" depends="compile">
- <icontract
- srcdir="${build.src}"
- instrumentdir="${instrumented.dir}"
- repositorydir="${repository.dir}"
- >
- <classpath>
- <fileset dir="./lib">
- <include name="*.jar"/>
- </fileset>
- </classpath>
- </icontract>
- </target>
+ <icontract
+ srcdir="${build.src}"
+ instrumentdir="${build.instrument}"
+ repositorydir="${build.repository}"
+ builddir="${build.instrclasses}"
+ updateicontrol="true"
+ classdir="${build.classes}"
+ controlfile="control"
+ targets="targets"
+ verbosity="error*,warning*"
+ quiet="true"
+ >
+ <classpath refid="compile-classpath"/>
+ </icontract>
</pre>
<hr>
1.3 +287 -138
jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/IContract.java
Index: IContract.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/IContract.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- IContract.java 2001/02/27 02:26:28 1.2
+++ IContract.java 2001/04/10 05:06:47 1.3
@@ -57,6 +57,7 @@
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -69,16 +70,24 @@
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Java;
+import org.apache.tools.ant.taskdefs.Javac;
+import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.taskdefs.Mkdir;
+import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
- * Instruments Java classes with <a
href="http://www.reliable-systems.com/tools/">iContract<a>
+ * Instruments Java classes with <a
href="http://www.reliable-systems.com/tools/">iContract</a>
* DBC preprocessor.
+ * <br/>
+ * The task can generate a properties file for <a
href="http://hjem.sol.no/hellesoy/icontrol.html">iControl</a>,
+ * a graphical user interface that lets you turn on/off assertions. iControl
generates a control file that you can refer to
+ * from this task using the controlfile attribute.
+ * <p/>
+ * Thanks to Rainer Schmitz for enhancements and comments.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Aslak Helles�y</a>
*
@@ -91,37 +100,54 @@
* </tr>
* <tr>
* <td valign="top">srcdir</td>
- * <td valign="top">Location of the java files</td>
+ * <td valign="top">Location of the java files.</td>
* <td valign="top" align="center">Yes</td>
* </tr>
* <tr>
* <td valign="top">instrumentdir</td>
- * <td valign="top">Indicates where the instrumented java and class files
- * should go</td>
+ * <td valign="top">Indicates where the instrumented source files should
go.</td>
* <td valign="top" align="center">Yes</td>
* </tr>
* <tr>
* <td valign="top">repositorydir</td>
- * <td valign="top">Indicates where the repository java and class files
should
- * go</td>
+ * <td valign="top">Indicates where the repository source files should
go.</td>
* <td valign="top" align="center">Yes</td>
* </tr>
* <tr>
+ * <td valign="top">builddir</td>
+ * <td valign="top">Indicates where the compiled instrumented classes
should go.
+ * Defaults to the value of instrumentdir.
+ * </p>
+ * <em>NOTE:</em> Don't use the same directory for compiled
instrumented classes
+ * and uninstrumented classes. It will break the dependency checking.
(Classes will
+ * not be reinstrumented if you change them).</td>
+ * <td valign="top" align="center">No</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">repositorybuilddir</td>
+ * <td valign="top">Indicates where the compiled repository classes
should go.
+ * Defaults to the value of repositorydir.</td>
+ * <td valign="top" align="center">No</td>
+ * </tr>
+ * <tr>
* <td valign="top">pre</td>
* <td valign="top">Indicates whether or not to instrument for
preconditions.
- * Defaults to <code>true</code></td>
+ * Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ * defaults to <code>false</code>.</td>
* <td valign="top" align="center">No</td>
* </tr>
* <tr>
* <td valign="top">post</td>
* <td valign="top">Indicates whether or not to instrument for
postconditions.
- * Defaults to <code>true</code></td>
+ * Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ * defaults to <code>false</code>.</td>
* <td valign="top" align="center">No</td>
* </tr>
* <tr>
* <td valign="top">invariant</td>
* <td valign="top">Indicates whether or not to instrument for
invariants.
- * Defaults to <code>true</code></td>
+ * Defaults to <code>true</code> unless controlfile is specified, in
which case it
+ * defaults to <code>false</code>.</td>
* <td valign="top" align="center">No</td>
* </tr>
* <tr>
@@ -131,56 +157,81 @@
* <td valign="top" align="center">No</td>
* </tr>
* <tr>
- * <td valign="top">controlfile</td>
- * <td valign="top">The name of the control file to pass to iContract.
Default
- * is to not pass a file</td>
- * <td valign="top" align="center">No</td>
- * </tr>
- * <tr>
* <td valign="top">verbosity</td>
* <td valign="top">Indicates the verbosity level of iContract. Any
combination
- * of error*,warning*,note*,info*,progress*,debug* (comma separated)
can be
+ * of <code>error*,warning*,note*,info*,progress*,debug*</code> (comma
separated) can be
* used. Defaults to <code>error*</code></td>
* <td valign="top" align="center">No</td>
* </tr>
* <tr>
+ * <td valign="top">quiet</td>
+ * <td valign="top">Indicates if iContract should be quiet. Turn it off
if many your classes extend uninstrumented classes
+ * and you don't want warnings about this. Defaults to
<code>false</code></td>
+ * <td valign="top" align="center">No</td>
+ * </tr>
+ * <tr>
* <td valign="top">updateicontrol</td>
* <td valign="top">If set to true, it indicates that the properties
file for
- * icontrol in the current directory should be updated (or created if
it doesn't exist)</td>
+ * iControl in the current directory should be updated (or created if
it doesn't exist).
+ * Defaults to <code>false</code>.</td>
+ * <td valign="top" align="center">No</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">controlfile</td>
+ * <td valign="top">The name of the control file to pass to iContract.
Consider using iControl to generate the file.
+ * Default is not to pass a file. </td>
+ * <td valign="top" align="center">Only if
<code>updateicontrol=true</code></td>
+ * </tr>
+ * <tr>
+ * <td valign="top">classdir</td>
+ * <td valign="top">Indicates where compiled (unistrumented) classes are
located.
+ * This is required in order to properly update the
icontrol.properties file, not
+ * for instrumentation.</td>
+ * <td valign="top" align="center">Only if
<code>updateicontrol=true</code></td>
+ * </tr>
+ * <tr>
+ * <td valign="top">targets</td>
+ * <td valign="top">Name of the file that will be generated by this
task, which lists all the
+ * classes that iContract will instrument. If specified, the file
will not be deleted after execution.
+ * If not specified, a file will still be created, but it will be
deleted after execution.</td>
* <td valign="top" align="center">No</td>
* </tr>
* </table>
*
* <p/>
* <b>Note:</b> iContract will use the java compiler indicated by the
project's
- * <code>build.compiler</code> property. See documentation for the Javac
task for
+ * <code>build.compiler</code> property. See documentation of the Javac task
for
* more information.
+ * <p/>
+ * Nested includes and excludes are also supported.
*
* <p><b>Example:</b></p>
- *
* <pre>
- * <!--
=================================================================== -->
- * <!-- Instruments source codes with iContract
-->
- * <!--
=================================================================== -->
- * <target name="instrument" depends="compile">
- * <icontract
- * srcdir="${build.src}"
- * instrumentdir="${instrumented.dir}"
- * repositorydir="${repository.dir}"
- * updateicontrol="true"
- * >
- * <classpath>
- * <fileset dir="./lib">
- * <include name="*.jar"/>
- * </fileset>
- * </classpath>
- * </icontract>
- * </target>
+ * <icontract
+ * srcdir="${build.src}"
+ * instrumentdir="${build.instrument}"
+ * repositorydir="${build.repository}"
+ * builddir="${build.instrclasses}"
+ * updateicontrol="true"
+ * classdir="${build.classes}"
+ * controlfile="control"
+ * targets="targets"
+ * verbosity="error*,warning*"
+ * quiet="true"
+ * >
+ * <classpath refid="compile-classpath"/>
+ * </icontract>
* </pre>
*
*/
-public class IContract extends Task {
+public class IContract extends MatchingTask {
+ private static final String ICONTROL_PROPERTIES_HEADER =
+ " You might want to set classRoot to point to your normal
compilation class root directory.";
+
+ private static final String ICONTROL_PROPERTIES_MESSAGE =
+ "You should probably modify icontrol.properties' classRoot to where
comiled (uninstrumented) classes go.";
+
/** \ on windows, / on linux/unix */
private static final String ps = System.getProperty( "path.separator" );
@@ -199,12 +250,18 @@
/** source file root */
private File srcDir = null;
- /** instrumentation root */
+ /** instrumentation src root */
private File instrumentDir = null;
+
+ /** instrumentation build root */
+ private File buildDir = null;
- /** repository root */
+ /** repository src root */
private File repositoryDir = null;
+ /** repository build root */
+ private File repBuildDir = null;
+
/** classpath */
private Path classpath = null;
@@ -214,6 +271,9 @@
/** The -v option */
private String verbosity = "error*";
+ /** The -q option */
+ private boolean quiet = false;
+
/** Indicates whether or not to use internal compilation */
private boolean internalcompilation = false;
@@ -222,16 +282,19 @@
/** Indicates whether or not to instrument for preconditions */
private boolean pre = true;
+ private boolean preModified = false;
/** Indicates whether or not to instrument for postconditions */
private boolean post = true;
+ private boolean postModified = false;
/** Indicates whether or not to instrument for invariants */
private boolean invariant = true;
+ private boolean invariantModified = false;
/** Indicates whether or not to instrument all files regardless of
timestamp */
// can't be explicitly set, is set if control file exists and is newer
than any source file
- private boolean instrumentall = true;
+ private boolean instrumentall = false;
/**
* Indicates the name of a properties file (intentionally for iControl)
where the classpath
@@ -240,6 +303,11 @@
private boolean updateIcontrol = false;
/**
+ * Regular compilation class root
+ */
+ private File classDir = null;
+
+ /**
* Sets the source directory
*
* @param srcDir the source directory
@@ -249,30 +317,64 @@
}
/**
+ * Sets the class directory (uninstrumented classes)
+ *
+ * @param srcDir the source directory
+ */
+ public void setClassdir( File classDir ) {
+ this.classDir = classDir;
+ }
+
+ /**
* Sets the instrumentation directory
*
* @param instrumentDir the source directory
*/
public void setInstrumentdir( File instrumentDir ) {
this.instrumentDir = instrumentDir;
+ if ( this.buildDir == null ) {
+ setBuilddir( instrumentDir );
+ }
}
/**
- * Sets the repository directory
+ * Sets the build directory for instrumented classes
*
+ * @param buildDir the build directory
+ */
+ public void setBuilddir( File buildDir ) {
+ this.buildDir = buildDir;
+ }
+
+ /**
+ * Sets the build directory for repository classes
+ *
* @param repositoryDir the source directory
*/
public void setRepositorydir( File repositoryDir ) {
this.repositoryDir = repositoryDir;
+ if( this.repBuildDir == null ) {
+ setRepbuilddir( repositoryDir );
+ }
}
/**
+ * Sets the build directory for instrumented classes
+ *
+ * @param buildDir the build directory
+ */
+ public void setRepbuilddir( File repBuildDir ) {
+ this.repBuildDir = repBuildDir;
+ }
+
+ /**
* Turns on/off precondition instrumentation
*
* @param pre true turns it on
*/
public void setPre( boolean pre ) {
this.pre = pre;
+ preModified = true;
}
/**
@@ -282,6 +384,7 @@
*/
public void setPost( boolean post ) {
this.post = post;
+ postModified = true;
}
/**
@@ -291,15 +394,16 @@
*/
public void setInvariant( boolean invariant ) {
this.invariant = invariant;
+ invariantModified = true;
}
/**
* Sets the Throwable (Exception) to be thrown on assertion violation
*
- * @param clazz the Throwable class
+ * @param clazz the fully qualified Throwable class name
*/
- public void setFailthrowable( Class clazz ) {
- this.failThrowable = clazz.getName();
+ public void setFailthrowable( String clazz ) {
+ this.failThrowable = clazz;
}
/**
@@ -307,35 +411,40 @@
* error*,warning*,note*,info*,progress*,debug* (comma separated)
* can be used. Defaults to error*,warning*
*
- * @param clazz the Throwable class
+ * @param verbosity verbosity level
*/
public void setVerbosity( String verbosity ) {
this.verbosity = verbosity;
}
/**
- * Turns on/off internal compilation.
- * <br/>
- * If set to true, Sun's javac will be run within the same VM as Ant.
- * <br/>
- * If set to false, the compiler indicated by the project property
- * <code>build.compiler</code> will be used, defaulting to javac,
- * and run in a separate VM.
- *
- * @param internalcompilation set to true for internal compilation
- */
- /* FIXME: Doesn't work
- public void setInternalcompilation( boolean internalcompilation ) {
- this.internalcompilation = internalcompilation;
- }
- */
+ * Tells iContract to be quiet.
+ *
+ * @param quiet true if iContract should be quiet.
+ */
+ public void setQuiet( boolean quiet ) {
+ this.quiet = quiet;
+ }
+
+ /**
+ * Sets the name of the file where targets will be written.
+ * That is the file that tells iContract what files to process.
+ *
+ * @param targets the targets file name
+ */
+ public void setTargets( File targets ) {
+ this.targets = targets;
+ }
/**
* Sets the control file to pass to iContract.
*
- * @param clazz the Throwable class
+ * @param controlFile the control file
*/
public void setControlfile( File controlFile ) {
+ if( !controlFile.exists() ) {
+ log( "WARNING: Control file " + controlFile.getAbsolutePath() +
" doesn't exist. iContract will be run without control file." );
+ }
this.controlFile = controlFile;
}
@@ -387,6 +496,25 @@
preconditions();
scan();
if( dirty ) {
+
+ // turn off assertions if we're using controlfile, unless they
are not explicitly set.
+ boolean useControlFile = (controlFile != null) &&
controlFile.exists();
+ if( useControlFile && !preModified ) {
+ pre = false;
+ }
+ if( useControlFile && !postModified ) {
+ post = false;
+ }
+ if( useControlFile && !invariantModified ) {
+ invariant = false;
+ }
+ // issue warning if pre,post or invariant is used together with
controlfile
+ if( ( pre || post || invariant ) && controlFile != null ) {
+ log( "WARNING: specifying pre,post or invariant will
override control file settings" );
+ }
+
+
+
// We want to be notified if iContract jar is missing. This
makes life easier for the user
// who didn't understand that iContract is a separate library
(duh!)
getProject().addBuildListener( new IContractPresenceDetector() );
@@ -397,15 +525,19 @@
Mkdir mkdir = (Mkdir) project.createTask( "mkdir" );
mkdir.setDir( instrumentDir );
mkdir.execute();
+ mkdir.setDir( buildDir );
+ mkdir.execute();
mkdir.setDir( repositoryDir );
mkdir.execute();
- // Set the compiler
- setCompiler();
-
// Set the classpath that is needed for regular Javac compilation
Path baseClasspath = createClasspath();
+ // Might need to add the core classes if we're not using Sun's
Javac (like Jikes)
+ String compiler = project.getProperty("build.compiler");
+ ClasspathHelper classpathHelper = new ClasspathHelper( compiler
);
+ classpathHelper.modify( baseClasspath );
+
// Create the classpath required to compile the sourcefiles
BEFORE instrumentation
Path beforeInstrumentationClasspath = ((Path)
baseClasspath.clone());
beforeInstrumentationClasspath.append( new Path( getProject(),
srcDir.getAbsolutePath() ) );
@@ -415,12 +547,14 @@
afterInstrumentationClasspath.append( new Path( getProject(),
instrumentDir.getAbsolutePath() ) );
afterInstrumentationClasspath.append( new Path( getProject(),
repositoryDir.getAbsolutePath() ) );
afterInstrumentationClasspath.append( new Path( getProject(),
srcDir.getAbsolutePath() ) );
+ afterInstrumentationClasspath.append( new Path( getProject(),
buildDir.getAbsolutePath() ) );
// Create the classpath required to automatically compile the
repository files
Path repositoryClasspath = ((Path) baseClasspath.clone());
repositoryClasspath.append( new Path( getProject(),
instrumentDir.getAbsolutePath() ) );
repositoryClasspath.append( new Path( getProject(),
srcDir.getAbsolutePath() ) );
repositoryClasspath.append( new Path( getProject(),
repositoryDir.getAbsolutePath() ) );
+ repositoryClasspath.append( new Path( getProject(),
buildDir.getAbsolutePath() ) );
// Create the classpath required for iContract itself
Path iContractClasspath = ((Path) baseClasspath.clone());
@@ -428,6 +562,7 @@
iContractClasspath.append( new Path( getProject(),
srcDir.getAbsolutePath() ) );
iContractClasspath.append( new Path( getProject(),
repositoryDir.getAbsolutePath() ) );
iContractClasspath.append( new Path( getProject(),
instrumentDir.getAbsolutePath() ) );
+ iContractClasspath.append( new Path( getProject(),
buildDir.getAbsolutePath() ) );
// Create a forked java process
Java iContract = (Java) project.createTask( "java" );
@@ -440,17 +575,18 @@
StringBuffer args = new StringBuffer();
args.append( directiveString() );
args.append( "-v" ).append( verbosity ).append( " " );
- args.append( "-b" ).append( icCompiler ).append( "\"" ).append(
" -classpath " ).append( beforeInstrumentationClasspath ).append( "\" " );
- args.append( "-c" ).append( icCompiler ).append( "\"" ).append(
" -classpath " ).append( afterInstrumentationClasspath ).append( "\" " );
- args.append( "-n" ).append( icCompiler ).append( "\"" ).append(
" -classpath " ).append( repositoryClasspath ).append( "\" " );
+ args.append( "-b" ).append( "\"" ).append( icCompiler ).append(
" -classpath " ).append( beforeInstrumentationClasspath ).append( "\" " );
+ args.append( "-c" ).append( "\"" ).append( icCompiler ).append(
" -classpath " ).append( afterInstrumentationClasspath ).append( " -d "
).append( buildDir ).append( "\" " );
+ args.append( "-n" ).append( "\"" ).append( icCompiler ).append(
" -classpath " ).append( repositoryClasspath ).append( "\" " );
args.append( "-d" ).append( failThrowable ).append( " " );
args.append( "-o" ).append( instrumentDir ).append(
File.separator ).append( "@p" ).append( File.separator ).append( "@[EMAIL
PROTECTED] " );
args.append( "-k" ).append( repositoryDir ).append(
File.separator ).append( "@p " );
- args.append( instrumentall ? "-a " : "" ); // reinstrument
everything if controlFile exists and is newer than source
+ args.append( quiet ? "-q " : "" );
+ args.append( instrumentall ? "-a " : "" ); // reinstrument
everything if controlFile exists and is newer than any class
args.append( "@" ).append( targets.getAbsolutePath() );
iContract.createArg().setLine( args.toString() );
-// System.out.println( "JAVA -classpath " + iContractClasspath + "
com.reliablesystems.iContract.Tool " + args.toString() );
+//System.out.println( "JAVA -classpath " + iContractClasspath + "
com.reliablesystems.iContract.Tool " + args.toString() );
// update iControlProperties if it's set.
if( updateIcontrol ) {
@@ -460,18 +596,21 @@
} catch( IOException e ) {
log( "File icontrol.properties not found. That's ok.
Writing a default one." );
}
- iControlProps.setProperty( "classRoot",
srcDir.getAbsolutePath() );
- iControlProps.setProperty( "classpath",
iContractClasspath.toString() );
- iControlProps.setProperty( "controlFile", "control" );
+ iControlProps.setProperty( "sourceRoot",
srcDir.getAbsolutePath() );
+ iControlProps.setProperty( "classRoot",
classDir.getAbsolutePath() );
+ iControlProps.setProperty( "classpath",
afterInstrumentationClasspath.toString() );
+ iControlProps.setProperty( "controlFile",
controlFile.getAbsolutePath() );
+ iControlProps.setProperty( "targetsFile",
targets.getAbsolutePath() );
try { // to read existing propertiesfile
- iControlProps.store( new FileOutputStream(
"icontrol.properties" ), "Edit the classRoot and controlfile properties if you
like" );
- log( "Updated file icontrol.properties." );
+ iControlProps.store( new FileOutputStream(
"icontrol.properties" ), ICONTROL_PROPERTIES_HEADER );
+ log( "Updated icontrol.properties" );
} catch( IOException e ) {
log( "Couldn't write icontrol.properties." );
}
}
+ // do it!
int result = iContract.executeJava();
if( result != 0 ) {
if( iContractMissing ) {
@@ -481,7 +620,8 @@
}
throw new BuildException( "iContract instrumentation failed.
Code=" + result );
}
- } else {
+
+ } else { // not dirty
//log( "Nothing to do. Everything up to date." );
}
}
@@ -502,36 +642,54 @@
if (repositoryDir == null) {
throw new BuildException( "repositorydir attribute must be
set!", location );
}
+ if (updateIcontrol == true && classDir == null) {
+ throw new BuildException( "classdir attribute must be specified
when updateicontrol=true!", location );
+ }
+ if( updateIcontrol == true && controlFile == null ) {
+ throw new BuildException( "controlfile attribute must be
specified when updateicontrol=true!", location );
+ }
}
/**
* Verifies whether any of the source files have changed. Done by
comparing date of source/class files.
- * The whole lot is "dirty" if at least one source file is newer than
the instrumented files. If not dirty,
- * iContract will not be executed.
+ * The whole lot is "dirty" if at least one source file or the control
file is newer than the instrumented
+ * files. If not dirty, iContract will not be executed.
* <br/>
* Also creates a temporary file with a list of the source files, that
will be deleted upon exit.
*/
private void scan() throws BuildException {
long now = (new Date()).getTime();
- FileSet fileset = new FileSet();
- fileset.setDefaultexcludes( true );
- fileset.setDir( srcDir );
- DirectoryScanner ds = fileset.getDirectoryScanner( project );
+ DirectoryScanner ds = null;
+ ds = getDirectoryScanner( srcDir );
String[] files = ds.getIncludedFiles();
+ FileOutputStream targetOutputStream = null;
+ PrintStream targetPrinter = null;
+ boolean writeTargets = false;
try {
- targets = File.createTempFile( "iContractTargets", "tmp", new
File( System.getProperty( "user.dir" ) ) );
- targets.deleteOnExit();
- FileOutputStream fos = new FileOutputStream( targets );
- PrintStream ps = new PrintStream( fos );
+ if( targets == null ) {
+ targets = new File( "targets" );
+ log( "Warning: targets file not specified. generating file:
" + targets.getName() );
+ writeTargets = true;
+ } else if( !targets.exists() ) {
+ log( "Specified targets file doesn't exist. generating file:
" + targets.getName() );
+ writeTargets = true;
+ }
+ if( writeTargets ) {
+ log( "You should consider using iControl to create a target
file." );
+ targetOutputStream = new FileOutputStream( targets );
+ targetPrinter = new PrintStream( targetOutputStream );
+ }
for (int i = 0; i < files.length; i++ ) {
File srcFile = new File(srcDir, files[i]);
if (files[i].endsWith(".java")) {
- ps.println( srcFile.getAbsolutePath() );
-
- File classFile = new File( instrumentDir,
files[i].substring( 0, files[i].indexOf( ".java" ) ) + ".class" );
+ // print the target, while we're at here. (Only if
generatetarget=true).
+ if( targetPrinter != null ) {
+ targetPrinter.println( srcFile.getAbsolutePath() );
+ }
+ File classFile = new File( buildDir, files[i].substring(
0, files[i].indexOf( ".java" ) ) + ".class" );
if (srcFile.lastModified() > now) {
log("Warning: file modified in the future: " +
@@ -543,24 +701,25 @@
dirty = true;
}
}
+ }
+ if( targetPrinter != null ) {
+ targetPrinter.flush();
+ targetPrinter.close();
}
- ps.flush();
- ps.close();
} catch( IOException e ) {
- throw new BuildException( "Could not create temporary file:" +
e.getMessage() );
+ throw new BuildException( "Could not create target file:" +
e.getMessage() );
}
// also, check controlFile timestamp
long controlFileTime = -1;
try {
if( controlFile != null ) {
- if( controlFile.exists() && instrumentDir.exists() ) {
+ if( controlFile.exists() && buildDir.exists() ) {
controlFileTime = controlFile.lastModified();
- fileset.setDir( instrumentDir );
- ds = fileset.getDirectoryScanner( project );
+ ds = getDirectoryScanner( buildDir );
files = ds.getIncludedFiles();
for( int i = 0; i < files.length; i++ ) {
- File srcFile = new File(srcDir, files[i]);
+ File srcFile = new File( srcDir, files[i] );
if( files[i].endsWith( ".class" ) ) {
if( controlFileTime > srcFile.lastModified() ) {
if( !dirty ) {
@@ -574,8 +733,7 @@
}
}
} catch( Throwable t ) {
- System.out.println( "FATAL" );
- t.printStackTrace();
+ throw new BuildException( "Got an interesting exception:" +
t.getMessage() );
}
}
@@ -586,10 +744,12 @@
private final String directiveString() {
StringBuffer sb = new StringBuffer();
boolean comma = false;
- if( (controlFile != null) || pre || post || invariant ) {
+
+ boolean useControlFile = (controlFile != null) &&
controlFile.exists();
+ if( useControlFile || pre || post || invariant ) {
sb.append( "-m" );
}
- if(controlFile != null) {
+ if( useControlFile ) {
sb.append( "@" ).append( controlFile );
comma = true;
}
@@ -612,50 +772,12 @@
sb.append( "," );
}
sb.append( "inv" );
- comma = true;
}
sb.append( " " );
return sb.toString();
}
/**
- * Sets the compiler as specified by the project's build.compiler
property
- * If the internalcompilation attribute is set to true, Sun's javac
- * will be run from the same VM as Ant.
- *
- * NOTE: This has not been tested, as I only have JDK.
- */
- private void setCompiler() {
- if( !internalcompilation ) {
- String compiler = project.getProperty("build.compiler");
- if (compiler == null) {
- if (Project.getJavaVersion().startsWith("1.3")) {
- compiler = "modern";
- } else {
- compiler = "classic";
- }
- }
-
- if (compiler.equalsIgnoreCase("classic")) {
- icCompiler = "javac";
- } else if (compiler.equalsIgnoreCase("modern")) {
- icCompiler = "javac";
- } else if (compiler.equalsIgnoreCase("jikes")) {
- icCompiler = "jikes";
- } else if (compiler.equalsIgnoreCase("jvc")) {
- icCompiler = "jvc";
- } else {
- String msg = "Don't know how to use compiler " + compiler;
- throw new BuildException(msg, location);
- }
- } else {
- // This is how we tell iContract to use internal compiler
- // FIXME: Doesn't work
-// icCompiler = ":";
- }
- }
-
- /**
* BuildListener that sets the iContractMissing flag to true if a
* message about missing iContract is missing. Used to indicate
* a more verbose error to the user, with advice about how to solve
@@ -673,5 +795,32 @@
public void targetStarted(BuildEvent event) {}
public void taskFinished(BuildEvent event) {}
public void taskStarted(BuildEvent event) {}
+ }
+
+ /**
+ * This class is a helper to set correct classpath for other compilers,
like Jikes.
+ * It reuses the logic from DefaultCompilerAdapter, which is protected,
so we have
+ * to subclass it.
+ */
+ private class ClasspathHelper extends DefaultCompilerAdapter {
+ private final String compiler;
+ public ClasspathHelper( String compiler ) {
+ super();
+ this.compiler = compiler;
+ }
+
+ // make it public
+ public void modify( Path path ) {
+ // depending on what compiler to use, set the includeJavaRuntime
flag
+ if( "jikes".equals( compiler ) ) {
+ icCompiler = compiler;
+ includeJavaRuntime = true;
+ path.append( getCompileClasspath() );
+ }
+ }
+
+ // dummy implementation. Never called
+ public void setJavac( Javac javac ) {}
+ public boolean execute() { return true; }
}
}