1 4 package net.sourceforge.pmd.cpd; 5 6 import org.apache.tools.ant.BuildException; 7 import org.apache.tools.ant.DirectoryScanner; 8 import org.apache.tools.ant.Project; 9 import org.apache.tools.ant.Task; 10 import org.apache.tools.ant.types.EnumeratedAttribute; 11 import org.apache.tools.ant.types.FileSet; 12 13 import java.io.File ; 14 import java.io.IOException ; 15 import java.util.ArrayList ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Properties ; 19 20 38 public class CPDTask extends Task { 39 40 private static final String TEXT_FORMAT = "text"; 41 private static final String XML_FORMAT = "xml"; 42 private static final String CSV_FORMAT = "csv"; 43 44 private String format = TEXT_FORMAT; 45 private String language = LanguageFactory.JAVA_KEY; 46 private int minimumTokenCount; 47 private boolean ignoreLiterals; 48 private boolean ignoreIdentifiers; 49 private File outputFile; 50 private List filesets = new ArrayList (); 51 52 public void execute() throws BuildException { 53 try { 54 validateFields(); 55 56 log("Tokenizing files", Project.MSG_INFO); 57 CPD cpd = new CPD(minimumTokenCount, createLanguage()); 58 tokenizeFiles(cpd); 59 60 log("Starting to analyze code", Project.MSG_INFO); 61 long timeTaken = analyzeCode(cpd); 62 log("Done analyzing code; that took " + timeTaken + " milliseconds"); 63 64 log("Generating report", Project.MSG_INFO); 65 report(cpd); 66 } catch (IOException ioe) { 67 log(ioe.toString(), Project.MSG_ERR); 68 throw new BuildException("IOException during task execution", ioe); 69 } catch (ReportException re) { 70 re.printStackTrace(); 71 log(re.toString(), Project.MSG_ERR); 72 throw new BuildException("ReportException during task execution", re); 73 } 74 } 75 76 private Language createLanguage() { 77 Properties p = new Properties (); 78 if (ignoreLiterals) { 79 p.setProperty(JavaTokenizer.IGNORE_LITERALS, "true"); 80 } 81 if (ignoreIdentifiers) { 82 p.setProperty(JavaTokenizer.IGNORE_IDENTIFIERS, "true"); 83 } 84 return new LanguageFactory().createLanguage(language, p); 85 } 86 87 private void report(CPD cpd) throws ReportException { 88 if (!cpd.getMatches().hasNext()) { 89 log("No duplicates over " + minimumTokenCount + " tokens found", Project.MSG_INFO); 90 } 91 Renderer renderer = createRenderer(); 92 if (outputFile.isAbsolute()) { 93 new FileReporter(outputFile).report(renderer.render(cpd.getMatches())); 94 } else { 95 new FileReporter(new File (getProject().getBaseDir(), outputFile.toString())); 96 } 97 } 98 99 private void tokenizeFiles(CPD cpd) throws IOException { 100 for (Iterator iterator = filesets.iterator(); iterator.hasNext();) { 101 FileSet fileSet = (FileSet) iterator.next(); 102 DirectoryScanner directoryScanner = fileSet.getDirectoryScanner(getProject()); 103 String [] includedFiles = directoryScanner.getIncludedFiles(); 104 for (int i = 0; i < includedFiles.length; i++) { 105 File file = new File (directoryScanner.getBasedir() + System.getProperty("file.separator") + includedFiles[i]); 106 log("Tokenizing " + file.getAbsolutePath(), Project.MSG_VERBOSE); 107 cpd.add(file); 108 } 109 } 110 } 111 112 private long analyzeCode(CPD cpd) { 113 long start = System.currentTimeMillis(); 114 cpd.go(); 115 long stop = System.currentTimeMillis(); 116 return stop - start; 117 } 118 119 private Renderer createRenderer() { 120 if (format.equals(TEXT_FORMAT)) { 121 return new SimpleRenderer(); 122 } else if (format.equals(CSV_FORMAT)) { 123 return new CSVRenderer(); 124 } 125 return new XMLRenderer(); 126 } 127 128 private void validateFields() throws BuildException { 129 if (minimumTokenCount == 0) { 130 throw new BuildException("minimumTokenCount is required and must be greater than zero"); 131 } else if (outputFile == null) { 132 throw new BuildException("outputFile is a required attribute"); 133 } else if (filesets.isEmpty()) { 134 throw new BuildException("Must include at least one FileSet"); 135 } 136 } 137 138 public void addFileset(FileSet set) { 139 filesets.add(set); 140 } 141 142 public void setMinimumTokenCount(int minimumTokenCount) { 143 this.minimumTokenCount = minimumTokenCount; 144 } 145 146 public void setIgnoreLiterals(boolean value) { 147 this.ignoreLiterals = value; 148 } 149 150 public void setIgnoreIdentifiers(boolean value) { 151 this.ignoreIdentifiers = value; 152 } 153 154 public void setOutputFile(File outputFile) { 155 this.outputFile = outputFile; 156 } 157 158 public void setFormat(FormatAttribute formatAttribute) { 159 format = formatAttribute.getValue(); 160 } 161 162 public void setLanguage(LanguageAttribute languageAttribute) { 163 language = languageAttribute.getValue(); 164 } 165 166 public static class FormatAttribute extends EnumeratedAttribute { 167 private static final String [] FORMATS = new String []{XML_FORMAT, TEXT_FORMAT, CSV_FORMAT}; 168 public String [] getValues() { 169 return FORMATS; 170 } 171 } 172 173 public static class LanguageAttribute extends EnumeratedAttribute { 174 private String [] LANGUAGES = new String []{LanguageFactory.JAVA_KEY, LanguageFactory.JSP_KEY, LanguageFactory.CPP_KEY, LanguageFactory.C_KEY, LanguageFactory.PHP_KEY, LanguageFactory.RUBY_KEY }; 175 public String [] getValues() { 176 return LANGUAGES; 177 } 178 } 179 } 180 | Popular Tags |