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