KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > codecoverage > v2 > ant > GroboReportTask


1 /*
2  * @(#)GroboReportTask.java
3  *
4  * Copyright (C) 2004 Matt Albrecht
5  * groboclown@users.sourceforge.net
6  * http://groboutils.sourceforge.net
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */

26
27 package net.sourceforge.groboutils.codecoverage.v2.ant;
28
29 import java.io.File JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.util.Vector JavaDoc;
33
34 import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule;
35 import net.sourceforge.groboutils.codecoverage.v2.IChannelLogReader;
36 import net.sourceforge.groboutils.codecoverage.v2.datastore.AnalysisModuleSet;
37 import net.sourceforge.groboutils.codecoverage.v2.datastore.DirMetaDataReader;
38 import net.sourceforge.groboutils.codecoverage.v2.datastore.IMetaDataReader;
39 import net.sourceforge.groboutils.codecoverage.v2.logger.DirectoryChannelLogReader;
40 import net.sourceforge.groboutils.codecoverage.v2.report.AnalysisModuleData;
41 import net.sourceforge.groboutils.codecoverage.v2.report.IReportGenerator;
42 import net.sourceforge.groboutils.codecoverage.v2.report.XmlCombinedReportGenerator;
43 import net.sourceforge.groboutils.codecoverage.v2.report.XmlReportGenerator;
44 import net.sourceforge.groboutils.codecoverage.v2.util.ILogFilter;
45 import net.sourceforge.groboutils.codecoverage.v2.util.SingleLogFilter;
46
47 import org.apache.tools.ant.BuildException;
48 import org.apache.tools.ant.Project;
49 import org.apache.tools.ant.Task;
50 import org.apache.tools.ant.types.EnumeratedAttribute;
51
52 import org.w3c.dom.Document JavaDoc;
53 import org.w3c.dom.Element JavaDoc;
54
55
56
57
58 /**
59  * A variation of the CoveragePostCompilerTask. This one is intended to
60  * simplify the Ant build files. See
61  * <a HREF="https://sourceforge.net/tracker/index.php?func=detail&aid=901588&group_id=22594&atid=375592">
62  * feature request 901588</a> for details.
63  *
64  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
65  * @version $Date: 2004/07/07 09:39:09 $
66  * @since March 13, 2004
67  */

68 public class GroboReportTask extends Task
69 {
70     private File JavaDoc baselogdir;
71     private File JavaDoc logdir;
72     private File JavaDoc datadir;
73     private Vector JavaDoc singleStyles = new Vector JavaDoc();
74     private Vector JavaDoc comboStyles = new Vector JavaDoc();
75     private boolean failOnError = true;
76     private LogFilter filter = null;
77     
78     
79     public static final class FilterTypeAttribute extends EnumeratedAttribute
80     {
81         private String JavaDoc[] types = { "single", "none" };
82         public String JavaDoc[] getValues()
83         {
84             return this.types;
85         }
86     }
87     
88     public static class LogFilter
89     {
90         private String JavaDoc type = "none";
91         
92         public void setType( FilterTypeAttribute fta )
93         {
94             this.type = fta.getValue();
95         }
96         
97         public ILogFilter getFilter()
98         {
99             if ("single".equalsIgnoreCase( this.type ))
100             {
101                 return new SingleLogFilter();
102             }
103             // else
104
return null;
105         }
106     }
107     
108     
109     /**
110      * Set the directory which contains the log and data directories.
111      */

112     public void setLogDir( File JavaDoc dir )
113     {
114         this.baselogdir = dir;
115     }
116     
117     
118     /**
119      * Add a filter to convert the Logger's output format to the standard
120      * format. If no filter is given, then we assume that the logs are
121      * already in the standard format.
122      */

123     public void addLogFilter( LogFilter lf )
124     {
125         this.filter = lf;
126     }
127     
128     
129     /**
130      *
131      */

132     public void addXml( XmlReportStyle xrs )
133     {
134         // creates an XML report for both the single and combo files.
135
_addSingle( xrs );
136         _addCombo( xrs );
137     }
138     
139     
140     /**
141      *
142      */

143     public void addXsl( SimpleXslReportStyle sxrs )
144     {
145         _addSingle( sxrs );
146     }
147     
148     
149     /**
150      *
151      */

152     public void addSourceXsl( SourceXslReportStyle sxrs )
153     {
154         _addCombo( sxrs );
155     }
156     
157     
158     /**
159      *
160      */

161     public void addSimpleHtml( SimpleHtmlReportStyle shrs )
162     {
163         _addSingle( shrs );
164     }
165     
166     
167     /**
168      *
169      */

170     public void addSimple( SimpleHtmlReportStyle shrs )
171     {
172         _addSingle( shrs );
173     }
174     
175     
176     /**
177      *
178      */

179     public void addSourceHtml( SourceHtmlReportStyle shrs )
180     {
181         _addCombo( shrs );
182     }
183     
184     
185     /**
186      *
187      */

188     public void addSource( SourceHtmlReportStyle shrs )
189     {
190         _addCombo( shrs );
191     }
192     
193     
194     /**
195      *
196      */

197     public void addFailOn( FailOnReportStyle fors )
198     {
199         _addCombo( fors );
200     }
201     
202     
203     public void setFailOnError( boolean f )
204     {
205         this.failOnError = f;
206     }
207     
208     
209     
210     public void execute()
211             throws BuildException
212     {
213         try
214         {
215             setupDirectories();
216         }
217         catch (IOException JavaDoc ioe)
218         {
219             throw new BuildException( "Error setting up the directories.", ioe );
220         }
221         
222         
223         IMetaDataReader mdr = createMetaDataReader();
224         IReportGenerator rg = new XmlReportGenerator();
225         boolean errors = false;
226         Vector JavaDoc reports = new Vector JavaDoc();
227         Vector JavaDoc errorList = new Vector JavaDoc();
228         try
229         {
230             AnalysisModuleSet ams = mdr.getAnalysisModuleSet();
231             IAnalysisModule amL[] = ams.getAnalysisModules();
232             for (int i = 0; i < amL.length; ++i)
233             {
234                 try
235                 {
236                     IChannelLogReader clr =
237                         createChannelLogReader( amL[i], ams );
238                     AnalysisModuleData amd =
239                         new AnalysisModuleData( amL[i], mdr, clr );
240                     Element JavaDoc rootEl = createReport( amL[i], amd, rg );
241                     if (rootEl == null)
242                     {
243                         log( "Creating the report returned null", Project.MSG_WARN );
244                         errors = true;
245                     }
246                     else
247                     {
248                         Document JavaDoc doc = rootEl.getOwnerDocument();
249                         reports.addElement( doc );
250                         processSingleStyles( doc, amL[i].getMeasureName() );
251                     }
252                 }
253                 catch (IllegalArgumentException JavaDoc iae)
254                 {
255                     iae.printStackTrace();
256                     log( iae.getMessage(), Project.MSG_WARN );
257                     errors = true;
258                 }
259             }
260             finishSingleStyles( errorList );
261         }
262         catch (IOException JavaDoc e)
263         {
264             throw new BuildException(
265                 "I/O Exception while creating a report.", e, getLocation() );
266         }
267         finally
268         {
269             try
270             {
271                 mdr.close();
272             }
273             catch (IOException JavaDoc e)
274             {
275                 throw new BuildException(
276                     "I/O Exception while closing meta-data reader.", e,
277                     getLocation() );
278             }
279         }
280         rg = null;
281         mdr = null;
282         try
283         {
284             processCombos( reports, errorList );
285         }
286         catch (IOException JavaDoc e)
287         {
288             throw new BuildException(
289                 "I/O Exception while creating a report.", e, getLocation() );
290         }
291         
292         
293         if (errors && this.failOnError)
294         {
295             throw new BuildException(
296                 "No coverage logs were generated, or the logs "+
297                 "are not located under '"+this.logdir+"'.",
298                 getLocation() );
299         }
300         
301         if (errorList.size() > 0)
302         {
303             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
304             Enumeration JavaDoc e = errorList.elements();
305             while (e.hasMoreElements())
306             {
307                 sb.append( "; " ).append( (String JavaDoc)e.nextElement() );
308             }
309             if (this.failOnError)
310             {
311                 throw new BuildException(
312                     "Error conditions caused failure" + sb.toString() );
313             }
314             else
315             {
316                 log( "Warning: " + sb.toString(), Project.MSG_WARN );
317             }
318         }
319     }
320     
321
322     
323     
324     private void processCombos( Vector JavaDoc reports, Vector JavaDoc errorList )
325             throws BuildException, IOException JavaDoc
326     {
327         // only process the combos (and thus create the uber XML file)
328
// if needed.
329
if (this.comboStyles.size() > 0)
330         {
331             // Create the uber document
332
Document JavaDoc docs[] = new Document JavaDoc[ reports.size() ];
333             reports.copyInto( docs );
334             
335             // a memory conservation item. This means this can only be
336
// the last method to run with the reports from execute()
337
reports.removeAllElements();
338             
339             XmlCombinedReportGenerator gen = new XmlCombinedReportGenerator();
340             log( "Creating combined coverage report", Project.MSG_INFO );
341             Element JavaDoc ret = null;
342             try
343             {
344                 ret = gen.createReport( docs );
345             }
346             catch (IllegalArgumentException JavaDoc iae)
347             {
348                 // throw new BuildException( iae );
349

350                 // this is a hack: really, the underlying code should be made
351
// more robust.
352
iae.printStackTrace();
353                 log( iae.getMessage(), Project.MSG_WARN );
354                 ret = null;
355             }
356             docs = null;
357             
358             if (ret != null)
359             {
360                 processComboStyles( ret.getOwnerDocument() );
361                 finishComboStyles( errorList );
362             }
363         }
364     }
365
366     
367     
368     private void processSingleStyles( Document JavaDoc doc, String JavaDoc moduleName )
369             throws BuildException, IOException JavaDoc
370     {
371         processStyles( doc, moduleName, this.singleStyles.elements() );
372     }
373     
374     
375     private void finishSingleStyles( Vector JavaDoc errorList )
376             throws BuildException, IOException JavaDoc
377     {
378         finishStyles( this.singleStyles.elements(), errorList );
379     }
380     
381     
382     private void processComboStyles( Document JavaDoc doc )
383             throws BuildException, IOException JavaDoc
384     {
385         processStyles( doc, "all", this.comboStyles.elements() );
386     }
387     
388     
389     private void finishComboStyles( Vector JavaDoc errorList )
390             throws BuildException, IOException JavaDoc
391     {
392         finishStyles( this.comboStyles.elements(), errorList );
393     }
394     
395     
396     private void processStyles( Document JavaDoc doc, String JavaDoc moduleName,
397             Enumeration JavaDoc styles )
398             throws BuildException, IOException JavaDoc
399     {
400         while (styles.hasMoreElements())
401         {
402             IReportStyle rs = (IReportStyle)styles.nextElement();
403             rs.generateReport( getProject(), doc, moduleName );
404         }
405     }
406     
407     
408     private void finishStyles( Enumeration JavaDoc styles, Vector JavaDoc errors )
409             throws BuildException, IOException JavaDoc
410     {
411         while (styles.hasMoreElements())
412         {
413             IReportStyle rs = (IReportStyle)styles.nextElement();
414             rs.reportComplete( getProject(), errors );
415         }
416     }
417     
418     
419     
420     /**
421      * Even though these are public, they take an interface, and so can't
422      * be called through the Ant script.
423      */

424     public void _addSingle( IReportStyle rs )
425     {
426         if (rs != null)
427         {
428             this.singleStyles.addElement( rs );
429         }
430     }
431     
432     
433     /**
434      * Even though these are public, they take an interface, and so can't
435      * be called through the Ant script.
436      */

437     public void _addCombo( IReportStyle rs )
438     {
439         if (rs != null)
440         {
441             this.comboStyles.addElement( rs );
442         }
443     }
444     
445     
446     private Element JavaDoc createReport( IAnalysisModule am,
447             AnalysisModuleData amd, IReportGenerator rg )
448             throws IOException JavaDoc, BuildException
449     {
450         log( "Creating coverage report for module "+am.getMeasureName(),
451             Project.MSG_INFO );
452         Element JavaDoc ret = null;
453         try
454         {
455             ret = rg.createReport( am, amd );
456         }
457         catch (IllegalArgumentException JavaDoc iae)
458         {
459             // throw new BuildException( iae );
460

461             // this is a hack: really, the underlying code should be made
462
// more robust.
463
iae.printStackTrace();
464             log( iae.getMessage(), Project.MSG_WARN );
465             ret = null;
466         }
467         
468         return ret;
469     }
470     
471     
472     private IChannelLogReader createChannelLogReader( IAnalysisModule am,
473             AnalysisModuleSet ams )
474             throws IOException JavaDoc
475     {
476         short mi = ams.getAnalysisModuleIndex( am );
477         IChannelLogReader clr = new DirectoryChannelLogReader( this.logdir,
478             mi );
479         return clr;
480     }
481     
482     
483     private IMetaDataReader createMetaDataReader()
484             throws BuildException
485     {
486         try
487         {
488             return new DirMetaDataReader( this.datadir );
489         }
490         catch (IOException JavaDoc e)
491         {
492             throw new BuildException( "I/O error creating meta-data reader.",
493                 e, getLocation() );
494         }
495     }
496
497
498     
499     /**
500      * setup the directories in the logdir - ensure we have adequate
501      * setup protections. This saves some head banging in figuring out
502      * why bad exceptions are thrown from the Ant script.
503      */

504     private void setupDirectories()
505             throws IOException JavaDoc, BuildException
506     {
507         // check specifications
508
if (this.baselogdir == null)
509         {
510             throw new BuildException( "Did not specify attribute 'datadir'." );
511         }
512         if (this.datadir == null)
513         {
514             this.datadir = new File JavaDoc( this.baselogdir, "data" );
515         }
516         if (this.logdir == null)
517         {
518             this.logdir = new File JavaDoc( this.baselogdir, "logs" );
519         }
520         
521         
522         if (!this.datadir.exists() ||
523             !this.datadir.isDirectory())
524         {
525             throw new BuildException("Data directory setting ("+
526                 this.datadir+") does not exist or is not a directory.");
527         }
528         if (!this.logdir.exists())
529         {
530             this.logdir.mkdirs();
531         }
532         if (!this.logdir.isDirectory())
533         {
534             throw new BuildException("Log directory setting ("+
535                 this.logdir+") is not a directory.");
536         }
537         String JavaDoc modules[] = this.datadir.list();
538         if (modules == null || modules.length <= 0)
539         {
540             throw new BuildException("There are no module data directories in "+
541                 this.datadir+".");
542         }
543         
544         String JavaDoc indicies[] = this.logdir.list();
545         if (indicies == null)
546         {
547             indicies = new String JavaDoc[0];
548         }
549         int count = modules.length;
550         
551         for (int i = 0; i <= count; ++i)
552         {
553             String JavaDoc dirname = Integer.toString(i);
554             boolean found = false;
555             for (int j = 0; j < indicies.length; ++j)
556             {
557                 if (indicies[j].equals( dirname ))
558                 {
559                     found = true;
560                     break;
561                 }
562             }
563             if (!found)
564             {
565                 File JavaDoc f = new File JavaDoc( this.logdir, dirname );
566                 f.mkdirs();
567             }
568         }
569         
570         if (this.filter != null)
571         {
572             ILogFilter lf = this.filter.getFilter();
573             if (lf != null)
574             {
575                 lf.process( count, this.logdir );
576             }
577         }
578     }
579 }
580
581
Popular Tags