View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cli;
5   
6   import java.io.IOException;
7   import java.util.ArrayList;
8   import java.util.List;
9   import java.util.Properties;
10  
11  import net.sourceforge.pmd.PMDConfiguration;
12  import net.sourceforge.pmd.RulePriority;
13  import net.sourceforge.pmd.lang.LanguageRegistry;
14  import net.sourceforge.pmd.lang.LanguageVersion;
15  
16  import com.beust.jcommander.IStringConverter;
17  import com.beust.jcommander.Parameter;
18  import com.beust.jcommander.ParameterException;
19  import com.beust.jcommander.validators.PositiveInteger;
20  
21  public class PMDParameters {
22  
23      @Parameter(names = { "-rulesets", "-R" }, description = "Comma separated list of ruleset names to use.", required = true)
24      private String rulesets;
25  
26      @Parameter(names = { "-uri", "-u" }, description = "Database URI for sources.", required = false)
27      private String uri;
28  
29      @Parameter(names = { "-dir", "-d" }, description = "Root directory for sources.", required = false)
30      private String sourceDir;
31  
32      @Parameter(names = { "-format", "-f" }, description = "Report format type.")
33      private String format = "text"; // Enhance to support other usage
34  
35      @Parameter(names = { "-debug", "-verbose", "-D", "-V" }, description = "Debug mode.")
36      private boolean debug = false;
37  
38      @Parameter(names = { "-help", "-h", "-H" }, description = "Display help on usage.", help = true)
39      private boolean help = false;
40  
41      @Parameter(names = { "-encoding", "-e" }, description = "Specifies the character set encoding of the source code files PMD is reading (i.e., UTF-8).")
42      private String encoding = "UTF-8";
43  
44      @Parameter(names = { "-threads", "-t" }, description = "Sets the number of threads used by PMD.", validateWith = PositiveInteger.class)
45      private Integer threads = 1;
46  
47      @Parameter(names = { "-benchmark", "-b" }, description = "Benchmark mode - output a benchmark report upon completion; default to System.err.")
48      private boolean benchmark = false;
49  
50      @Parameter(names = { "-stress", "-S" }, description = "Performs a stress test.")
51      private boolean stress = false;
52  
53      @Parameter(names = "-shortnames", description = "Prints shortened filenames in the report.")
54      private boolean shortnames = false;
55  
56      @Parameter(names = "-showsuppressed", description = "Report should show suppressed rule violations.")
57      private boolean showsuppressed = false;
58  
59      @Parameter(names = "-suppressmarker", description = "Specifies the string that marks the a line which PMD should ignore; default is NOPMD.")
60      private String suppressmarker = "NOPMD";
61  
62      @Parameter(names = { "-minimumpriority", "-min" }, description = "Rule priority threshold; rules with lower priority than configured here won't be used. Default is '5' which is the lowest priority.", converter = RulePriorityConverter.class)
63      private RulePriority minimumPriority = RulePriority.LOW;
64  
65      @Parameter(names = { "-property", "-P" }, description = "{name}={value}: Define a property for the report format.",
66              converter = PropertyConverter.class)
67      private List<Properties> properties = new ArrayList<Properties>();
68  
69      @Parameter(names = { "-reportfile", "-r" }, description = "Sends report output to a file; default to System.out.")
70      private String reportfile = null;
71  
72      @Parameter(names = { "-version", "-v" }, description = "Specify version of a language PMD should use.")
73      private String version = null;
74  
75      @Parameter(names = { "-language", "-l" }, description = "Specify a language PMD should use.")
76      private String language = null;
77  
78      @Parameter(names = "-auxclasspath", description = "Specifies the classpath for libraries used by the source code. This is used by the type resolution. Alternatively, a 'file://' URL to a text file containing path elements on consecutive lines can be specified.")
79      private String auxclasspath;
80  
81      // this has to be a public static class, so that JCommander can use it!
82      public static class PropertyConverter implements IStringConverter<Properties> {
83  
84          private static final char SEPARATOR = '=';
85  
86          public Properties convert(String value) {
87              int indexOfSeparator = value.indexOf(SEPARATOR);
88              if (indexOfSeparator < 0) {
89                  throw new ParameterException(
90                          "Property name must be separated with an = sign from it value: name=value.");
91              }
92              String propertyName = value.substring(0, indexOfSeparator);
93              String propertyValue = value.substring(indexOfSeparator + 1);
94              Properties properties = new Properties();
95              properties.put(propertyName, propertyValue);
96              return properties;
97          }
98      }
99  
100     // this has to be a public static class, so that JCommander can use it!
101     public static class RulePriorityConverter implements IStringConverter<RulePriority> {
102 
103         public int validate(String value) throws ParameterException {
104             int minPriorityValue = Integer.parseInt(value);
105             if (minPriorityValue < 1 || minPriorityValue > 5) {
106                 throw new ParameterException("Priority values can only be integer value, between 1 and 5," + value
107                         + " is not valid");
108             }
109             return minPriorityValue;
110         }
111 
112         public RulePriority convert(String value) {
113             return RulePriority.valueOf(validate(value));
114         }
115     }
116 
117     public static PMDConfiguration transformParametersIntoConfiguration(PMDParameters params) {
118         if (null == params.getSourceDir() && null == params.getUri()) {
119             throw new IllegalArgumentException(
120                     "Please provide either source root directory (-dir or -d) or database URI (-uri or -u) parameter");
121         }
122         PMDConfiguration configuration = new PMDConfiguration();
123         configuration.setInputPaths(params.getSourceDir());
124         configuration.setInputUri(params.getUri());
125         configuration.setReportFormat(params.getFormat());
126         configuration.setBenchmark(params.isBenchmark());
127         configuration.setDebug(params.isDebug());
128         configuration.setMinimumPriority(params.getMinimumPriority());
129         configuration.setReportFile(params.getReportfile());
130         configuration.setReportProperties(params.getProperties());
131         configuration.setReportShortNames(params.isShortnames());
132         configuration.setRuleSets(params.getRulesets());
133         configuration.setShowSuppressedViolations(params.isShowsuppressed());
134         configuration.setSourceEncoding(params.getEncoding());
135         configuration.setStressTest(params.isStress());
136         configuration.setSuppressMarker(params.getSuppressmarker());
137         configuration.setThreads(params.getThreads());
138 
139         LanguageVersion languageVersion = LanguageRegistry.findLanguageVersionByTerseName(params.getLanguage() + " " + params.getVersion());
140         if(languageVersion != null) {
141             configuration.getLanguageVersionDiscoverer().setDefaultLanguageVersion(languageVersion);
142         }
143         try {
144             configuration.prependClasspath(params.getAuxclasspath());
145         } catch (IOException e) {
146             throw new IllegalArgumentException("Invalid auxiliary classpath: " + e.getMessage(), e);
147         }
148         return configuration;
149     }
150 
151     public boolean isDebug() {
152         return debug;
153     }
154 
155     public boolean isHelp() {
156         return help;
157     }
158 
159     public String getEncoding() {
160         return encoding;
161     }
162 
163     public Integer getThreads() {
164         return threads;
165     }
166 
167     public boolean isBenchmark() {
168         return benchmark;
169     }
170 
171     public boolean isStress() {
172         return stress;
173     }
174 
175     public boolean isShortnames() {
176         return shortnames;
177     }
178 
179     public boolean isShowsuppressed() {
180         return showsuppressed;
181     }
182 
183     public String getSuppressmarker() {
184         return suppressmarker;
185     }
186 
187     public RulePriority getMinimumPriority() {
188         return minimumPriority;
189     }
190 
191     public Properties getProperties() {
192         Properties result = new Properties();
193         for (Properties p : properties) {
194             result.putAll(p);
195         }
196         return result;
197     }
198 
199     public String getReportfile() {
200         return reportfile;
201     }
202 
203     public String getVersion() {
204         return version != null ? version : LanguageRegistry.getDefaultLanguage().getDefaultVersion().getVersion();
205     }
206 
207     public String getLanguage() {
208         return language != null ? language : LanguageRegistry.getDefaultLanguage().getTerseName();
209     }
210 
211     public String getAuxclasspath() {
212         return auxclasspath;
213     }
214 
215     public String getRulesets() {
216         return rulesets;
217     }
218 
219     public String getSourceDir() {
220         return sourceDir;
221     }
222 
223     public String getFormat() {
224         return format;
225     }
226 
227     /**
228      * @return the uri alternative to source directory.
229      */
230     public String getUri() {
231         return uri;
232     }
233 
234     /**
235      * @param uri the uri specifying the source directory.
236      */
237     public void setUri(String uri) {
238         this.uri = uri;
239     }
240 
241 }