KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > visitclass > PreorderVisitor


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003,2004 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.visitclass;
21
22 import java.util.HashSet JavaDoc;
23 import java.util.Set JavaDoc;
24 import java.util.regex.Matcher JavaDoc;
25 import java.util.regex.Pattern JavaDoc;
26
27 import org.apache.bcel.classfile.Attribute;
28 import org.apache.bcel.classfile.Code;
29 import org.apache.bcel.classfile.CodeException;
30 import org.apache.bcel.classfile.Constant;
31 import org.apache.bcel.classfile.ConstantClass;
32 import org.apache.bcel.classfile.ConstantPool;
33 import org.apache.bcel.classfile.ConstantUtf8;
34 import org.apache.bcel.classfile.Field;
35 import org.apache.bcel.classfile.InnerClass;
36 import org.apache.bcel.classfile.InnerClasses;
37 import org.apache.bcel.classfile.JavaClass;
38 import org.apache.bcel.classfile.LineNumber;
39 import org.apache.bcel.classfile.LineNumberTable;
40 import org.apache.bcel.classfile.LocalVariable;
41 import org.apache.bcel.classfile.LocalVariableTable;
42 import org.apache.bcel.classfile.Method;
43
44 /**
45  * Interface to make the use of a visitor pattern programming style possible.
46  * I.e. a class that implements this interface can traverse the contents of
47  * a Java class just by calling the `accept' method which all classes have.
48  * <p/>
49  * Implemented by wish of
50  * <A HREF="http://www.inf.fu-berlin.de/~bokowski">Boris Bokowski</A>.
51  * <p/>
52  * If don't like it, blame him. If you do like it thank me 8-)
53  *
54  * @author <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
55  * @version 970819
56  */

57 public abstract class PreorderVisitor extends BetterVisitor implements Constants2 {
58
59     // Available when visiting a class
60
private ConstantPool constantPool;
61     private JavaClass thisClass;
62     private String JavaDoc className = "none";
63     private String JavaDoc dottedClassName = "none";
64     private String JavaDoc packageName = "none";
65     private String JavaDoc sourceFile = "none";
66     private String JavaDoc superclassName = "none";
67     private String JavaDoc dottedSuperclassName = "none";
68
69     // Available when visiting a method
70
private boolean visitingMethod = false;
71     private String JavaDoc methodSig = "none";
72     private String JavaDoc dottedMethodSig = "none";
73     private Method method = null;
74     private String JavaDoc methodName = "none";
75     private String JavaDoc fullyQualifiedMethodName = "none";
76
77     // Available when visiting a field
78
private Field field;
79     private boolean visitingField = false;
80     private String JavaDoc fullyQualifiedFieldName = "none";
81     private String JavaDoc fieldName = "none";
82     private String JavaDoc fieldSig = "none";
83     private String JavaDoc dottedFieldSig = "none";
84     private boolean fieldIsStatic;
85     
86     // Available when visiting a Code
87
private Code code;
88
89     protected String JavaDoc getStringFromIndex(int i) {
90         ConstantUtf8 name = (ConstantUtf8) constantPool.getConstant(i);
91         return name.getBytes();
92     }
93
94     protected int asUnsignedByte(byte b) {
95         return 0xff & b;
96     }
97
98     /**
99      * Return the current Code attribute; assuming one is being visited
100      * @return current code attribute
101      */

102      public Code getCode() {
103         if (code == null) throw new IllegalStateException JavaDoc("Not visiting Code");
104         return code;
105     }
106      
107      public Set JavaDoc<String JavaDoc> getSurroundingCaughtExceptions(int pc) {
108          HashSet JavaDoc<String JavaDoc> result = new HashSet JavaDoc<String JavaDoc>();
109             if (code == null) throw new IllegalStateException JavaDoc("Not visiting Code");
110             int size = Integer.MAX_VALUE;
111             if (code.getExceptionTable() == null) return result;
112             for (CodeException catchBlock : code.getExceptionTable()) {
113                 int startPC = catchBlock.getStartPC();
114                 int endPC = catchBlock.getEndPC();
115                 if (pc >= startPC && pc <= endPC) {
116                     int thisSize = endPC - startPC;
117                     if (size > thisSize) {
118                         result.clear();
119                         size = thisSize;
120                         result.add("C" + catchBlock.getCatchType());
121                     } else if (size == thisSize)
122                         result.add("C" + catchBlock.getCatchType());
123                 }
124             }
125             return result;
126      }
127      /**
128       * Get lines of code in try block that surround pc
129       * @param pc
130       * @return number of lines of code in try block
131       */

132      public int getSizeOfSurroundingTryBlock(int pc) {
133          return getSizeOfSurroundingTryBlock(null, pc);
134      }
135      /**
136       * Get lines of code in try block that surround pc
137       * @param pc
138       * @return number of lines of code in try block
139       */

140      public int getSizeOfSurroundingTryBlock(String JavaDoc vmNameOfExceptionClass, int pc) {
141             if (code == null) throw new IllegalStateException JavaDoc("Not visiting Code");
142             return Util.getSizeOfSurroundingTryBlock(constantPool, code, vmNameOfExceptionClass, pc);
143      }
144     // Attributes
145
@Override JavaDoc
146          public void visitCode(Code obj) {
147         code = obj;
148         super.visitCode(obj);
149         CodeException[] exceptions = obj.getExceptionTable();
150         for (CodeException exception : exceptions)
151             exception.accept(this);
152         Attribute[] attributes = obj.getAttributes();
153         for (Attribute attribute : attributes)
154             attribute.accept(this);
155         code = null;
156     }
157
158     // Constants
159
@Override JavaDoc
160          public void visitConstantPool(ConstantPool obj) {
161         super.visitConstantPool(obj);
162         Constant[] constant_pool = obj.getConstantPool();
163         for (int i = 1; i < constant_pool.length; i++) {
164             constant_pool[i].accept(this);
165             byte tag = constant_pool[i].getTag();
166             if ((tag == CONSTANT_Double) || (tag == CONSTANT_Long))
167                 i++;
168         }
169     }
170
171     private void doVisitField(Field field) {
172         if (visitingField)
173             throw new IllegalStateException JavaDoc("visitField called when already visiting a field");
174         visitingField = true;
175         this.field = field;
176         try {
177             fieldName = fieldSig = dottedFieldSig = fullyQualifiedFieldName = null;
178             
179             fieldIsStatic = field.isStatic();
180             field.accept(this);
181             Attribute[] attributes = field.getAttributes();
182             for (Attribute attribute : attributes)
183                 attribute.accept(this);
184         } finally {
185             visitingField = false;
186             this.field = null;
187         }
188     }
189
190     public void doVisitMethod(Method method) {
191         if (visitingMethod)
192             throw new IllegalStateException JavaDoc("doVisitMethod called when already visiting a method");
193         visitingMethod = true;
194         try {
195             this.method = method;
196             methodName = methodSig = dottedMethodSig = fullyQualifiedMethodName = null;
197
198             this.method.accept(this);
199             Attribute[] attributes = method.getAttributes();
200             for (Attribute attribute : attributes)
201                 attribute.accept(this);
202         } finally {
203             visitingMethod = false;
204         }
205     }
206
207     // Extra classes (i.e. leaves in this context)
208
@Override JavaDoc
209          public void visitInnerClasses(InnerClasses obj) {
210         super.visitInnerClasses(obj);
211         InnerClass[] inner_classes = obj.getInnerClasses();
212         for (InnerClass inner_class : inner_classes)
213             inner_class.accept(this);
214     }
215
216     public void visitAfter(JavaClass obj) {
217     }
218
219     // General classes
220
@Override JavaDoc
221          public void visitJavaClass(JavaClass obj) {
222         setupVisitorForClass(obj);
223         constantPool.accept(this);
224         Field[] fields = obj.getFields();
225         Method[] methods = obj.getMethods();
226         Attribute[] attributes = obj.getAttributes();
227         for (Field field : fields)
228             doVisitField(field);
229         for (Method method1 : methods)
230             doVisitMethod(method1);
231         for (Attribute attribute : attributes)
232             attribute.accept(this);
233         visitAfter(obj);
234     }
235
236     public void setupVisitorForClass(JavaClass obj) {
237         constantPool = obj.getConstantPool();
238         thisClass = obj;
239         ConstantClass c = (ConstantClass) constantPool.getConstant(obj.getClassNameIndex());
240         className = getStringFromIndex(c.getNameIndex());
241         dottedClassName = className.replace('/', '.');
242         packageName = obj.getPackageName();
243         sourceFile = obj.getSourceFileName();
244         superclassName = obj.getSuperclassName();
245         dottedSuperclassName = superclassName.replace('/', '.');
246
247         super.visitJavaClass(obj);
248     }
249
250     @Override JavaDoc
251          public void visitLineNumberTable(LineNumberTable obj) {
252         super.visitLineNumberTable(obj);
253         LineNumber[] line_number_table = obj.getLineNumberTable();
254         for (LineNumber aLine_number_table : line_number_table)
255             aLine_number_table.accept(this);
256     }
257
258     @Override JavaDoc
259          public void visitLocalVariableTable(LocalVariableTable obj) {
260         super.visitLocalVariableTable(obj);
261         LocalVariable[] local_variable_table = obj.getLocalVariableTable();
262         for (LocalVariable aLocal_variable_table : local_variable_table)
263             aLocal_variable_table.accept(this);
264     }
265
266     // Accessors
267

268     /** Get the constant pool for the current or most recently visited class */
269     public ConstantPool getConstantPool() {
270         return constantPool;
271     }
272
273     /** Get the slash-formatted class name for the current or most recently visited class */
274     public String JavaDoc getClassName() {
275         return className;
276     }
277
278     /** Get the dotted class name for the current or most recently visited class */
279     public String JavaDoc getDottedClassName() {
280         return dottedClassName;
281     }
282
283     /** Get the (slash-formatted?) package name for the current or most recently visited class */
284     public String JavaDoc getPackageName() {
285         return packageName;
286     }
287
288     /** Get the source file name for the current or most recently visited class */
289     public String JavaDoc getSourceFile() {
290         return sourceFile;
291     }
292
293     /** Get the slash-formatted superclass name for the current or most recently visited class */
294     public String JavaDoc getSuperclassName() {
295         return superclassName;
296     }
297
298     /** Get the dotted superclass name for the current or most recently visited class */
299     public String JavaDoc getDottedSuperclassName() {
300         return dottedSuperclassName;
301     }
302
303     /** Get the JavaClass object for the current or most recently visited class */
304     public JavaClass getThisClass() {
305         return thisClass;
306     }
307
308     /** If currently visiting a method, get the method's fully qualified name */
309     public String JavaDoc getFullyQualifiedMethodName() {
310         if (!visitingMethod)
311             throw new IllegalStateException JavaDoc("getFullyQualifiedMethodName called while not visiting method");
312         if (fullyQualifiedMethodName == null) {
313             getDottedSuperclassName();
314             getMethodName();
315             getDottedMethodSig();
316             StringBuffer JavaDoc ref = new StringBuffer JavaDoc(5 + dottedClassName.length()
317                     + methodName.length()
318                     + dottedMethodSig.length());
319
320             ref.append(dottedClassName)
321                     .append(".")
322                     .append(methodName)
323                     .append(" : ")
324                     .append(dottedMethodSig);
325             fullyQualifiedMethodName = ref.toString();
326         }
327         return fullyQualifiedMethodName;
328     }
329
330     /**
331     * is the visitor currently visiting a method?
332     */

333     public boolean visitingMethod() {
334         return visitingMethod;
335         }
336     /**
337     * is the visitor currently visiting a field?
338     */

339     public boolean visitingField() {
340         return visitingField;
341         }
342     /** If currently visiting a method, get the method's Method object */
343     public Field getField() {
344         if (!visitingField)
345             throw new IllegalStateException JavaDoc("getField called while not visiting method");
346         return field;
347     }
348     /** If currently visiting a method, get the method's Method object */
349     public Method getMethod() {
350         if (!visitingMethod)
351             throw new IllegalStateException JavaDoc("getMethod called while not visiting method");
352         return method;
353     }
354
355     /** If currently visiting a method, get the method's name */
356     public String JavaDoc getMethodName() {
357         if (!visitingMethod)
358             throw new IllegalStateException JavaDoc("getMethodName called while not visiting method");
359         if (methodName == null)
360             methodName = getStringFromIndex(method.getNameIndex());
361         
362         return methodName;
363     }
364
365     static Pattern JavaDoc argumentSignature = Pattern.compile("\\[*([BCDFIJSZ]|L[^;]*;)");
366     
367     public static int getNumberArguments(String JavaDoc signature) {
368         int paren = signature.indexOf(')');
369         
370         if (paren == -1) throw new IllegalArgumentException JavaDoc(signature);
371         Matcher JavaDoc m = argumentSignature.matcher(signature.substring(1, paren));
372         int result = 0;
373         while(m.find())
374             result++;
375         return result;
376         
377     }
378     
379     
380     public int getNumberMethodArguments() {
381         return getNumberArguments(getMethodSig());
382     }
383     /** If currently visiting a method, get the method's slash-formatted signature */
384     public String JavaDoc getMethodSig() {
385         if (!visitingMethod)
386             throw new IllegalStateException JavaDoc("getMethodSig called while not visiting method");
387         if (methodSig == null)
388             methodSig = getStringFromIndex(method.getSignatureIndex());
389         return methodSig;
390     }
391
392     /** If currently visiting a method, get the method's dotted method signature */
393     public String JavaDoc getDottedMethodSig() {
394         if (!visitingMethod)
395             throw new IllegalStateException JavaDoc("getDottedMethodSig called while not visiting method");
396         if (dottedMethodSig == null)
397             dottedMethodSig = getMethodSig().replace('/', '.');
398         return dottedMethodSig;
399     }
400
401     /** If currently visiting a field, get the field's name */
402     public String JavaDoc getFieldName() {
403         if (!visitingField)
404             throw new IllegalStateException JavaDoc("getFieldName called while not visiting field");
405         if (fieldName == null)
406             fieldName = getStringFromIndex(field.getNameIndex());
407     
408         
409
410         return fieldName;
411     }
412
413     /** If currently visiting a field, get the field's slash-formatted signature */
414     public String JavaDoc getFieldSig() {
415         if (!visitingField)
416             throw new IllegalStateException JavaDoc("getFieldSig called while not visiting field");
417         if (fieldSig == null) fieldSig = getStringFromIndex(field.getSignatureIndex());
418         return fieldSig;
419     }
420
421     /** If currently visiting a field, return whether or not the field is static */
422     public boolean getFieldIsStatic() {
423         if (!visitingField)
424             throw new IllegalStateException JavaDoc("getFieldIsStatic called while not visiting field");
425         return fieldIsStatic;
426     }
427
428     /** If currently visiting a field, get the field's fully qualified name */
429     public String JavaDoc getFullyQualifiedFieldName() {
430         if (!visitingField)
431             throw new IllegalStateException JavaDoc("getFullyQualifiedFieldName called while not visiting field");
432         if (fullyQualifiedFieldName == null)
433             fullyQualifiedFieldName = getDottedClassName() + "." + getFieldName()
434             + " : " + getFieldSig();
435         return fullyQualifiedFieldName;
436     }
437
438     /** If currently visiting a field, get the field's dot-formatted signature */
439     @Deprecated JavaDoc
440     public String JavaDoc getDottedFieldSig() {
441         if (!visitingField)
442             throw new IllegalStateException JavaDoc("getDottedFieldSig called while not visiting field");
443         if (dottedFieldSig == null)
444             dottedFieldSig = fieldSig.replace('/', '.');
445         return dottedFieldSig;
446     }
447
448 }
449
Popular Tags