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