001 package net.sourceforge.pmd;
002
003 import java.io.IOException;
004 import java.util.Arrays;
005 import java.util.List;
006 import java.util.Properties;
007
008 import net.sourceforge.pmd.lang.Language;
009 import net.sourceforge.pmd.lang.LanguageVersion;
010 import net.sourceforge.pmd.lang.LanguageVersionDiscoverer;
011 import net.sourceforge.pmd.renderers.Renderer;
012 import net.sourceforge.pmd.renderers.RendererFactory;
013 import net.sourceforge.pmd.util.ClasspathClassLoader;
014
015 /**
016 * This class contains the details for the runtime configuration of PMD.
017 * There are several aspects to the configuration of PMD.
018 * <p>
019 * The aspects related to generic PMD behavior:
020 * <ul>
021 * <li>Suppress marker is used in source files to suppress a RuleViolation,
022 * defaults to {@link PMD#SUPPRESS_MARKER}.
023 * {@link #getSuppressMarker()}</li>
024 * <li>The number of threads to create when invoking on multiple files,
025 * defaults one thread per available processor.
026 * {@link #getThreads()}</li>
027 * <li>A ClassLoader to use when loading classes during Rule processing
028 * (e.g. during type resolution), defaults to ClassLoader of the
029 * Configuration class.
030 * {@link #getClassLoader()}</li>
031 * <li>A means to configure a ClassLoader using a prepended classpath
032 * String, instead of directly setting it programmatically.
033 * {@link #prependClasspath(String)}</li>
034 * <li>A LanguageVersionDiscoverer instance, which defaults to using the
035 * default LanguageVersion of each Language. Means are provided to
036 * change the LanguageVersion for each Language.
037 * {@link #getLanguageVersionDiscoverer()}</li>
038 * </ul>
039 * <p>
040 * The aspects related to Rules and Source files are:
041 * <ul>
042 * <li>A comma separated list of RuleSets URIs.
043 * {@link #getRuleSets()}</li>
044 * <li>A minimum priority threshold when loading Rules from RuleSets,
045 * defaults to {@link RulePriority#LOW}.
046 * {@link #getMinimumPriority()}</li>
047 * <li>The character encoding of source files, defaults to the system default
048 * as returned by <code>System.getProperty("file.encoding")</code>.
049 * {@link #getSourceEncoding()}</li>
050 * <li>A comma separated list of input paths to process for source files.
051 * This may include files, directories, archives (e.g. ZIP files), etc.
052 * {@link #getInputPaths()}</li>
053 * </ul>
054 * <p>
055 * <ul>
056 * <li>The renderer format to use for Reports.
057 * {@link #getReportFormat()}</li>
058 * <li>The file to which the Report should render.
059 * {@link #getReportFile()}</li>
060 * <li>An indicator of whether to use File short names in Reports, defaults
061 * to <code>false</code>.
062 * {@link #isReportShortNames()}</li>
063 * <li>The initialization properties to use when creating a Renderer instance.
064 * {@link #getReportProperties()}</li>
065 * <li>An indicator of whether to show suppressed Rule violations in Reports.
066 * {@link #isShowSuppressedViolations()}</li>
067 * </ul>
068 * <p>
069 * The aspects related to special PMD behavior are:
070 * <ul>
071 * <li>An indicator of whether PMD should log debug information.
072 * {@link #isDebug()}</li>
073 * <li>An indicator of whether PMD should perform stress testing behaviors,
074 * such as randomizing the order of file processing.
075 * {@link #isStressTest()}</li>
076 * <li>An indicator of whether PMD should log benchmarking information.
077 * {@link #isBenchmark()}</li>
078 * </ul>
079 */
080 public class Configuration {
081
082 // General behavior options
083 private String suppressMarker = PMD.SUPPRESS_MARKER;
084 private int threads = Runtime.getRuntime().availableProcessors();
085 private ClassLoader classLoader = getClass().getClassLoader();
086 private LanguageVersionDiscoverer languageVersionDiscoverer = new LanguageVersionDiscoverer();
087
088 // Rule and source file options
089 private String ruleSets;
090 private RulePriority minimumPriority = RulePriority.LOW;
091 private String sourceEncoding = System.getProperty("file.encoding");
092 private String inputPaths;
093
094 // Reporting options
095 private String reportFormat;
096 private String reportFile;
097 private boolean reportShortNames = false;
098 private Properties reportProperties = new Properties();
099 private boolean showSuppressedViolations = false;
100
101 // Special behavior options
102 private boolean debug;
103 private boolean stressTest;
104 private boolean benchmark;
105
106 /**
107 * Get the suppress marker. This the source level marker used to indicate
108 * a RuleViolation should be suppressed.
109 * @return The suppress marker.
110 */
111 public String getSuppressMarker() {
112 return suppressMarker;
113 }
114
115 /**
116 * Set the suppress marker.
117 * @param suppressMarker The suppress marker to use.
118 */
119 public void setSuppressMarker(String suppressMarker) {
120 this.suppressMarker = suppressMarker;
121 }
122
123 /**
124 * Get the number of threads to use when processing Rules.
125 * @return The number of threads.
126 */
127 public int getThreads() {
128 return threads;
129 }
130
131 /**
132 * Set the number of threads to use when processing Rules.
133 * @param threads The number of threads.
134 */
135 public void setThreads(int threads) {
136 this.threads = threads;
137 }
138
139 /**
140 * Get the ClassLoader being used by PMD when processing Rules.
141 * @return The ClassLoader being used
142 */
143 public ClassLoader getClassLoader() {
144 return classLoader;
145 }
146
147 /**
148 * Set the ClassLoader being used by PMD when processing Rules.
149 * Setting a value of <code>null</code> will cause the default
150 * ClassLoader to be used.
151 * @param classLoader The ClassLoader to use
152 */
153 public void setClassLoader(ClassLoader classLoader) {
154 if (classLoader == null) {
155 classLoader = getClass().getClassLoader();
156 }
157 this.classLoader = classLoader;
158 }
159
160 /**
161 * Prepend the specified classpath like string to the current ClassLoader
162 * of the configuration. If no ClassLoader is currently configured, the
163 * ClassLoader used to load the {@link Configuration} class will be used as
164 * the parent ClassLoader of the created ClassLoader.
165 * <p>
166 * If the classpath String looks like a URL to a file (i.e. starts with
167 * <code>file://</code>) the file will be read with each line representing
168 * an entry on the classpath.
169 *
170 * @param classpath The prepended classpath.
171 * @see Configuration#setClassLoader(ClassLoader)
172 * @see ClasspathClassLoader
173 */
174 public void prependClasspath(String classpath) throws IOException {
175 if (classLoader == null) {
176 classLoader = Configuration.class.getClassLoader();
177 }
178 if (classpath != null) {
179 classLoader = new ClasspathClassLoader(classpath, classLoader);
180 }
181 }
182
183 /**
184 * Get the LanguageVersionDiscoverer, used to determine the LanguageVersion
185 * of a source file.
186 * @return The LanguageVersionDiscoverer.
187 */
188 public LanguageVersionDiscoverer getLanguageVersionDiscoverer() {
189 return languageVersionDiscoverer;
190 }
191
192 /**
193 * Set the given LanguageVersion as the current default for it's Language.
194 *
195 * @param languageVersion the LanguageVersion
196 */
197 public void setDefaultLanguageVersion(LanguageVersion languageVersion) {
198 setDefaultLanguageVersions(Arrays.asList(languageVersion));
199 }
200
201 /**
202 * Set the given LanguageVersions as the current default for their Languages.
203 *
204 * @param languageVersions The LanguageVersions.
205 */
206 public void setDefaultLanguageVersions(List<LanguageVersion> languageVersions) {
207 for (LanguageVersion languageVersion : languageVersions) {
208 languageVersionDiscoverer.setDefaultLanguageVersion(languageVersion);
209 }
210 }
211
212 /**
213 * Get the LanguageVersion of the source file with given name. This depends on the fileName
214 * extension, and the java version.
215 * <p/>
216 * For compatibility with older code that does not always pass in a correct filename,
217 * unrecognized files are assumed to be java files.
218 *
219 * @param fileName Name of the file, can be absolute, or simple.
220 * @return the LanguageVersion
221 */
222 // FUTURE Delete this? I can't think of a good reason to keep it around. Failure to determine the LanguageVersion for a file should be a hard error, or simply cause the file to be skipped?
223 public LanguageVersion getLanguageVersionOfFile(String fileName) {
224 LanguageVersion languageVersion = languageVersionDiscoverer.getDefaultLanguageVersionForFile(fileName);
225 if (languageVersion == null) {
226 // For compatibility with older code that does not always pass in
227 // a correct filename.
228 languageVersion = languageVersionDiscoverer.getDefaultLanguageVersion(Language.JAVA);
229 }
230 return languageVersion;
231 }
232
233 /**
234 * Get the comma separated list of RuleSets URIs.
235 * @return The RuleSet URIs.
236 */
237 public String getRuleSets() {
238 return ruleSets;
239 }
240
241 /**
242 * Set the command separated list of RuleSet URIs.
243 * @param ruleSets
244 */
245 public void setRuleSets(String ruleSets) {
246 this.ruleSets = ruleSets;
247 }
248
249 /**
250 * Get the minimum priority threshold when loading Rules from RuleSets.
251 * @return The minimum priority threshold.
252 */
253 public RulePriority getMinimumPriority() {
254 return minimumPriority;
255 }
256
257 /**
258 * Set the minimum priority threshold when loading Rules from RuleSets.
259 * @param minimumPriority The minimum priority.
260 */
261 public void setMinimumPriority(RulePriority minimumPriority) {
262 this.minimumPriority = minimumPriority;
263 }
264
265 /**
266 * Get the character encoding of source files.
267 * @return The character encoding.
268 */
269 public String getSourceEncoding() {
270 return sourceEncoding;
271 }
272
273 /**
274 * Set the character encoding of source files.
275 * @param sourceEncoding The character encoding.
276 */
277 public void setSourceEncoding(String sourceEncoding) {
278 this.sourceEncoding = sourceEncoding;
279 }
280
281 /**
282 * Get the comma separated list of input paths to process for source files.
283 * @return A comma separated list.
284 */
285 public String getInputPaths() {
286 return inputPaths;
287 }
288
289 /**
290 * Set the comma separated list of input paths to process for source files.
291 * @param inputPaths The comma separated list.
292 */
293 public void setInputPaths(String inputPaths) {
294 this.inputPaths = inputPaths;
295 }
296
297 /**
298 * Get whether to use File short names in Reports.
299 * @return <code>true</code> when using short names in reports.
300 */
301 public boolean isReportShortNames() {
302 return reportShortNames;
303 }
304
305 /**
306 * Set whether to use File short names in Reports.
307 * @param reportShortNames <code>true</code> when using short names in reports.
308 */
309 public void setReportShortNames(boolean reportShortNames) {
310 this.reportShortNames = reportShortNames;
311 }
312
313 /**
314 * Create a Renderer instance based upon the configured reporting options.
315 * @return A Renderer instance.
316 */
317 public Renderer createRenderer() {
318 Renderer renderer = RendererFactory.createRenderer(reportFormat, this.reportProperties);
319 renderer.setShowSuppressedViolations(this.showSuppressedViolations);
320 return renderer;
321 }
322
323 /**
324 * Get the report format.
325 * @return The report format.
326 */
327 public String getReportFormat() {
328 return reportFormat;
329 }
330
331 /**
332 * Set the report format. This should be a name of a Renderer.
333 * @param reportFormat The report format.
334 *
335 * @see Renderer
336 */
337 public void setReportFormat(String reportFormat) {
338 this.reportFormat = reportFormat;
339 }
340
341 /**
342 * Get the file to which the report should render.
343 * @return The file to which to render.
344 */
345 public String getReportFile() {
346 return reportFile;
347 }
348
349 /**
350 * Set the file to which the report should render.
351 * @param reportFile
352 */
353 public void setReportFile(String reportFile) {
354 this.reportFile = reportFile;
355 }
356
357 /**
358 * Get whether the report should show suppressed violations.
359 * @return <code>true</code> if showing suppressed violations,
360 * <code>false</code> otherwise.
361 */
362 public boolean isShowSuppressedViolations() {
363 return showSuppressedViolations;
364 }
365
366 /**
367 * Set whether the report should show suppressed violations.
368 * @param showSuppressedViolations <code>true</code> if showing suppressed
369 * violations, <code>false</code> otherwise.
370 */
371 public void setShowSuppressedViolations(boolean showSuppressedViolations) {
372 this.showSuppressedViolations = showSuppressedViolations;
373 }
374
375 /**
376 * Get the Report properties. These are used to create the Renderer.
377 * @return The report properties.
378 */
379 public Properties getReportProperties() {
380 return reportProperties;
381 }
382
383 /**
384 * Set the Report properties. These are used to create the Renderer.
385 * @param reportProperties The Report properties to set.
386 */
387 public void setReportProperties(Properties reportProperties) {
388 this.reportProperties = reportProperties;
389 }
390
391 /**
392 * Return the debug indicator. If this value is <code>true</code>
393 * then PMD will log debug information.
394 * @return <code>true</code> if debug logging is enbaled, <code>false</code> otherwise.
395 */
396 public boolean isDebug() {
397 return debug;
398 }
399
400 /**
401 * Set the debug indicator.
402 * @param debug The debug indicator to set.
403 * @see #isDebug()
404 */
405 public void setDebug(boolean debug) {
406 this.debug = debug;
407 }
408
409 /**
410 * Return the stress test indicator. If this value is <code>true</code>
411 * then PMD will randomize the order of file processing to attempt to
412 * shake out bugs.
413 * @return <code>true</code> if stress test is enbaled, <code>false</code> otherwise.
414 */
415 public boolean isStressTest() {
416 return stressTest;
417 }
418
419 /**
420 * Set the stress test indicator.
421 * @param stressTest The stree test indicator to set.
422 * @see #isStressTest()
423 */
424 public void setStressTest(boolean stressTest) {
425 this.stressTest = stressTest;
426 }
427
428 /**
429 * Return the benchmark indicator. If this value is <code>true</code>
430 * then PMD will log benchmark information.
431 * @return <code>true</code> if benchmark logging is enbaled, <code>false</code> otherwise.
432 */
433 public boolean isBenchmark() {
434 return benchmark;
435 }
436
437 /**
438 * Set the benchmark indicator.
439 * @param benchmark The benchmark indicator to set.
440 * @see #isBenchmark()
441 */
442 public void setBenchmark(boolean benchmark) {
443 this.benchmark = benchmark;
444 }
445 }
|