diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDCommandLineInterface.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDCommandLineInterface.java index 0294f5c3a9..4e7c5f70a8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDCommandLineInterface.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDCommandLineInterface.java @@ -12,6 +12,7 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Logger; +import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.util.database.DBURI; import com.beust.jcommander.JCommander; @@ -63,7 +64,7 @@ public class CPDCommandLineInterface { } catch (ParameterException e) { jcommander.usage(); System.out.println(buildUsageText()); - System.out.println(e.getMessage()); + System.out.println(" " + e.getMessage()); setStatusCodeOrExit(1); return; } @@ -141,24 +142,21 @@ public class CPDCommandLineInterface { } } - private static final char EOL = '\n'; - public static String buildUsageText() { - String helpText = "Usage:"; + public static String buildUsageText() { + String helpText = " For example on Windows:" + PMD.EOL; - helpText += " java net.sourceforge.pmd.cpd.CPD --minimum-tokens xxx --files xxx [--language xxx] [--encoding xxx] [--format (xml|text|csv|vs)] [--skip-duplicate-files] [--non-recursive]" + EOL; - helpText += "i.e: " + EOL; + helpText += " C:\\>" + "pmd-bin-" + PMD.VERSION + "\\bin\\cpd.bat" + + " --minimum-tokens 100 --files c:\\jdk18\\src\\java" + PMD.EOL; + helpText += PMD.EOL; - helpText += " java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --files c:\\jdk14\\src\\java " + EOL; - helpText += "or: " + EOL; + helpText += " For example on *nix:" + PMD.EOL; + helpText += " $ " + "pmd-bin-" + PMD.VERSION + "/bin/run.sh cpd" + + " --minimum-tokens 100 --files /path/to/java/code" + PMD.EOL; + helpText += PMD.EOL; - helpText += " java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --files /path/to/c/code --language c " + EOL; - helpText += "or: " + EOL; - - helpText += " java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --encoding UTF-16LE --files /path/to/java/code --format xml" + EOL; - helpText += EOL; - - helpText += EOL + " Supported languages: " + Arrays.toString(LanguageFactory.supportedLanguages) + EOL; - return helpText; - } + helpText += " Supported languages: " + Arrays.toString(LanguageFactory.supportedLanguages) + PMD.EOL; + helpText += " Formats: " + Arrays.toString(CPDConfiguration.getRenderers()) + PMD.EOL; + return helpText; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java index 8fe283cf4f..a0aa170400 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPDConfiguration.java @@ -3,11 +3,17 @@ */ package net.sourceforge.pmd.cpd; +import java.beans.PropertyDescriptor; import java.io.File; import java.io.FilenameFilter; import java.io.Reader; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Properties; import java.util.Set; @@ -148,25 +154,46 @@ public class CPDConfiguration extends AbstractConfiguration { return getRendererFromString(name, System.getProperty("file.encoding")); } + private static final Map> renderers = new HashMap>(); + static { + renderers.put(DEFAULT_RENDERER, SimpleRenderer.class); + renderers.put("xml", XMLRenderer.class); + renderers.put("csv", CSVRenderer.class); + renderers.put("csv_with_linecount_per_file", CSVWithLinecountPerFileRenderer.class); + renderers.put("vs", VSRenderer.class); + } public static Renderer getRendererFromString(String name, String encoding) { - if (name.equalsIgnoreCase(DEFAULT_RENDERER) || name.equals("")) { - return new SimpleRenderer(); - } else if ("xml".equals(name)) { - return new XMLRenderer(encoding); - } else if ("csv".equals(name)) { - return new CSVRenderer(); - } else if ("csv_with_linecount_per_file".equals(name)) { - return new CSVRenderer(true); - } else if ("vs".equals(name)) { - return new VSRenderer(); - } - try { - return (Renderer) Class.forName(name).newInstance(); - } catch (Exception e) { - System.out.println("Can't find class '" + name - + "', defaulting to SimpleRenderer."); - } - return new SimpleRenderer(); + String clazzname = name; + if (clazzname == null || "".equals(clazzname)) { + clazzname = DEFAULT_RENDERER; + } + Class clazz = renderers.get(clazzname.toLowerCase(Locale.ROOT)); + if (clazz == null) { + try { + clazz = Class.forName(clazzname).asSubclass(Renderer.class); + } catch (ClassNotFoundException e) { + System.err.println("Can't find class '" + name + "', defaulting to SimpleRenderer."); + clazz = SimpleRenderer.class; + } + } + try { + Renderer renderer = clazz.getDeclaredConstructor().newInstance(); + + PropertyDescriptor encodingProperty = new PropertyDescriptor("encoding", clazz); + Method method = encodingProperty.getWriteMethod(); + if (method != null) { + method.invoke(renderer, encoding); + } + return renderer; + } catch (Exception e) { + System.err.println("Couldn't instantiate renderer, defaulting to SimpleRenderer: " + e); + return new SimpleRenderer(); + } + } + public static String[] getRenderers() { + String[] result = renderers.keySet().toArray(new String[renderers.size()]); + Arrays.sort(result); + return result; } public static Language getLanguageFromString(String languageString) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CSVWithLinecountPerFileRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CSVWithLinecountPerFileRenderer.java new file mode 100644 index 0000000000..59a221a4c3 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CSVWithLinecountPerFileRenderer.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +public class CSVWithLinecountPerFileRenderer extends CSVRenderer { + + public CSVWithLinecountPerFileRenderer() { + super(true); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/XMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/XMLRenderer.java index e0509625dd..83d2dbc584 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/XMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/XMLRenderer.java @@ -26,7 +26,7 @@ import org.w3c.dom.Element; */ public final class XMLRenderer implements Renderer { - private final String encoding; + private String encoding; /** * Creates a XML Renderer with the default (platform dependent) encoding. @@ -40,13 +40,20 @@ public final class XMLRenderer implements Renderer { * @param encoding the encoding to use or null. If null, default (platform dependent) encoding is used. */ public XMLRenderer(String encoding) { - if (encoding != null) { - this.encoding = encoding; - } else { - this.encoding = System.getProperty("file.encoding"); - } + setEncoding(encoding); } + public final void setEncoding(String encoding) { + if (encoding != null) { + this.encoding = encoding; + } else { + this.encoding = System.getProperty("file.encoding"); + } + } + public final String getEncoding() { + return this.encoding; + } + private Document createDocument() { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();