1 package org.apache.maven.plugin.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.ByteArrayOutputStream;
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStreamWriter;
27 import java.io.UnsupportedEncodingException;
28 import java.io.Writer;
29 import java.util.Iterator;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Properties;
33 import java.util.ResourceBundle;
34
35 import net.sourceforge.pmd.cpd.CPD;
36 import net.sourceforge.pmd.cpd.CSVRenderer;
37 import net.sourceforge.pmd.cpd.JavaLanguage;
38 import net.sourceforge.pmd.cpd.JavaTokenizer;
39 import net.sourceforge.pmd.cpd.Renderer;
40 import net.sourceforge.pmd.cpd.XMLRenderer;
41
42 import org.apache.maven.reporting.MavenReportException;
43 import org.codehaus.plexus.util.FileUtils;
44 import org.codehaus.plexus.util.IOUtil;
45 import org.codehaus.plexus.util.WriterFactory;
46 import org.codehaus.plexus.util.StringUtils;
47
48
49
50
51
52
53
54
55
56
57
58
59 public class CpdReport
60 extends AbstractPmdReport
61 {
62
63
64
65
66
67 private int minimumTokens;
68
69
70
71
72
73
74
75
76 private boolean skip;
77
78
79
80
81
82
83
84
85
86 private boolean ignoreLiterals;
87
88
89
90
91
92
93
94 private boolean ignoreIdentifiers;
95
96
97 public String getName( Locale locale )
98 {
99 return getBundle( locale ).getString( "report.cpd.name" );
100 }
101
102
103 public String getDescription( Locale locale )
104 {
105 return getBundle( locale ).getString( "report.cpd.description" );
106 }
107
108
109 public void executeReport( Locale locale )
110 throws MavenReportException
111 {
112 try
113 {
114 execute( locale );
115 }
116 finally
117 {
118 if ( getSink() != null )
119 {
120 getSink().close();
121 }
122 }
123 }
124
125 private void execute( Locale locale )
126 throws MavenReportException
127 {
128 if ( !skip && canGenerateReport() )
129 {
130 ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
131 try
132 {
133 Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
134
135 CPD cpd = generateReport( locale );
136
137 if ( !isHtml() )
138 {
139 writeNonHtml( cpd );
140 }
141 }
142 finally
143 {
144 Thread.currentThread().setContextClassLoader( origLoader );
145 }
146
147 }
148 }
149
150 private CPD generateReport( Locale locale )
151 throws MavenReportException
152 {
153 Properties p = new Properties();
154 if ( ignoreLiterals )
155 {
156 p.setProperty( JavaTokenizer.IGNORE_LITERALS, "true" );
157 }
158 if ( ignoreIdentifiers )
159 {
160 p.setProperty( JavaTokenizer.IGNORE_IDENTIFIERS, "true" );
161 }
162 CPD cpd = new CPD( minimumTokens, new JavaLanguage( p ) );
163
164 Map files = null;
165 try
166 {
167 files = getFilesToProcess();
168
169 if ( StringUtils.isNotEmpty( getSourceEncoding() ) )
170 {
171 cpd.setEncoding( getSourceEncoding() );
172
173
174 WriterFactory.newWriter( new ByteArrayOutputStream(), getSourceEncoding() );
175 }
176 else if ( !files.isEmpty() )
177 {
178 getLog().warn(
179 "File encoding has not been set, using platform encoding "
180 + WriterFactory.FILE_ENCODING + ", i.e. build is platform dependent!" );
181 }
182
183 for ( Iterator it = files.keySet().iterator(); it.hasNext(); )
184 {
185 cpd.add( (File) it.next() );
186 }
187 }
188 catch ( UnsupportedEncodingException e )
189 {
190 throw new MavenReportException( "Encoding '" + getSourceEncoding() + "' is not supported.", e );
191 }
192 catch ( IOException e )
193 {
194 throw new MavenReportException( e.getMessage(), e );
195 }
196 cpd.go();
197
198 CpdReportGenerator gen =
199 new CpdReportGenerator( getSink(), files, getBundle( locale ), aggregate );
200 gen.generate( cpd.getMatches() );
201
202 return cpd;
203 }
204
205 void writeNonHtml( CPD cpd )
206 throws MavenReportException
207 {
208 Renderer r = createRenderer();
209
210 if ( r == null )
211 {
212 return;
213 }
214
215 String buffer = r.render( cpd.getMatches() );
216 Writer writer = null;
217 try
218 {
219 targetDirectory.mkdirs();
220 File targetFile = new File( targetDirectory, "cpd." + format );
221 FileOutputStream tStream = new FileOutputStream( targetFile );
222 writer = new OutputStreamWriter( tStream, getOutputEncoding() );
223 writer.write( buffer );
224 writer.close();
225
226 File siteDir = getReportOutputDirectory();
227 siteDir.mkdirs();
228 FileUtils.copyFile( targetFile, new File( siteDir, "cpd." + format ) );
229 }
230 catch ( IOException ioe )
231 {
232 throw new MavenReportException( ioe.getMessage(), ioe );
233 }
234 finally
235 {
236 IOUtil.close( writer );
237 }
238 }
239
240
241 public String getOutputName()
242 {
243 return "cpd";
244 }
245
246 private static ResourceBundle getBundle( Locale locale )
247 {
248 return ResourceBundle.getBundle( "cpd-report", locale, CpdReport.class.getClassLoader() );
249 }
250
251
252
253
254
255
256
257
258 public Renderer createRenderer()
259 throws MavenReportException
260 {
261 Renderer renderer = null;
262 if ( "xml".equals( format ) )
263 {
264 renderer = new XMLRenderer( getOutputEncoding() );
265 }
266 else if ( "csv".equals( format ) )
267 {
268 renderer = new CSVRenderer();
269 }
270 else if ( !"".equals( format ) && !"none".equals( format ) )
271 {
272 try
273 {
274 renderer = (Renderer) Class.forName( format ).newInstance();
275 }
276 catch ( Exception e )
277 {
278 throw new MavenReportException(
279 "Can't find CPD custom format " + format + ": " + e.getClass().getName(), e );
280 }
281 }
282
283 return renderer;
284 }
285 }