View Javadoc

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.javassist;
9   
10  import org.codehaus.aspectwerkz.annotation.AnnotationInfo;
11  import org.codehaus.aspectwerkz.annotation.instrumentation.AttributeExtractor;
12  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
13  import org.codehaus.aspectwerkz.reflect.ClassInfo;
14  import org.codehaus.aspectwerkz.reflect.MethodInfo;
15  import org.codehaus.aspectwerkz.transform.delegation.JavassistHelper;
16  
17  import java.util.List;
18  
19  import javassist.CtBehavior;
20  import javassist.CtClass;
21  import javassist.CtMethod;
22  import javassist.NotFoundException;
23  
24  /***
25   * Implementation of the MethodInfo interface for Javassist.
26   * 
27   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
28   */
29  public class JavassistMethodInfo extends JavassistCodeInfo implements MethodInfo {
30      /***
31       * The return type.
32       */
33      private ClassInfo m_returnType = null;
34  
35      /***
36       * Creates a new method meta data instance.
37       * 
38       * @param method
39       * @param declaringType
40       * @param loader
41       * @param attributeExtractor
42       */
43      JavassistMethodInfo(final CtMethod method,
44                          final JavassistClassInfo declaringType,
45                          final ClassLoader loader,
46                          final AttributeExtractor attributeExtractor) {
47          super(method, declaringType, loader, attributeExtractor);
48          addAnnotations();
49      }
50  
51      /***
52       * Returns the method info for the method specified.
53       * 
54       * @param method the method
55       * @param loader the class loader
56       * @return the method info
57       */
58      public static MethodInfo getMethodInfo(final CtMethod method, final ClassLoader loader) {
59          CtClass declaringClass = method.getDeclaringClass();
60          JavassistClassInfoRepository repository = JavassistClassInfoRepository.getRepository(loader);
61          ClassInfo classInfo = repository.getClassInfo(declaringClass.getName());
62          if (classInfo == null) {
63              classInfo = JavassistClassInfo.getClassInfo(declaringClass, loader);
64          }
65          return classInfo.getMethod(calculateHash(method));
66      }
67  
68      /***
69       * Calculates the method hash.
70       * 
71       * @param method
72       * @return the hash
73       */
74      public static int calculateHash(final CtMethod method) {
75          int hash = method.getName().hashCode();
76          try {
77              for (int i = 0; i < method.getParameterTypes().length; i++) {
78                  String name = method.getParameterTypes()[i].getName();
79                  name = JavassistHelper.convertJavassistTypeSignatureToReflectTypeSignature(name);
80                  hash = (17 * hash) + name.hashCode();
81              }
82          } catch (NotFoundException e) {
83              // swallow, since ok
84          }
85          return hash;
86      }
87  
88      /***
89       * Returns the annotations.
90       * 
91       * @return the annotations
92       */
93      public List getAnnotations() {
94          return m_annotations;
95      }
96  
97      /***
98       * Returns the return type.
99       * 
100      * @return the return type
101      */
102     public ClassInfo getReturnType() {
103         if (m_returnType == null) {
104             try {
105                 CtClass returnTypeClass = ((CtMethod) m_member).getReturnType();
106                 if (m_classInfoRepository.hasClassInfo(returnTypeClass.getName())) {
107                     m_returnType = m_classInfoRepository.getClassInfo(returnTypeClass.getName());
108                 } else {
109                     m_returnType = JavassistClassInfo.getClassInfo(returnTypeClass, (ClassLoader) m_loaderRef.get());
110                     m_classInfoRepository.addClassInfo(m_returnType);
111                 }
112             } catch (NotFoundException e) {
113                 // swallow, since ok
114             }
115         }
116         return m_returnType;
117     }
118 
119     public boolean equals(Object o) {
120         if (this == o) {
121             return true;
122         }
123         if (!(o instanceof MethodInfo)) {
124             return false;
125         }
126         MethodInfo methodInfo = (MethodInfo) o;
127         if (!m_declaringType.getName().toString().equals(methodInfo.getDeclaringType().getName().toString())) {
128             return false;
129         }
130         if (!m_member.getName().toString().equals(methodInfo.getName().toString())) {
131             return false;
132         }
133         ClassInfo[] parameterTypes = methodInfo.getParameterTypes();
134         if (m_parameterTypes.length != parameterTypes.length) {
135             return false;
136         }
137         for (int i = 0; i < m_parameterTypes.length; i++) {
138             if (!m_parameterTypes[i].getName().toString().equals(parameterTypes[i].getName().toString())) {
139                 return false;
140             }
141         }
142         return true;
143     }
144 
145     public int hashCode() {
146         int result = 29;
147         result = (29 * result) + m_declaringType.getName().toString().hashCode();
148         result = (29 * result) + m_member.getName().toString().hashCode();
149         if (m_parameterTypes == null) {
150             getParameterTypes();
151         }
152         for (int i = 0; i < m_parameterTypes.length; i++) {
153             result = (29 * result) + m_parameterTypes[i].getName().toString().hashCode();
154         }
155         return result;
156     }
157 
158     /***
159      * Adds annotations to the method info.
160      */
161     private void addAnnotations() {
162         if (m_attributeExtractor == null) {
163             return;
164         }
165         try {
166             CtClass[] parameterTypes = ((CtBehavior) m_member).getParameterTypes();
167             String[] parameterNames = new String[parameterTypes.length];
168             for (int i = 0; i < parameterTypes.length; i++) {
169                 parameterNames[i] = parameterTypes[i].getName();
170             }
171             Object[] attributes = m_attributeExtractor.getMethodAttributes(getName(), parameterNames);
172             for (int i = 0; i < attributes.length; i++) {
173                 Object attribute = attributes[i];
174                 if (attribute instanceof AnnotationInfo) {
175                     m_annotations.add(attribute);
176                 }
177             }
178         } catch (NotFoundException e) {
179             // swallow, since ok
180         }
181     }
182 
183     public String toString() {
184         return m_member.toString();
185     }
186 }