KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > csdl > jblanket > ant > JBlanketModifierTask


1 package csdl.jblanket.ant;
2
3 import java.util.ArrayList JavaDoc;
4 import java.util.Date JavaDoc;
5 import java.util.Iterator JavaDoc;
6 import java.util.List JavaDoc;
7
8 import org.apache.tools.ant.BuildException;
9 import org.apache.tools.ant.DirectoryScanner;
10 import org.apache.tools.ant.types.FileSet;
11
12 /**
13  * Implements the JBlanket Apache Ant task definition that instruments the byte code. All files
14  * (.class or .jar files) specified by the fileSet element in the Ant task are processed by the
15  * Modifier class and stored in the directory specified by the jblanket.dir system property.
16  * If not set, the default directory is <user_home>/<user_account>/jblanket/.
17  * <p>
18  * <b>Required</b> nested element for the instrumentation task:
19  * <ul>
20  * <p>
21  * 'fileset' - describes the files to be modified<br>
22  * <i>For example</i>: see <a HREF="http://jakarta.apache.org/ant/manual/index.html">Ant</a>
23  * </ul>
24  * <p>
25  * Use multiple 'fileset' elements to specify different locations of files to modify.
26  * <p>
27  * <b>Optional</b> nested element for the instrumentation task:
28  * <ul>
29  * <p>
30  * 'packageprefix' - describes the package prefixes to be modified in a JAR file. To instrument
31  * all classes in a JAR file, do not included this nested element.<br>
32  * <i>For example</i>: see <a HREF="PackagePrefix.html" target="classFrame">PackagePrefix</a>
33  * <p>
34  * 'sysproperty' - describes additional system properties not set in the environment. If
35  * jblanket.dir is not set as an environment variable, include this nested element
36  * to set it.
37  * <i>For example</i>: see <a HREF="http://jakarta.apache.org/ant/manual/index.html">Ant</a>
38  * </ul>
39  * <p>
40  * <b>Required</b> attribute for the instrumentation task:
41  * <ul>
42  * <p>
43  * 'testgrammar' - grammar describing the names of JUnit test classes<br>
44  * <i>For example</i>: testgrammar="Test*.class"
45  * </ul>
46  * <p>
47  * <b>Optional</b> attributes for the instrumentation task:
48  * <ul>
49  * <p>
50  * 'enable' - describes if the byte code should be modified. Valid values include "true", "on",
51  * "yes" to modify byte code or "false", "off", or "no" to not modify byte code.<br>
52  * <i>For example</i>: enable="true"
53  * <p>
54  * 'verbose' - describes if additional output should be sent to standard out.
55  * Valid values include "true", "on", "yes" for additional output
56  * or "false", "off", or "no" for no additional output.<br>
57  * <i>For example</i>: verbose="false"
58  * <p>
59  * 'excludeonelinemethods' - describes if methods with one line of code should be excluded from
60  * the coverage measurement. Values include "true", "on", "yes" to
61  * exclude one-line methods or "false", "off", or "no" to include them.
62  * <br>
63  * <i>For example</i>: excludeonelinemethods="false"
64  * <p>
65  * 'excludeconstructors' - describes if constructors should be excluded from the coverage
66  * measurement. Values include "true", "on", "yes" to exclude constructors
67  * or "false", "off", or "no" to include them.<br>
68  * <i>For example</i>: excludeconstructors="false"
69  * <p>
70  * 'totalfile' - name of XML file to contain all methods included in the coverage measurement<br>
71  * <i>For example</i>: totalfile="totalMethods.xml"
72  * <p>
73  * 'untestablefile' - name of XML file to contain all abstract or native methods<br>
74  * <i>For example</i>: untestablefile="untestableMethods.xml"
75  * <p>
76  * 'excludedfile' - name of XML file to contain all methods excluded from the coverage measurement
77  * by either the fileset or packageprefix nested element<br>
78  * <i>For example</i>: excludedfile="excludedMethods.xml"
79  * <p>
80  * 'onelinefile' - name of XML file to contain all one-line methods<br>
81  * <i>For example</i>: onelinefile="oneLineMethods.xml"
82  * <p>
83  * 'constructionfile' - name of XML file to contain all constructors<br>
84  * <i>For example</i>: constructorfile="constructorMethods.xml"
85  * </ul>
86  * <p>
87  * If any of the optional attributes are not specified, their default values specified in the
88  * examples are used. For example, to exclude methods with one line of source code from the
89  * coverage measurement, specify the 'excludeonelinemethods' attribute with a 'true' value.
90  * When not specified, one-line methods will be included in the coverage measurement.
91  * <p>
92  * Use this class to execute JBlanket with Ant. One example of the 'jblanket' Ant target is:
93  * <pre>
94  * &lt;taskdef name="jblanket" classname="csdl.jblanket.ant.JBlanketModifierTask"/&gt;
95  * &lt;jblanket testgrammar="Test&#42;.class"
96  * excludeonelinemethods="true"
97  * totalfile="myTotalMethods.xml"
98  * untestablefile="myUntestableMethods.xml"&gt;
99  * &lt;fileset dir="${basedir}"&gt;
100  * &lt;include name="&#42;&#42;/stackmvc/&#42;&#42;/&#42;.class"/&gt;
101  * &lt;/fileset&gt;
102  * &lt;fileset dir="${lib.dir}"&gt;
103  * &lt;include name="stack.jar"/&gt;
104  * &lt;/fileset&gt;
105  * &lt;/jblanket&gt;
106  * </pre>
107  * From the example, one-line methods are excluded and constructors are included. The total
108  * methods will be stored in 'myTotalMethods.xml' and untestable methods are stored in
109  * 'myUntestableMethods.xml'. The default file names for excluded methods and one-line methods are
110  * used. No additional output will be sent to standard out. The files to be modified are the
111  * .class files found in the subdirectories beginning with 'stackmvc' and the 'stack.jar' file in
112  * ${lib.dir}.
113  * <p>
114  * Another example is:
115  * <pre>
116  * &lt;jblanket testgrammar="&#42;Test.class"
117  * verbose="true"&gt;
118  * &lt;fileset dir="${src.dir}"&gt;
119  * &lt;include name="&#42;&#42;/foo/&#42;.class"/&gt;
120  * &lt;/fileset&gt;
121  * &lt;/jblanket&gt;
122  * </pre>
123  * where the total methods, untestable methods, and excluded methods are stored in the default
124  * files. One-line methods and constructors are included in coverage. Additional output will be
125  * sent to standard out. The files to be modified are the .class files found in the
126  * subdirectories beginning with 'foo'.
127  * <p>
128  * NOTE: For JBlanket to collect data, all files MUST be compiled with debug turned "on".
129  *
130  * @author Joy M. Agustin
131  * @version $Id: JBlanketModifierTask.java,v 1.2 2005/02/19 05:55:19 timshadel Exp $id
132  */

133 public class JBlanketModifierTask extends JBlanketTask {
134
135   /** Grammar for test class names */
136   private String JavaDoc testGrammar;
137   
138   /** Name of file for untestable methods, i.e., abstract and native methods */
139   protected String JavaDoc untestableFile;
140   /** Name of file for excluded methods, i.e., methods in classes user specifically excludes */
141   protected String JavaDoc excludedFile;
142
143   /** Set(s) of files to be modified */
144   private ArrayList JavaDoc fileSets;
145   /** Package prefixes of packages modify */
146   private ArrayList JavaDoc packagePrefixes;
147
148   /**
149    * Constructs a new JBlanketModifierTask object.
150    */

151   public JBlanketModifierTask() {
152     super();
153     
154     this.testGrammar = null;
155     
156     this.untestableFile = null;
157     this.excludedFile = null;
158     
159     this.fileSets = new ArrayList JavaDoc();
160     this.packagePrefixes = new ArrayList JavaDoc();
161   }
162   
163   /**
164    * Adds a set of files specified by a nested fileset element.
165    *
166    * @param fileSet set of files to be modified.
167    */

168   public void addFileSet(FileSet fileSet) {
169     this.fileSets.add(fileSet);
170   }
171
172   /**
173    * Adds a PackagePrefix specified by a nested packageprefix element.
174    *
175    * @param packagePrefix the PackagePrefix to include in coverage.
176    */

177   public void addPackagePrefix(PackagePrefix packagePrefix) {
178     this.packagePrefixes.add(packagePrefix);
179   }
180
181   /**
182    * Sets the grammar describing the names of test classes.
183    * <p>
184    * For example, testGrammar="Test*.class" means that the names of all test class begin with
185    * "Test".
186    *
187    * @param testGrammar the new grammar.
188    */

189   public void setTestgrammar(String JavaDoc testGrammar) {
190     this.testGrammar = testGrammar;
191   }
192
193   /**
194    * Sets the name of the XML file for untestable methods. I.e., abstract and native methods.
195    *
196    * @param untestableFile the untestable file name.
197    */

198   public void setUntestablefile(String JavaDoc untestableFile) {
199     this.untestableFile = untestableFile;
200   }
201
202   /**
203    * Sets the name of the XML file for excluded methods. I.e., methods found in classes
204    * that are excluded by either the fileset or the packageprefix.
205    *
206    * @param excludedFile the excluded file name.
207    */

208   public void setExcludedfile(String JavaDoc excludedFile) {
209     this.excludedFile = excludedFile;
210   }
211
212   /**
213    * Transforms <code>array</code> to a ';' delimited String.
214    *
215    * @param array the array of Strings to transform.
216    * @param message a message to associate with each <code>array</code> element.
217    * Used for verbose mode.
218    * @return a ';' delimited String.
219    */

220   private String JavaDoc arrayToString(String JavaDoc[] array, String JavaDoc message) {
221
222     StringBuffer JavaDoc delimitedString = new StringBuffer JavaDoc();
223
224     for (int i = 0; i < array.length; i++) {
225
226       if (i > 0) {
227         delimitedString.append(";");
228       }
229
230       delimitedString.append(array[i]);
231
232       if (super.verbose) {
233         System.out.println(message + ": " + array[i]);
234       }
235     }
236
237     return delimitedString.toString();
238   }
239
240   /**
241    * Transforms <code>list</code> to a ';' delimited String.
242    *
243    * @param list the List of Strings to transform.
244    * @param message a message to associate with each message. Used for verbose mode.
245    * @return a ';' delimited String.
246    */

247   private String JavaDoc listToString(List JavaDoc list, String JavaDoc message) {
248     
249     StringBuffer JavaDoc delimitedString = new StringBuffer JavaDoc();
250
251     for (Iterator JavaDoc i = list.iterator(); i.hasNext(); ) {
252
253       if (delimitedString.length() != 0) {
254         delimitedString.append(";");
255       }
256
257       String JavaDoc next = ((PackagePrefix) i.next()).getName();
258       delimitedString.append(next);
259
260       if (super.verbose) {
261         System.out.println(message + ": " + next);
262       }
263     }
264
265     return delimitedString.toString();
266   }
267
268   /**
269    * Executes the byte code instrumentation Ant taskdef.
270    */

271   public void execute() {
272
273     Date JavaDoc startTime = new Date JavaDoc();
274
275     // Return without modifying files if jblanket is disabled.
276
if (!super.enable) {
277       
278       if (super.verbose) {
279         System.out.println("JBlanket disabled; no files modified.");
280       }
281       
282       return;
283     }
284
285     // process each fileset separately because each may have different base directories
286
for (Iterator JavaDoc i = this.fileSets.iterator(); i.hasNext(); ) {
287       
288       // Format Modifier arguments.
289
ArrayList JavaDoc args = new ArrayList JavaDoc();
290
291       // add the directory containing all the files
292
FileSet fileSet = (FileSet) i.next();
293       DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
294       args.add("-classDir");
295       args.add(scanner.getBasedir().getAbsolutePath());
296
297       // add all files to modify
298
args.add("-include");
299       args.add(arrayToString(scanner.getIncludedFiles(), "modifying"));
300
301       // add all files to not modify
302
args.add("-exclude");
303       args.add(arrayToString(scanner.getExcludedFiles(), "excluding"));
304
305       // add verbose
306
args.add("-verbose");
307       args.add(new Boolean JavaDoc(super.verbose));
308
309       // add grammar for test file names
310
args.add("-testGrammar");
311       args.add(this.testGrammar);
312
313       // add oneLineFile if user specified
314
if (super.excludeOneLineMethods) {
315         args.add("-excludeOneLineMethods");
316         args.add(new Boolean JavaDoc(super.excludeOneLineMethods));
317         if (super.oneLineFile != null) {
318           args.add("-oneLineFile");
319           args.add(super.oneLineFile);
320         }
321       }
322
323       // add constructorFile if user specified
324
if (super.excludeConstructors) {
325         args.add("-excludeConstructors");
326         args.add(new Boolean JavaDoc(super.excludeConstructors));
327         if (super.constructorFile != null) {
328           args.add("-constructorFile");
329           args.add(super.constructorFile);
330         }
331       }
332
333       // add totalFile if user specified
334
if (super.totalFile != null) {
335         args.add("-totalFile");
336         args.add(super.totalFile);
337       }
338
339       // add untestableFile if user specified
340
if (this.untestableFile != null) {
341         args.add("-untestableFile");
342         args.add(this.untestableFile);
343       }
344
345       // add constructorFile if user specified
346
if (super.excludeIndividualMethods) {
347         args.add("-excludeIndividualMethods");
348         args.add(new Boolean JavaDoc(super.excludeIndividualMethods));
349       }
350
351       // add excludedFile if user specified
352
if (this.excludedFile != null) {
353         args.add("-excludedFile");
354         args.add(this.excludedFile);
355       }
356
357       // add any package prefixes
358
if (this.packagePrefixes.size() != 0) {
359         args.add("-packagePrefix");
360         args.add(listToString(packagePrefixes, "package prefixes"));
361       }
362
363       // Execute Modifier.main on arguments.
364
// TODO write out Exceptions to a Log, and print an error message to the screen.
365
try {
366         csdl.jblanket.modifier.Modifier.main(args);
367       }
368       catch (Exception JavaDoc e) {
369         e.printStackTrace();
370         throw new BuildException("Error in JBlanket.");
371       }
372       catch (Throwable JavaDoc t) {
373         t.printStackTrace();
374         throw new BuildException("Unsuccessful modification of files");
375       }
376     }
377     
378     Date JavaDoc endTime = new Date JavaDoc();
379     long elapsedTime = (endTime.getTime() - startTime.getTime()) / 1000;
380     System.out.println("JBlanket modify task completed " + "(" + elapsedTime + " secs.)");
381   }
382 }
383
Popular Tags