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