001: package com.mockrunner.gen.proc;
002:
003: import java.lang.reflect.Array;
004: import java.util.ArrayList;
005: import java.util.Arrays;
006: import java.util.HashMap;
007: import java.util.List;
008: import java.util.Map;
009:
010: import org.apache.bcel.Repository;
011: import org.apache.bcel.classfile.Attribute;
012: import org.apache.bcel.classfile.Deprecated;
013: import org.apache.bcel.classfile.EmptyVisitor;
014: import org.apache.bcel.classfile.JavaClass;
015: import org.apache.bcel.classfile.LocalVariable;
016: import org.apache.bcel.classfile.LocalVariableTable;
017: import org.apache.bcel.generic.ArrayType;
018: import org.apache.bcel.generic.BasicType;
019: import org.apache.bcel.generic.ObjectType;
020: import org.apache.bcel.generic.Type;
021:
022: public class BCELClassAnalyzer {
023: private Map methodMap;
024:
025: public BCELClassAnalyzer(Class clazz) {
026: methodMap = new HashMap();
027: try {
028: prepareMethodMap(clazz);
029: } catch (ClassNotFoundException exc) {
030: throw new RuntimeException(exc);
031: }
032: }
033:
034: public boolean isMethodDeprecated(
035: java.lang.reflect.Method reflectMethod) {
036: org.apache.bcel.classfile.Method bcelMethod = getBCELMethod(reflectMethod);
037: if (null == bcelMethod)
038: return false;
039: Attribute[] attributes = bcelMethod.getAttributes();
040: DeprecatedVisitor visitor = new DeprecatedVisitor();
041: for (int ii = 0; ii < attributes.length; ii++) {
042: attributes[ii].accept(visitor);
043: if (visitor.isDeprecated()) {
044: return true;
045: }
046: }
047: return false;
048: }
049:
050: public String[] getArgumentNames(
051: java.lang.reflect.Method reflectMethod) {
052: org.apache.bcel.classfile.Method bcelMethod = getBCELMethod(reflectMethod);
053: if (null == bcelMethod)
054: return null;
055: LocalVariableTable table = bcelMethod.getLocalVariableTable();
056: if (null == table)
057: return null;
058: LocalVariable[] variables = table.getLocalVariableTable();
059: if (null == variables)
060: return null;
061: int firstIndex = 0;
062: while ((firstIndex < variables.length)
063: && (variables[firstIndex].getName().equals("this"))) {
064: firstIndex++;
065: }
066: Type[] types = bcelMethod.getArgumentTypes();
067: if (null == types)
068: return null;
069: if ((variables.length - firstIndex) < types.length)
070: return null;
071: String[] names = new String[types.length];
072: for (int ii = 0; ii < types.length; ii++) {
073: names[ii] = variables[firstIndex + ii].getName();
074: }
075: return names;
076: }
077:
078: private org.apache.bcel.classfile.Method getBCELMethod(
079: java.lang.reflect.Method reflectMethod) {
080: return (org.apache.bcel.classfile.Method) methodMap
081: .get(reflectMethod);
082: }
083:
084: private void prepareMethodMap(Class clazz)
085: throws ClassNotFoundException {
086: java.lang.reflect.Method[] reflectMethods = clazz
087: .getDeclaredMethods();
088: JavaClass javaClass = Repository.lookupClass(clazz);
089: org.apache.bcel.classfile.Method[] bcelMethods = javaClass
090: .getMethods();
091: List reflectMethodList = new ArrayList(Arrays
092: .asList(reflectMethods));
093: List bcelMethodList = new ArrayList(Arrays.asList(bcelMethods));
094: while (!reflectMethodList.isEmpty()) {
095: findAndAddBCELMethod(reflectMethodList, bcelMethodList);
096: }
097: }
098:
099: private void findAndAddBCELMethod(List reflectMethodList,
100: List bcelMethodList) {
101: java.lang.reflect.Method reflectMethod = (java.lang.reflect.Method) reflectMethodList
102: .remove(0);
103: for (int ii = 0; ii < bcelMethodList.size(); ii++) {
104: org.apache.bcel.classfile.Method bcelMethod = (org.apache.bcel.classfile.Method) bcelMethodList
105: .get(ii);
106: if (areMethodsEqual(reflectMethod, bcelMethod)) {
107: methodMap.put(reflectMethod, bcelMethod);
108: }
109: }
110: }
111:
112: private boolean areMethodsEqual(
113: java.lang.reflect.Method reflectMethod,
114: org.apache.bcel.classfile.Method bcelMethod) {
115: if (null == reflectMethod || null == bcelMethod)
116: return false;
117: if (!(reflectMethod.getName().equals(bcelMethod.getName())))
118: return false;
119: Class reflectReturnType = reflectMethod.getReturnType();
120: Class bcelReturnType = typeToClass(bcelMethod.getReturnType());
121: if (!(reflectReturnType.equals(bcelReturnType)))
122: return false;
123: Class[] reflectArgumentTypes = reflectMethod
124: .getParameterTypes();
125: Class[] bcelArgumentTypes = getBCELArgumentList(bcelMethod);
126: return Arrays.equals(reflectArgumentTypes, bcelArgumentTypes);
127: }
128:
129: private Class[] getBCELArgumentList(
130: org.apache.bcel.classfile.Method bcelMethod) {
131: Type[] bcelArguments = bcelMethod.getArgumentTypes();
132: List argumentList = new ArrayList();
133: for (int ii = 0; ii < bcelArguments.length; ii++) {
134: Class currentClass = typeToClass(bcelArguments[ii]);
135: if (null != currentClass) {
136: argumentList.add(currentClass);
137: }
138: }
139: return (Class[]) argumentList.toArray(new Class[argumentList
140: .size()]);
141: }
142:
143: private Class typeToClass(Type type) {
144: if (!(type instanceof ArrayType)) {
145: return simpleTypeToClass(type);
146: }
147: ArrayType arrayType = (ArrayType) type;
148: Class basicClass = simpleTypeToClass(arrayType.getBasicType());
149: if (null == basicClass)
150: return null;
151: return Array.newInstance(basicClass,
152: new int[arrayType.getDimensions()]).getClass();
153: }
154:
155: private Class simpleTypeToClass(Type type) {
156: if (null == type)
157: return null;
158: if (type instanceof BasicType) {
159: BasicType basicType = (BasicType) type;
160: if (basicType.equals(Type.BOOLEAN)) {
161: return Boolean.TYPE;
162: }
163: if (basicType.equals(Type.BYTE)) {
164: return Byte.TYPE;
165: }
166: if (basicType.equals(Type.CHAR)) {
167: return Character.TYPE;
168: }
169: if (basicType.equals(Type.DOUBLE)) {
170: return Double.TYPE;
171: }
172: if (basicType.equals(Type.FLOAT)) {
173: return Float.TYPE;
174: }
175: if (basicType.equals(Type.INT)) {
176: return Integer.TYPE;
177: }
178: if (basicType.equals(Type.LONG)) {
179: return Long.TYPE;
180: }
181: if (basicType.equals(Type.SHORT)) {
182: return Short.TYPE;
183: }
184: if (basicType.equals(Type.VOID)) {
185: return Void.TYPE;
186: }
187: } else if (type instanceof ObjectType) {
188: ObjectType objectType = (ObjectType) type;
189: try {
190: return Class.forName(objectType.getClassName());
191: } catch (ClassNotFoundException exc) {
192: throw new RuntimeException(exc);
193: }
194: }
195: return null;
196: }
197:
198: private class DeprecatedVisitor extends EmptyVisitor {
199: private boolean deprecated = false;
200:
201: public void visitDeprecated(Deprecated deprecatedValue) {
202: deprecated = true;
203: }
204:
205: public boolean isDeprecated() {
206: return deprecated;
207: }
208: }
209: }
|