1 package org.apache.maven.plugins.pmd;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.UnsupportedEncodingException;
24 import java.util.Locale;
25 import java.util.Properties;
26 import java.util.ResourceBundle;
27
28 import org.apache.maven.plugins.annotations.Mojo;
29 import org.apache.maven.plugins.annotations.Parameter;
30 import org.apache.maven.plugins.pmd.exec.CpdExecutor;
31 import org.apache.maven.plugins.pmd.exec.CpdRequest;
32 import org.apache.maven.plugins.pmd.exec.CpdResult;
33 import org.apache.maven.reporting.MavenReportException;
34 import org.apache.maven.shared.utils.logging.MessageUtils;
35 import org.apache.maven.toolchain.Toolchain;
36
37 import net.sourceforge.pmd.cpd.JavaTokenizer;
38 import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
39
40
41
42
43
44
45
46
47
48
49
50
51 @Mojo( name = "cpd", threadSafe = true )
52 public class CpdReport
53 extends AbstractPmdReport
54 {
55
56
57
58
59
60
61 @Parameter( defaultValue = "java" )
62 private String language;
63
64
65
66
67 @Parameter( property = "minimumTokens", defaultValue = "100" )
68 private int minimumTokens;
69
70
71
72
73
74
75 @Parameter( property = "cpd.skip", defaultValue = "false" )
76 private boolean skip;
77
78
79
80
81
82
83
84
85 @Parameter( property = "cpd.ignoreLiterals", defaultValue = "false" )
86 private boolean ignoreLiterals;
87
88
89
90
91
92
93 @Parameter( property = "cpd.ignoreIdentifiers", defaultValue = "false" )
94 private boolean ignoreIdentifiers;
95
96
97
98
99
100
101 @Parameter( property = "cpd.ignoreAnnotations", defaultValue = "false" )
102 private boolean ignoreAnnotations;
103
104
105
106
107
108
109 private CpdResult cpdResult;
110
111
112
113
114 public String getName( Locale locale )
115 {
116 return getBundle( locale ).getString( "report.cpd.name" );
117 }
118
119
120
121
122 public String getDescription( Locale locale )
123 {
124 return getBundle( locale ).getString( "report.cpd.description" );
125 }
126
127
128
129
130 @Override
131 public void executeReport( Locale locale )
132 throws MavenReportException
133 {
134 ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
135 try
136 {
137 Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
138
139 generateMavenSiteReport( locale );
140 }
141 finally
142 {
143 Thread.currentThread().setContextClassLoader( origLoader );
144 }
145 }
146
147 @Override
148 public boolean canGenerateReport()
149 {
150 if ( skip )
151 {
152 getLog().info( "Skipping CPD execution" );
153 return false;
154 }
155
156 boolean result = super.canGenerateReport();
157 if ( result )
158 {
159 try
160 {
161 executeCpd();
162 if ( skipEmptyReport )
163 {
164 result = cpdResult.hasDuplications();
165 if ( !result )
166 {
167 getLog().debug( "Skipping report since skipEmptyReport is true and there are no CPD issues." );
168 }
169 }
170 }
171 catch ( MavenReportException e )
172 {
173 throw new RuntimeException( e );
174 }
175 }
176 return result;
177 }
178
179 private void executeCpd()
180 throws MavenReportException
181 {
182 if ( cpdResult != null )
183 {
184
185 getLog().debug( "CPD has already been run - skipping redundant execution." );
186 return;
187 }
188
189 Properties languageProperties = new Properties();
190 if ( ignoreLiterals )
191 {
192 languageProperties.setProperty( JavaTokenizer.IGNORE_LITERALS, "true" );
193 }
194 if ( ignoreIdentifiers )
195 {
196 languageProperties.setProperty( JavaTokenizer.IGNORE_IDENTIFIERS, "true" );
197 }
198 if ( ignoreAnnotations )
199 {
200 languageProperties.setProperty( JavaTokenizer.IGNORE_ANNOTATIONS, "true" );
201 }
202 try
203 {
204 filesToProcess = getFilesToProcess();
205
206 CpdRequest request = new CpdRequest();
207 request.setMinimumTokens( minimumTokens );
208 request.setLanguage( language );
209 request.setLanguageProperties( languageProperties );
210 request.setSourceEncoding( getInputEncoding() );
211 request.addFiles( filesToProcess.keySet() );
212
213 request.setShowPmdLog( showPmdLog );
214 request.setColorizedLog( MessageUtils.isColorEnabled() );
215 request.setLogLevel( determineCurrentRootLogLevel() );
216
217 request.setExcludeFromFailureFile( excludeFromFailureFile );
218 request.setTargetDirectory( targetDirectory.getAbsolutePath() );
219 request.setOutputEncoding( getOutputEncoding() );
220 request.setFormat( format );
221 request.setIncludeXmlInSite( includeXmlInSite );
222 request.setReportOutputDirectory( getReportOutputDirectory().getAbsolutePath() );
223
224 Toolchain tc = getToolchain();
225 if ( tc != null )
226 {
227 getLog().info( "Toolchain in maven-pmd-plugin: " + tc );
228 String javaExecutable = tc.findTool( "java" );
229 request.setJavaExecutable( javaExecutable );
230 }
231
232 getLog().info( "PMD version: " + AbstractPmdReport.getPmdVersion() );
233 cpdResult = CpdExecutor.execute( request );
234 }
235 catch ( UnsupportedEncodingException e )
236 {
237 throw new MavenReportException( "Encoding '" + getInputEncoding() + "' is not supported.", e );
238 }
239 catch ( IOException e )
240 {
241 throw new MavenReportException( e.getMessage(), e );
242 }
243 }
244
245 private void generateMavenSiteReport( Locale locale )
246 {
247 CpdReportGenerator gen = new CpdReportGenerator( getSink(), filesToProcess, getBundle( locale ),
248 isAggregator() );
249 gen.generate( cpdResult.getDuplications() );
250 }
251
252
253
254
255 public String getOutputName()
256 {
257 return "cpd";
258 }
259
260 private static ResourceBundle getBundle( Locale locale )
261 {
262 return ResourceBundle.getBundle( "cpd-report", locale, CpdReport.class.getClassLoader() );
263 }
264
265
266
267
268
269
270
271
272 @Deprecated
273 public CPDRenderer createRenderer() throws MavenReportException
274 {
275 return CpdExecutor.createRenderer( format, getOutputEncoding() );
276 }
277 }