001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.aspectwerkz.reflect.impl.asm;
006:
007: import com.tc.asm.Type;
008: import com.tc.aspectwerkz.reflect.ClassInfo;
009: import com.tc.aspectwerkz.reflect.MethodInfo;
010: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
011: import com.tc.backport175.bytecode.AnnotationElement;
012:
013: /**
014: * ASM implementation of the MethodInfo interface.
015: *
016: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
017: */
018: public class AsmMethodInfo extends AsmMemberInfo implements MethodInfo {
019:
020: /**
021: * The return type name.
022: */
023: private String m_returnTypeName = null;
024:
025: /**
026: * A list with the parameter names as they appear in the source code. This information may not be available.
027: */
028: protected String[] m_parameterNames = null;
029:
030: /**
031: * A list with the parameter type names.
032: */
033: protected String[] m_parameterTypeNames = null;
034:
035: /**
036: * A list with the exception type names.
037: */
038: private String[] m_exceptionTypeNames = null;
039:
040: /**
041: * The return type.
042: */
043: private ClassInfo m_returnType = null;
044:
045: /**
046: * A list with the parameter types.
047: */
048: private ClassInfo[] m_parameterTypes = null;
049:
050: /**
051: * A list with the exception types.
052: */
053: private ClassInfo[] m_exceptionTypes = null;
054:
055: /**
056: * Creates a new method info instance.
057: *
058: * @param method
059: * @param declaringType
060: * @param loader
061: */
062: AsmMethodInfo(final MethodStruct method,
063: final String declaringType, final ClassLoader loader) {
064: super (method, declaringType, loader);
065:
066: m_returnTypeName = Type.getReturnType(method.desc)
067: .getClassName();
068: Type[] argTypes = Type.getArgumentTypes(method.desc);
069: m_parameterTypeNames = new String[argTypes.length];
070: for (int i = 0; i < argTypes.length; i++) {
071: m_parameterTypeNames[i] = argTypes[i].getClassName();
072: }
073: // TODO how to do exceptions?
074: m_exceptionTypeNames = new String[] {};
075: }
076:
077: /**
078: * Returns the method info for the method specified.
079: *
080: * @param methodName
081: * @param methodDesc
082: * @param bytecode
083: * @param loader
084: * @return the method info
085: */
086: public static MethodInfo getMethodInfo(final String methodName,
087: final String methodDesc, final byte[] bytecode,
088: final ClassLoader loader) {
089: String className = AsmClassInfo
090: .retrieveClassNameFromBytecode(bytecode);
091: AsmClassInfoRepository repository = AsmClassInfoRepository
092: .getRepository(loader);
093: ClassInfo classInfo = repository.getClassInfo(className);
094: if (classInfo == null) {
095: classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
096: }
097: return classInfo.getMethod(AsmHelper.calculateMethodHash(
098: methodName, methodDesc));
099: }
100:
101: /**
102: * Returns the signature for the element.
103: *
104: * @return the signature for the element
105: */
106: public String getSignature() {
107: return m_member.desc;
108: }
109:
110: public String getGenericsSignature() {
111: return m_member.signature;
112: }
113:
114: /**
115: * Returns the return type.
116: *
117: * @return the return type
118: */
119: public ClassInfo getReturnType() {
120: if (m_returnType == null) {
121: m_returnType = AsmClassInfo.getClassInfo(m_returnTypeName,
122: (ClassLoader) m_loaderRef.get());
123: }
124: return m_returnType;
125: }
126:
127: /**
128: * Returns the parameter types.
129: *
130: * @return the parameter types
131: */
132: public synchronized ClassInfo[] getParameterTypes() {
133: if (m_parameterTypes == null) {
134: m_parameterTypes = new ClassInfo[m_parameterTypeNames.length];
135: for (int i = 0; i < m_parameterTypeNames.length; i++) {
136: m_parameterTypes[i] = AsmClassInfo.getClassInfo(
137: m_parameterTypeNames[i],
138: (ClassLoader) m_loaderRef.get());
139: }
140: }
141: return m_parameterTypes;
142: }
143:
144: /**
145: * Returns the parameter names as they appear in the source code. This information is available only when class are
146: * compiled with javac -g (debug info), but is required for Aspect that are using args() and target()/this() bindings.
147: * <p/> It returns null if not available.
148: *
149: * @return
150: */
151: public String[] getParameterNames() {
152: return m_parameterNames;
153: }
154:
155: /**
156: * Returns the exception types.
157: *
158: * @return the exception types
159: */
160: public synchronized ClassInfo[] getExceptionTypes() {
161: if (m_exceptionTypes == null) {
162: m_exceptionTypes = new ClassInfo[m_exceptionTypeNames.length];
163: for (int i = 0; i < m_exceptionTypeNames.length; i++) {
164: m_exceptionTypes[i] = AsmClassInfo.getClassInfo(
165: m_exceptionTypeNames[i],
166: (ClassLoader) m_loaderRef.get());
167: }
168: }
169: return m_exceptionTypes;
170: }
171:
172: /**
173: * Returns the annotations.
174: *
175: * @return the annotations
176: */
177: public AnnotationElement.Annotation[] getAnnotations() {
178: return getDeclaringType().getAnnotationReader()
179: .getMethodAnnotationElements(m_member.name,
180: m_member.desc);
181: }
182:
183: public boolean equals(Object o) {
184: if (this == o) {
185: return true;
186: }
187: if (!(o instanceof MethodInfo)) {
188: return false;
189: }
190: MethodInfo methodInfo = (MethodInfo) o;
191: if (!m_declaringTypeName.equals(methodInfo.getDeclaringType()
192: .getName())) {
193: return false;
194: }
195: if (!m_member.name.equals(methodInfo.getName())) {
196: return false;
197: }
198: ClassInfo[] parameterTypes = methodInfo.getParameterTypes();
199: if (m_parameterTypeNames.length != parameterTypes.length) {// check on names length for lazyness optim
200: return false;
201: }
202: for (int i = 0; i < m_parameterTypeNames.length; i++) {
203: if (!m_parameterTypeNames[i].equals(parameterTypes[i]
204: .getName())) {
205: return false;
206: }
207: }
208: return true;
209: }
210:
211: public int hashCode() {
212: int result = 29;
213: result = (29 * result) + m_declaringTypeName.hashCode();
214: result = (29 * result) + m_member.name.hashCode();
215: for (int i = 0; i < m_parameterTypeNames.length; i++) {
216: result = (29 * result) + m_parameterTypeNames[i].hashCode();
217: }
218: return result;
219: }
220:
221: public String toString() {
222: StringBuffer sb = new StringBuffer(m_declaringTypeName);
223: sb.append('.').append(m_member.name);
224: sb.append(m_member.desc);
225: return sb.toString();
226: }
227:
228: }
|