git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@126 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
CtMethod cm = ((CtClassType)cc).getMethodsCache(); | CtMethod cm = ((CtClassType)cc).getMethodsCache(); | ||||
while (cm != null) { | while (cm != null) { | ||||
if (Modifier.isPublic(cm.getModifiers())) | if (Modifier.isPublic(cm.getModifiers())) | ||||
h.put(cm, cm); | |||||
h.put(cm.getStringRep(), cm); | |||||
cm = cm.next; | cm = cm.next; | ||||
} | } |
*/ | */ | ||||
public final class CtMethod extends CtBehavior { | public final class CtMethod extends CtBehavior { | ||||
protected CtMethod next; | protected CtMethod next; | ||||
protected int cachedHashCode; | |||||
protected String cachedStringRep; | |||||
CtMethod(MethodInfo minfo, CtClass declaring) { | CtMethod(MethodInfo minfo, CtClass declaring) { | ||||
super(declaring, minfo); | super(declaring, minfo); | ||||
next = null; | next = null; | ||||
cachedHashCode = 0; | |||||
cachedStringRep = null; | |||||
} | } | ||||
/** | /** | ||||
* the hash codes for the two methods are equal. | * the hash codes for the two methods are equal. | ||||
*/ | */ | ||||
public int hashCode() { | public int hashCode() { | ||||
/* This method is overridden in ExistingMethod for optimization. | |||||
*/ | |||||
if (cachedHashCode == 0) { | |||||
String signature | |||||
= methodInfo.getName() + ':' + methodInfo.getDescriptor(); | |||||
return getStringRep().hashCode(); | |||||
} | |||||
// System.identityHashCode() returns 0 only for null. | |||||
cachedHashCode = System.identityHashCode(signature.intern()); | |||||
} | |||||
/* This method is also called by CtClassType.getMethods0(). | |||||
*/ | |||||
final String getStringRep() { | |||||
if (cachedStringRep == null) | |||||
cachedStringRep = methodInfo.getName() | |||||
+ Descriptor.getParamDescriptor(methodInfo.getDescriptor()); | |||||
return cachedHashCode; | |||||
return cachedStringRep; | |||||
} | } | ||||
/** | /** | ||||
*/ | */ | ||||
public boolean equals(Object obj) { | public boolean equals(Object obj) { | ||||
return obj != null && obj instanceof CtMethod | return obj != null && obj instanceof CtMethod | ||||
&& obj.hashCode() == hashCode(); | |||||
&& ((CtMethod)obj).getStringRep().equals(getStringRep()); | |||||
} | } | ||||
/** | /** |
while (it.hasNext()) { | while (it.hasNext()) { | ||||
MethodInfo minfo = (MethodInfo)it.next(); | MethodInfo minfo = (MethodInfo)it.next(); | ||||
if (minfo.getName().equals(name) | if (minfo.getName().equals(name) | ||||
&& Descriptor.eqSignature(minfo.getDescriptor(), descriptor)) | |||||
&& Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor)) | |||||
throw new CannotCompileException("duplicate method: " + name); | throw new CannotCompileException("duplicate method: " + name); | ||||
} | } | ||||
} | } |
} | } | ||||
/** | /** | ||||
* Returns true if desc1 and desc2 has the same signature. | |||||
* Returns true if the list of the parameter types of desc1 is equal to | |||||
* that of desc2. | |||||
* For example, "(II)V" and "(II)I" are equal. | |||||
*/ | */ | ||||
public static boolean eqSignature(String desc1, String desc2) { | |||||
public static boolean eqParamTypes(String desc1, String desc2) { | |||||
if (desc1.charAt(0) != '(') | if (desc1.charAt(0) != '(') | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Returns the signature of the given descriptor. The signature does | |||||
* not include the return type. For example, the signature of "(I)V" | |||||
* is "(I)". | |||||
*/ | |||||
public static String getParamDescriptor(String decl) { | |||||
return decl.substring(0, decl.indexOf(')') + 1); | |||||
} | |||||
/** | /** | ||||
* Returns the <code>CtClass</code> object representing the return | * Returns the <code>CtClass</code> object representing the return | ||||
* type specified by the given descriptor. | * type specified by the given descriptor. |
return methods; | return methods; | ||||
Class baseclass = getJavaClass(); | Class baseclass = getJavaClass(); | ||||
Method[] allmethods = baseclass.getMethods(); | |||||
Method[] allmethods = baseclass.getDeclaredMethods(); | |||||
int n = allmethods.length; | int n = allmethods.length; | ||||
methods = new Method[n]; | methods = new Method[n]; | ||||
for (int i = 0; i < n; ++i) { | for (int i = 0; i < n; ++i) { | ||||
Method m = allmethods[i]; | Method m = allmethods[i]; | ||||
if (m.getDeclaringClass() == baseclass) { | |||||
String mname = m.getName(); | |||||
if (mname.startsWith(methodPrefix)) { | |||||
int k = 0; | |||||
for (int j = methodPrefixLen;; ++j) { | |||||
char c = mname.charAt(j); | |||||
if ('0' <= c && c <= '9') | |||||
k = k * 10 + c - '0'; | |||||
else | |||||
break; | |||||
} | |||||
methods[k] = m; | |||||
String mname = m.getName(); | |||||
if (mname.startsWith(methodPrefix)) { | |||||
int k = 0; | |||||
for (int j = methodPrefixLen;; ++j) { | |||||
char c = mname.charAt(j); | |||||
if ('0' <= c && c <= '9') | |||||
k = k * 10 + c - '0'; | |||||
else | |||||
break; | |||||
} | } | ||||
methods[k] = m; | |||||
} | } | ||||
} | } | ||||
* <p>If a class is reflective, | * <p>If a class is reflective, | ||||
* then all the method invocations on every | * then all the method invocations on every | ||||
* instance of that class are intercepted by the runtime | * instance of that class are intercepted by the runtime | ||||
* metaobject controlling that instance. | |||||
* To do this, the original class file representing a reflective class: | |||||
* metaobject controlling that instance. The methods inherited from the | |||||
* super classes are also intercepted except final methods. To intercept | |||||
* a final method in a super class, that super class must be also reflective. | |||||
* | |||||
* <p>To do this, the original class file representing a reflective class: | |||||
* | * | ||||
* <ul><pre> | * <ul><pre> | ||||
* class Person { | * class Person { | ||||
return; | return; | ||||
m2 = m; | m2 = m; | ||||
if (Modifier.isFinal(mod)) { | |||||
mod &= ~Modifier.FINAL; | |||||
m2.setModifiers(mod); | |||||
} | |||||
} | } | ||||
else { | else { | ||||
if (Modifier.isFinal(mod)) | if (Modifier.isFinal(mod)) |