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