View Javadoc

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