1 /*** 2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 3 */ 4 package net.sourceforge.pmd; 5 6 import net.sourceforge.pmd.ast.ASTCompilationUnit; 7 import net.sourceforge.pmd.ast.JavaParser; 8 import net.sourceforge.pmd.ast.ParseException; 9 import net.sourceforge.pmd.cpd.FileFinder; 10 import net.sourceforge.pmd.cpd.JavaLanguage; 11 import net.sourceforge.pmd.renderers.Renderer; 12 import net.sourceforge.pmd.symboltable.SymbolFacade; 13 14 import java.io.File; 15 import java.io.FileInputStream; 16 import java.io.FileNotFoundException; 17 import java.io.InputStream; 18 import java.io.InputStreamReader; 19 import java.io.Reader; 20 import java.io.UnsupportedEncodingException; 21 import java.util.ArrayList; 22 import java.util.Iterator; 23 import java.util.List; 24 import java.util.StringTokenizer; 25 26 public class PMD { 27 28 public static final String EOL = System.getProperty("line.separator", "\n"); 29 30 private TargetJDKVersion targetJDKVersion; 31 32 public PMD() { 33 targetJDKVersion = new TargetJDK1_4(); 34 } 35 36 public PMD(TargetJDKVersion targetJDKVersion) { 37 this.targetJDKVersion = targetJDKVersion; 38 } 39 40 /*** 41 * @param reader - a Reader to the Java code to analyse 42 * @param ruleSet - the set of rules to process against the file 43 * @param ctx - the context in which PMD is operating. This contains the Renderer and whatnot 44 */ 45 public void processFile(Reader reader, RuleSet ruleSet, RuleContext ctx) throws PMDException { 46 try { 47 JavaParser parser = targetJDKVersion.createParser(reader); 48 ASTCompilationUnit c = parser.CompilationUnit(); 49 Thread.yield(); 50 SymbolFacade stb = new SymbolFacade(); 51 stb.initializeWith(c); 52 List acus = new ArrayList(); 53 acus.add(c); 54 ruleSet.apply(acus, ctx); 55 reader.close(); 56 } catch (ParseException pe) { 57 throw new PMDException("Error while parsing " + ctx.getSourceCodeFilename(), pe); 58 } catch (Exception e) { 59 throw new PMDException("Error while processing " + ctx.getSourceCodeFilename(), e); 60 } 61 } 62 63 /*** 64 * @param fileContents - an InputStream to the Java code to analyse 65 * @param encoding - the source code's character set encoding 66 * @param ruleSet - the set of rules to process against the file 67 * @param ctx - the context in which PMD is operating. This contains the Report and whatnot 68 */ 69 public void processFile(InputStream fileContents, String encoding, RuleSet ruleSet, RuleContext ctx) throws PMDException { 70 try { 71 processFile(new InputStreamReader(fileContents, encoding), ruleSet, ctx); 72 } catch (UnsupportedEncodingException uee) { 73 throw new PMDException("Unsupported encoding exception: " + uee.getMessage()); 74 } 75 } 76 77 /*** 78 * @param fileContents - an InputStream to the Java code to analyse 79 * @param ruleSet - the set of rules to process against the source code 80 * @param ctx - the context in which PMD is operating. This contains the Report and whatnot 81 */ 82 public void processFile(InputStream fileContents, RuleSet ruleSet, RuleContext ctx) throws PMDException { 83 processFile(fileContents, System.getProperty("file.encoding"), ruleSet, ctx); 84 } 85 86 public static void main(String[] args) { 87 CommandLineOptions opts = new CommandLineOptions(args); 88 89 List files; 90 if (opts.containsCommaSeparatedFileList()) { 91 files = collectFromCommaDelimitedString(opts.getInputFileName()); 92 } else { 93 files = collectFilesFromOneName(opts.getInputFileName()); 94 } 95 96 PMD pmd; 97 if (opts.jdk13()) { 98 pmd = new PMD(new TargetJDK1_3()); 99 } else { 100 pmd = new PMD(); 101 } 102 103 RuleContext ctx = new RuleContext(); 104 ctx.setReport(new Report()); 105 106 try { 107 RuleSetFactory ruleSetFactory = new RuleSetFactory(); 108 RuleSet rules = ruleSetFactory.createRuleSet(opts.getRulesets()); 109 for (Iterator i = files.iterator(); i.hasNext();) { 110 File file = (File) i.next(); 111 ctx.setSourceCodeFilename(glomName(opts.shortNamesEnabled(), opts.getInputFileName(), file)); 112 try { 113 pmd.processFile(new FileInputStream(file), opts.getEncoding(), rules, ctx); 114 } catch (PMDException pmde) { 115 if (opts.debugEnabled()) { 116 pmde.getReason().printStackTrace(); 117 } 118 ctx.getReport().addError(new Report.ProcessingError(pmde.getMessage(), glomName(opts.shortNamesEnabled(), opts.getInputFileName(), file))); 119 } 120 } 121 } catch (FileNotFoundException fnfe) { 122 System.out.println(opts.usage()); 123 fnfe.printStackTrace(); 124 } catch (RuleSetNotFoundException rsnfe) { 125 System.out.println(opts.usage()); 126 rsnfe.printStackTrace(); 127 } 128 129 try { 130 Renderer r = opts.createRenderer(); 131 System.out.println(r.render(ctx.getReport())); 132 } catch (Exception e) { 133 System.out.println(e.getMessage()); 134 System.out.println(opts.usage()); 135 if (opts.debugEnabled()) { 136 e.printStackTrace(); 137 } 138 } 139 } 140 141 private static String glomName(boolean shortNames, String inputFileName, File file) { 142 if (shortNames && inputFileName.indexOf(',') == -1) { 143 if ((new File(inputFileName)).isDirectory()) { 144 return trimAnyPathSep(file.getAbsolutePath().substring(inputFileName.length())); 145 } else { 146 if (inputFileName.indexOf(System.getProperty("file.separator").charAt(0)) == -1) { 147 return inputFileName; 148 } 149 return trimAnyPathSep(inputFileName.substring(inputFileName.lastIndexOf(System.getProperty("file.separator")))); 150 } 151 } else { 152 return file.getAbsolutePath(); 153 } 154 } 155 156 private static String trimAnyPathSep(String name) { 157 if (name.startsWith(System.getProperty("file.separator"))) { 158 name = name.substring(1); 159 } 160 return name; 161 } 162 163 private static List collectFilesFromOneName(String inputFileName) { 164 return collect(inputFileName); 165 } 166 167 private static List collectFromCommaDelimitedString(String fileList) { 168 List files = new ArrayList(); 169 for (StringTokenizer st = new StringTokenizer(fileList, ","); st.hasMoreTokens();) { 170 files.addAll(collect(st.nextToken())); 171 } 172 return files; 173 } 174 175 private static List collect(String filename) { 176 File inputFile = new File(filename); 177 if (!inputFile.exists()) { 178 throw new RuntimeException("File " + inputFile.getName() + " doesn't exist"); 179 } 180 List files; 181 if (!inputFile.isDirectory()) { 182 files = new ArrayList(); 183 files.add(inputFile); 184 } else { 185 FileFinder finder = new FileFinder(); 186 files = finder.findFilesFrom(inputFile.getAbsolutePath(), new JavaLanguage.JavaFileOrDirectoryFilter(), true); 187 } 188 return files; 189 } 190 191 }