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 java.io.File;
7   import java.util.ArrayList;
8   import java.util.Collection;
9   import java.util.Iterator;
10  import java.util.List;
11  
12  import net.sourceforge.pmd.util.Benchmark;
13  import net.sourceforge.pmd.util.filter.Filter;
14  import net.sourceforge.pmd.util.filter.Filters;
15  
16  
17  /**
18   * This class represents a collection of rules.
19   *
20   * @see Rule
21   */
22  //FUTURE Implement Cloneable and clone()
23  public class RuleSet {
24  
25      private List<Rule> rules = new ArrayList<Rule>();
26      private String fileName;
27      private String name = "";
28      private String description = "";
29      private Language language;
30      private List<String> excludePatterns = new ArrayList<String>(0);
31      private List<String> includePatterns = new ArrayList<String>(0);
32      private Filter<File> filter;
33  
34      /**
35       * Returns the number of rules in this ruleset
36       *
37       * @return an int representing the number of rules
38       */
39      public int size() {
40          return rules.size();
41      }
42  
43      /**
44       * Add a new rule to this ruleset
45       *
46       * @param rule the rule to be added
47       */
48      public void addRule(Rule rule) {
49          if (rule == null) {
50              throw new RuntimeException("Null Rule reference added to a RuleSet; that's a bug somewhere in PMD");
51          }
52          rules.add(rule);
53      }
54  
55      /**
56       * Add a new rule by reference to this ruleset.
57       *
58       * @param ruleSetFileName the ruleset which contains the rule
59       * @param rule the rule to be added
60       */
61      public void addRuleByReference(String ruleSetFileName, Rule rule) {
62          if (ruleSetFileName == null) {
63              throw new RuntimeException("Adding a rule by reference is not allowed with a null rule set file name.");
64          }
65          if (rule == null) {
66              throw new RuntimeException("Null Rule reference added to a RuleSet; that's a bug somewhere in PMD");
67          }
68          if (!(rule instanceof RuleReference)) {
69          	RuleSetReference ruleSetReference = new RuleSetReference();
70          	ruleSetReference.setRuleSetFileName(ruleSetFileName);
71  	        RuleReference ruleReference = new RuleReference();
72  	        ruleReference.setRule(rule);
73  	        ruleReference.setRuleSetReference(ruleSetReference);
74  	        rule = ruleReference;
75          }
76          rules.add(rule);
77      }
78  
79      /**
80       * Returns the actual Collection of rules in this ruleset
81       *
82       * @return a Collection with the rules. All objects are of type {@link Rule}
83       */
84      public Collection<Rule> getRules() {
85          return rules;
86      }
87  
88      /**
89       * @return true if any rule in the RuleSet needs the DFA layer
90       */
91      public boolean usesDFA() {
92          for (Rule r: rules) {
93              if (r.usesDFA()) {
94                  return true;
95              }
96          }
97          return false;
98      }
99  
100     /**
101      * Returns the Rule with the given name
102      *
103      * @param ruleName the name of the rule to find
104      * @return the rule or null if not found
105      */
106     public Rule getRuleByName(String ruleName) {
107         Rule rule = null;
108         for (Iterator<Rule> i = rules.iterator(); i.hasNext() && (rule == null);) {
109             Rule r = i.next();
110             if (r.getName().equals(ruleName)) {
111                 rule = r;
112             }
113         }
114         return rule;
115     }
116 
117     /**
118      * Add a whole RuleSet to this RuleSet
119      *
120      * @param ruleSet the RuleSet to add
121      */
122     public void addRuleSet(RuleSet ruleSet) {
123         rules.addAll(rules.size(), ruleSet.getRules());
124     }
125 
126     /**
127      * Add all rules by reference from one RuleSet to this RuleSet.  The rules
128      * can be added as individual references, or collectively as an all rule
129      * reference.
130      *
131      * @param ruleSet the RuleSet to add
132      * @param allRules 
133      */
134     public void addRuleSetByReference(RuleSet ruleSet, boolean allRules) {
135     	if (ruleSet.getFileName() == null) {
136             throw new RuntimeException("Adding a rule by reference is not allowed with a null rule set file name.");
137     	}
138     	RuleSetReference ruleSetReference = new RuleSetReference();
139     	ruleSetReference.setRuleSetFileName(ruleSet.getFileName());
140     	ruleSetReference.setAllRules(allRules);
141     	for(Rule rule: ruleSet.getRules()) {
142     		RuleReference ruleReference = new RuleReference();
143     		ruleReference.setRule(rule);
144     		ruleReference.setRuleSetReference(ruleSetReference);
145     		rules.add(ruleReference);
146     	}
147     }
148 
149    /**
150     * Check if a given source file should be checked by rules in this RuleSet.  A file
151     * should not be checked if there is an <code>exclude</code> pattern which matches
152     * the file, unless there is an <code>include</code> pattern which also matches
153     * the file.  In other words, <code>include</code> patterns override <code>exclude</code>
154     * patterns.
155     *
156     * @param file the source file to check
157     * @return <code>true</code> if the file should be checked, <code>false</code> otherwise
158     */
159     public boolean applies(File file) {
160     	// Initialize filter based on patterns
161         if (filter == null) {
162         	Filter<String> regexFilter = Filters.buildRegexFilterIncludeOverExclude(includePatterns, excludePatterns);
163         	filter = Filters.toNormalizedFileFilter(regexFilter);
164         }
165  
166         return file != null ? filter.filter(file) : true;
167     }
168     
169     public void start(RuleContext ctx) {
170         for (Rule rule: rules) {
171             rule.start(ctx);
172         }
173     }
174 
175     public void apply(List acuList, RuleContext ctx) {
176         long start = System.nanoTime();
177         for (Rule rule: rules) {
178             if (!rule.usesRuleChain()) {
179                 rule.apply(acuList, ctx);
180                 long end = System.nanoTime();
181                 Benchmark.mark(Benchmark.TYPE_RULE, rule.getName(), end - start, 1);
182                 start = end;
183             }
184         }
185     }
186     
187     public void end(RuleContext ctx) {
188         for (Rule rule: rules) {
189             rule.end(ctx);
190         }
191     }
192 
193     /**
194      * @see java.lang.Object#equals(java.lang.Object)
195      */
196     public boolean equals(Object o) {
197         if ((o == null) || !(o instanceof RuleSet)) {
198             return false; // Trivial
199         }
200 
201         if (this == o) {
202             return true; // Basic equality
203         }
204 
205         RuleSet ruleSet = (RuleSet) o;
206         return this.getName().equals(ruleSet.getName()) && this.getRules().equals(ruleSet.getRules());
207     }
208 
209     /**
210      * @see java.lang.Object#hashCode()
211      */
212     public int hashCode() {
213         return this.getName().hashCode() + 13 * this.getRules().hashCode();
214     }
215 
216     public Language getLanguage() {
217         return language;
218     }
219 
220     public void setLanguage(Language language) {
221         this.language = language;
222     }
223 
224     public String getFileName() {
225 		return fileName;
226 	}
227 
228 	public void setFileName(String fileName) {
229 		this.fileName = fileName;
230 	}
231 
232 	public String getName() {
233         return name;
234     }
235 
236     public void setName(String name) {
237         this.name = name;
238     }
239 
240     public String getDescription() {
241         return description;
242     }
243 
244     public void setDescription(String description) {
245         this.description = description;
246     }
247 
248     public List<String> getExcludePatterns() {
249         return this.excludePatterns;
250     }
251 
252     public void addExcludePattern(String excludePattern) {
253         this.excludePatterns.add(excludePattern);
254     }
255 
256     public void addExcludePatterns(List<String> excludePatterns) {
257         this.excludePatterns.addAll(excludePatterns);
258     }
259 
260     public void setExcludePatterns(List<String> excludePatterns) {
261     	this.excludePatterns = excludePatterns;
262     }
263 
264     public List<String> getIncludePatterns() {
265         return this.includePatterns;
266     }
267  
268     public void addIncludePattern(String includePattern) {
269         this.includePatterns.add(includePattern);
270     }
271     
272     public void addIncludePatterns(List<String> includePatterns) {
273         this.includePatterns.addAll(includePatterns);
274     }
275 
276     public void setIncludePatterns(List<String> includePatterns) {
277     	this.includePatterns = includePatterns;
278     }
279 
280 	public boolean usesTypeResolution() {
281         for (Rule r: rules) {
282             if (r.usesTypeResolution()) {
283                 return true;
284             }
285         }
286         return false;
287 	}
288 
289 }