Configuration.java
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 classpaththrows 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 }