1
2
3
4 package net.sourceforge.pmd.cli;
5
6 import java.util.Properties;
7
8 import net.sourceforge.pmd.PMD;
9 import net.sourceforge.pmd.PropertyDescriptor;
10 import net.sourceforge.pmd.lang.LanguageRegistry;
11 import net.sourceforge.pmd.renderers.Renderer;
12 import net.sourceforge.pmd.renderers.RendererFactory;
13
14 import com.beust.jcommander.JCommander;
15 import com.beust.jcommander.ParameterException;
16
17
18
19
20
21 public class PMDCommandLineInterface {
22
23 public static final String PROG_NAME = "pmd";
24
25 public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
26 public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
27
28 public static final int ERROR_STATUS = 1;
29 public static final int VIOLATIONS_FOUND = 4;
30
31 public static PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
32 JCommander jcommander = new JCommander(arguments);
33 jcommander.setProgramName(progName);
34
35 try {
36 jcommander.parse(args);
37 if (arguments.isHelp()) {
38 jcommander.usage();
39 System.out.println(buildUsageText(jcommander));
40 setStatusCodeOrExit(0);
41 }
42 } catch (ParameterException e) {
43 jcommander.usage();
44 System.out.println(buildUsageText(jcommander));
45 System.err.println(e.getMessage());
46 setStatusCodeOrExit(ERROR_STATUS);
47 }
48 return arguments;
49 }
50
51 public static String buildUsageText() {
52 return buildUsageText(null);
53 }
54
55 public static String buildUsageText(JCommander jcommander) {
56 StringBuilder usage = new StringBuilder();
57
58 String allCommandsDescription = null;
59 if ( jcommander != null && jcommander.getCommands() != null ) {
60 for ( String command : jcommander.getCommands().keySet() ) {
61 allCommandsDescription += jcommander.getCommandDescription(command) + PMD.EOL;
62 }
63 }
64
65
66 String fullText = PMD.EOL
67 + "Mandatory arguments:" + PMD.EOL
68 + "1) A java source code filename or directory" + PMD.EOL
69 + "2) A report format " + PMD.EOL
70 + "3) A ruleset filename or a comma-delimited string of ruleset filenames" + PMD.EOL
71 + PMD.EOL
72 + "For example: " + PMD.EOL
73 + getWindowsLaunchCmd() + " -d c:\\my\\source\\code -f html -R java-unusedcode" + PMD.EOL
74 + PMD.EOL;
75
76 fullText += supportedVersions() + PMD.EOL;
77
78 if ( allCommandsDescription != null ) {
79 fullText += "Optional arguments that may be put before or after the mandatory arguments: " + PMD.EOL
80 + allCommandsDescription + PMD.EOL;
81 }
82
83 fullText += "Available report formats and their configuration properties are:" + PMD.EOL
84 + getReports() + PMD.EOL
85 + getExamples() + PMD.EOL
86 + PMD.EOL + PMD.EOL;
87
88 return fullText += usage.toString();
89 }
90
91 private static String getExamples() {
92 return getWindowsExample() + getUnixExample();
93 }
94
95 private static String getWindowsLaunchCmd() {
96 final String WINDOWS_PROMPT = "C:\\>";
97 final String launchCmd = "pmd-bin-" + PMD.VERSION + "\\bin\\pmd.bat";
98 return WINDOWS_PROMPT + launchCmd;
99 }
100 private static String getWindowsExample() {
101 final String launchCmd = getWindowsLaunchCmd();
102 final String WINDOWS_PATH_TO_CODE = "c:\\my\\source\\code ";
103
104 return "For example on windows: " + PMD.EOL
105 + launchCmd + " -dir " + WINDOWS_PATH_TO_CODE + "-format text -R java-unusedcode,java-imports -version 1.5 -language java -debug" + PMD.EOL
106 + launchCmd + " -dir " + WINDOWS_PATH_TO_CODE + "-f xml -rulesets java-basic,java-design -encoding UTF-8" + PMD.EOL
107 + launchCmd + " -d " + WINDOWS_PATH_TO_CODE + "-rulesets java-typeresolution -auxclasspath commons-collections.jar;derby.jar" + PMD.EOL
108 + launchCmd + " -d " + WINDOWS_PATH_TO_CODE + "-f html -R java-typeresolution -auxclasspath file:///C:/my/classpathfile" + PMD.EOL
109 + PMD.EOL;
110 }
111
112 private static String getUnixExample() {
113 final String UNIX_PROMPT = "$ ";
114 final String launchCmd = "pmd-bin-" + PMD.VERSION + "/bin/run.sh pmd";
115 return "For example on *nix: " + PMD.EOL
116 + UNIX_PROMPT + launchCmd + " -dir /home/workspace/src/main/java/code -f html -rulesets java-basic,java-design" + PMD.EOL
117 + UNIX_PROMPT + launchCmd + " -d ./src/main/java/code -f xslt -R java-basic,java-design -property xsltFilename=my-own.xsl" + PMD.EOL
118 + UNIX_PROMPT + launchCmd + " -d ./src/main/java/code -f html -R java-typeresolution -auxclasspath commons-collections.jar:derby.jar"
119 + PMD.EOL;
120 }
121
122 private static String supportedVersions() {
123 return "Languages and version suported:" + PMD.EOL +
124 LanguageRegistry.commaSeparatedTerseNamesForLanguage(LanguageRegistry.findWithRuleSupport()) + PMD.EOL;
125 }
126
127
128
129
130
131
132 public static void main(String[] args) {
133 System.out.println(PMDCommandLineInterface.buildUsageText());
134 }
135
136 public static String jarName() {
137 return "pmd-" + PMD.VERSION + ".jar";
138 }
139
140 private static String getReports() {
141 StringBuilder buf = new StringBuilder();
142 for (String reportName : RendererFactory.REPORT_FORMAT_TO_RENDERER.keySet()) {
143 Renderer renderer = RendererFactory.createRenderer(reportName, new Properties());
144 buf.append(" ").append(reportName).append(": ");
145 if (!reportName.equals(renderer.getName())) {
146 buf.append(" Deprecated alias for '" + renderer.getName()).append(PMD.EOL);
147 continue;
148 }
149 buf.append(renderer.getDescription()).append(PMD.EOL);
150
151 for (PropertyDescriptor<?> property : renderer.getPropertyDescriptors()) {
152 buf.append(" ").append(property.name()).append(" - ");
153 buf.append(property.description());
154 Object deflt = property.defaultValue();
155 if (deflt != null) {
156 buf.append(" default: ").append(deflt);
157 }
158 buf.append(PMD.EOL);
159 }
160
161
162 }
163 return buf.toString();
164 }
165
166 public static void run(String[] args) {
167 setStatusCodeOrExit(PMD.run(args));
168 }
169
170 public static void setStatusCodeOrExit(int status) {
171 if ( isExitAfterRunSet() ) {
172 System.exit(status);
173 } else {
174 setStatusCode(status);
175 }
176 }
177
178 private static boolean isExitAfterRunSet() {
179 String noExit = System.getenv(NO_EXIT_AFTER_RUN);
180 if (noExit == null) {
181 noExit = System.getProperty(NO_EXIT_AFTER_RUN);
182 }
183 return (noExit == null ? true : false);
184 }
185
186 private static void setStatusCode(int statusCode) {
187 System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
188 }
189
190 }