View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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  		// Pass extra parameters as System properties to allow language
72  		// implementation to retrieve their associate values...
73  		CPDConfiguration.setSystemProperties(arguments);
74  		CPD cpd = new CPD(arguments);
75  
76                  //Add files 
77                  if ( null != arguments.getFiles() && ! arguments.getFiles().isEmpty() )
78                  {
79                    addSourcesFilesToCPD(arguments.getFiles(), cpd, !arguments.isNonRecursive());
80                  }
81  
82                  //Add Database URIS
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 }