/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.cli;
import java.util.Properties;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PropertyDescriptor;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.renderers.RendererFactory;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
/**
* @author Romain Pelisse <belaran@gmail.com>
*
*/
public class PMDCommandLineInterface {
public static final String PROG_NAME = "pmd";
public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
public static final int ERROR_STATUS = 1;
public static final int VIOLATIONS_FOUND = 4;
private PMDCommandLineInterface() { }
public static PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
JCommander jcommander = new JCommander(arguments);
jcommander.setProgramName(progName);
try {
jcommander.parse(args);
if (arguments.isHelp()) {
jcommander.usage();
System.out.println(buildUsageText(jcommander));
setStatusCodeOrExit(ERROR_STATUS);
}
} catch (ParameterException e) {
jcommander.usage();
System.out.println(buildUsageText(jcommander));
System.err.println(e.getMessage());
setStatusCodeOrExit(ERROR_STATUS);
}
return arguments;
}
public static String buildUsageText() {
return buildUsageText(null);
}
public static String buildUsageText(JCommander jcommander) {
StringBuilder usage = new StringBuilder();
String allCommandsDescription = null;
if (jcommander != null && jcommander.getCommands() != null) {
for (String command : jcommander.getCommands().keySet()) {
allCommandsDescription += jcommander.getCommandDescription(command) + PMD.EOL;
}
}
// TODO: Externalize that to a file available within the classpath ? -
// with a poor's man templating ?
String fullText = PMD.EOL + "Mandatory arguments:" + PMD.EOL + "1) A java source code filename or directory"
+ PMD.EOL + "2) A report format " + PMD.EOL
+ "3) A ruleset filename or a comma-delimited string of ruleset filenames" + PMD.EOL + PMD.EOL
+ "For example: " + PMD.EOL + getWindowsLaunchCmd()
+ " -d c:\\my\\source\\code -f html -R java-unusedcode" + PMD.EOL + PMD.EOL;
fullText += supportedVersions() + PMD.EOL;
if (allCommandsDescription != null) {
fullText += "Optional arguments that may be put before or after the mandatory arguments: " + PMD.EOL
+ allCommandsDescription + PMD.EOL;
}
fullText += "Available report formats and their configuration properties are:" + PMD.EOL + getReports()
+ PMD.EOL + getExamples() + PMD.EOL + PMD.EOL + PMD.EOL;
fullText += usage.toString();
return fullText;
}
private static String getExamples() {
return getWindowsExample() + getUnixExample();
}
private static String getWindowsLaunchCmd() {
final String WINDOWS_PROMPT = "C:\\>";
final String launchCmd = "pmd-bin-" + PMD.VERSION + "\\bin\\pmd.bat";
return WINDOWS_PROMPT + launchCmd;
}
private static String getWindowsExample() {
final String launchCmd = getWindowsLaunchCmd();
final String WINDOWS_PATH_TO_CODE = "c:\\my\\source\\code ";
return "For example on windows: " + PMD.EOL + launchCmd + " -dir " + WINDOWS_PATH_TO_CODE
+ "-format text -R java-unusedcode,java-imports -version 1.5 -language java -debug" + PMD.EOL
+ launchCmd + " -dir " + WINDOWS_PATH_TO_CODE
+ "-f xml -rulesets java-basic,java-design -encoding UTF-8" + PMD.EOL + launchCmd + " -d "
+ WINDOWS_PATH_TO_CODE + "-rulesets java-typeresolution -auxclasspath commons-collections.jar;derby.jar"
+ PMD.EOL + launchCmd + " -d " + WINDOWS_PATH_TO_CODE
+ "-f html -R java-typeresolution -auxclasspath file:///C:/my/classpathfile" + PMD.EOL + PMD.EOL;
}
private static String getUnixExample() {
final String UNIX_PROMPT = "$ ";
final String launchCmd = "pmd-bin-" + PMD.VERSION + "/bin/run.sh pmd";
return "For example on *nix: " + PMD.EOL + UNIX_PROMPT + launchCmd
+ " -dir /home/workspace/src/main/java/code -f html -rulesets java-basic,java-design" + PMD.EOL
+ UNIX_PROMPT + launchCmd
+ " -d ./src/main/java/code -f xslt -R java-basic,java-design -property xsltFilename=my-own.xsl"
+ PMD.EOL + UNIX_PROMPT + launchCmd
+ " -d ./src/main/java/code -f html -R java-typeresolution -auxclasspath commons-collections.jar:derby.jar"
+ PMD.EOL;
}
private static String supportedVersions() {
return "Languages and version suported:" + PMD.EOL
+ LanguageRegistry.commaSeparatedTerseNamesForLanguage(LanguageRegistry.findWithRuleSupport())
+ PMD.EOL;
}
/**
* For testing purpose only...
*
* @param args
*/
public static void main(String[] args) {
System.out.println(PMDCommandLineInterface.buildUsageText());
}
public static String jarName() {
return "pmd-" + PMD.VERSION + ".jar";
}
private static String getReports() {
StringBuilder buf = new StringBuilder();
for (String reportName : RendererFactory.REPORT_FORMAT_TO_RENDERER.keySet()) {
Renderer renderer = RendererFactory.createRenderer(reportName, new Properties());
buf.append(" ").append(reportName).append(": ");
if (!reportName.equals(renderer.getName())) {
buf.append(" Deprecated alias for '" + renderer.getName()).append(PMD.EOL);
continue;
}
buf.append(renderer.getDescription()).append(PMD.EOL);
for (PropertyDescriptor<?> property : renderer.getPropertyDescriptors()) {
buf.append(" ").append(property.name()).append(" - ");
buf.append(property.description());
Object deflt = property.defaultValue();
if (deflt != null) {
buf.append(" default: ").append(deflt);
}
buf.append(PMD.EOL);
}
}
return buf.toString();
}
public static void run(String[] args) {
setStatusCodeOrExit(PMD.run(args));
}
public static void setStatusCodeOrExit(int status) {
if (isExitAfterRunSet()) {
System.exit(status);
} else {
setStatusCode(status);
}
}
private static boolean isExitAfterRunSet() {
String noExit = System.getenv(NO_EXIT_AFTER_RUN);
if (noExit == null) {
noExit = System.getProperty(NO_EXIT_AFTER_RUN);
}
return (noExit == null ? true : false);
}
private static void setStatusCode(int statusCode) {
System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
}
}