1 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.util.HashMap ; 10 import java.util.HashSet ; 11 import java.util.Iterator ; 12 import java.util.List ; 13 import java.util.Map ; 14 import java.util.Set ; 15 16 public class CPD { 17 18 private Map source = new HashMap (); 19 private CPDListener listener = new CPDNullListener(); 20 private Tokens tokens = new Tokens(); 21 private int minimumTileSize; 22 private MatchAlgorithm matchAlgorithm; 23 private Language language; 24 private boolean skipDuplicates; 25 26 public CPD(int minimumTileSize, Language language) { 27 this.minimumTileSize = minimumTileSize; 28 this.language = language; 29 } 30 31 public void skipDuplicates() { 32 this.skipDuplicates = true; 33 } 34 35 public void setCpdListener(CPDListener cpdListener) { 36 this.listener = cpdListener; 37 } 38 39 public void go() { 40 TokenEntry.clearImages(); 41 matchAlgorithm = new MatchAlgorithm(source, tokens, minimumTileSize, listener); 42 matchAlgorithm.findMatches(); 43 } 44 45 public Iterator getMatches() { 46 return matchAlgorithm.matches(); 47 } 48 49 public void add(File file) throws IOException { 50 add(1, file); 51 } 52 53 public void addAllInDirectory(String dir) throws IOException { 54 addDirectory(dir, false); 55 } 56 57 public void addRecursively(String dir) throws IOException { 58 addDirectory(dir, true); 59 } 60 61 public void add(List files) throws IOException { 62 for (Iterator i = files.iterator(); i.hasNext();) { 63 add(files.size(), (File ) i.next()); 64 } 65 } 66 67 private void addDirectory(String dir, boolean recurse) throws IOException { 68 if (!(new File (dir)).exists()) { 69 throw new FileNotFoundException ("Couldn't find directory " + dir); 70 } 71 FileFinder finder = new FileFinder(); 72 add(finder.findFilesFrom(dir, language.getFileFilter(), recurse)); 74 } 75 76 private Set current = new HashSet (); 77 78 private void add(int fileCount, File file) throws IOException { 79 80 if (skipDuplicates) { 81 String signature = file.getName() + '_' + file.length(); 83 if (current.contains(signature)) { 84 System.out.println("Skipping " + file.getAbsolutePath() + " since it appears to be a duplicate file and --skip-duplicate-files is set"); 85 return; 86 } 87 current.add(signature); 88 } 89 90 if (!file.getCanonicalPath().equals(file.getAbsolutePath())) { 91 System.out.println("Skipping " + file + " since it appears to be a symlink"); 92 return; 93 } 94 95 listener.addedFile(fileCount, file); 96 SourceCode sourceCode = new SourceCode(new SourceCode.FileCodeLoader(file)); 97 language.getTokenizer().tokenize(sourceCode, tokens); 98 source.put(sourceCode.getFileName(), sourceCode); 99 } 100 101 public static Renderer getRendererFromString(String name) { 102 if (name.equalsIgnoreCase("text") || name.equals("")) { 103 return new SimpleRenderer(); 104 } 105 try { 106 return (Renderer) Class.forName(name).newInstance(); 107 } catch (Exception e) { 108 System.out.println("Can't find class '" + name + "', defaulting to SimpleRenderer."); 109 } 110 return new SimpleRenderer(); 111 } 112 113 private static boolean findBooleanSwitch(String [] args, String name) { 114 for (int i = 0; i < args.length; i++) { 115 if (args[i].equals(name)) { 116 return true; 117 } 118 } 119 return false; 120 } 121 122 private static String findRequiredStringValue(String [] args, String name) { 123 for (int i = 0; i < args.length; i++) { 124 if (args[i].equals(name)) { 125 return args[i + 1]; 126 } 127 } 128 System.out.println("No " + name + " value passed in"); 129 usage(); 130 throw new RuntimeException (); 131 } 132 133 private static String findOptionalStringValue(String [] args, String name, String defaultValue) { 134 for (int i = 0; i < args.length; i++) { 135 if (args[i].equals(name)) { 136 return args[i + 1]; 137 } 138 } 139 return defaultValue; 140 } 141 142 public static void main(String [] args) { 143 if (args.length == 0) { 144 usage(); 145 } 146 147 try { 148 boolean skipDuplicateFiles = findBooleanSwitch(args, "--skip-duplicate-files"); 149 String pathToFiles = findRequiredStringValue(args, "--files"); 150 String languageString = findOptionalStringValue(args, "--language", "java"); 151 String formatString = findOptionalStringValue(args, "--format", "text"); 152 int minimumTokens = Integer.parseInt(findRequiredStringValue(args, "--minimum-tokens")); 153 LanguageFactory f = new LanguageFactory(); 154 Language language = f.createLanguage(languageString); 155 Renderer renderer = CPD.getRendererFromString(formatString); 156 CPD cpd = new CPD(minimumTokens, language); 157 if (skipDuplicateFiles) { 158 cpd.skipDuplicates(); 159 } 160 cpd.addRecursively(pathToFiles); 161 cpd.go(); 162 System.out.println(renderer.render(cpd.getMatches())); 163 } catch (Exception e) { 164 e.printStackTrace(); 165 } 166 } 167 168 private static void usage() { 169 System.out.println("Usage:"); 170 System.out.println(" java net.sourceforge.pmd.cpd.CPD --minimum-tokens xxx --files xxx [--language xxx] [--format (xml|text|csv)] [--skip-duplicate-files] "); 171 System.out.println("i.e: "); 172 System.out.println(" java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --files c:\\jdk14\\src\\java "); 173 System.out.println("or: "); 174 System.out.println(" java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --files /path/to/c/code --language c "); 175 System.out.println("or: "); 176 System.out.println(" java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 --files /path/to/java/code --format xml"); 177 } 178 179 } 180 | Popular Tags |