/*
* $Id$
*
* Copyright 2006, The jCoderZ.org Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
* * Neither the name of the jCoderZ.org Project nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jcoderz.phoenix.report;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.LogStreamHandler;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.Path;
/**
* jCoderZ Report Ant Task.
*
* This Task takes none, one or more input reports such as Checkstyle or PMD
* and generates a normalized report file (XML) for any Java source under
* <code>srcdir</code>.
*
* @author Michael Griffel (Michael.Griffel@jcoderz.com)
*/
public final class JcoderzReportAntTask
extends MatchingTask
{
/** the current working directory when forking JVM. */
private File mWorkingDir = null;
/** Output directory for XML/HTML report. */
private File mOut = new File(".");
/** The Filter Filename. */
private File mFilter = null;
/** The project's name. */
private String mName = "Not defined";
/** The output format. */
private OutputFormat mOutputFormat = OutputFormat.XML;
/** Flag: exit build process if an error occurred. */
private boolean mFailOnError = false;
/** List of input report of type JcoderzReportAntTask.Report. */
private final List mReportFiles = new ArrayList();
/** The Java Commandline. */
private final CommandlineJava mCommandline = new CommandlineJava();
/**
* List of source directories of type JcoderzReportAntTask.SourceDirectory.
*/
private final List mSourceDirectories = new ArrayList();
/** Debug output flag. */
private boolean mDebug = false;
/**
* Sets the output directory.
* This directory is used to store the report file(s).
*
* @param dir the output directory
*/
public final void setOut (File dir)
{
mOut = dir;
}
/**
* Sets the filter file.
*
* @param f the filter file
*/
public final void setFilter (File f)
{
mFilter = f;
}
/**
* Sets the projectName to given <code>projectName</code>.
*
* @param projectName the project name
*/
public final void setName (String projectName)
{
mName = projectName;
}
/**
* The directory to invoke the VM in. Ignored if no JVM is forked.
*
* @param dir the directory to invoke the JVM from
*/
public void setDir (File dir)
{
mWorkingDir = dir;
}
/**
* Set whether we should fail on an error.
*
* @param b whether we should fail on an error
*/
public void setFailonerror (boolean b)
{
mFailOnError = b;
}
/**
* Sets the output format.
*
* @param s the output format
* @throws BuildException throws a BuildException when the format
* name is not valid
*/
public void setFormat (String s)
throws BuildException
{
try
{
mOutputFormat = OutputFormat.fromString(s);
}
catch (IllegalArgumentException e)
{
throw new BuildException("Unsupported output format '"
+ s + "'", e, getLocation());
}
}
/**
* Sets the debug flag.
*
* @param b the debug mode
*/
public void setDebug (boolean b)
{
mDebug = b;
}
/**
* Adds a classpath to the command line.
*
* @return the created classpath
*/
public Path createClasspath ()
{
return mCommandline.createClasspath(getProject()).createPath();
}
/**
* Adds a bootclasspath to the command line.
*
* @return the created bootclasspath
*/
public Path createBootclasspath ()
{
return mCommandline.createBootclasspath(getProject()).createPath();
}
/**
* Adds a system property.
*
* @param sysp system property
*/
public void addSysproperty (Environment.Variable sysp)
{
mCommandline.addSysproperty(sysp);
}
/**
* Adds a JVM argument.
*
* @return the created command line argument
*/
public Commandline.Argument createJvmarg ()
{
return mCommandline.createVmArgument();
}
/**
* Adds a report to the list of reports.
*
* @return the created report
*/
public Report createReport ()
{
final Report ret = new Report();
mReportFiles.add(ret);
return ret;
}
/**
* Adds a source directory to the list of directories.
*
* @return the created source directory
*/
public SourceDirectory createSrcDir ()
{
final SourceDirectory ret = new SourceDirectory();
mSourceDirectories.add(ret);
return ret;
}
/**
* Executes this task.
*
* @throws BuildException An building exception occurred.
*/
public void execute ()
throws BuildException
{
checkParameters();
try
{
int exitValue;
exitValue = executeAsForked();
if (exitValue != 0)
{
final String msg = "ReportNormalizer returned with exit code '"
+ exitValue + "'";
log(msg, Project.MSG_WARN);
throw new BuildException(msg, getLocation());
}
}
catch (BuildException e)
{
if (mFailOnError)
{
throw e;
}
log(e.getMessage(), e, Project.MSG_ERR);
}
}
/**
* Create a Java command line for executing the ReportNormalizer.
*
* @return the Java command line
*/
private CommandlineJava createCommandline ()
{
final CommandlineJava cmd;
try
{
cmd = (CommandlineJava) mCommandline.clone();
}
catch (CloneNotSupportedException unexpected)
{
throw new RuntimeException(
"Ups, CommandLineJava doesn't support the method clone()",
unexpected);
}
cmd.setClassname(ReportNormalizer.class.getName());
cmd.createArgument().setValue("-out");
cmd.createArgument().setFile(mOut);
cmd.createArgument().setValue("-projectName");
cmd.createArgument().setValue(mName);
cmd.createArgument().setValue("-format");
cmd.createArgument().setValue(mOutputFormat.toString());
cmd.createArgument().setValue("-loglevel");
if (mDebug)
{
cmd.createArgument().setValue("ALL");
}
else
{
cmd.createArgument().setValue("INFO");
}
if (mFilter != null)
{
cmd.createArgument().setValue("-filter");
cmd.createArgument().setFile(mFilter);
}
for (final Iterator iterator = mSourceDirectories.iterator();
iterator.hasNext();)
{
final SourceDirectory sourceDir = (SourceDirectory) iterator.next();
cmd.createArgument().setValue("-srcDir");
cmd.createArgument().setPath(
new Path(getProject(), sourceDir.getDir()));
}
for (final Iterator iterator = mReportFiles.iterator();
iterator.hasNext();)
{
final Report reportFile = (Report) iterator.next();
if (reportFile.testIfCondition())
{
cmd.createArgument().setValue("-" + reportFile.getFormat());
cmd.createArgument().setFile(reportFile.getFile());
}
}
return cmd;
}
private int executeAsForked ()
throws BuildException
{
final Execute execute
= new Execute(new LogStreamHandler(
this, Project.MSG_INFO, Project.MSG_WARN));
final CommandlineJava cmd = createCommandline();
execute.setCommandline(cmd.getCommandline());
if (mWorkingDir != null)
{
log("Setting working directory to : "
+ mWorkingDir, Project.MSG_VERBOSE);
execute.setWorkingDirectory(mWorkingDir);
execute.setAntRun(getProject());
}
final Path classpath = mCommandline.getClasspath();
if (classpath != null)
{
log("Using CLASSPATH " + classpath, Project.MSG_VERBOSE);
}
log("Executing: [fork] " + cmd.toString(), Project.MSG_VERBOSE);
try
{
return execute.execute();
}
catch (IOException e)
{
throw new BuildException("Process fork failed.", e, getLocation());
}
}
private void checkParameters ()
{
if (mSourceDirectories.size() == 0)
{
throw new BuildException(
"at least one srcdir element must be specified!", getLocation());
}
}
/** This class represents input report with a format and filename. */
public final class Report
{
private ReportFormat mReportFormat;
private File mReportFilename;
private String mIfCondition = "";
/**
* Returns the report filename.
*
* @return the report filename
*/
public File getFile ()
{
return mReportFilename;
}
/**
* Sets the report filename.
*
* @param reportFilename the report filename
*/
public void setFile (File reportFilename)
{
mReportFilename = reportFilename;
}
/**
* Returns the report format.
*
* @return the report format
*/
public ReportFormat getFormat ()
{
return mReportFormat;
}
/**
* Sets the report format.
*
* @param reportFormat the report format
*/
public void setFormat (String reportFormat)
{
mReportFormat = ReportFormat.fromString(reportFormat);
}
/**
* Only use report file if the property is set to <code>true</code>.
*
* @param property the property name to check
*/
public void setif (String property)
{
mIfCondition = (property == null) ? "" : property;
}
/**
* Tests whether or not the "if" condition is satisfied.
*
* @return whether or not the "if" condition is satisfied. If no
* condition (or an empty condition) has been set,
* <code>true</code> is returned
*/
private boolean testIfCondition ()
{
final boolean result;
if ("".equals(mIfCondition))
{
result = true;
}
else
{
final String test = getProject().replaceProperties(mIfCondition);
result = getProject().getProperty(test) != null;
}
return result;
}
}
public static final class SourceDirectory
{
private String mSourceDir;
/**
* Returns the sourceDir.
*
* @return the source directory
*/
public final String getDir ()
{
return mSourceDir;
}
/**
* Sets the source directory.
*
* @param sourceDir the source directory
*/
public final void setDir (String sourceDir)
{
mSourceDir = sourceDir;
}
}
}