Source code: com/puppycrawl/tools/checkstyle/bcel/classfile/JavaClassDefinition.java
1 //Tested with BCEL-5.1
2 //http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
3
4 package com.puppycrawl.tools.checkstyle.bcel.classfile;
5
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Map;
9 import java.util.Set;
10
11 import org.apache.bcel.Repository;
12 import org.apache.bcel.classfile.Field;
13 import org.apache.bcel.classfile.JavaClass;
14 import org.apache.bcel.classfile.Method;
15 import org.apache.bcel.generic.Type;
16
17
18 /**
19 * Contains the definition of a org.apache.bcel.classfile.JavaClass and
20 * the definitions of Methods and Fields of the JavaClass
21 * @author Rick Giles
22 */
23 public class JavaClassDefinition
24 {
25 /** the JavaClass */
26 private JavaClass mJavaClass;
27
28 /** the method definitions */
29 private MethodDefinition[] mMethodDefs;
30
31 /** field definitions, keyed on field name */
32 private Map mFieldDefs;
33
34 /**
35 * Creates a JavaClassDefinition from a JavaClass. The fields and
36 * methods of the JavaClassDefinition are those whose scopes are
37 * in restricted sets of Scopes.
38 * @param aJavaClass the JavaClass for the definition.
39 * @param aFieldScopes the restricted set of field scopes.
40 * @param aMethodScopes the restriced set of method scopes.
41 */
42 public JavaClassDefinition(
43 JavaClass aJavaClass,
44 Set aFieldScopes,
45 Set aMethodScopes)
46 {
47 mJavaClass = aJavaClass;
48
49 // create method definitions, restricted by scope
50 final Method[] methods = aJavaClass.getMethods();
51 final Set methodSet = new HashSet();
52 mMethodDefs = new MethodDefinition[methods.length];
53 for (int i = 0; i < methods.length; i++) {
54 if (Utils.inScope(methods[i], aMethodScopes)) {
55 methodSet.add(new MethodDefinition(methods[i]));
56 }
57 }
58 mMethodDefs =
59 (MethodDefinition[]) methodSet.toArray(
60 new MethodDefinition[methodSet.size()]);
61
62 // create field definitions, restricted by scope
63 final Field[] fields = aJavaClass.getFields();
64 mFieldDefs = new HashMap(fields.length);
65 for (int i = 0; i < fields.length; i++) {
66 if (Utils.inScope(fields[i], aFieldScopes)) {
67 mFieldDefs.put(
68 fields[i].getName(),
69 new FieldDefinition(fields[i]));
70 }
71 }
72 }
73
74 /**
75 * Gets the JavaClass for this definition.
76 * @return the JavaClass
77 */
78 public JavaClass getJavaClass()
79 {
80 return mJavaClass;
81 }
82
83 /**
84 * Gets the method definitions for Methods of the JavaClass.
85 * @return the method definitions for Methods of the JavaClass.
86 */
87 public MethodDefinition[] getMethodDefs()
88 {
89 return mMethodDefs;
90 }
91
92 /**
93 * Gets the field definitions for Fields of the JavaClass.
94 * @return the method definitions for Fields of the JavaClass.
95 */
96 public FieldDefinition[] getFieldDefs()
97 {
98 return (FieldDefinition[]) mFieldDefs.values().toArray(
99 new FieldDefinition[mFieldDefs.size()]);
100 }
101
102 /**
103 * Finds the narrowest method that is compatible with a method.
104 * An invocation of the given method can be resolved as an invocation
105 * of the narrowest method.
106 * @param aClassName the class for the method.
107 * @param aMethodName the name of the method.
108 * @param aArgTypes the types for the method.
109 * @return the narrowest compatible method.
110 */
111 public MethodDefinition findNarrowestMethod(
112 String aClassName,
113 String aMethodName,
114 Type[] aArgTypes)
115 {
116 MethodDefinition result = null;
117 final String javaClassName = mJavaClass.getClassName();
118 if (Repository.instanceOf(aClassName, javaClassName)) {
119 // check all
120 for (int i = 0; i < mMethodDefs.length; i++) {
121 // TODO: check access privileges
122 if (mMethodDefs[i].isCompatible(aMethodName, aArgTypes)) {
123 if (result == null) {
124 result = mMethodDefs[i];
125 }
126 //else if (mMethodDefs[i].isAsNarrow(result)) {
127 else if (result.isCompatible(mMethodDefs[i])) {
128 result = mMethodDefs[i];
129 }
130 }
131 }
132 }
133 return result;
134 }
135
136 /**
137 * Finds a field definition.
138 * @param aFieldName the name of the field.
139 * @return the field definition named aFieldName.
140 */
141 public FieldDefinition findFieldDef(String aFieldName)
142 {
143 return (FieldDefinition) mFieldDefs.get(aFieldName);
144 }
145
146 /**
147 * Determines whether there is reference to a given Method in this JavaClass
148 * definition or a definition in a superclass.
149 * @param aMethodDef the Method to check.
150 * @param aReferenceDAO reference DAO.
151 * @return true if there is a reference to the method of aMethodDef in
152 * this JavaClass or a superclass.
153 */
154 public boolean hasReference(
155 MethodDefinition aMethodDef,
156 ReferenceDAO aReferenceDAO)
157 {
158 final String methodName = aMethodDef.getName();
159 final Type[] argTypes = aMethodDef.getArgumentTypes();
160
161 // search the inheritance hierarchy
162 JavaClass currentJavaClass = getJavaClass();
163 while (currentJavaClass != null) {
164 final JavaClassDefinition javaClassDef =
165 aReferenceDAO.findJavaClassDef(currentJavaClass);
166 if (javaClassDef != null) {
167 final MethodDefinition methodDef =
168 javaClassDef.findNarrowestMethod(
169 getJavaClass().getClassName(),
170 methodName,
171 argTypes);
172 if ((methodDef != null)
173 && (methodDef.hasReference(getJavaClass())))
174 {
175 return true;
176 }
177 }
178 currentJavaClass = currentJavaClass.getSuperClass();
179 }
180 return false;
181 }
182
183 /** @see java.lang.Object#toString() */
184 public String toString()
185 {
186 return getJavaClass().toString();
187 }
188 }