View Javadoc

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 }