KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hammurapi > inspectors > filters > LanguageElementFilter


1 /*
2   * Hammurapi
3  * Automated Java code review system.
4  * Copyright (C) 2004 Hammurapi Group
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * URL: http://www.hammurapi.org
21  * e-Mail: support@hammurapi.biz
22  */

23 package org.hammurapi.inspectors.filters;
24
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.util.Stack JavaDoc;
28
29 import org.apache.oro.text.GlobCompiler;
30 import org.apache.oro.text.regex.MalformedPatternException;
31 import org.apache.oro.text.regex.Pattern;
32 import org.apache.oro.text.regex.Perl5Matcher;
33 import org.hammurapi.InspectorBase;
34 import org.hammurapi.FilteringInspector;
35
36 import com.pavelvlasov.config.ConfigurationException;
37 import com.pavelvlasov.config.Parameterizable;
38 import com.pavelvlasov.jsel.CompilationUnit;
39 import com.pavelvlasov.jsel.JselException;
40 import com.pavelvlasov.jsel.Operation;
41 import com.pavelvlasov.jsel.Package;
42 import com.pavelvlasov.jsel.TypeBody;
43 import com.pavelvlasov.jsel.TypeDefinition;
44
45 /**
46  * Initial behavior of the filter to approve everything.
47  * @author Pavel Vlasov
48  * @version $Revision: 1.6 $
49  */

50 public class LanguageElementFilter extends InspectorBase implements
51         FilteringInspector, Parameterizable {
52     
53     private Stack JavaDoc approvals=new Stack JavaDoc();
54     
55     {
56         //Initial state of filter is approve
57
approvals.push(Boolean.TRUE);
58     }
59     
60     private static class ElementEntry {
61         boolean exclude;
62         String JavaDoc name;
63         String JavaDoc operationSignature;
64         Pattern fileNamePattern;
65     }
66     
67     private LinkedList JavaDoc elements=new LinkedList JavaDoc();
68     
69     public Boolean JavaDoc approve(Object JavaDoc element) {
70         return (Boolean JavaDoc) approvals.peek();
71     }
72         
73     private Perl5Matcher matcher=new Perl5Matcher();
74     
75     public void visit(CompilationUnit compilationUnit) {
76         Package JavaDoc pkg=compilationUnit.getPackage();
77         // Carry over previous state.
78
boolean decision=((Boolean JavaDoc) approvals.peek()).booleanValue();
79         
80         Iterator JavaDoc it=elements.iterator();
81         while (it.hasNext()) {
82             ElementEntry entry=(ElementEntry) it.next();
83             if (entry.name!=null && entry.operationSignature==null &&
84                     ("*".equals(entry.name)
85                             || pkg.getName().equals(entry.name)
86                             || (entry.name.endsWith(".*") && pkg.getName().startsWith(entry.name.substring(0, entry.name.length()-2))))) {
87                 decision = !entry.exclude;
88                 break;
89             }
90         }
91         approvals.push(decision ? Boolean.TRUE : Boolean.FALSE);
92
93         
94         // Carry over previous state.
95
decision=((Boolean JavaDoc) approvals.peek()).booleanValue();
96         
97         it=elements.iterator();
98         while (it.hasNext()) {
99             ElementEntry entry=(ElementEntry) it.next();
100             if (entry.fileNamePattern!=null && matcher.matches(compilationUnit.getName(), entry.fileNamePattern)) {
101                 decision = !entry.exclude;
102                 break;
103             }
104         }
105         approvals.push(decision ? Boolean.TRUE : Boolean.FALSE);
106     }
107     
108     public void leave(CompilationUnit compilaitonUnit) {
109         approvals.pop();
110         approvals.pop();
111     }
112     
113     /**
114      * Includes/excludes type only if package is included.
115      * @param typeBody
116      */

117     public void visit(TypeBody typeBody) {
118         // Carry over previous state.
119
boolean decision=((Boolean JavaDoc) approvals.peek()).booleanValue();
120         
121         // Evaluate only if package included
122
if (decision) {
123             Iterator JavaDoc it=elements.iterator();
124             while (it.hasNext()) {
125                 ElementEntry entry=(ElementEntry) it.next();
126                 try {
127                     if (entry.name!=null && entry.operationSignature==null && typeBody.isKindOf(entry.name)) {
128                         decision = !entry.exclude;
129                         break;
130                     }
131                 } catch (JselException e) {
132                     if (!(e.getCause() instanceof ClassNotFoundException JavaDoc)) {
133                         context.warn(typeBody, e);
134                         break;
135                     }
136                 }
137             }
138         }
139         
140         approvals.push(decision ? Boolean.TRUE : Boolean.FALSE);
141     }
142         
143     public void leave(TypeDefinition typeDefinition) {
144         approvals.pop();
145     }
146     
147     public void visit(Operation operation) {
148         // Carry over previous state.
149
boolean decision=((Boolean JavaDoc) approvals.peek()).booleanValue();
150         
151         // Evaluate only if type included
152
if (decision) {
153             Iterator JavaDoc it=elements.iterator();
154             while (it.hasNext()) {
155                 ElementEntry entry=(ElementEntry) it.next();
156                 try {
157                     if (entry.name!=null && entry.operationSignature!=null && ("*".equals(entry.name) || operation.getEnclosingType().isKindOf(entry.name)) && operation.getInfo().isArgumentCompatible(entry.operationSignature)) {
158                         decision = !entry.exclude;
159                         break;
160                     }
161                 } catch (JselException e) {
162                     context.warn(operation, e);
163                     break;
164                 }
165             }
166         }
167         
168         approvals.push(decision ? Boolean.TRUE : Boolean.FALSE);
169     }
170     
171     public void leave(Operation operation) {
172         approvals.pop();
173     }
174
175     /**
176      * Supports <CODE>include</CODE>, <CODE>exclude</CODE>, <code>include-file</code>, and <code>exclude-file</code>.
177      * parameters. The first two apply to package, type and operation. The last two apply to compilation units.
178      * Order is significant - includes/excludes are applied
179      * in the same order as they defined. So including org.hammurapi.* and then excluding org.hammurapi.inspectors.* makes sense, but
180      * not vice versa.<BR>
181      * If package excluded all types and operations in it are excluded. If type is excluded all
182      * operations in this type are excluded.
183      * Operation parameters can contain <CODE>?</CODE> which matches any type.
184      * <P/>&lt;init&gt; shall be used as operation name for constructors.<P/>
185      * <CODE>include</CODE> and <CODE>exclude</CODE> parameters format:
186      * <UL>
187      * <LI><CODE>*</code> - matches anything</LI>
188      * <LI><code>&lt;string&gt;</code> - matches package, type or operation (if contains '(')</LI>
189      * <LI><code>&lt;string&gt;.*</code> - matches package and its subpackages</LI>
190      * </UL>
191      * Packages are matched literally, types are matched based on isKindOf(), including operation types as well.
192      * If operation doesn't contain type name then any type will match.<BR/>
193      *
194      * <code>include-file</code> and <code>exclude-file</code> parameter values are file name patterns. ? states for zero or one
195      * character, * states for zero or more characters. See {@link org.apache.oro.text.GlobCompiler} for more details.<p/>
196      * <DL>
197      * <DT><B>Examples</B></DT>
198      * <DD><code>&lt;parameter name="include"&gt;org.hammurapi&lt;/parameter&gt;</code> - includes package org.hammurapi</DD>
199      * <DD><code>&lt;parameter name="exclude"&gt;org.hammurapi.*&lt;/parameter&gt;</code> - excludes package org.hammurapi and its subpackages</DD>
200      * <DD><code>&lt;parameter name="exclude"&gt;org.hammurapi.InspectorDescriptor&lt;/parameter&gt;</code> - excludes interface org.hammurapi.InspectorDescriptor and its implementations</DD>
201      * <DD><code>&lt;parameter name="include"&gt;org.hammurapi.InspectorDescriptor.getMessage(java.lang.String)&lt;/parameter&gt;</code> -
202      * includes method interface org.hammurapi.InspectorDescriptor.getMessage(java.lang.String) and its implementations</DD>
203      * <DD><code>&lt;parameter name="exclude"&gt;toString()&lt;/parameter&gt;</code> - excludes toString() in all classes/interfaces</DD>
204      * <DD><code>&lt;parameter name="exclude"&gt;org.somepackage.SomeClass.&lt;init&gt;(?, java.util.List)&lt;/parameter&gt;</code> -
205      * excludes constructors which take two parameters, the first one of any type and the
206      * second one of type <code>java.util.List</code> or its implementations in <code>org.somepackage.SomeClass</code> and its subclasses</DD>
207      * <DD><code>&lt;parameter name="include-file"&gt;*.bpf&lt;/parameter&gt;</code> - includes .bpf files</DD>
208      */

209     public boolean setParameter(String JavaDoc name, Object JavaDoc parameter) throws ConfigurationException {
210         if ("include".equals(name)) {
211             ElementEntry entry=new ElementEntry();
212             entry.exclude=false;
213             parseParameter(parameter, entry);
214             elements.addFirst(entry);
215         } else if ("exclude".equals(name)) {
216             ElementEntry entry=new ElementEntry();
217             entry.exclude=true;
218             parseParameter(parameter, entry);
219             elements.addFirst(entry);
220         } else if ("include-file".equals(name)) {
221             GlobCompiler compiler=new GlobCompiler();
222             ElementEntry entry=new ElementEntry();
223             entry.exclude=false;
224             try {
225                 entry.fileNamePattern=compiler.compile((String JavaDoc) parameter);
226             } catch (MalformedPatternException e) {
227                 throw new ConfigurationException(e);
228             }
229             elements.addFirst(entry);
230         } else if ("exclude-file".equals(name)) {
231             GlobCompiler compiler=new GlobCompiler();
232             ElementEntry entry=new ElementEntry();
233             entry.exclude=true;
234             try {
235                 entry.fileNamePattern=compiler.compile((String JavaDoc) parameter);
236             } catch (MalformedPatternException e) {
237                 throw new ConfigurationException(e);
238             }
239             elements.addFirst(entry);
240         } else {
241             throw new ConfigurationException("Not supported parameter: "+name);
242         }
243         return true;
244     }
245
246     /**
247      * @param parameter
248      * @param entry
249      */

250     private static void parseParameter(Object JavaDoc parameter, ElementEntry entry) {
251         String JavaDoc value = (String JavaDoc) parameter;
252         int pi = value.indexOf('(');
253         if (pi==-1) {
254             entry.name=value;
255         } else {
256             int lastDot=value.lastIndexOf('.', pi);
257             if (lastDot==-1) {
258                 entry.name="*";
259                 entry.operationSignature=value;
260             } else {
261                 entry.name=value.substring(0, lastDot);
262                 entry.operationSignature=value.substring(lastDot+1);
263             }
264         }
265     }
266 }
267
Popular Tags