Move all CLI related logic into a class in the subpackage 'cli' - mostly to simplify and clarifiy PMD main class code.

This commit is contained in:
Romain PELISSE committed 2012-08-04 17:41:27 +02:00
1 parent f0b17e35ce
commit a0236ee67f
3 files changed
+154 -37

No files matched your search

+16 -25
View File
@@ -21,6 +21,8 @@ import java.util.logging.Logger;
import net.sourceforge.pmd.benchmark.Benchmark;
import net.sourceforge.pmd.benchmark.Benchmarker;
import net.sourceforge.pmd.benchmark.TextReport;
import net.sourceforge.pmd.cli.PMDCommandLineInterface;
import net.sourceforge.pmd.cli.PMDParameters;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageFilenameFilter;
import net.sourceforge.pmd.lang.LanguageVersion;
@@ -49,8 +51,6 @@ public class PMD {
public static final String EOL = System.getProperty("line.separator", "\n");
public static final String SUPPRESS_MARKER = "NOPMD";
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";
protected final PMDConfiguration configuration;
@@ -191,12 +191,14 @@ public class PMD {
LOG.log(Level.SEVERE, "Exception during processing", e);
}
LOG.log(Level.FINE, "Exception during processing", e);
LOG.info(CommandLineParser.usage());
LOG.info(PMDCommandLineInterface.buildUsageText());
} finally {
Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
}
}
public static RuleContext newRuleContext(String sourceCodeFilename, File sourceCodeFile) {
RuleContext context = new RuleContext();
@@ -340,20 +342,9 @@ public class PMD {
* @param args
*/
public static void main(String[] args) {
if ( isExitAfterRunSet() )
System.exit(run(args));
else
setStatusCode(run(args));
PMDCommandLineInterface.run(args);
}
private static boolean isExitAfterRunSet() {
return (System.getenv(NO_EXIT_AFTER_RUN) == null ? false : true);
}
private static void setStatusCode(int statusCode) {
System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
}
/**
*
* @param args String[]
@@ -362,24 +353,24 @@ public class PMD {
public static int run(String[] args) {
int status = 0;
long start = System.nanoTime();
final CommandLineParser opts = new CommandLineParser(args);
final PMDConfiguration configuration = opts.getConfiguration();
final Level logLevel = configuration.isDebug() ? Level.FINER : Level.INFO;
final PMDParameters params = PMDCommandLineInterface.extractParameters(new PMDParameters(), args, "pmd");
final PMDConfiguration configuration = PMDParameters.transformParametersIntoConfiguration(params);
final Level logLevel = params.isDebug() ? Level.FINER : Level.INFO;
final Handler logHandler = new ConsoleLogHandler();
final ScopedLogHandlersManager logHandlerManager = new ScopedLogHandlersManager(logLevel, logHandler);
final Level oldLogLevel = LOG.getLevel();
LOG.setLevel(logLevel); //Need to do this, since the static logger has already been initialized at this point
try {
PMD.doPMD(opts.getConfiguration());
PMD.doPMD(configuration);
} catch (Exception e) {
System.out.print(CommandLineParser.usage());
PMDCommandLineInterface.buildUsageText();
System.out.println(e.getMessage());
status = ERROR_STATUS;
} finally {
logHandlerManager.close();
LOG.setLevel(oldLogLevel);
if (configuration.isBenchmark()) {
if (params.isBenchmark()) {
long end = System.nanoTime();
Benchmarker.mark(Benchmark.TotalPMD, end - start, 0);
@@ -389,8 +380,8 @@ public class PMD {
}
return status;
}
public static final String VERSION;
public static final String VERSION;
/**
* Determines the version from maven's generated pom.properties file.
*/
@@ -0,0 +1,129 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.cli;
import java.util.Map;
import java.util.Properties;
import net.sourceforge.pmd.PMD;
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 {
private static JCommander jcommander = null;
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 PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
try {
jcommander = new JCommander(arguments, args);
jcommander.setProgramName(progName);
if (arguments.isHelp()) {
jcommander.usage();
System.exit(0);
}
} catch (ParameterException e) {
System.out.println(buildUsageText());
System.out.println(e.getMessage());
System.exit(1);
}
return arguments;
}
public static String buildUsageText() {
final String launchCmd = "java -jar " + jarName();
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;
}
final String WINDOWS_PROMPT = "c:\\> ";
final String WINDOWS_PATH_TO_CODE = "c:\\my\\source\\code";
final String UNIX_PROMPT = "$ ";
// 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
+ "c:\\> " + launchCmd + " c:\\my\\source\\code html java-unusedcode" + PMD.EOL
+ 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
+ "For example on windows: " + PMD.EOL
+ WINDOWS_PROMPT + launchCmd + " -dir" + WINDOWS_PATH_TO_CODE + "-format text java-unusedcode,java-imports -version 1.5 -language java -debug" + PMD.EOL
+ WINDOWS_PROMPT + launchCmd + " -dir" + WINDOWS_PATH_TO_CODE + "-f xml -rulesets java-basic,java-design -encoding UTF-8" + PMD.EOL
+ WINDOWS_PROMPT + launchCmd + " -d" + WINDOWS_PATH_TO_CODE + "-rulesets java-typeresolution -auxclasspath commons-collections.jar;derby.jar" + PMD.EOL
+ WINDOWS_PROMPT + launchCmd + " -d" + WINDOWS_PATH_TO_CODE + "-f html java-typeresolution -auxclasspath file:///C:/my/classpathfile" + PMD.EOL
+ PMD.EOL
+ "For example on *nix: " + PMD.EOL
+ UNIX_PROMPT + launchCmd + " -dir /home/workspace/src/main/java/code -f nicehtml -rulesets java-basic,java-design" + PMD.EOL
+ UNIX_PROMPT + launchCmd + " -d ./src/main/java/code -f nicehtml -r java-basic,java-design -xslt my-own.xsl" + PMD.EOL
+ UNIX_PROMPT + launchCmd + " -d ./src/main/java/code -f nicehtml -r java-typeresolution -auxclasspath commons-collections.jar:derby.jar"
+ PMD.EOL + PMD.EOL;
fullText += usage.toString();
return fullText;
}
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 (Map.Entry<String, String> entry : renderer
.getPropertyDefinitions().entrySet()) {
buf.append(" ").append(entry.getKey()).append(" - ");
buf.append(entry.getValue()).append(PMD.EOL);
}
}
return buf.toString();
}
public static void run(String[] args) {
if ( isExitAfterRunSet() )
System.exit(PMD.run(args));
else
setStatusCode(PMD.run(args));
}
private static boolean isExitAfterRunSet() {
return (System.getenv(NO_EXIT_AFTER_RUN) == null ? false : true);
}
private static void setStatusCode(int statusCode) {
System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
}
}
@@ -15,7 +15,6 @@ import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.util.FileUtil;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@@ -35,10 +34,10 @@ public class CLITest {
*/
@BeforeClass
public static void setUp() throws Exception {
System.setProperty(PMD.NO_EXIT_AFTER_RUN, "true");
System.setProperty(PMDCommandLineInterface.NO_EXIT_AFTER_RUN, "true");
File testOuputDir = new File(TEST_OUPUT_DIRECTORY);
testOuputDir.delete();
assertTrue("failed to create output directory for test:" + testOuputDir.getAbsolutePath(),testOuputDir.mkdirs());
testOuputDir.mkdirs();
//assertTrue("failed to create output directory for test:" + testOuputDir.getAbsolutePath(),);
}
private void createTestOutputFile(String filename) {
@@ -53,31 +52,29 @@ public class CLITest {
@Test
public void minimalArgs() {
String[] args = { SOURCE_FOLDER,"xml", "java-basic,java-design"};
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design"};
runTest(args,"minimalArgs");
}
@Test
public void usingDebug() {
String[] args = { SOURCE_FOLDER
,"text", "java-basic,java-design","-debug"};
String[] args = { "-d", SOURCE_FOLDER, "-f" ,"text","-R", "java-basic,java-design","-debug"};
runTest(args,"minimalArgsWithDebug");
}
@Test
public void changeJavaVersion() {
String[] args = { SOURCE_FOLDER,"text", "java-basic,java-design", "-version", "java","1.5", "-debug"};
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "java-basic,java-design", "-version","1.5", "-language", "java", "-debug"};
String resultFilename = runTest(args, "chgJavaVersion");
assertTrue("Invalid Java version",FileUtil.findPatternInFile(new File(resultFilename), "Using Java version: Java 1.5"));
}
@Test
@Ignore // FIXME: fix CLI to take EcmaScript into account
public void useEcmaScript() {
String[] args = { SOURCE_FOLDER,"xml", "java-basic,java-design", "-version", "ecmascript","3", "-debug"};
String[] args = { "-d", SOURCE_FOLDER, "-f", "xml", "-R", "ecmascript-basic", "-version","3","-l", "ecmascript", "-debug"};
String resultFilename = runTest(args,"useEcmaScript");
assertTrue("Invalid Java version",FileUtil.findPatternInFile(new File(resultFilename), "Using Java version: EcmaScript 3"));
assertTrue("Invalid Java version",FileUtil.findPatternInFile(new File(resultFilename), "Using Ecmascript version: Ecmascript 3"));
}
private String runTest(String[] args, String testname) {
@@ -101,7 +98,7 @@ public class CLITest {
}
private void checkStatusCode() {
int statusCode = Integer.valueOf(System.getProperty(PMD.STATUS_CODE_PROPERTY));
int statusCode = Integer.valueOf(System.getProperty(PMDCommandLineInterface.STATUS_CODE_PROPERTY));
if ( statusCode > 0 )
fail("PMD failed with status code:" + statusCode);
}