blob: df314e1c5a0fb416df3c81efa6b4a7d3488928f5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.adobe.ac.pmd.maven;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.doxia.site.renderer.SiteRenderer;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import com.adobe.ac.pmd.FlexPmdParameters;
import com.adobe.ac.pmd.FlexPmdViolations;
import com.adobe.ac.pmd.LoggerUtils;
import com.adobe.ac.pmd.engines.AbstractFlexPmdEngine;
import com.adobe.ac.pmd.engines.FlexPmdXmlEngine;
import com.adobe.ac.pmd.engines.PmdEngineUtils;
abstract class AbstractFlexPmdMojo extends AbstractMavenReport
{
protected static final Logger LOGGER = Logger.getLogger( AbstractFlexPmdMojo.class.getName() );
private static final String OUTPUT_NAME = "flexpmd";
protected static ResourceBundle getBundle( final Locale locale )
{
return ResourceBundle.getBundle( "flexPmd",
locale,
FlexPmdReportMojo.class.getClassLoader() ); // NOPMD
}
/**
* Location of the file.
*
* @parameter expression="${flexpmd.excludePackage}"
*/
private String excludePackage = "";
/**
* Build fails if an violation error occurs.
*
* @parameter expression="${flexpmd.failOnError}"
*/
private boolean failOnError;
/**
* Build fails if an violation error occurs.
*
* @parameter expression="${flexpmd.failOnRuleViolation}"
*/
private boolean failOnRuleViolation;
/**
* Location of the file.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private File outputDirectory;
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* Location of the file.
*
* @parameter expression="${flexpmd.ruleset}"
*/
private File ruleSet;
/**
* @parameter
* expression="${component.org.codehaus.doxia.site.renderer.SiteRenderer}"
* @required
* @readonly
*/
private SiteRenderer siteRenderer;
/**
* Specifies the location of the source files to be used.
*
* @parameter expression="${project.build.sourceDirectory}"
* @required
*/
private File sourceDirectory;
/**
* URL of the file
*
* @parameter expression="${flexpmd.url}"
*/
private URL url;
public AbstractFlexPmdMojo()
{
super();
excludePackage = "";
}
public AbstractFlexPmdMojo( final MavenProject projectToBeSet,
final FlexPmdParameters parameters )
{
this();
project = projectToBeSet;
outputDirectory = parameters.getOutputDirectory();
ruleSet = parameters.getRuleSet();
sourceDirectory = parameters.getSource();
failOnError = parameters.isFailOnError();
failOnRuleViolation = parameters.isFailOnRuleViolation();
excludePackage = parameters.getExcludePackage();
}
public final String getDescription( final Locale locale )
{
return getBundle( locale ).getString( "report.flexPmd.description" );
}
public final String getName( final Locale locale )
{
return getBundle( locale ).getString( "report.flexPmd.name" );
}
public final String getOutputName()
{
return OUTPUT_NAME;
}
@Override
protected final void executeReport( final Locale locale ) throws MavenReportException
{
new LoggerUtils().loadConfiguration();
getLog().info( "FlexPmdMojo starts" );
getLog().info( " failOnError "
+ failOnError );
getLog().info( " ruleSet "
+ ruleSet );
getLog().info( " sourceDirectory "
+ sourceDirectory );
getLog().info( " ruleSetURL "
+ url );
try
{
final AbstractFlexPmdEngine engine = new FlexPmdXmlEngine( new FlexPmdParameters( excludePackage,
failOnError,
failOnRuleViolation,
outputDirectory,
getRuleSet(),
sourceDirectory ) );
final FlexPmdViolations violations = new FlexPmdViolations();
engine.executeReport( violations );
onXmlReportExecuted( violations,
locale );
}
catch ( final Exception e )
{
throw new MavenReportException( "A system exception has been thrown", e );
}
}
protected final String getExcludePackage()
{
return excludePackage;
}
@Override
protected final String getOutputDirectory()
{
return outputDirectory.getAbsolutePath();
}
protected final File getOutputDirectoryFile()
{
return outputDirectory;
}
@Override
protected final MavenProject getProject()
{
return project;
}
protected final File getRuleSet()
{
if ( ruleSet == null )
{
try
{
getRulesetFromURL();
}
catch ( final IOException ioe )
{
throw new RuntimeException( "Could not get ruleset from URL", ioe );
}
catch ( final Exception e )
{
// if this goes wrong, we're experiencing an unrecoverable
// error, so we'll fall back on the default rules
}
}
return ruleSet;
}
@Override
protected final SiteRenderer getSiteRenderer()
{
return siteRenderer;
}
protected final File getSourceDirectory()
{
return sourceDirectory;
}
protected void onXmlReportExecuted( final FlexPmdViolations violations,
final Locale locale ) throws MavenReportException
{
if ( failOnError )
{
final String message = PmdEngineUtils.findFirstViolationError( violations );
if ( message.length() > 0 )
{
throw new MavenReportException( message );
}
}
if ( failOnRuleViolation
&& !violations.getViolations().isEmpty() )
{
throw new MavenReportException( "At least one violation has been found" );
}
}
protected final void setSiteRenderer( final SiteRenderer siteRendererToBeSet ) // NO_UCD
{
this.siteRenderer = siteRendererToBeSet;
}
/**
* @throws ParserConfigurationException
* @throws SAXException
* @throws SAXException
* @throws TransformerException
* @throws TransformerFactoryConfigurationError
* @throws IOException
*/
private void getRulesetFromURL() throws ParserConfigurationException,
SAXException,
TransformerFactoryConfigurationError,
TransformerException,
IOException
{
getLog().info( "getting RuleSet from URL" );
if ( url == null )
{
getLog().info( "Ruleset URL is not set" );
return;
}
ruleSet = File.createTempFile( "pmdRuleset",
"" );
final DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
try
{
final Document pmdRules = db.parse( url.toExternalForm() );
writeToFile( pmdRules,
ruleSet );
}
catch ( final SAXException sax )
{
saveUTF8SafeXML();
}
}
private void saveUTF8SafeXML() throws IOException,
FileNotFoundException
{
final InputStream inputstream = url.openStream();
final OutputStream outputstream = new FileOutputStream( ruleSet );
int thisByteAsInt;
while ( ( thisByteAsInt = inputstream.read() ) != -1 )
{
outputstream.write( stripNonValidXMLCharacters( ( byte ) thisByteAsInt ) );
}
inputstream.close();
outputstream.flush();
outputstream.close();
}
private byte stripNonValidXMLCharacters( final byte in )
{
byte current; // Used to reference the current character.
current = in;
if ( current == 0x9
|| current == 0xA || current == 0xD || current >= 0x20 && current <= 0xD7FF || current >= 0xE000
&& current <= 0xFFFD || current >= 0x10000 && current <= 0x10FFFF )
{
return current;
}
return '\n';
}
private void writeToFile( final Document pmdRules,
final File ruleSet ) throws TransformerFactoryConfigurationError,
IOException,
TransformerException
{
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty( OutputKeys.INDENT,
"yes" );
final StreamResult result = new StreamResult( new FileWriter( ruleSet ) );
final DOMSource source = new DOMSource( pmdRules );
transformer.transform( source,
result );
}
}