Author: olamy Date: Mon May 21 19:58:41 2012 New Revision: 1341175 URL: http://svn.apache.org/viewvc?rev=1341175&view=rev Log: [MPMD-147] Migrate to PMD 5.0.0 Submitted by Andreas Dangel.
Modified: maven/plugins/trunk/maven-pmd-plugin/pom.xml maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/CpdReport.java maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReport.java maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReportListener.java maven/plugins/trunk/maven-pmd-plugin/src/main/resources/rulesets/maven.xml maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/CpdReportTest.java maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdReportTest.java maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdViolationCheckMojoTest.java maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml Modified: maven/plugins/trunk/maven-pmd-plugin/pom.xml URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/pom.xml?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/pom.xml (original) +++ maven/plugins/trunk/maven-pmd-plugin/pom.xml Mon May 21 19:58:41 2012 @@ -64,7 +64,7 @@ under the License. <properties> <mavenVersion>2.2.1</mavenVersion> <doxiaVersion>1.1.3</doxiaVersion> - <pmdVersion>4.3</pmdVersion> + <pmdVersion>5.0.0</pmdVersion> <sitePluginVersion>3.0</sitePluginVersion> </properties> @@ -156,7 +156,7 @@ under the License. <!-- pmd --> <dependency> - <groupId>pmd</groupId> + <groupId>net.sourceforge.pmd</groupId> <artifactId>pmd</artifactId> <version>${pmdVersion}</version> </dependency> Modified: maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/CpdReport.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/CpdReport.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/CpdReport.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/CpdReport.java Mon May 21 19:58:41 2012 @@ -32,6 +32,7 @@ import java.util.Properties; import java.util.ResourceBundle; import net.sourceforge.pmd.cpd.CPD; +import net.sourceforge.pmd.cpd.CPDConfiguration; import net.sourceforge.pmd.cpd.CSVRenderer; import net.sourceforge.pmd.cpd.JavaLanguage; import net.sourceforge.pmd.cpd.JavaTokenizer; @@ -158,26 +159,17 @@ public class CpdReport { p.setProperty( JavaTokenizer.IGNORE_IDENTIFIERS, "true" ); } - CPD cpd = new CPD( minimumTokens, new JavaLanguage( p ) ); + CPD cpd; Map<File, PmdFileInfo> files = null; + try { files = getFilesToProcess(); + String encoding = determineEncoding( !files.isEmpty() ); - if ( StringUtils.isNotEmpty( getSourceEncoding() ) ) - { - cpd.setEncoding( getSourceEncoding() ); - - // test encoding as CPD will convert exception into a RuntimeException - WriterFactory.newWriter( new ByteArrayOutputStream(), getSourceEncoding() ); - } - else if ( !files.isEmpty() ) - { - getLog().warn( - "File encoding has not been set, using platform encoding " - + WriterFactory.FILE_ENCODING + ", i.e. build is platform dependent!" ); - } + CPDConfiguration cpdConfiguration = new CPDConfiguration( minimumTokens, new JavaLanguage( p ), encoding ); + cpd = new CPD( cpdConfiguration ); for ( File file : files.keySet() ) { @@ -201,6 +193,23 @@ public class CpdReport return cpd; } + private String determineEncoding(boolean showWarn) throws UnsupportedEncodingException { + String encoding = WriterFactory.FILE_ENCODING; + if ( StringUtils.isNotEmpty( getSourceEncoding() ) ) { + + encoding = getSourceEncoding(); + // test encoding as CPD will convert exception into a RuntimeException + WriterFactory.newWriter( new ByteArrayOutputStream(), encoding ); + + } else if ( showWarn ) { + getLog().warn( + "File encoding has not been set, using platform encoding " + + WriterFactory.FILE_ENCODING + ", i.e. build is platform dependent!" ); + encoding = WriterFactory.FILE_ENCODING; + } + return encoding; + } + void writeNonHtml( CPD cpd ) throws MavenReportException { @@ -262,7 +271,9 @@ public class CpdReport Renderer renderer = null; if ( "xml".equals( format ) ) { - renderer = new XMLRenderer( getOutputEncoding() ); + //TODO: pmd should provide a better way to specify the output encoding (getOutputEncoding()); + System.setProperty("file.encoding", getOutputEncoding()); + renderer = new XMLRenderer(); } else if ( "csv".equals( format ) ) { Modified: maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReport.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReport.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReport.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReport.java Mon May 21 19:58:41 2012 @@ -20,33 +20,34 @@ package org.apache.maven.plugin.pmd; */ import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Properties; import java.util.ResourceBundle; -import net.sourceforge.pmd.IRuleViolation; import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.PMDException; +import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.Report; -import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.SourceType; +import net.sourceforge.pmd.RuleSetReferenceId; +import net.sourceforge.pmd.RuleViolation; +import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.renderers.CSVRenderer; import net.sourceforge.pmd.renderers.HTMLRenderer; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.TextRenderer; import net.sourceforge.pmd.renderers.XMLRenderer; +import net.sourceforge.pmd.util.datasource.DataSource; +import net.sourceforge.pmd.util.datasource.FileDataSource; import org.apache.maven.doxia.sink.Sink; import org.apache.maven.reporting.MavenReportException; @@ -73,9 +74,10 @@ public class PmdReport { /** * The target JDK to analyze based on. Should match the target used in the compiler plugin. Valid values are - * currently <code>1.3</code>, <code>1.4</code>, <code>1.5</code> and <code>1.6</code>. + * currently <code>1.3</code>, <code>1.4</code>, <code>1.5</code>, <code>1.6</code> and <code>1.7</code>. * <p> - * <b>Note:</b> support for <code>1.6</code> was added in version 2.3 of this plugin. + * <b>Note:</b> support for <code>1.6</code> was added in version 2.3 of this plugin, + * support for <code>1.7</code> was added in version 2.7 of this plugin. * </p> * * @parameter expression="${targetJdk}" @@ -103,12 +105,11 @@ public class PmdReport /** * The PMD rulesets to use. See the <a href="http://pmd.sourceforge.net/rules/index.html">Stock Rulesets</a> for a * list of some included. Since version 2.5, the ruleset "rulesets/maven.xml" is also available. Defaults to the - * basic, imports and unusedcode rulesets. + * java-basic, java-imports and java-unusedcode rulesets. * * @parameter */ - private String[] rulesets = - new String[]{ "rulesets/basic.xml", "rulesets/unusedcode.xml", "rulesets/imports.xml", }; + private String[] rulesets = new String[]{ "java-basic", "java-unusedcode", "java-imports" }; /** * @component @@ -191,49 +192,36 @@ public class PmdReport { Sink sink = getSink(); - PMD pmd = getPMD(); - RuleContext ruleContext = new RuleContext(); - Report report = new Report(); - PmdReportListener reportSink = new PmdReportListener( sink, getBundle( locale ), aggregate ); - - report.addListener( reportSink ); - ruleContext.setReport( report ); + PMDConfiguration pmdConfiguration = getPMDConfiguration(); + final PmdReportListener reportSink = new PmdReportListener( sink, getBundle( locale ), aggregate ); + RuleContext ruleContext = new RuleContext() { + @Override + public void setReport(Report report) { + super.setReport( report ); + // make sure our listener is added - the Report is created by PMD internally now + report.addListener( reportSink ); + } + }; reportSink.beginDocument(); RuleSetFactory ruleSetFactory = new RuleSetFactory(); - ruleSetFactory.setMinimumPriority( this.minimumPriority ); - RuleSet[] sets = new RuleSet[rulesets.length]; + ruleSetFactory.setMinimumPriority( RulePriority.valueOf( this.minimumPriority ) ); + String[] sets = new String[rulesets.length]; try { for ( int idx = 0; idx < rulesets.length; idx++ ) { String set = rulesets[idx]; getLog().debug( "Preparing ruleset: " + set ); - File ruleset = locator.getResourceAsFile( set, getLocationTemp( set ) ); - + RuleSetReferenceId id = new RuleSetReferenceId( set ); + File ruleset = locator.getResourceAsFile( id.getRuleSetFileName(), getLocationTemp( set ) ); if ( null == ruleset ) { throw new MavenReportException( "Could not resolve " + set ); } - - InputStream rulesInput = new FileInputStream( ruleset ); - try - { - RuleSet ruleSet = ruleSetFactory.createRuleSet( rulesInput ); - sets[idx] = ruleSet; - - ruleSet.start( ruleContext ); - } - finally - { - rulesInput.close(); - } + sets[idx] = ruleset.getAbsolutePath(); } } - catch ( IOException e ) - { - throw new MavenReportException( e.getMessage(), e ); - } catch ( ResourceNotFoundException e ) { throw new MavenReportException( e.getMessage(), e ); @@ -242,6 +230,7 @@ public class PmdReport { throw new MavenReportException( e.getMessage(), e ); } + pmdConfiguration.setRuleSets( StringUtils.join( sets, "," )); Map<File, PmdFileInfo> files; try @@ -253,86 +242,84 @@ public class PmdReport throw new MavenReportException( "Can't get file list", e ); } - if ( StringUtils.isEmpty( getSourceEncoding() ) && !files.isEmpty() ) + String encoding = getSourceEncoding(); + if ( StringUtils.isEmpty( encoding ) && !files.isEmpty() ) { getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING + ", i.e. build is platform dependent!" ); + encoding = ReaderFactory.FILE_ENCODING; } + pmdConfiguration.setSourceEncoding( encoding ); - for ( Map.Entry<File, PmdFileInfo> entry : files.entrySet() ) + reportSink.setFiles(files); + List<DataSource> dataSources = new ArrayList<DataSource>( files.size() ); + for ( File f : files.keySet() ) { - File file = entry.getKey(); - PmdFileInfo fileInfo = entry.getValue(); + dataSources.add( new FileDataSource( f ) ); + } - // TODO: lazily call beginFile in case there are no rules + try + { + List<Renderer> renderers = Collections.emptyList(); - reportSink.beginFile( file, fileInfo ); - ruleContext.setSourceCodeFilename( file.getAbsolutePath() ); - for ( int idx = 0; idx < rulesets.length; idx++ ) - { - try - { - // PMD closes this Reader even though it did not open it so we have - // to open a new one with every call to processFile(). - Reader reader; - if ( StringUtils.isNotEmpty( getSourceEncoding() ) ) - { - reader = ReaderFactory.newReader( file, getSourceEncoding() ); - } - else - { - reader = ReaderFactory.newPlatformReader( file ); - } - - try - { - pmd.processFile( reader, sets[idx], ruleContext ); - } - finally - { - reader.close(); - } - } - catch ( UnsupportedEncodingException e1 ) - { - throw new MavenReportException( "Encoding '" + getSourceEncoding() + "' is not supported.", e1 ); - } - catch ( PMDException pe ) - { - String msg = pe.getLocalizedMessage(); - Throwable r = pe.getCause(); - if ( r != null ) - { - msg = msg + ": " + r.getLocalizedMessage(); - } - getLog().warn( msg ); - reportSink.ruleViolationAdded( new ProcessingErrorRuleViolation( file, msg ) ); - } - catch ( FileNotFoundException e2 ) - { - getLog().warn( "Error opening source file: " + file ); - reportSink.ruleViolationAdded( new ProcessingErrorRuleViolation( file, e2.getLocalizedMessage() ) ); - } - catch ( Exception e3 ) - { - getLog().warn( "Failure executing PMD for: " + file, e3 ); - reportSink.ruleViolationAdded( new ProcessingErrorRuleViolation( file, e3.getLocalizedMessage() ) ); - } - } - reportSink.endFile( file ); - } + // Unfortunately we need to disable multi-threading for now - as otherwise our PmdReportListener + // will be ignored. + // Longer term solution could be to use a custom renderer instead. And collect with this renderer + // all the violations. + pmdConfiguration.setThreads( 0 ); - for ( int idx = 0; idx < rulesets.length; idx++ ) + PMD.processFiles(pmdConfiguration, ruleSetFactory, dataSources, ruleContext, renderers ); + } + catch ( Exception e ) { - sets[idx].end( ruleContext ); + getLog().warn( "Failure executing PMD: " + e.getLocalizedMessage(), e ); } reportSink.endDocument(); + // copy over the violations into a single report - PMD now creates one report per file + Report report = new Report(); + for ( RuleViolation v : reportSink.getViolations() ) + { + report.addRuleViolation( v ); + } return report; } /** + * Convenience method to get the location of the specified file name. + * + * @param name the name of the file whose location is to be resolved + * @return a String that contains the absolute file name of the file + */ + protected String getLocationTemp( String name ) + { + String loc = name; + if ( loc.indexOf( '/' ) != -1 ) + { + loc = loc.substring( loc.lastIndexOf( '/' ) + 1 ); + } + if ( loc.indexOf( '\\' ) != -1 ) + { + loc = loc.substring( loc.lastIndexOf( '\\' ) + 1 ); + } + + // MPMD-127 in the case that the rules are defined externally on a url + // we need to replace some special url characters that cannot be + // used in filenames on disk or produce ackward filenames. + // replace all occurrences of the following characters: ? : & = % + loc = loc.replaceAll( "[\\?\\:\\&\\=\\%]", "_" ); + + if (!loc.endsWith( ".xml" )) + { + loc = loc + ".xml"; + } + + getLog().debug( "Before: " + name + " After: " + loc ); + return loc; + } + + /** * Use the PMD renderers to render in any format aside from HTML. * * @param report @@ -379,57 +366,29 @@ public class PmdReport } /** - * Convenience method to get the location of the specified file name. - * - * @param name the name of the file whose location is to be resolved - * @return a String that contains the absolute file name of the file - */ - protected String getLocationTemp( String name ) - { - String loc = name; - if ( loc.indexOf( '/' ) != -1 ) - { - loc = loc.substring( loc.lastIndexOf( '/' ) + 1 ); - } - if ( loc.indexOf( '\\' ) != -1 ) - { - loc = loc.substring( loc.lastIndexOf( '\\' ) + 1 ); - } - - // MPMD-127 in the case that the rules are defined externally on a url - // we need to replace some special url characters that cannot be - // used in filenames on disk or produce ackward filenames. - // replace all occurrences of the following characters: ? : & = % - loc = loc.replaceAll( "[\\?\\:\\&\\=\\%]", "_" ); - - getLog().debug( "Before: " + name + " After: " + loc ); - return loc; - } - - /** - * Constructs the PMD class, passing it an argument + * Constructs the PMD configuration class, passing it an argument * that configures the target JDK. * * @return the resulting PMD * @throws org.apache.maven.reporting.MavenReportException * if targetJdk is not supported */ - public PMD getPMD() + public PMDConfiguration getPMDConfiguration() throws MavenReportException { - PMD pmd = new PMD(); + PMDConfiguration configuration = new PMDConfiguration(); if ( null != targetJdk ) { - SourceType sourceType = SourceType.getSourceTypeForId( "java " + targetJdk ); - if ( sourceType == null ) + LanguageVersion languageVersion = LanguageVersion.findByTerseName( "java " + targetJdk ); + if ( languageVersion == null ) { throw new MavenReportException( "Unsupported targetJdk value '" + targetJdk + "'." ); } - pmd.setJavaVersion( sourceType ); + configuration.setDefaultLanguageVersion( languageVersion ); } - return pmd; + return configuration; } /** @@ -462,21 +421,23 @@ public class PmdReport } else if ( "txt".equals( format ) ) { - renderer = new TextRenderer(); + renderer = new TextRenderer( new Properties() ); } else if ( "csv".equals( format ) ) { - renderer = new CSVRenderer(); + renderer = new CSVRenderer( new Properties() ); } else if ( "html".equals( format ) ) { - renderer = new HTMLRenderer(); + renderer = new HTMLRenderer( new Properties() ); } else if ( !"".equals( format ) && !"none".equals( format ) ) { try { - renderer = (Renderer) Class.forName( format ).newInstance(); + renderer = (Renderer) Class.forName( format ) + .getConstructor( Properties.class ) + .newInstance( new Properties() ); } catch ( Exception e ) { @@ -493,122 +454,8 @@ public class PmdReport { public PmdXMLRenderer( String encoding ) { - super(); + super( new Properties() ); this.encoding = encoding; } } - - /** - * @author <a href="mailto:douglass.d...@gmail.com">Doug Douglass</a> - */ - private static class ProcessingErrorRuleViolation - implements IRuleViolation - { - - private String filename; - - private String description; - - public ProcessingErrorRuleViolation( File file, String description ) - { - filename = file.getPath(); - this.description = description; - } - - /** - * {@inheritDoc} - */ - public String getFilename() - { - return this.filename; - } - - /** - * {@inheritDoc} - */ - public int getBeginLine() - { - return 0; - } - - /** - * {@inheritDoc} - */ - public int getBeginColumn() - { - return 0; - } - - /** - * {@inheritDoc} - */ - public int getEndLine() - { - return 0; - } - - /** - * {@inheritDoc} - */ - public int getEndColumn() - { - return 0; - } - - /** - * {@inheritDoc} - */ - public Rule getRule() - { - return null; - } - - /** - * {@inheritDoc} - */ - public String getDescription() - { - return this.description; - } - - /** - * {@inheritDoc} - */ - public String getPackageName() - { - return null; - } - - /** - * {@inheritDoc} - */ - public String getMethodName() - { - return null; - } - - /** - * {@inheritDoc} - */ - public String getClassName() - { - return null; - } - - /** - * {@inheritDoc} - */ - public boolean isSuppressed() - { - return false; - } - - /** - * {@inheritDoc} - */ - public String getVariableName() - { - return null; - } - } } \ No newline at end of file Modified: maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReportListener.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReportListener.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReportListener.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/main/java/org/apache/maven/plugin/pmd/PmdReportListener.java Mon May 21 19:58:41 2012 @@ -23,11 +23,13 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.ResourceBundle; -import net.sourceforge.pmd.IRuleViolation; import net.sourceforge.pmd.ReportListener; +import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.stat.Metric; import org.apache.maven.doxia.sink.Sink; @@ -46,20 +48,20 @@ public class PmdReportListener private String currentFilename; - private boolean fileInitialized; - private ResourceBundle bundle; private PmdFileInfo fileInfo; - private List<IRuleViolation> violations = new ArrayList<IRuleViolation>(); + private List<RuleViolation> violations = new ArrayList<RuleViolation>(); private boolean aggregate; // The number of erroneous files private int fileCount = 0; - //private List metrics = new ArrayList(); + private Map<File, PmdFileInfo> files; + +// private List<Metric> metrics = new ArrayList<Metric>(); public PmdReportListener( Sink sink, ResourceBundle bundle, boolean aggregate ) { @@ -74,70 +76,118 @@ public class PmdReportListener } /** {@inheritDoc} */ - public void ruleViolationAdded( IRuleViolation ruleViolation ) + public void ruleViolationAdded( RuleViolation ruleViolation ) { - if ( !fileInitialized ) + violations.add( ruleViolation ); + } + + public List<RuleViolation> getViolations() { + return violations; + } + + private void startFileSection(String currentFilename, PmdFileInfo fileInfo) { + sink.section2(); + sink.sectionTitle2(); + + // prepare the filename + this.currentFilename = StringUtils.substring( currentFilename, + fileInfo.getSourceDirectory().getAbsolutePath().length() + 1 ); + this.currentFilename = StringUtils.replace( this.currentFilename, "\\", "/" ); + + String title = this.currentFilename; + if (aggregate) { - sink.section2(); - sink.sectionTitle2(); - String title = currentFilename; - if ( aggregate ) - { - title = fileInfo.getProject().getName() + " - " + currentFilename; - } - sink.text( title ); - sink.sectionTitle2_(); + title = fileInfo.getProject().getName() + " - " + currentFilename; + } + sink.text( title ); + sink.sectionTitle2_(); - sink.table(); - sink.tableRow(); - sink.tableHeaderCell(); - sink.text( bundle.getString( "report.pmd.column.violation" ) ); - sink.tableHeaderCell_(); - sink.tableHeaderCell(); - sink.text( bundle.getString( "report.pmd.column.line" ) ); - sink.tableHeaderCell_(); - sink.tableRow_(); + sink.table(); + sink.tableRow(); + sink.tableHeaderCell(); + sink.text( bundle.getString( "report.pmd.column.violation" ) ); + sink.tableHeaderCell_(); + sink.tableHeaderCell(); + sink.text( bundle.getString( "report.pmd.column.line" ) ); + sink.tableHeaderCell_(); + sink.tableRow_(); + } + + private void endFileSection() { + sink.table_(); + sink.section2_(); + } - fileInitialized = true; + private void processSingleRuleViolation(RuleViolation ruleViolation) { + sink.tableRow(); + sink.tableCell(); + sink.text( ruleViolation.getDescription() ); + sink.tableCell_(); + sink.tableCell(); + + int beginLine = ruleViolation.getBeginLine(); + outputLineLink( beginLine ); + int endLine = ruleViolation.getEndLine(); + if (endLine != beginLine) { + sink.text( " - " ); + outputLineLink( endLine ); } - violations.add( ruleViolation ); + + sink.tableCell_(); + sink.tableRow_(); } - // When dealing with multiple rulesets, the violations will get out of order - // wrt their source line number. We re-sort them before writing them to the report. + // PMD might run the analysis multi-threaded, so the violations might be reported + // out of order. We sort them here by filename and line number before writing them to + // the report. private void processViolations() { - fileCount++; - Collections.sort( violations, new Comparator<IRuleViolation>() - { + fileCount = files.size(); + Collections.sort( violations, new Comparator<RuleViolation>() { /** {@inheritDoc} */ - public int compare( IRuleViolation o1, IRuleViolation o2 ) - { - return o1.getBeginLine() - o2.getBeginLine(); + public int compare(RuleViolation o1, RuleViolation o2) { + int filenames = o1.getFilename().compareTo( o2.getFilename() ); + if (filenames == 0) { + return o1.getBeginLine() - o2.getBeginLine(); + } + else { + return filenames; + } } } ); - for ( IRuleViolation ruleViolation : violations ) + Map<String, PmdFileInfo> fileLookup = new HashMap<String, PmdFileInfo>( fileCount ); + for ( Map.Entry<File, PmdFileInfo> entry : files.entrySet() ) { - sink.tableRow(); - sink.tableCell(); - sink.text( ruleViolation.getDescription() ); - sink.tableCell_(); - sink.tableCell(); + fileLookup.put( entry.getKey().getAbsolutePath(), entry.getValue() ); + } - int beginLine = ruleViolation.getBeginLine(); - outputLineLink( beginLine ); - int endLine = ruleViolation.getEndLine(); - if ( endLine != beginLine ) + boolean fileSectionStarted = false; + String previousFilename = null; + for ( RuleViolation ruleViolation : violations ) + { + String currentFn = ruleViolation.getFilename(); + if ( !currentFn.equalsIgnoreCase( previousFilename ) && fileSectionStarted ) + { + endFileSection(); + fileSectionStarted = false; + } + if ( !fileSectionStarted ) { - sink.text( " - " ); - outputLineLink( endLine ); + fileInfo = fileLookup.get( currentFn ); + startFileSection( currentFn, fileInfo ); + fileSectionStarted = true; } - sink.tableCell_(); - sink.tableRow_(); + processSingleRuleViolation( ruleViolation ); + + previousFilename = currentFn; + } + + if ( fileSectionStarted ) + { + endFileSection(); } - violations.clear(); } private void outputLineLink( int line ) @@ -199,26 +249,7 @@ public class PmdReportListener // TODO files summary } - public void beginFile( File file, PmdFileInfo finfo ) - { - fileInfo = finfo; - currentFilename = StringUtils.substring( file.getAbsolutePath(), - finfo.getSourceDirectory().getAbsolutePath().length() + 1 ); - currentFilename = StringUtils.replace( currentFilename, "\\", "/" ); - fileInitialized = false; - } - - public void endFile( File file ) - { - if ( fileInitialized ) - { - processViolations(); - sink.table_(); - sink.section2_(); - } - } - - /* +/* private void processMetrics() { if ( metrics.size() == 0 ) @@ -250,9 +281,8 @@ public class PmdReportListener sink.tableHeaderCell_(); sink.tableRow_(); - for ( Iterator iter = metrics.iterator(); iter.hasNext(); ) + for ( Metric met : metrics ) { - Metric met = (Metric) iter.next(); sink.tableRow(); sink.tableCell(); sink.text( met.getMetricName() ); @@ -274,10 +304,12 @@ public class PmdReportListener sink.table_(); sink.section1_(); } - */ +*/ public void endDocument() { + processViolations(); + if ( fileCount == 0 ) { sink.paragraph(); @@ -292,7 +324,7 @@ public class PmdReportListener // of excessive imports metrics, none of which is really any use. // TODO Determine if we are going to just ignore metrics. - // processMetrics(); +// processMetrics(); sink.body_(); @@ -300,4 +332,8 @@ public class PmdReportListener sink.close(); } + + public void setFiles(Map<File, PmdFileInfo> files) { + this.files = files; + } } \ No newline at end of file Modified: maven/plugins/trunk/maven-pmd-plugin/src/main/resources/rulesets/maven.xml URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/main/resources/rulesets/maven.xml?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/main/resources/rulesets/maven.xml (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/main/resources/rulesets/maven.xml Mon May 21 19:58:41 2012 @@ -32,16 +32,16 @@ under the License. This ruleset checks the code for discouraged programming constructs. </description> - <rule ref="rulesets/basic.xml"> + <rule ref="rulesets/java/basic.xml"> <exclude name="EmptyCatchBlock"/> </rule> - <rule ref="rulesets/basic.xml/EmptyCatchBlock"> + <rule ref="rulesets/java/basic.xml/EmptyCatchBlock"> <properties> <property name="allowCommentedBlocks" value="true"/> </properties> </rule> - <rule ref="rulesets/unusedcode.xml"/> + <rule ref="rulesets/java/unusedcode.xml"/> - <rule ref="rulesets/imports.xml"/> + <rule ref="rulesets/java/imports.xml"/> </ruleset> Modified: maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/CpdReportTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/CpdReportTest.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/CpdReportTest.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/CpdReportTest.java Mon May 21 19:58:41 2012 @@ -31,8 +31,8 @@ import javax.xml.parsers.DocumentBuilder import javax.xml.parsers.DocumentBuilderFactory; import net.sourceforge.pmd.cpd.CPD; +import net.sourceforge.pmd.cpd.CPDConfiguration; import net.sourceforge.pmd.cpd.JavaLanguage; -import net.sourceforge.pmd.cpd.Language; import net.sourceforge.pmd.cpd.Match; import net.sourceforge.pmd.cpd.TokenEntry; @@ -201,7 +201,8 @@ public class CpdReportTest tMatch.setSourceCodeSlice( "// ----- ACCESSEURS avec �l�ments -----" ); tList.add( tMatch ); - CPD tCpd = new MockCpd( 100, new JavaLanguage(), tList.iterator() ); + CPDConfiguration cpdConfiguration = new CPDConfiguration( 100, new JavaLanguage(), "UTF-8" ); + CPD tCpd = new MockCpd( cpdConfiguration, tList.iterator() ); tCpd.go(); mojo.writeNonHtml( tCpd ); @@ -220,9 +221,9 @@ public class CpdReportTest private Iterator<Match> matches; - public MockCpd( int minimumTileSize, Language language, Iterator<Match> tMatch ) + public MockCpd( CPDConfiguration configuration, Iterator<Match> tMatch ) { - super( minimumTileSize, language ); + super( configuration ); matches = tMatch; } Modified: maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdReportTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdReportTest.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdReportTest.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdReportTest.java Mon May 21 19:58:41 2012 @@ -62,13 +62,14 @@ public class PmdReportTest File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" ); assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) ); - generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/basic.xml" ); + // check if the rulesets, that have been applied, have been copied + generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/java-basic.xml" ); assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) ); - generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/imports.xml" ); + generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/java-imports.xml" ); assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) ); - generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/unusedcode.xml" ); + generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/java-unusedcode.xml" ); assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) ); generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" ); @@ -96,9 +97,9 @@ public class PmdReportTest "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml" ); PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom ); - URL url = getClass().getClassLoader().getResource( "rulesets/basic.xml" ); - URL url2 = getClass().getClassLoader().getResource( "rulesets/unusedcode.xml" ); - URL url3 = getClass().getClassLoader().getResource( "rulesets/imports.xml" ); + URL url = getClass().getClassLoader().getResource( "rulesets/java/basic.xml" ); + URL url2 = getClass().getClassLoader().getResource( "rulesets/java/unusedcode.xml" ); + URL url3 = getClass().getClassLoader().getResource( "rulesets/java/imports.xml" ); mojo.setRulesets( new String[]{ url.toString(), url2.toString(), url3.toString() } ); mojo.execute(); @@ -181,8 +182,6 @@ public class PmdReportTest PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom ); mojo.execute(); - File basedir = new File( getBasedir(), "target/test/unit/skip-configuration" ); - // verify the generated files do not exist because PMD was skipped File generatedFile = new File( getBasedir(), "target/test/unit/skip-configuration/target/pmd.csv" ); assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) ); @@ -281,7 +280,7 @@ public class PmdReportTest PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom ); assertEquals( "locationTemp is not correctly encoding filename", - "export_format_pmd_language_java_name_some_2520name", mojo.getLocationTemp( + "export_format_pmd_language_java_name_some_2520name.xml", mojo.getLocationTemp( "http://nemo.sonarsource.org/sonar/profiles/export?format=pmd&language=java&name=some%2520name" ) ); } Modified: maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdViolationCheckMojoTest.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdViolationCheckMojoTest.java?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdViolationCheckMojoTest.java (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/test/java/org/apache/maven/plugin/pmd/PmdViolationCheckMojoTest.java Mon May 21 19:58:41 2012 @@ -76,6 +76,11 @@ public class PmdViolationCheckMojoTest throws Exception { File testPom = new File( getBasedir(), + "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml" ); + PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom ); + mojo.execute(); + + testPom = new File( getBasedir(), "src/test/resources/unit/default-configuration/pmd-check-failonpriority-plugin-config.xml" ); PmdViolationCheckMojo pmdViolationMojo = (PmdViolationCheckMojo) lookupMojo( "check", testPom ); pmdViolationMojo.execute(); Modified: maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml Mon May 21 19:58:41 2012 @@ -42,9 +42,9 @@ under the License. <sourceEncoding>ISO-8859-1</sourceEncoding> <rulesets> <ruleset>${basedir}/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml</ruleset> - <ruleset>rulesets/basic.xml</ruleset> - <ruleset>rulesets/unusedcode.xml</ruleset> - <ruleset>rulesets/imports.xml</ruleset> + <ruleset>java-basic</ruleset> + <ruleset>rulesets/java/unusedcode.xml</ruleset> + <ruleset>java-imports</ruleset> </rulesets> <targetJdk>1.4</targetJdk> <minimumPriority>4</minimumPriority> Modified: maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml?rev=1341175&r1=1341174&r2=1341175&view=diff ============================================================================== --- maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml (original) +++ maven/plugins/trunk/maven-pmd-plugin/src/test/resources/unit/custom-configuration/resources/rulesets/custom.xml Mon May 21 19:58:41 2012 @@ -22,13 +22,13 @@ under the License. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> <description>Just the braces rules I like</description> - <rule ref="rulesets/braces.xml"> + <rule ref="rulesets/java/braces.xml"> <exclude name="WhileLoopsMustUseBracesRule"/> <exclude name="IfElseStmtsMustUseBracesRule"/> </rule> <description>Lowest priority for unnecessary constructor</description> - <rule ref="rulesets/controversial.xml/UnnecessaryConstructor" > + <rule ref="rulesets/java/controversial.xml/UnnecessaryConstructor" > <priority>5</priority> </rule>