View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd;
5   
6   import java.io.IOException;
7   import java.util.Arrays;
8   import java.util.List;
9   import java.util.Properties;
10  
11  import net.sourceforge.pmd.lang.Language;
12  import net.sourceforge.pmd.lang.LanguageVersion;
13  import net.sourceforge.pmd.lang.LanguageVersionDiscoverer;
14  import net.sourceforge.pmd.renderers.Renderer;
15  import net.sourceforge.pmd.renderers.RendererFactory;
16  import net.sourceforge.pmd.util.ClasspathClassLoader;
17  import net.sourceforge.pmd.util.IOUtil;
18  
19  /**
20   * This class contains the details for the runtime configuration of PMD.
21   * There are several aspects to the configuration of PMD.
22   * <p>
23   * The aspects related to generic PMD behavior:
24   * <ul>
25   * 	<li>Suppress marker is used in source files to suppress a RuleViolation,
26   *	    defaults to {@link PMD#SUPPRESS_MARKER}.
27   *          {@link #getSuppressMarker()}</li>
28   *  <li>The number of threads to create when invoking on multiple files,
29   *      defaults one thread per available processor.
30   *          {@link #getThreads()}</li>
31   *  <li>A ClassLoader to use when loading classes during Rule processing
32   *      (e.g. during type resolution), defaults to ClassLoader of the
33   *      Configuration class.
34   *          {@link #getClassLoader()}</li>
35   *  <li>A means to configure a ClassLoader using a prepended classpath
36   *     String, instead of directly setting it programmatically.
37   *          {@link #prependClasspath(String)}</li>
38   *  <li>A LanguageVersionDiscoverer instance, which defaults to using the
39   *      default LanguageVersion of each Language.  Means are provided to
40   *      change the LanguageVersion for each Language.
41   *          {@link #getLanguageVersionDiscoverer()}</li>
42   * </ul>
43   * <p>
44   * The aspects related to Rules and Source files are:
45   * <ul>
46   *  <li>A comma separated list of RuleSets URIs.
47   *          {@link #getRuleSets()}</li>
48   *  <li>A minimum priority threshold when loading Rules from RuleSets,
49   *      defaults to {@link RulePriority#LOW}.
50   *          {@link #getMinimumPriority()}</li>
51   *  <li>The character encoding of source files, defaults to the system default
52   *      as returned by <code>System.getProperty("file.encoding")</code>.
53   *          {@link #getSourceEncoding()}</li>
54   *  <li>A comma separated list of input paths to process for source files.
55   *      This may include files, directories, archives (e.g. ZIP files), etc.
56   *          {@link #getInputPaths()}</li>
57   * </ul>
58   * <p>
59   * <ul>
60   *  <li>The renderer format to use for Reports.
61   *          {@link #getReportFormat()}</li>
62   *  <li>The file to which the Report should render.
63   *          {@link #getReportFile()}</li>
64   *  <li>An indicator of whether to use File short names in Reports, defaults
65   *      to <code>false</code>.
66   *          {@link #isReportShortNames()}</li>
67   *  <li>The initialization properties to use when creating a Renderer instance.
68   *          {@link #getReportProperties()}</li>
69   *  <li>An indicator of whether to show suppressed Rule violations in Reports.
70   *          {@link #isShowSuppressedViolations()}</li>
71   * </ul>
72   * <p>
73   * The aspects related to special PMD behavior are:
74   * <ul>
75   *  <li>An indicator of whether PMD should log debug information.
76   *          {@link #isDebug()}</li>
77   *  <li>An indicator of whether PMD should perform stress testing behaviors,
78   *          such as randomizing the order of file processing.
79   *          {@link #isStressTest()}</li>
80   *  <li>An indicator of whether PMD should log benchmarking information.
81   *          {@link #isBenchmark()}</li>
82   * </ul>
83   */
84  public class PMDConfiguration extends AbstractConfiguration {
85  
86      // General behavior options
87      private String suppressMarker = PMD.SUPPRESS_MARKER;
88      private int threads = Runtime.getRuntime().availableProcessors();
89      private ClassLoader classLoader = getClass().getClassLoader();
90      private LanguageVersionDiscoverer languageVersionDiscoverer = new LanguageVersionDiscoverer();
91  
92      // Rule and source file options
93      private String ruleSets;
94      private RulePriority minimumPriority = RulePriority.LOW;
95      private String inputPaths;
96      private String inputUri;
97  
98      // Reporting options
99      private String reportFormat;
100     private String reportFile;
101     private boolean reportShortNames = false;
102     private Properties reportProperties = new Properties();
103     private boolean showSuppressedViolations = false;
104 
105     private boolean stressTest;
106     private boolean benchmark;
107 
108     /**
109      * Get the suppress marker. This the source level marker used to indicate a
110      * RuleViolation should be suppressed.
111      * 
112      * @return The suppress marker.
113      */
114     public String getSuppressMarker() {
115         return suppressMarker;
116     }
117 
118     /**
119      * Set the suppress marker.
120      * 
121      * @param suppressMarker
122      *            The suppress marker to use.
123      */
124     public void setSuppressMarker(String suppressMarker) {
125         this.suppressMarker = suppressMarker;
126     }
127 
128     /**
129      * Get the number of threads to use when processing Rules.
130      * 
131      * @return The number of threads.
132      */
133     public int getThreads() {
134         return threads;
135     }
136 
137     /**
138      * Set the number of threads to use when processing Rules.
139      * 
140      * @param threads
141      *            The number of threads.
142      */
143     public void setThreads(int threads) {
144         this.threads = threads;
145     }
146 
147     /**
148      * Get the ClassLoader being used by PMD when processing Rules.
149      * 
150      * @return The ClassLoader being used
151      */
152     public ClassLoader getClassLoader() {
153         return classLoader;
154     }
155 
156     /**
157      * Set the ClassLoader being used by PMD when processing Rules. Setting a
158      * value of <code>null</code> will cause the default ClassLoader to be used.
159      * 
160      * @param classLoader
161      *            The ClassLoader to use
162      */
163     public void setClassLoader(ClassLoader classLoader) {
164         if (classLoader == null) {
165             this.classLoader = getClass().getClassLoader();
166         } else {
167             this.classLoader = classLoader;
168         }
169     }
170 
171     /**
172      * Prepend the specified classpath like string to the current ClassLoader of
173      * the configuration. If no ClassLoader is currently configured, the
174      * ClassLoader used to load the {@link PMDConfiguration} class will be used
175      * as the parent ClassLoader of the created ClassLoader.
176      * <p>
177      * If the classpath String looks like a URL to a file (i.e. starts with
178      * <code>file://</code>) the file will be read with each line representing
179      * an entry on the classpath.
180      * 
181      * @param classpath The prepended classpath.
182      * @throws IOException if the given classpath is invalid (e.g. does not exist)
183      * @see PMDConfiguration#setClassLoader(ClassLoader)
184      * @see ClasspathClassLoader
185      */
186     public void prependClasspath(String classpath) throws IOException {
187         if (classLoader == null) {
188             classLoader = PMDConfiguration.class.getClassLoader();
189         }
190         if (classpath != null) {
191             classLoader = new ClasspathClassLoader(classpath, classLoader);
192         }
193     }
194 
195     /**
196      * Get the LanguageVersionDiscoverer, used to determine the LanguageVersion
197      * of a source file.
198      * 
199      * @return The LanguageVersionDiscoverer.
200      */
201     public LanguageVersionDiscoverer getLanguageVersionDiscoverer() {
202         return languageVersionDiscoverer;
203     }
204 
205     /**
206      * Set the given LanguageVersion as the current default for it's Language.
207      * 
208      * @param languageVersion
209      *            the LanguageVersion
210      */
211     public void setDefaultLanguageVersion(LanguageVersion languageVersion) {
212         setDefaultLanguageVersions(Arrays.asList(languageVersion));
213     }
214 
215     /**
216      * Set the given LanguageVersions as the current default for their
217      * Languages.
218      * 
219      * @param languageVersions
220      *            The LanguageVersions.
221      */
222     public void setDefaultLanguageVersions(List<LanguageVersion> languageVersions) {
223         for (LanguageVersion languageVersion : languageVersions) {
224             languageVersionDiscoverer.setDefaultLanguageVersion(languageVersion);
225         }
226     }
227 
228     /**
229      * Get the LanguageVersion of the source file with given name. This depends
230      * on the fileName extension, and the java version.
231      * <p/>
232      * For compatibility with older code that does not always pass in a correct
233      * filename, unrecognized files are assumed to be java files.
234      * 
235      * @param fileName
236      *            Name of the file, can be absolute, or simple.
237      * @return the LanguageVersion
238      */
239     // FUTURE Delete this? I can't think of a good reason to keep it around.
240     // Failure to determine the LanguageVersion for a file should be a hard
241     // error, or simply cause the file to be skipped?
242     public LanguageVersion getLanguageVersionOfFile(String fileName) {
243         LanguageVersion languageVersion = languageVersionDiscoverer.getDefaultLanguageVersionForFile(fileName);
244         if (languageVersion == null) {
245             // For compatibility with older code that does not always pass in
246             // a correct filename.
247             languageVersion = languageVersionDiscoverer.getDefaultLanguageVersion(Language.JAVA);
248         }
249         return languageVersion;
250     }
251 
252     /**
253      * Get the comma separated list of RuleSet URIs.
254      * 
255      * @return The RuleSet URIs.
256      */
257     public String getRuleSets() {
258         return ruleSets;
259     }
260 
261     /**
262      * Set the comma separated list of RuleSet URIs.
263      * 
264      * @param ruleSets the rulesets to set
265      */
266     public void setRuleSets(String ruleSets) {
267         this.ruleSets = ruleSets;
268     }
269 
270     /**
271      * Get the minimum priority threshold when loading Rules from RuleSets.
272      * 
273      * @return The minimum priority threshold.
274      */
275     public RulePriority getMinimumPriority() {
276         return minimumPriority;
277     }
278 
279     /**
280      * Set the minimum priority threshold when loading Rules from RuleSets.
281      * 
282      * @param minimumPriority
283      *            The minimum priority.
284      */
285     public void setMinimumPriority(RulePriority minimumPriority) {
286         this.minimumPriority = minimumPriority;
287     }
288 
289     /**
290      * Get the comma separated list of input paths to process for source files.
291      * 
292      * @return A comma separated list.
293      */
294     public String getInputPaths() {
295         return inputPaths;
296     }
297 
298     /**
299      * Set the comma separated list of input paths to process for source files.
300      * 
301      * @param inputPaths
302      *            The comma separated list.
303      */
304     public void setInputPaths(String inputPaths) {
305         this.inputPaths = inputPaths;
306     }
307 
308     /**
309      * Get the input URI to process for source code objects.
310      * 
311      * @return URI
312      */
313     public String getInputUri() {
314         return inputUri;
315     }
316 
317     /**
318      * Set the input URI to process for source code objects.
319      * 
320      * @param inputUri
321      *            a single URI
322      */
323     public void setInputUri(String inputUri) {
324         this.inputUri = inputUri;
325     }
326 
327     /**
328      * Get whether to use File short names in Reports.
329      * 
330      * @return <code>true</code> when using short names in reports.
331      */
332     public boolean isReportShortNames() {
333         return reportShortNames;
334     }
335 
336     /**
337      * Set whether to use File short names in Reports.
338      * 
339      * @param reportShortNames
340      *            <code>true</code> when using short names in reports.
341      */
342     public void setReportShortNames(boolean reportShortNames) {
343         this.reportShortNames = reportShortNames;
344     }
345 
346     /**
347      * Create a Renderer instance based upon the configured reporting options.
348      * No writer is created.
349      * 
350      * @return renderer
351      */
352     public Renderer createRenderer() {
353         return createRenderer(false);
354     }
355 
356     /**
357      * Create a Renderer instance based upon the configured reporting options.
358      * If withReportWriter then we'll configure it with a writer for the
359      * reportFile specified.
360      * 
361      * @param withReportWriter whether to configure a writer or not
362      * @return A Renderer instance.
363      */
364     public Renderer createRenderer(boolean withReportWriter) {
365         Renderer renderer = RendererFactory.createRenderer(reportFormat, reportProperties);
366         renderer.setShowSuppressedViolations(showSuppressedViolations);
367         if (withReportWriter)
368             renderer.setWriter(IOUtil.createWriter(reportFile));
369         return renderer;
370     }
371 
372     /**
373      * Get the report format.
374      * 
375      * @return The report format.
376      */
377     public String getReportFormat() {
378         return reportFormat;
379     }
380 
381     /**
382      * Set the report format. This should be a name of a Renderer.
383      * 
384      * @param reportFormat
385      *            The report format.
386      * 
387      * @see Renderer
388      */
389     public void setReportFormat(String reportFormat) {
390         this.reportFormat = reportFormat;
391     }
392 
393     /**
394      * Get the file to which the report should render.
395      * 
396      * @return The file to which to render.
397      */
398     public String getReportFile() {
399         return reportFile;
400     }
401 
402     /**
403      * Set the file to which the report should render.
404      * 
405      * @param reportFile the file to set
406      */
407     public void setReportFile(String reportFile) {
408         this.reportFile = reportFile;
409     }
410 
411     /**
412      * Get whether the report should show suppressed violations.
413      * 
414      * @return <code>true</code> if showing suppressed violations,
415      *         <code>false</code> otherwise.
416      */
417     public boolean isShowSuppressedViolations() {
418         return showSuppressedViolations;
419     }
420 
421     /**
422      * Set whether the report should show suppressed violations.
423      * 
424      * @param showSuppressedViolations
425      *            <code>true</code> if showing suppressed violations,
426      *            <code>false</code> otherwise.
427      */
428     public void setShowSuppressedViolations(boolean showSuppressedViolations) {
429         this.showSuppressedViolations = showSuppressedViolations;
430     }
431 
432     /**
433      * Get the Report properties. These are used to create the Renderer.
434      * 
435      * @return The report properties.
436      */
437     public Properties getReportProperties() {
438         return reportProperties;
439     }
440 
441     /**
442      * Set the Report properties. These are used to create the Renderer.
443      * 
444      * @param reportProperties
445      *            The Report properties to set.
446      */
447     public void setReportProperties(Properties reportProperties) {
448         this.reportProperties = reportProperties;
449     }
450 
451     /**
452      * Return the stress test indicator. If this value is <code>true</code> then
453      * PMD will randomize the order of file processing to attempt to shake out
454      * bugs.
455      * 
456      * @return <code>true</code> if stress test is enbaled, <code>false</code>
457      *         otherwise.
458      */
459     public boolean isStressTest() {
460         return stressTest;
461     }
462 
463     /**
464      * Set the stress test indicator.
465      * 
466      * @param stressTest
467      *            The stree test indicator to set.
468      * @see #isStressTest()
469      */
470     public void setStressTest(boolean stressTest) {
471         this.stressTest = stressTest;
472     }
473 
474     /**
475      * Return the benchmark indicator. If this value is <code>true</code> then
476      * PMD will log benchmark information.
477      * 
478      * @return <code>true</code> if benchmark logging is enbaled,
479      *         <code>false</code> otherwise.
480      */
481     public boolean isBenchmark() {
482         return benchmark;
483     }
484 
485     /**
486      * Set the benchmark indicator.
487      * 
488      * @param benchmark
489      *            The benchmark indicator to set.
490      * @see #isBenchmark()
491      */
492     public void setBenchmark(boolean benchmark) {
493         this.benchmark = benchmark;
494     }
495 }