001: package org.acm.seguin.pmd;
002:
003: import net.sourceforge.jrefactory.ast.ASTCompilationUnit;
004: import net.sourceforge.jrefactory.parser.JavaParser;
005: import net.sourceforge.jrefactory.parser.ParseException;
006: import org.acm.seguin.pmd.cpd.FileFinder;
007: import org.acm.seguin.pmd.cpd.JavaLanguage;
008: import org.acm.seguin.pmd.renderers.CSVRenderer;
009: import org.acm.seguin.pmd.renderers.EmacsRenderer;
010: import org.acm.seguin.pmd.renderers.HTMLRenderer;
011: import org.acm.seguin.pmd.renderers.IDEAJRenderer;
012: import org.acm.seguin.pmd.renderers.Renderer;
013: import org.acm.seguin.pmd.renderers.TextRenderer;
014: import org.acm.seguin.pmd.renderers.XMLRenderer;
015: import org.acm.seguin.pmd.symboltable.SymbolFacade;
016:
017: import java.io.File;
018: import java.io.FileInputStream;
019: import java.io.FileNotFoundException;
020: import java.io.InputStream;
021: import java.io.InputStreamReader;
022: import java.io.Reader;
023: import java.util.ArrayList;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.StringTokenizer;
027:
028: public class PMD {
029: public static final String EOL = System.getProperty(
030: "line.separator", "\n");
031:
032: private JLSVersion jlsVersion;
033:
034: public PMD() {
035: jlsVersion = new JLS1_4();
036: }
037:
038: public PMD(JLSVersion jlsVersion) {
039: this .jlsVersion = jlsVersion;
040: }
041:
042: /**
043: * @param reader - a Reader to the Java code to analyse
044: * @param ruleSet - the set of rules to process against the file
045: * @param ctx - the context in which PMD is operating. This contains the Renderer and whatnot
046: */
047: public void processFile(Reader reader, RuleSet ruleSet,
048: RuleContext ctx) throws PMDException {
049: try {
050: JavaParser parser = jlsVersion.createParser(reader);
051: ASTCompilationUnit c = parser.CompilationUnit();
052: Thread.yield();
053: SymbolFacade stb = new SymbolFacade();
054: stb.initializeWith(c);
055: List acus = new ArrayList();
056: acus.add(c);
057: ruleSet.apply(acus, ctx);
058: reader.close();
059: } catch (ParseException pe) {
060: throw new PMDException("Error while parsing "
061: + ctx.getSourceCodeFilename(), pe);
062: } catch (Exception e) {
063: throw new PMDException("Error while processing "
064: + ctx.getSourceCodeFilename(), e);
065: }
066: }
067:
068: /**
069: * @param fileContents - an InputStream to the Java code to analyse
070: * @param ruleSet - the set of rules to process against the file
071: * @param ctx - the context in which PMD is operating. This contains the Report and whatnot
072: */
073: public void processFile(InputStream fileContents, RuleSet ruleSet,
074: RuleContext ctx) throws PMDException {
075: processFile(new InputStreamReader(fileContents), ruleSet, ctx);
076: }
077:
078: public static void main(String[] args) {
079: CommandLineOptions opts = new CommandLineOptions(args);
080:
081: List files;
082: if (opts.containsCommaSeparatedFileList()) {
083: files = collectFromCommaDelimitedString(opts
084: .getInputFileName());
085: } else {
086: files = collectFilesFromOneName(opts.getInputFileName());
087: }
088:
089: PMD pmd = new PMD();
090:
091: RuleContext ctx = new RuleContext();
092: ctx.setReport(new Report());
093:
094: try {
095: RuleSetFactory ruleSetFactory = new RuleSetFactory();
096: RuleSet rules = ruleSetFactory.createRuleSet(opts
097: .getRulesets());
098: for (Iterator i = files.iterator(); i.hasNext();) {
099: File file = (File) i.next();
100: ctx.setSourceCodeFilename(glomName(opts
101: .shortNamesEnabled(), opts.getInputFileName(),
102: file));
103: try {
104: pmd.processFile(new FileInputStream(file), rules,
105: ctx);
106: } catch (PMDException pmde) {
107: if (opts.debugEnabled()) {
108: pmde.getReason().printStackTrace();
109: }
110: ctx.getReport().addError(
111: new Report.ProcessingError(pmde
112: .getMessage(), glomName(opts
113: .shortNamesEnabled(), opts
114: .getInputFileName(), file)));
115: }
116: }
117: } catch (FileNotFoundException fnfe) {
118: System.out.println(opts.usage());
119: fnfe.printStackTrace();
120: } catch (RuleSetNotFoundException rsnfe) {
121: System.out.println(opts.usage());
122: rsnfe.printStackTrace();
123: }
124:
125: try {
126: Renderer r = opts.createRenderer();
127: System.out.println(r.render(ctx.getReport()));
128: } catch (Exception e) {
129: System.out.println(e.getMessage());
130: System.out.println(opts.usage());
131: if (opts.debugEnabled()) {
132: e.printStackTrace();
133: }
134: }
135: }
136:
137: private static String glomName(boolean shortNames,
138: String inputFileName, File file) {
139: if (shortNames && inputFileName.indexOf(',') == -1
140: && (new File(inputFileName)).isDirectory()) {
141: String name = file.getAbsolutePath().substring(
142: inputFileName.length());
143: if (name.startsWith(System.getProperty("file.separator"))) {
144: name = name.substring(1);
145: }
146: return name;
147: } else {
148: return file.getAbsolutePath();
149: }
150: }
151:
152: private static List collectFilesFromOneName(String inputFileName) {
153: return collect(inputFileName);
154: }
155:
156: private static List collectFromCommaDelimitedString(String fileList) {
157: List files = new ArrayList();
158: for (StringTokenizer st = new StringTokenizer(fileList, ","); st
159: .hasMoreTokens();) {
160: files.addAll(collect(st.nextToken()));
161: }
162: return files;
163: }
164:
165: private static List collect(String filename) {
166: File inputFile = new File(filename);
167: if (!inputFile.exists()) {
168: throw new RuntimeException("File " + inputFile.getName()
169: + " doesn't exist");
170: }
171: List files;
172: if (!inputFile.isDirectory()) {
173: files = new ArrayList();
174: files.add(inputFile);
175: } else {
176: FileFinder finder = new FileFinder();
177: files = finder.findFilesFrom(inputFile.getAbsolutePath(),
178: new JavaLanguage.JavaFileOrDirectoryFilter(), true);
179: }
180: return files;
181: }
182:
183: }
|