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