root/trunk/src/java/org/jcoderz/phoenix/report/JcReportAntTask.java

Revision 1466, 47.7 kB (checked in by amandel, 3 years ago)

Testing the historic view, next build.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.phoenix.report;
34
35import java.io.File;
36import java.io.FileOutputStream;
37import java.io.IOException;
38import java.nio.charset.Charset;
39import java.util.ArrayList;
40import java.util.Collections;
41import java.util.HashSet;
42import java.util.Iterator;
43import java.util.List;
44import java.util.Set;
45import java.util.concurrent.ArrayBlockingQueue;
46import java.util.concurrent.Callable;
47import java.util.concurrent.CompletionService;
48import java.util.concurrent.ExecutionException;
49import java.util.concurrent.ExecutorCompletionService;
50import java.util.concurrent.Future;
51import java.util.concurrent.ThreadPoolExecutor;
52import java.util.concurrent.TimeUnit;
53import java.util.logging.Level;
54
55import javax.xml.bind.JAXBException;
56import javax.xml.transform.TransformerException;
57
58import org.apache.tools.ant.BuildException;
59import org.apache.tools.ant.Project;
60import org.apache.tools.ant.Task;
61import org.apache.tools.ant.taskdefs.Execute;
62import org.apache.tools.ant.taskdefs.LogStreamHandler;
63import org.apache.tools.ant.taskdefs.PumpStreamHandler;
64import org.apache.tools.ant.types.CommandlineJava;
65import org.apache.tools.ant.types.Path;
66import org.apache.tools.ant.types.Environment.Variable;
67import org.jcoderz.commons.taskdefs.AntTaskUtil;
68import org.jcoderz.commons.types.Date;
69import org.jcoderz.commons.util.ArraysUtil;
70import org.jcoderz.commons.util.FileUtils;
71import org.jcoderz.commons.util.StringUtil;
72
73/**
74 * This is the Ant task for the Jcoderz Report.
75 * This task forks all processing steps as separate processes
76 * so that memory for each process can be controlled separately.
77 *
78 * TODO: Why are the inner classes static + take a JcReportAntTask?
79 *
80 * @author Michael Rumpf
81 */
82public class JcReportAntTask
83   extends Task
84{
85   private static final int DEFAULT_MAX_HEAP = 256;
86   private static final Date CREATION_TIMESTAMP = Date.now();
87   private static final int DEFAULT_CPUS = 2;
88
89   private NestedReportsElement mReports = null;
90   private NestedMappingsElement mMappings = null;
91   private NestedToolsElement mTools = null;
92   private final NestedFiltersElement mFilterElements
93       = new NestedFiltersElement();
94   private NestedLogfilesElement mLogfilesElements
95       = new NestedLogfilesElement();
96
97   private String mName = null;
98   private File mDest = null;
99   private File mOldReportFile = null;
100   private String mWikiBase = null;
101   private String mWebRcsBase = null;
102   private String mWebRcsSuffix = null;
103   private String mPackageBase = null;
104   private String mProjectBase = null;
105   private String mStylesheet = null;
106   private File mTempfolder = null;
107   private int mMaxHeap = DEFAULT_MAX_HEAP;
108   private int mCpus = DEFAULT_CPUS;
109   private Charset mSourceEncoding = null;
110   private boolean mDebug = false;
111
112   private File mWorkingDir = null;
113
114   /** The global Java Commandline instance */
115   private final CommandlineJava mCommandline = new CommandlineJava();
116   private int mMaxInner;
117
118   /**
119    * @return the number of cpus to put load on.
120    */
121    public int getCpus ()
122    {
123        return mCpus;
124    }
125
126    /**
127     * @param cpus the cpus to set
128     */
129    public void setCpus (int cpus)
130    {
131        mCpus = cpus;
132    }
133
134    /**
135     * @return the sourceEncoding
136     */
137    public String getEncoding ()
138    {
139        return mSourceEncoding.name();
140    }
141
142    /**
143     * @param encoding the sourceEncoding to set
144     */
145    public void setEncoding (String encoding)
146    {
147        mSourceEncoding = Charset.forName(encoding);
148    }
149
150    /**
151    * Returns the working directory.
152    *
153    * @return the working directory.
154    */
155   public File getWorkingDir ()
156   {
157      return mWorkingDir;
158   }
159
160   /**
161    * Sets the maximum heap value.
162    * If not defined in the Ant task the default value of 512MB will be used.
163    *
164    * @param maxheap the max heap value.
165    */
166   public void setMaxHeap (String maxheap)
167   {
168      mMaxHeap = Integer.parseInt(maxheap);
169   }
170
171
172   /**
173    * Sets the name of the report.
174    *
175    * @param name the report name.
176    */
177   public void setName (String name)
178   {
179      mName = name;
180   }
181
182
183   /**
184    * Sets the destination of the report.
185    *
186    * @param dest the report destination.
187    */
188   public void setDest (String dest)
189   {
190      mDest = new File(dest);
191      AntTaskUtil.ensureDirectory(mDest);
192   }
193
194
195   public void setPackageBase (String packageBase)
196   {
197      mPackageBase = packageBase;
198   }
199
200
201   public void setProjectBase (String projectBase)
202   {
203      mProjectBase = projectBase;
204   }
205
206
207   public void setWebRcsBase (String webRcsBase)
208   {
209      mWebRcsBase = webRcsBase;
210   }
211
212
213   public void setWebRcsSuffix (String webRcsSuffix)
214   {
215      mWebRcsSuffix = webRcsSuffix;
216   }
217
218
219   public void setWikiBase (String wikiBase)
220   {
221      mWikiBase = wikiBase;
222   }
223
224   public void setOldReportFile (String oldReportFile)
225   {
226      mOldReportFile = new File(oldReportFile);
227   }
228
229   /**
230    * Sets the stylesheet to be used for the report.
231    *
232    * @param stylesheet the report stylesheet.
233    */
234   public void setStylesheet (String stylesheet)
235   {
236      mStylesheet = stylesheet;
237   }
238
239
240   /**
241    * Sets the temporary folder.
242    *
243    * @param tempfolder the temporary folder.
244    */
245   public void setTempfolder (String tempfolder)
246   {
247      mTempfolder = new File(tempfolder);
248   }
249
250
251   /**
252    * Sets the debug parameter.
253    *
254    * @param debug the debug parameter.
255    */
256   public void setDebug (Boolean debug)
257   {
258      mDebug = debug.booleanValue();
259   }
260
261
262   public Path createClasspath ()
263   {
264      return mCommandline.createClasspath(getProject()).createPath();
265   }
266
267
268   /**
269    * This method is called by Ant for executing this task.
270    *
271    * @throws BuildException whenever a problem occurs.
272    */
273   public void execute ()
274      throws BuildException
275   {
276      try
277      {
278         // Always show this line
279         super.log("Executing JcReportAntTask...");
280
281         checkParameters();
282
283         // Delete the dest folder in case it exists so that we don't mix
284         // already deleted files. And create a fresh folder afterwards again.
285         if (mDest.exists())
286         {
287            FileUtils.rmdir(mDest);
288            AntTaskUtil.ensureDirectory(mDest);
289         }
290
291         // Now start processing the different reports
292         log("Processing reports...");
293
294         final int max
295             = Math.min(mCpus + 1 , mReports.getReports().size());
296         mMaxInner = 1 + (mCpus / max);
297         super.log("Decided to have " + max + " report types with "
298             + mMaxInner + " reports each in parallel.");
299         final CompletionService<File> service
300             = new ExecutorCompletionService<File>(
301                 new ThreadPoolExecutor(max, max, 0, TimeUnit.SECONDS,
302                     new ArrayBlockingQueue<Runnable>(
303                         mReports.getReports().size())));
304
305         final List<Future<File>> jcReports = new ArrayList<Future<File>>();
306         final Iterator<NestedReportElement> iterReport
307             = mReports.getReports().iterator();
308         while (iterReport.hasNext())
309         {
310            final NestedReportElement nre = iterReport.next();
311            log("Processing report '" + nre.getName() + "' ...");
312            final Future<File> jcReport  = service.submit(
313                new Callable<File> ()
314                {
315                    public File call ()
316                        throws InterruptedException, ExecutionException,
317                            IOException, JAXBException, TransformerException
318                    {
319                        final File result;
320                        log("Starting: " + nre.getName()
321                            + " for " + nre.getSourcePath() + ".");
322                        result = performNestedReport(nre);
323                        log("Done: " + nre.getName()
324                            + " got " + nre.getSourcePath() + ".");
325                        return result;
326                    }
327                }
328            );
329            jcReports.add(jcReport);
330         }
331
332         final File jcReport = executeReportMerger(jcReports);
333         executeJava2Html(jcReport);
334      }
335      catch (Exception ex)
336      {
337         log(ex.toString(), ex, Project.MSG_ERR); // CHECKME!
338         throw new BuildException("An unexpected exception occured!", ex);
339      }
340   }
341
342
343    private File performNestedReport (final NestedReportElement nre)
344        throws InterruptedException, ExecutionException, IOException,
345            JAXBException, TransformerException
346    {
347        // Create a temp folder for this report
348        final File reportTmpDir = new File(mWorkingDir, nre.getName());
349        AntTaskUtil.ensureDirectory(reportTmpDir);
350        final File srcDir = new File(nre.getSourcePath());
351        final File clsDir = new File(nre.getClassPath());
352
353        final CompletionService<File> service
354            = new ExecutorCompletionService<File>(
355                new ThreadPoolExecutor(mMaxInner, mMaxInner, 0,
356                    TimeUnit.SECONDS,
357                    new ArrayBlockingQueue<Runnable>(5))); // 2 max threads?
358
359
360        File pmdXml = null;
361        final Future<File> pmdResult
362            = submit(mTools.getPmd(), reportTmpDir,
363                srcDir, clsDir, service);
364
365        File checkstyleXml = null;
366        final Future<File> checkstyleResult
367            = submit(mTools.getCheckstyle(), reportTmpDir,
368                srcDir, clsDir, service);
369
370        File findbugsXml = null;
371        final Future<File> findbugsResult
372            = submit(mTools.getFindbugs(), reportTmpDir,
373                srcDir, clsDir, service);
374
375        File cpdXml = null;
376        final Future<File> cpdResult
377            = submit(mTools.getCpd(), reportTmpDir,
378                srcDir, clsDir, service);
379
380        File coberturaXml = null;
381        final Future<File> coberturaResult
382            = submit(mTools.getCobertura(), reportTmpDir,
383                srcDir, clsDir, service);
384
385        // now get the results....
386        if (checkstyleResult != null)
387        {   // EXCEPTION?
388            checkstyleXml = checkstyleResult.get();
389        }
390        if (findbugsResult != null)
391        {   // EXCEPTION?
392            findbugsXml = findbugsResult.get();
393        }
394        if (pmdResult != null)
395        {   // EXCEPTION?
396            pmdXml = pmdResult.get();
397        }
398        if (cpdResult != null)
399        {   // EXCEPTION?
400            cpdXml = cpdResult.get();
401        }
402        if (coberturaResult != null)
403        {   // EXCEPTION?
404            coberturaXml = coberturaResult.get();
405        }
406
407        final File emmaFile;
408        if (mTools.getEmma() != null)
409        {   // EXCEPTION?
410            emmaFile = new File(mTools.getEmma().mDatafile);
411        }
412        else
413        {
414            emmaFile = null;
415        }
416
417        // Merge the different reports into one jcoderz-report.xml
418        // This must be done on a level by level basis
419        return executeReportNormalizer(srcDir, reportTmpDir,
420              nre.getLevel(), checkstyleXml, findbugsXml, pmdXml,
421              cpdXml, coberturaXml, emmaFile);
422    }
423
424
425    private Future<File> submit (final NestedToolElement nce,
426        final File reportTmpDir, final File srcDir, final File clsDir,
427        CompletionService<File> service)
428    {
429        Future<File> result = null;
430        if (nce != null)
431        {
432           result = service.submit(
433               new Callable<File> ()
434               {
435                   public File call ()
436                   {
437                       final File result;
438                       log("Starting: " + nce.toString() + " for " + srcDir
439                           + ".");
440                       result = nce.execute(reportTmpDir, srcDir, clsDir);
441                       log("Done: " + nce.toString() + " got " + result + ".");
442                       return result;
443                   }
444               }
445           );
446        }
447        return result;
448    }
449
450
451   private void checkParameters ()
452   {
453       if (mTempfolder == null)
454       {
455           throw new BuildException("You must specify a temporary folder!",
456               getLocation());
457       }
458       AntTaskUtil.ensureDirectory(mTempfolder);
459       mWorkingDir = new File(mTempfolder, mName);
460       AntTaskUtil.ensureDirectory(mWorkingDir);
461
462       // Check that the names of the reports differ!
463       final Set<String> reportNames = new HashSet<String>();
464       final Iterator<NestedReportElement> iterReport
465           = mReports.getReports().iterator();
466       while (iterReport.hasNext())
467       {
468           final NestedReportElement nre = iterReport.next();
469           reportNames.add(nre.getName());
470       }
471       if (reportNames.size() != mReports.getReports().size())
472       {
473           throw new BuildException("Reports must not have the same names!",
474               getLocation());
475       }
476   }
477
478
479   /**
480    * Executes the report normalizer in a separate process.
481    *
482    * The following command line parameters are supported:
483    * <ul>
484    *   <li><code>-cobertura coberturareport.xml</code>
485    *   (http://cobertura.sf.net)</li>
486    *   <li><code>-checkstyle checkstylereport.xml</code>
487    *   (http://checkstyle.sf.net)</li>
488    *   <li><code>-findbugs findbugsreport.xml</code>
489    *   (http://findbugs.sf.net)</li>
490    *   <li><code>-pmd pmdreport.xml</code>
491    *   (http://pmd.sf.net)</li>
492    *   <li><code>-cpd cpdreport.xml</code>
493    *   (http://pmd.sf.net)</li>
494    *   <li><code>-projectHome</code></li>
495    *   <li><code>-srcDir</code></li>
496    *   <li><code>-projectName</code></li>
497    *   <li><code>-level PROD|TEST|MISC</code> The weight level</li>
498    *   <li><code>-out</code></li>
499    * </ul>
500    */
501   private File executeReportNormalizer (File srcDir, File reportDir,
502            ReportLevel level, File checkstyleXml,
503            File findbugsXml, File pmdXml, File cpdXml, File coberturaXml,
504            File emmaSummary)
505       throws IOException, JAXBException, TransformerException
506   {
507      // INLINE failed, got java.lang.OutOfMemoryError: PermGen space
508      log("Creating report normalizer command line...");
509      final CommandlineJava cmd = createCommandlineJava(mCommandline, mMaxHeap);
510
511      cmd.setClassname("org.jcoderz.phoenix.report.ReportNormalizer");
512
513      cmd.createArgument().setValue("-srcDir");
514      cmd.createArgument().setFile(srcDir);
515
516      cmd.createArgument().setValue("-level");
517      cmd.createArgument().setValue(level.toString());
518
519      if (mDebug)
520      {
521         cmd.createArgument().setValue("-loglevel");
522         cmd.createArgument().setValue("FINEST");
523      }
524
525      cmd.createArgument().setValue("-projectName");
526      cmd.createArgument().setValue(mName);
527
528      cmd.createArgument().setValue("-out");
529      cmd.createArgument().setFile(reportDir);
530
531      if (checkstyleXml != null)
532      {
533         cmd.createArgument().setValue("-checkstyle");
534         cmd.createArgument().setFile(checkstyleXml);
535      }
536
537      if (findbugsXml != null)
538      {
539         cmd.createArgument().setValue("-findbugs");
540         cmd.createArgument().setFile(findbugsXml);
541      }
542
543      if (pmdXml != null)
544      {
545         cmd.createArgument().setValue("-pmd");
546         cmd.createArgument().setFile(pmdXml);
547      }
548
549      if (cpdXml != null)
550      {
551         cmd.createArgument().setValue("-cpd");
552         cmd.createArgument().setFile(cpdXml);
553      }
554
555      if (coberturaXml != null)
556      {
557         cmd.createArgument().setValue("-cobertura");
558         cmd.createArgument().setFile(coberturaXml);
559      }
560
561      if (emmaSummary != null)
562      {
563         cmd.createArgument().setValue("-emma");
564         cmd.createArgument().setFile(emmaSummary);
565      }
566
567      for (NestedLogfileElement nge : mLogfilesElements.mGenericReaders)
568      {
569          cmd.createArgument().setValue("-generic");
570          cmd.createArgument().setFile(nge.getFile());
571          cmd.createArgument().setValue(nge.getType());
572      }
573
574      forkToolProcess(this, cmd, new LogStreamHandler(this, Project.MSG_INFO,
575         Project.MSG_WARN));
576
577      return new File(reportDir, ReportNormalizer.JCODERZ_REPORT_XML);
578   }
579
580
581   private File executeReportMerger (List<Future<File>> jcReports)
582       throws InterruptedException, ExecutionException, IOException,
583           JAXBException, TransformerException
584   {
585      log("Preparing report merger...");
586      final ReportMerger merger = new ReportMerger();
587      if (mDebug)
588      {
589          merger.setLogLevel(Level.ALL);
590      }
591      merger.setOutFile(mWorkingDir);
592      final Iterator<Future<File>> jcReportIter = jcReports.iterator();
593      while (jcReportIter.hasNext())
594      {
595         final File jcReport = jcReportIter.next().get();
596         merger.addReport(jcReport);
597      }
598      final Iterator<NestedFilterElement> filterIter
599          = mFilterElements.getFilters().iterator();
600      while (filterIter.hasNext())
601      {
602         final NestedFilterElement filterElement = filterIter.next();
603         merger.addFilter(filterElement.getFile());
604      }
605      merger.merge();
606      merger.filter();
607      if (mOldReportFile != null)
608      {
609          merger.setOldFile(mOldReportFile);
610          merger.flagNewFindings();
611      }
612
613      final File outFile = new File(mWorkingDir,
614         ReportNormalizer.JCODERZ_REPORT_XML);
615      try
616      {
617         FileUtils.copy(outFile, mDest);
618      }
619      catch (IOException e)
620      {
621         throw new BuildException("Could not copy '" + outFile
622               + "' to destination folder '" + mDest + "'!", e, getLocation());
623      }
624
625      return outFile;
626   }
627
628
629   /**
630    * Executes the Java2Html tool in a separate process.
631    *
632    * The following command line parameters are supported:
633    * <pre>
634    * -outDir
635    * -report
636    * -projectHome
637    * -projectName
638    * -cvsBase
639    * -timestamp
640    * -wikiBase
641    * -reportStyle
642    * -packageBase
643    * </pre>
644    */
645   private void executeJava2Html (File jcReport)
646   {
647      log("Creating java2html command line...");
648
649      final CommandlineJava cmd = createCommandlineJava(mCommandline, mMaxHeap);
650
651      cmd.setClassname("org.jcoderz.phoenix.report.Java2Html");
652
653      // let it run in headless mode to avoid exceptions because of a missing X
654      cmd.createVmArgument().setValue("-Djava.awt.headless=true");
655
656      cmd.createArgument().setValue("-outDir");
657      cmd.createArgument().setFile(mDest);
658
659      cmd.createArgument().setValue("-report");
660      cmd.createArgument().setFile(jcReport);
661
662      cmd.createArgument().setValue("-timestamp");
663      cmd.createArgument().setValue(CREATION_TIMESTAMP.toString(
664            "yyyyMMddHHmmss"));
665
666      if (mProjectBase != null)
667      {
668         cmd.createArgument().setValue("-projectHome");
669         cmd.createArgument().setValue(mProjectBase);
670      }
671
672      if (mStylesheet != null)
673      {
674         cmd.createArgument().setValue("-reportStyle");
675         cmd.createArgument().setValue(mStylesheet);
676      }
677
678      cmd.createArgument().setValue("-projectName");
679      cmd.createArgument().setValue(mName);
680
681      cmd.createArgument().setValue("-cvsBase");
682      cmd.createArgument().setValue(mWebRcsBase);
683
684      if (!StringUtil.isNullOrBlank(mWebRcsSuffix))
685      {
686          cmd.createArgument().setValue("-cvsSuffix");
687          cmd.createArgument().setValue(mWebRcsSuffix);
688      }
689
690      cmd.createArgument().setValue("-wikiBase");
691      cmd.createArgument().setValue(mWikiBase);
692
693      if (mPackageBase != null)
694      {
695         cmd.createArgument().setValue("-packageBase");
696         cmd.createArgument().setValue(mPackageBase);
697      }
698
699      if (mSourceEncoding != null)
700      {
701          cmd.createArgument().setValue("-sourceEncoding");
702          cmd.createArgument().setValue(getEncoding());
703      }
704      if (mDebug)
705      {
706         cmd.createArgument().setValue("-loglevel");
707         cmd.createArgument().setValue("FINEST");
708      }
709
710      forkToolProcess(this, cmd, new LogStreamHandler(this, Project.MSG_INFO,
711         Project.MSG_WARN));
712   }
713
714
715   //
716   // Reports section
717   //
718
719
720   /**
721    * This method is called by Ant to create an instance of the
722    * NestedReportsElement class when the 'reports' tag is read.
723    *
724    * @return the new instance of type NestedReportsElement.
725    */
726   public NestedReportsElement createReports ()
727   {
728      mReports = new NestedReportsElement(this);
729      return mReports;
730   }
731
732
733   public static class NestedReportsElement
734   {
735      private List<NestedReportElement> mReports
736          = new ArrayList<NestedReportElement>();
737      private JcReportAntTask mTask;
738
739      public NestedReportsElement (JcReportAntTask task)
740      {
741         mTask = task;
742      }
743
744
745      public NestedReportElement createReport ()
746      {
747         mTask.log("Creating report element...");
748         final NestedReportElement nre = new NestedReportElement();
749         mReports.add(nre);
750         return nre;
751      }
752
753
754      public List<NestedReportElement> getReports ()
755      {
756         return Collections.unmodifiableList(mReports);
757      }
758   }
759
760
761   /**
762    * This class represents a &lt;report&gt; tag in an Ant
763    * <code>build.xml</code> file.
764    *
765    * @author Michael Rumpf
766    */
767   public static class NestedReportElement
768   {
769      private String mName;
770      private ReportLevel mLevel;
771      private String mSourcePath;
772      private String mClassPath;
773
774      public String getName ()
775      {
776         return mName;
777      }
778
779
780      public void setName (String name)
781      {
782         mName = name;
783      }
784
785      public ReportLevel getLevel ()
786      {
787         return mLevel;
788      }
789
790
791      public void setLevel (String level)
792      {
793         mLevel = ReportLevel.fromString(level);
794      }
795
796
797      public String getClassPath ()
798      {
799         return mClassPath;
800      }
801
802
803      public void setClassPath (String classPath)
804      {
805         mClassPath = classPath;
806      }
807
808
809      public String getSourcePath ()
810      {
811         return mSourcePath;
812      }
813
814
815      public void setSourcePath (String sourcePath)
816      {
817         mSourcePath = sourcePath;
818      }
819   }
820
821
822   //
823   // Mappings section
824   //
825
826
827   /**
828    * This method is called by Ant to create an instance of the
829    * NestedMappingsElement class when the 'mappings' tag is read.
830    *
831    * @return the new instance of type NestedMappingsElement.
832    */
833   public NestedMappingsElement createMappings ()
834   {
835      mMappings = new NestedMappingsElement(this);
836      return mMappings;
837   }
838
839
840   public static class NestedMappingsElement
841   {
842      private List<NestedMappingElement> mMappings
843          = new ArrayList<NestedMappingElement>();
844      private JcReportAntTask mTask;
845
846      public NestedMappingsElement (JcReportAntTask task)
847      {
848         mTask = task;
849      }
850
851      public NestedMappingElement createWebRcs ()
852      {
853         mTask.log("Creating mapping element...");
854         final NestedMappingElement nme = new NestedMappingElement();
855         mMappings.add(nme);
856         return nme;
857      }
858
859      public List<NestedMappingElement> getMappings ()
860      {
861         return mMappings;
862      }
863   }
864
865
866   public static class NestedMappingElement
867   {
868      private String mPattern;
869      private String mUrl;
870      private String mSuffix;
871
872
873      public String getPattern ()
874      {
875         return mPattern;
876      }
877
878
879      public void setPattern (String pattern)
880      {
881         mPattern = pattern;
882      }
883
884
885      public String getSuffix ()
886      {
887         return mSuffix;
888      }
889
890
891      public void setSuffix (String suffix)
892      {
893         mSuffix = suffix;
894      }
895
896
897      public String getUrl ()
898      {
899         return mUrl;
900      }
901
902
903      public void setUrl (String url)
904      {
905         mUrl = url;
906      }
907   }
908
909
910   //
911   // Tools section
912   //
913
914
915   /**
916    * This method is called by Ant to create an instance of the
917    * NestedToolsElement class when the 'tools' tag is read.
918    *
919    * @return the new instance of type NestedToolsElement.
920    */
921   public NestedToolsElement createTools ()
922   {
923      mTools = new NestedToolsElement(this);
924      return mTools;
925   }
926
927
928   public static class NestedToolsElement
929   {
930      private JcReportAntTask mTask;
931      private NestedPmdElement mPmd = null;
932      private NestedCpdElement mCpd = null;
933      private NestedFindbugsElement mFindbugs = null;
934      private NestedCheckstyleElement mCheckstyle = null;
935      private NestedCoberturaElement mCobertura = null;
936      private NestedEmmaElement mEmma = null;
937
938      public NestedToolsElement (JcReportAntTask task)
939      {
940         mTask = task;
941      }
942
943
944      public NestedPmdElement createPmd ()
945      {
946         mTask.log("Creating Pmd element...");
947         mPmd = new NestedPmdElement(mTask);
948         return mPmd;
949      }
950
951
952      public NestedPmdElement getPmd ()
953      {
954         return mPmd;
955      }
956
957
958      public NestedCpdElement createCpd ()
959      {
960         mTask.log("Creating Cpd element...");
961         mCpd = new NestedCpdElement(mTask);
962         return mCpd;
963      }
964
965
966      public NestedCpdElement getCpd ()
967      {
968         return mCpd;
969      }
970
971
972      public NestedFindbugsElement createFindbugs ()
973      {
974         mTask.log("Creating Findbugs element...");
975         mFindbugs = new NestedFindbugsElement(mTask);
976         return mFindbugs;
977      }
978
979
980      public NestedFindbugsElement getFindbugs ()
981      {
982         return mFindbugs;
983      }
984
985
986      public NestedCheckstyleElement createCheckstyle ()
987      {
988         mTask.log("Creating Checkstyle element...");
989         mCheckstyle = new NestedCheckstyleElement(mTask);
990         return mCheckstyle;
991      }
992
993
994      public NestedCheckstyleElement getCheckstyle ()
995      {
996         return mCheckstyle;
997      }
998
999
1000      public NestedCoberturaElement createCobertura ()
1001      {
1002         mTask.log("Creating Cobertura element...");
1003         mCobertura = new NestedCoberturaElement(mTask);
1004         return mCobertura;
1005      }
1006
1007
1008      public NestedCoberturaElement getCobertura ()
1009      {
1010         return mCobertura;
1011      }
1012
1013      public NestedEmmaElement createEmma ()
1014      {
1015         mTask.log("Creating Emma element...");
1016         mEmma = new NestedEmmaElement(mTask);
1017         return mEmma;
1018      }
1019
1020      public NestedEmmaElement getEmma ()
1021      {
1022         return mEmma;
1023      }
1024   }
1025
1026
1027   /**
1028    * This is the base class for all tool elements.
1029    * It provides support for the maxheap attribute
1030    * and the nested classpath element.
1031    *
1032    * @author Michael Rumpf
1033    */
1034   public abstract static class NestedToolElement
1035   {
1036      protected JcReportAntTask mTask;
1037      protected Path mPath;
1038      protected int mMaxHeap;
1039
1040      /** The global Java Commandline instance */
1041      protected final CommandlineJava mCommandline = new CommandlineJava();
1042
1043      public NestedToolElement (JcReportAntTask task)
1044      {
1045          mTask = task;
1046          mMaxHeap = mTask.mMaxHeap;
1047      }
1048
1049      /**
1050       * Sets the maximum heap value.
1051       * If not defined in the Ant task the default value of 512MB will be used.
1052       *
1053       * @param maxheap the max heap value.
1054       */
1055      public void setMaxheap (String maxheap)
1056      {
1057         mMaxHeap = Integer.parseInt(maxheap);
1058      }
1059
1060
1061      /**
1062       * Creates a classpath for the tool element.
1063       *
1064       * @return the created classpath.
1065       */
1066      public Path createClasspath ()
1067      {
1068         mPath = mCommandline.createClasspath(mTask.getProject()).createPath();
1069         return mPath;
1070      }
1071
1072      public abstract File execute (File reportDir, File srcDir, File clsDir);
1073   }
1074
1075
1076   public static class NestedPmdElement
1077         extends NestedToolElement
1078   {
1079      private String mConfig;
1080      private String mTargetjdk;
1081      private String mEncoding;
1082
1083      public NestedPmdElement (JcReportAntTask task)
1084      {
1085         super(task);
1086         mCommandline.setClassname("net.sourceforge.pmd.PMD");
1087      }
1088
1089
1090      public void setConfig (String config)
1091      {
1092         mConfig = config;
1093      }
1094
1095
1096      public void setTargetjdk (String targetjdk)
1097      {
1098         mTargetjdk = targetjdk;
1099      }
1100
1101
1102      public void setEncoding (String encoding)
1103      {
1104         mEncoding = encoding;
1105      }
1106
1107
1108      public File execute (File reportDir, File srcDir, File clsDir)
1109      {
1110         mTask.log("Creating pmd command line...");
1111         final CommandlineJava cmd
1112             = createCommandlineJava(mCommandline, mMaxHeap);
1113
1114         cmd.createArgument().setFile(srcDir);
1115
1116         // We always write pmd reports in XML format
1117         cmd.createArgument().setValue("xml");
1118
1119         if (mConfig != null)
1120         {
1121            cmd.createArgument().setFile(new File(mConfig));
1122         }
1123
1124         if (mEncoding != null)
1125         {
1126            cmd.createArgument().setValue("-encoding");
1127            cmd.createArgument().setValue(mEncoding);
1128         }
1129         else if (mTask.getEncoding() != null)
1130         {
1131             cmd.createArgument().setValue("-encoding");
1132             cmd.createArgument().setValue(mTask.getEncoding());
1133         }
1134
1135         if (mTargetjdk != null)
1136         {
1137            cmd.createArgument().setValue("-targetjdk");
1138            cmd.createArgument().setValue(mTargetjdk);
1139         }
1140
1141         final File outFile = new File(reportDir, "pmd.xml");
1142         FileOutputStream fos = null;
1143         try
1144         {
1145            fos = new FileOutputStream(outFile);
1146         }
1147         catch (IOException e)
1148         {
1149            throw new BuildException("Could not find output file: "
1150                  + outFile.getAbsolutePath(), e, mTask.getLocation());
1151         }
1152
1153         forkToolProcess(mTask, cmd, new PumpStreamHandler(fos, System.err));
1154
1155         return outFile;
1156      }
1157   }
1158
1159
1160   public static class NestedCpdElement
1161         extends NestedToolElement
1162   {
1163      private static final int DEFAULT_MINIMUM_TOKENS = 100;
1164      private int mMinimumtokens = DEFAULT_MINIMUM_TOKENS;
1165      private String mEncoding = null;
1166      private String mOutputEncoding = "UTF-8";
1167
1168      public NestedCpdElement (JcReportAntTask task)
1169      {
1170          super(task);
1171         mCommandline.setClassname("net.sourceforge.pmd.cpd.CPD");
1172      }
1173
1174      public void setMinimumtokens (String minimumtokens)
1175      {
1176         mMinimumtokens = Integer.parseInt(minimumtokens);
1177      }
1178
1179      public void setEncoding (String encoding)
1180      {
1181         mEncoding = encoding;
1182      }
1183
1184      public void setOutputEncoding (String encoding)
1185      {
1186         mOutputEncoding = encoding;
1187      }
1188
1189      /**
1190       * Executes the cpd tool in a separate process.
1191       *
1192       * The following command line switches are supported by this method:
1193       * <pre>
1194       * CPD --minimum-tokens xxx --files xxx
1195       * </pre>
1196       */
1197      public File execute (File reportDir, File srcDir, File clsDir)
1198      {
1199         mTask.log("Creating cpd command line...");
1200         final CommandlineJava cmd
1201             = createCommandlineJava(mCommandline, mMaxHeap);
1202
1203         final Variable var = new Variable();
1204         var.setKey("file.encoding");
1205         var.setValue(mOutputEncoding);
1206         cmd.getSystemProperties().addVariable(var);
1207
1208         cmd.createArgument().setFile(srcDir);
1209
1210         // We always write pmd reports in XML format
1211         cmd.createArgument().setValue("--format");
1212         cmd.createArgument().setValue("net.sourceforge.pmd.cpd.XMLRenderer");
1213
1214         if (mEncoding != null)
1215         {
1216             cmd.createArgument().setValue("--encoding");
1217             cmd.createArgument().setValue(mEncoding);
1218         }
1219         else if (mTask.getEncoding() != null)
1220         {
1221             cmd.createArgument().setValue("--encoding");
1222             cmd.createArgument().setValue(mTask.getEncoding());
1223         }
1224
1225
1226         cmd.createArgument().setValue("--language");
1227         cmd.createArgument().setValue("java");
1228
1229         cmd.createArgument().setValue("--files");
1230         cmd.createArgument().setFile(srcDir);
1231
1232         cmd.createArgument().setValue("--minimum-tokens");
1233         cmd.createArgument().setValue(String.valueOf(mMinimumtokens));
1234
1235         final File outFile = new File(reportDir, "cpd.xml");
1236         FileOutputStream fos = null;
1237         try
1238         {
1239            fos = new FileOutputStream(outFile);
1240         }
1241         catch (IOException e)
1242         {
1243            throw new BuildException("Could not find output file: "
1244                  + outFile.getAbsolutePath(), e, mTask.getLocation());
1245         }
1246
1247         forkToolProcess(mTask, cmd, new PumpStreamHandler(fos, System.err));
1248
1249         return outFile;
1250      }
1251   }
1252
1253
1254   public static class NestedFindbugsElement
1255         extends NestedToolElement
1256   {
1257      private String mConfig;
1258      private String mWarninglevel = "medium";
1259      private String mEffort = "default";
1260      private String mOmitVisitors = "";
1261      private Path mAuxPath;
1262      private boolean mFindBugsDebug = false;
1263      /**
1264       * Path of the findbugs plugin jar files. Must at least contain
1265       * the coreplugin.jar
1266       */
1267      private Path mPluginList;
1268
1269      public NestedFindbugsElement (JcReportAntTask task)
1270      {
1271         super(task);
1272         mCommandline.setClassname("edu.umd.cs.findbugs.FindBugs2");
1273      }
1274
1275
1276      /**
1277       * Sets the debug parameter.
1278       * @param debug the debug parameter.
1279       */
1280      public void setDebug (Boolean debug)
1281      {
1282          mFindBugsDebug = debug.booleanValue();
1283      }
1284
1285      public void setOmitVisitors (String omitVisitors)
1286      {
1287         mOmitVisitors = omitVisitors;
1288      }
1289
1290      public void setConfig (String config)
1291      {
1292         mConfig = config;
1293      }
1294
1295      public void setEffort (String effort)
1296      {
1297         if ("min".equals(effort) || "default".equals(effort)
1298               || "max".equals(effort))
1299         {
1300            mEffort = effort;
1301         }
1302         else
1303         {
1304            mTask.log("Invalid effort value '" + effort + "!'");
1305         }
1306      }
1307
1308
1309      public void setWarninglevel (String warninglevel)
1310      {
1311         if ("experimental".equals(warninglevel) || "low".equals(warninglevel)
1312               || "medium".equals(warninglevel) || "high".equals(warninglevel))
1313         {
1314            mWarninglevel = warninglevel;
1315         }
1316         else
1317         {
1318            mTask.log("Invalid warninglevel value '" + warninglevel + "!'");
1319         }
1320      }
1321
1322
1323      /**
1324       * The findbugs tool needs an list of jar files where all the plugins are
1325       * defined in. Minimum plugin list contains the coreplugin.
1326       *
1327       * @return the created plugin list path.
1328       */
1329      public Path createPluginlist ()
1330      {
1331         mPluginList = new Path(mTask.getProject());
1332         return mPluginList;
1333      }
1334
1335      /**
1336       * The findbugs tool needs an auxiliary classpath with all the classes,
1337       * referenced from the project class files.
1338       *
1339       * @return the created auxiliary classpath.
1340       */
1341      public Path createAuxclasspath ()
1342      {
1343         mAuxPath = new Path(mTask.getProject());
1344         return mAuxPath;
1345      }
1346
1347
1348      /**
1349       * Executes the findbugs tool in a separate process.
1350       * <pre>
1351       * maxheap:
1352       *   -maxHeap size    Maximum Java heap size in megabytes (default=256)
1353       *
1354       * effort:
1355       *   -effort[:min|default|max] set analysis effort level
1356       *
1357       *  warninglevel:
1358       *     -experimental   report all warnings including experimental bug
1359       *                     patterns
1360       *     -low            report all warnings
1361       *     -medium         report only medium and high priority warnings
1362       *                     [default]
1363       *     -high           report only high priority warnings
1364       *
1365       * config:
1366       *   -exclude &lt;filter file>     include only bugs matching given filter
1367       *
1368       * internally:
1369       *   -outputFile &lt;filename>       Save output in named file
1370       *   -xml[:withMessages]          XML output (optionally with messages)
1371       *
1372       * auxclasspath:
1373       *   -auxclasspath &lt;classpath>    set aux classpath for analysis
1374       *
1375       * report: sourcepath
1376       *   -sourcepath &lt;source path>    set source path for analyzed classes
1377       * </pre>
1378       * The target assumes that all libs needed by findbugs are on the
1379       * classpath and the plugins are set via pluginlist element.
1380       *
1381       */
1382      public File execute (File reportDir, File srcDir, File clsDir)
1383      {
1384         mTask.log("Creating findbugs command line...");
1385         final CommandlineJava cmd
1386             = createCommandlineJava(mCommandline, mMaxHeap);
1387
1388          if (mFindBugsDebug)
1389          {
1390              cmd.createVmArgument().setValue("-Dfindbugs.debug=true");
1391          }
1392
1393         if (mPluginList != null)
1394         {
1395             cmd.createArgument().setValue("-pluginList");
1396             cmd.createArgument().setPath(mPluginList);
1397         }
1398
1399         if (!StringUtil.isEmptyOrNull(mOmitVisitors))
1400         {
1401             cmd.createArgument().setValue("-omitVisitors");
1402             cmd.createArgument().setValue(mOmitVisitors);
1403         }
1404
1405
1406         final File outFile = new File(reportDir, "findbugs.xml");
1407         cmd.createArgument().setValue("-output");
1408         cmd.createArgument().setFile(outFile);
1409
1410         cmd.createArgument().setValue("-sourcepath");
1411         cmd.createArgument().setFile(srcDir);
1412
1413         // We always write findbugs reports in XML format
1414         cmd.createArgument().setValue("-xml:withMessages");
1415
1416         if (mConfig != null)
1417         {
1418            cmd.createArgument().setValue("-exclude");
1419            cmd.createArgument().setFile(new File(mConfig));
1420         }
1421
1422         if (mAuxPath != null)
1423         {
1424            cmd.createArgument().setValue("-auxclasspath");
1425            cmd.createArgument().setPath(mAuxPath);
1426         }
1427
1428         cmd.createArgument().setValue("-" + mWarninglevel);
1429
1430         cmd.createArgument().setValue("-effort:" + mEffort);
1431
1432         cmd.createArgument().setFile(clsDir);
1433
1434         // TODO: use PumpStreamHandler to suppress info messages from FindBugs
1435         forkToolProcess(mTask, cmd, new LogStreamHandler(mTask,
1436            Project.MSG_INFO, Project.MSG_WARN));
1437
1438         return outFile;
1439      }
1440
1441   }
1442
1443
1444   public static class NestedCheckstyleElement
1445         extends NestedToolElement
1446   {
1447      private String mConfig;
1448      private String mProperties;
1449
1450      public NestedCheckstyleElement (JcReportAntTask task)
1451      {
1452         super(task);
1453         mCommandline.setClassname("com.puppycrawl.tools.checkstyle.Main");
1454      }
1455
1456
1457      public void setConfig (String config)
1458      {
1459         mConfig = config;
1460      }
1461
1462
1463      public void setProperties (String properties)
1464      {
1465         mProperties = properties;
1466      }
1467
1468      public String toString ()
1469      {
1470          return "Checkstyle";
1471      }
1472
1473      public File execute (File reportDir, File srcDir, File clsPath)
1474      {
1475         mTask.log("Creating checkstyle command line...");
1476         final CommandlineJava cmd
1477             = createCommandlineJava(mCommandline, mMaxHeap);
1478
1479         cmd.createArgument().setValue("-o");
1480         final File outFile = new File(reportDir, "checkstyle.xml");
1481         cmd.createArgument().setFile(outFile);
1482
1483         if (mConfig == null)
1484         {
1485            throw new BuildException("The 'config' attribute is mandatory"
1486                  + " for the checkstyle task!", mTask.getLocation());
1487         }
1488         cmd.createArgument().setValue("-c");
1489         cmd.createArgument().setFile(new File(mConfig));
1490
1491         // We always write checkstyle reports in XML format
1492         cmd.createArgument().setValue("-f");
1493         cmd.createArgument().setValue("xml");
1494
1495         if (mProperties != null)
1496         {
1497            cmd.createArgument().setValue("-p");
1498            cmd.createArgument().setFile(new File(mProperties));
1499         }
1500
1501         cmd.createArgument().setValue("-r");
1502         cmd.createArgument().setFile(srcDir);
1503
1504         if (mTask.getEncoding() != null)
1505         {
1506             final Variable var = new Variable();
1507             var.setKey("file.encoding");
1508             var.setValue(mTask.getEncoding());
1509             cmd.getSystemProperties().addVariable(var);
1510         }
1511
1512         forkToolProcess(mTask, cmd, new LogStreamHandler(mTask,
1513            Project.MSG_INFO, Project.MSG_WARN));
1514
1515         return outFile;
1516      }
1517   }
1518
1519
1520   public static class NestedCoberturaElement
1521         extends NestedToolElement
1522   {
1523      private String mDatafile;
1524
1525      public NestedCoberturaElement (JcReportAntTask task)
1526      {
1527         super(task);
1528         mCommandline.setClassname("net.sourceforge.cobertura.reporting.Main");
1529      }
1530
1531
1532      public void setDatafile (String datafile)
1533      {
1534         mDatafile = datafile;
1535      }
1536
1537
1538      /**
1539       * Executes the cobertura tool in a separate process.
1540       *
1541       * <pre>
1542       * [--datafile file]
1543       * [--destination dir]
1544       * source code directory [...]
1545       * </pre>
1546       */
1547      public File execute (File reportDir, File srcDir, File clsPath)
1548      {
1549         mTask.log("Creating cobertura command line...");
1550         final CommandlineJava cmd
1551             = createCommandlineJava(mCommandline, mMaxHeap);
1552
1553         File dataFile = null;
1554         if (mDatafile == null)
1555         {
1556            throw new BuildException("The datafile attribute is mandatory!",
1557               mTask.getLocation());
1558         }
1559         dataFile = new File(mDatafile);
1560         if (!dataFile.exists())
1561         {
1562             throw new BuildException(
1563                 "The datafile '" + mDatafile + "' was not found!",
1564                 mTask.getLocation());
1565         }
1566
1567         cmd.createArgument().setValue("--destination");
1568         final File outFile = new File(reportDir, "coverage.xml");
1569         cmd.createArgument().setFile(reportDir);
1570
1571         // We always write checkstyle reports in XML format
1572         cmd.createArgument().setValue("--format");
1573         cmd.createArgument().setValue("xml");
1574
1575         cmd.createArgument().setValue("--datafile");
1576         cmd.createArgument().setFile(dataFile);
1577
1578         cmd.createArgument().setFile(srcDir);
1579
1580         forkToolProcess(mTask, cmd, new LogStreamHandler(mTask,
1581            Project.MSG_INFO, Project.MSG_WARN));
1582
1583         return outFile;
1584      }
1585   }
1586
1587   public static class NestedEmmaElement
1588        extends NestedToolElement
1589    {
1590        private String mDatafile;
1591
1592        public NestedEmmaElement (JcReportAntTask task)
1593        {
1594            super(task);
1595        }
1596
1597        public void setDatafile (String datafile)
1598        {
1599            mDatafile = datafile;
1600        }
1601
1602        /**
1603         * Nothing to be done for emma.
1604         */
1605        public File execute (File reportDir, File srcDir, File clsPath)
1606        {
1607            return new File(mDatafile);
1608        }
1609    }
1610
1611   //
1612   // Generic input
1613   //
1614   /**
1615    * This method is called by Ant to create an instance of the
1616    * NestedLogfilesElement class when the 'logfiles' tag is read.
1617    *
1618    * @return the new instance of type NestedFiltersElement.
1619    */
1620   public NestedLogfilesElement createLogfiles ()
1621   {
1622      return mLogfilesElements;
1623   }
1624
1625
1626   public static class NestedLogfilesElement
1627   {
1628      private List<NestedLogfileElement> mGenericReaders
1629          = new ArrayList<NestedLogfileElement>();
1630
1631
1632      public void addLogfile (NestedLogfileElement nge)
1633      {
1634          mGenericReaders.add(nge);
1635      }
1636
1637
1638      public List<NestedLogfileElement> getLogfile ()
1639      {
1640         return mGenericReaders;
1641      }
1642   }
1643
1644   public static class NestedLogfileElement
1645   {
1646       private String mType;
1647       private File mFile;
1648       
1649       public File getFile ()
1650       {
1651            return mFile;
1652       }
1653   
1654        public String getType ()
1655        {
1656            return mType;
1657        }
1658
1659       public void setFile (File file)
1660       {
1661           mFile = file;
1662       }
1663   
1664       public void setType (String type)
1665       {
1666           mType = type;
1667       }
1668    }
1669   //
1670   // Filters section
1671   //
1672
1673
1674   /**
1675    * This method is called by Ant to create an instance of the
1676    * NestedFiltersElement class when the 'filters' tag is read.
1677    *
1678    * @return the new instance of type NestedFiltersElement.
1679    */
1680   public NestedFiltersElement createFilters ()
1681   {
1682      return mFilterElements;
1683   }
1684
1685
1686   public static class NestedFiltersElement
1687   {
1688      private List<NestedFilterElement> mFilters
1689          = new ArrayList<NestedFilterElement>();
1690
1691
1692      public void addFilter (NestedFilterElement nfe)
1693      {
1694         mFilters.add(nfe);
1695      }
1696
1697
1698      public List<NestedFilterElement> getFilters ()
1699      {
1700         return mFilters;
1701      }
1702   }
1703
1704
1705   public static class NestedFilterElement
1706   {
1707      private File mFile;
1708
1709      public File getFile ()
1710      {
1711         return mFile;
1712      }
1713
1714
1715      public void setFile (String file)
1716      {
1717         mFile = new File(file);
1718      }
1719   }
1720
1721
1722   //
1723   // Helper methods
1724   //
1725
1726
1727   /**
1728    * Creates a copy of the global command line instance
1729    * and sets the maximum heap vm parameter.
1730    *
1731    * @param cmdline the global command line instance.
1732    * @param maxHeap the maximum heap size for the process.
1733    * @return a copy of the global command line instance.
1734    */
1735   private static CommandlineJava createCommandlineJava (
1736            CommandlineJava cmdline, int maxHeap)
1737   {
1738      final CommandlineJava cmd;
1739      try
1740      {
1741          cmd = (CommandlineJava) cmdline.clone();
1742      }
1743      catch (CloneNotSupportedException unexpected)
1744      {
1745          throw new RuntimeException(
1746                  "Ups, CommandLineJava doesn't support the method clone()",
1747                  unexpected);
1748      }
1749
1750      cmd.createVmArgument().setValue("-Xmx" + maxHeap + "m");
1751      return cmd;
1752   }
1753
1754
1755   /**
1756    * Forks the tool as external process.
1757    *
1758    * @param cmdline the command line.
1759    * @param psh the pump stream handler for redirecting the process streams.
1760    */
1761   private static void forkToolProcess (JcReportAntTask task,
1762            CommandlineJava cmdline, PumpStreamHandler psh)
1763   {
1764      final Execute execute = new Execute(psh);
1765      execute.setCommandline(cmdline.getCommandline());
1766
1767      try
1768      {
1769         task.logCommandLine(cmdline.getCommandline());
1770         final int exitCode = execute.execute();
1771         if (exitCode != 0)
1772         {
1773            task.log("Process returned with exit code: " + exitCode);
1774         }
1775      }
1776      catch (IOException e)
1777      {
1778         throw new BuildException(
1779             "Process fork failed. " 
1780                 + ArraysUtil.toString(cmdline.getCommandline()), e,
1781            task.getLocation());
1782      }
1783   }
1784
1785
1786   /**
1787    * This is a special logging method to print the array of command
1788    * line parameters to the ant logging sub-system.
1789    *
1790    * @param cmdLine the command line parameter array.
1791    */
1792   private void logCommandLine (String[] cmdLine)
1793   {
1794      log("Command line: ");
1795      for (int i = 0; i < cmdLine.length; i++)
1796      {
1797         log("   " + cmdLine[i]);
1798      }
1799   }
1800
1801
1802   /**
1803    * Overwrites the method from the super class in order to
1804    * check for debug mode.
1805    *
1806    * @param msg the message to log.
1807    */
1808   public void log (String msg)
1809   {
1810      if (mDebug)
1811      {
1812         super.log(msg);
1813      }
1814   }
1815}
Note: See TracBrowser for help on using the browser.