1
2
3
4 package net.sourceforge.pmd.cpd;
5
6 import java.io.File;
7 import java.io.FileNotFoundException;
8 import java.io.IOException;
9 import java.net.URISyntaxException;
10 import java.util.Arrays;
11 import java.util.List;
12 import java.util.logging.Logger;
13
14 import net.sourceforge.pmd.PMD;
15 import net.sourceforge.pmd.util.database.DBURI;
16
17 import com.beust.jcommander.JCommander;
18 import com.beust.jcommander.ParameterException;
19
20 public class CPDCommandLineInterface {
21 private final static Logger LOGGER = Logger.getLogger(CPDCommandLineInterface.class.getName());
22
23 private static final int DUPLICATE_CODE_FOUND = 4;
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 private static final String PROGRAM_NAME = "cpd";
29
30 public static void setStatusCodeOrExit(int status) {
31 if (isExitAfterRunSet()) {
32 System.exit(status);
33 } else {
34 setStatusCode(status);
35 }
36 }
37
38 private static boolean isExitAfterRunSet() {
39 String noExit = System.getenv(NO_EXIT_AFTER_RUN);
40 if (noExit == null) {
41 noExit = System.getProperty(NO_EXIT_AFTER_RUN);
42 }
43 return (noExit == null ? true : false);
44 }
45
46 private static void setStatusCode(int statusCode) {
47 System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
48 }
49
50 public static void main(String[] args) {
51 CPDConfiguration arguments = new CPDConfiguration();
52 JCommander jcommander = new JCommander(arguments);
53 jcommander.setProgramName(PROGRAM_NAME);
54
55 try {
56 jcommander.parse(args);
57 if (arguments.isHelp()) {
58 jcommander.usage();
59 System.out.println(buildUsageText());
60 setStatusCodeOrExit(1);
61 return;
62 }
63 } catch (ParameterException e) {
64 jcommander.usage();
65 System.out.println(buildUsageText());
66 System.err.println(" " + e.getMessage());
67 setStatusCodeOrExit(1);
68 return;
69 }
70 arguments.postContruct();
71
72
73 CPDConfiguration.setSystemProperties(arguments);
74 CPD cpd = new CPD(arguments);
75
76
77 if ( null != arguments.getFiles() && ! arguments.getFiles().isEmpty() )
78 {
79 addSourcesFilesToCPD(arguments.getFiles(), cpd, !arguments.isNonRecursive());
80 }
81
82
83 if ( null != arguments.getURI() && ! "".equals(arguments.getURI()) )
84 {
85 addSourceURIToCPD(arguments.getURI(),cpd);
86 }
87
88 cpd.go();
89 if (cpd.getMatches().hasNext()) {
90 System.out.println(arguments.getRenderer().render(cpd.getMatches()));
91 setStatusCodeOrExit(DUPLICATE_CODE_FOUND);
92 }
93 }
94
95 private static void addSourcesFilesToCPD(List<File> files, CPD cpd, boolean recursive) {
96 try {
97 for (File file : files) {
98 if (!file.exists()) {
99 throw new FileNotFoundException("Couldn't find directory/file '" + file + "'");
100 } else if (file.isDirectory()) {
101 if (recursive) {
102 cpd.addRecursively(file);
103 } else {
104 cpd.addAllInDirectory(file);
105 }
106 } else {
107 cpd.add(file);
108 }
109 }
110 } catch (IOException e) {
111 throw new IllegalStateException(e);
112 }
113 }
114
115 private static void addSourceURIToCPD(String uri, CPD cpd) {
116 try {
117 LOGGER.fine(String.format("Attempting DBURI=%s" , uri));
118 DBURI dburi = new DBURI(uri);
119 LOGGER.fine(String.format("Initialised DBURI=%s"
120 , dburi
121 )
122 );
123 LOGGER.fine(String.format("Adding DBURI=%s with DBType=%s"
124 , dburi.toString()
125 , dburi.getDbType().toString()
126 )
127 );
128 cpd.add(dburi);
129 } catch (IOException e) {
130 throw new IllegalStateException( "uri="+uri, e);
131 } catch (URISyntaxException ex) {
132 throw new IllegalStateException( "uri="+uri, ex);
133 } catch (Exception ex) {
134 throw new IllegalStateException( "uri="+uri, ex);
135 }
136 }
137
138 public static String buildUsageText() {
139 String helpText = " For example on Windows:" + PMD.EOL;
140
141 helpText += " C:\\>" + "pmd-bin-" + PMD.VERSION + "\\bin\\cpd.bat"
142 + " --minimum-tokens 100 --files c:\\jdk18\\src\\java" + PMD.EOL;
143 helpText += PMD.EOL;
144
145 helpText += " For example on *nix:" + PMD.EOL;
146 helpText += " $ " + "pmd-bin-" + PMD.VERSION + "/bin/run.sh cpd"
147 + " --minimum-tokens 100 --files /path/to/java/code" + PMD.EOL;
148 helpText += PMD.EOL;
149
150 helpText += " Supported languages: " + Arrays.toString(LanguageFactory.supportedLanguages) + PMD.EOL;
151 helpText += " Formats: " + Arrays.toString(CPDConfiguration.getRenderers()) + PMD.EOL;
152 return helpText;
153 }
154
155 }