KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > reflect > impl > asm > AsmMethodInfo


1 /**************************************************************************************
2  * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.reflect.impl.asm;
9
10 import org.codehaus.aspectwerkz.reflect.ClassInfo;
11 import org.codehaus.aspectwerkz.reflect.MethodInfo;
12 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
13 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
14 import org.codehaus.aspectwerkz.exception.DefinitionException;
15 import org.codehaus.aspectwerkz.proxy.ProxyCompiler;
16 import org.objectweb.asm.Type;
17 import org.objectweb.asm.ClassReader;
18 import org.objectweb.asm.attrs.Attributes;
19
20 import java.util.List JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.lang.reflect.Modifier JavaDoc;
25
26 /**
27  * ASM implementation of the MethodInfo interface.
28  *
29  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
30  */

31 public class AsmMethodInfo extends AsmMemberInfo implements MethodInfo {
32
33     /**
34      * The return type name.
35      */

36     private String JavaDoc m_returnTypeName = null;
37
38     /**
39      * A list with the parameter names as they appear in the source code.
40      * This information may not be available.
41      */

42     protected String JavaDoc[] m_parameterNames = null;
43
44     /**
45      * A list with the parameter type names.
46      */

47     private String JavaDoc[] m_parameterTypeNames = null;
48
49     /**
50      * A list with the exception type names.
51      */

52     private String JavaDoc[] m_exceptionTypeNames = null;
53
54     /**
55      * The return type.
56      */

57     private ClassInfo m_returnType = null;
58
59     /**
60      * A list with the parameter types.
61      */

62     private ClassInfo[] m_parameterTypes = null;
63
64     /**
65      * A list with the exception types.
66      */

67     private ClassInfo[] m_exceptionTypes = null;
68
69     /**
70      * Creates a new method info instance.
71      *
72      * @param method
73      * @param declaringType
74      * @param loader
75      */

76     AsmMethodInfo(final MethodStruct method, final String JavaDoc declaringType, final ClassLoader JavaDoc loader) {
77         super(method, declaringType, loader);
78
79         m_returnTypeName = Type.getReturnType(method.desc).getClassName();
80         Type[] argTypes = Type.getArgumentTypes(method.desc);
81         m_parameterTypeNames = new String JavaDoc[argTypes.length];
82         for (int i = 0; i < argTypes.length; i++) {
83             m_parameterTypeNames[i] = argTypes[i].getClassName();
84         }
85         // FIXME: how to do exceptions? needed?
86
m_exceptionTypeNames = new String JavaDoc[]{};
87     }
88
89     /**
90      * Returns the method info for the method specified.
91      *
92      * @param methodName
93      * @param methodDesc
94      * @param bytecode
95      * @param loader
96      * @return the method info
97      */

98     public static MethodInfo getMethodInfo(final String JavaDoc methodName,
99                                            final String JavaDoc methodDesc,
100                                            final byte[] bytecode,
101                                            final ClassLoader JavaDoc loader) {
102         String JavaDoc className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
103         AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
104         ClassInfo classInfo = repository.getClassInfo(className);
105         if (classInfo == null) {
106             classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
107         }
108         return classInfo.getMethod(AsmHelper.calculateMethodHash(methodName, methodDesc));
109     }
110
111     /**
112      * Returns the signature for the element.
113      *
114      * @return the signature for the element
115      */

116     public String JavaDoc getSignature() {
117         return AsmHelper.getMethodDescriptor(this);
118     }
119
120     /**
121      * Returns the return type.
122      *
123      * @return the return type
124      */

125     public ClassInfo getReturnType() {
126         if (m_returnType == null) {
127             m_returnType = AsmClassInfo.getClassInfo(m_returnTypeName, (ClassLoader JavaDoc) m_loaderRef.get());
128         }
129         return m_returnType;
130     }
131
132     /**
133      * Returns the parameter types.
134      *
135      * @return the parameter types
136      */

137     public ClassInfo[] getParameterTypes() {
138         if (m_parameterTypes == null) {
139             m_parameterTypes = new ClassInfo[m_parameterTypeNames.length];
140             for (int i = 0; i < m_parameterTypeNames.length; i++) {
141                 m_parameterTypes[i] = AsmClassInfo.getClassInfo(
142                         m_parameterTypeNames[i],
143                         (ClassLoader JavaDoc) m_loaderRef.get()
144                 );
145             }
146         }
147         return m_parameterTypes;
148     }
149
150     /**
151      * Returns the parameter names as they appear in the source code.
152      * This information is available only when class are compiled with javac -g (debug info), but is required
153      * for Aspect that are using args() and target()/this() bindings.
154      * <p/>
155      * It returns null if not available.
156      *
157      * @return
158      */

159     public String JavaDoc[] getParameterNames() {
160         return m_parameterNames;
161     }
162
163     /**
164      * Returns the exception types.
165      *
166      * @return the exception types
167      */

168     public ClassInfo[] getExceptionTypes() {
169         if (m_exceptionTypes == null) {
170             m_exceptionTypes = new ClassInfo[m_exceptionTypeNames.length];
171             for (int i = 0; i < m_exceptionTypeNames.length; i++) {
172                 m_exceptionTypes[i] = AsmClassInfo.getClassInfo(
173                         m_exceptionTypeNames[i],
174                         (ClassLoader JavaDoc) m_loaderRef.get()
175                 );
176             }
177         }
178         return m_exceptionTypes;
179     }
180
181     /**
182      * Returns the annotations.
183      *
184      * @return the annotations
185      */

186     public List JavaDoc getAnnotations() {
187         if (m_annotations == null) {
188             try {
189                 InputStream JavaDoc in = null;
190                 ClassReader cr = null;
191                 try {
192                     if ((ClassLoader JavaDoc) m_loaderRef.get() != null) {
193                         in = ((ClassLoader JavaDoc) m_loaderRef.get()).getResourceAsStream(
194                                 m_declaringTypeName.replace('.', '/') + ".class"
195                         );
196                     } else {
197                         in = ClassLoader.getSystemClassLoader().getResourceAsStream(
198                                 m_declaringTypeName.replace('.', '/') + ".class"
199                         );
200                     }
201                     if (in == null) {
202                         in = ProxyCompiler.getProxyResourceAsStream((ClassLoader JavaDoc) m_loaderRef.get(), m_declaringTypeName);
203                     }
204                     cr = new ClassReader(in);
205                 } finally {
206                     try {
207                         in.close();
208                     } catch (Exception JavaDoc e) {
209                         ;
210                     }
211                 }
212                 List JavaDoc annotations = new ArrayList JavaDoc();
213                 cr.accept(
214                         new AsmAnnotationHelper.MethodAnnotationExtractor(
215                                 annotations, m_member.name, m_member.desc, (ClassLoader JavaDoc) m_loaderRef.get()
216                         ),
217                         Attributes.getDefaultAttributes(),
218                         true
219                 );
220                 m_annotations = annotations;
221             } catch (IOException JavaDoc e) {
222                 // unlikely to occur since ClassInfo relies on getResourceAsStream
223
System.err.println(
224                         "WARN - could not load " + m_declaringTypeName + " as a resource to retrieve annotations"
225                 );
226                 m_annotations = AsmClassInfo.EMPTY_LIST;
227             }
228         }
229         return m_annotations;
230     }
231
232     public boolean equals(Object JavaDoc o) {
233         if (this == o) {
234             return true;
235         }
236         if (!(o instanceof MethodInfo)) {
237             return false;
238         }
239         MethodInfo methodInfo = (MethodInfo) o;
240         if (!m_declaringTypeName.equals(methodInfo.getDeclaringType().getName())) {
241             return false;
242         }
243         if (!m_member.name.equals(methodInfo.getName())) {
244             return false;
245         }
246         ClassInfo[] parameterTypes = methodInfo.getParameterTypes();
247         if (m_parameterTypeNames.length != parameterTypes.length) {//check on names length for lazyness optim
248
return false;
249         }
250         for (int i = 0; i < m_parameterTypeNames.length; i++) {
251             if (!m_parameterTypeNames[i].equals(parameterTypes[i].getName())) {
252                 return false;
253             }
254         }
255         return true;
256     }
257
258     public int hashCode() {
259         int result = 29;
260         result = (29 * result) + m_declaringTypeName.hashCode();
261         result = (29 * result) + m_member.name.hashCode();
262         for (int i = 0; i < m_parameterTypeNames.length; i++) {
263             result = (29 * result) + m_parameterTypeNames[i].hashCode();
264         }
265         return result;
266     }
267
268     public String JavaDoc toString() {
269         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(m_declaringTypeName);
270         sb.append('.').append(m_member.name);
271         sb.append(m_member.desc);
272         return sb.toString();
273     }
274
275     /**
276      * Update the parameter name given the parameter information
277      * the index is the one from the register ie a long or double will needs 2 register
278      *
279      * @param registerIndex
280      * @param parameterName
281      */

282     public void pushParameterNameFromRegister(int registerIndex, String JavaDoc parameterName) {
283         int registerStart = 1;
284         if (Modifier.isStatic(m_member.modifiers)) {
285             registerStart = 0;
286         }
287         // assume we have a stack starting at the first parameter
288
int registerIndexFrom0 = registerIndex - registerStart;
289         Type[] parameters = Type.getArgumentTypes(m_member.desc);
290         int typeIndex = AsmHelper.getTypeIndexOf(parameters, registerIndexFrom0);
291         if (typeIndex >= 0 && typeIndex < m_parameterNames.length) {
292             m_parameterNames[typeIndex] = parameterName;
293         } else {
294             throw new DefinitionException("Could not register parameter named " + parameterName
295                 + " from register " + registerIndex + " for " + m_member.name + "." + m_member.desc);
296         }
297     }
298 }
Popular Tags