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.asm;
9   
10  import org.codehaus.aspectwerkz.reflect.ClassInfo;
11  import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
12  import org.codehaus.aspectwerkz.reflect.MethodInfo;
13  import org.codehaus.aspectwerkz.transform.AsmHelper;
14  import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
15  import org.objectweb.asm.Type;
16  import org.objectweb.asm.ClassReader;
17  
18  import java.util.List;
19  import java.util.ArrayList;
20  import java.io.IOException;
21  
22  /***
23   * ASM implementation of the ConstructorInfo interface.
24   * 
25   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
26   */
27  public class AsmConstructorInfo extends AsmMemberInfo implements ConstructorInfo {
28  
29      /***
30       * A list with the parameter type names.
31       */
32      private String[] m_parameterTypeNames = null;
33  
34      /***
35       * A list with the exception type names.
36       */
37      private String[] m_exceptionTypeNames = null;
38  
39      /***
40       * A list with the parameter types.
41       */
42      private ClassInfo[] m_parameterTypes = null;
43  
44      /***
45       * A list with the exception types.
46       */
47      private ClassInfo[] m_exceptionTypes = null;
48  
49      /***
50       * Creates a new method meta data instance.
51       * 
52       * @param method
53       * @param declaringType
54       * @param loader
55       */
56      AsmConstructorInfo(final MethodStruct method, final String declaringType, final ClassLoader loader) {
57          super(method, declaringType, loader);
58          Type[] argTypes = Type.getArgumentTypes(method.desc);
59          m_parameterTypeNames = new String[argTypes.length];
60          for (int i = 0; i < argTypes.length; i++) {
61              m_parameterTypeNames[i] = argTypes[i].getClassName();
62          }
63          // FIXME: how to do exceptions?
64          m_exceptionTypeNames = new String[] {};
65      }
66  
67      /***
68       * Returns the constructor info for the constructor specified.
69       * 
70       * @param constructorDesc
71       * @param bytecode
72       * @param loader
73       * @return the constructor info
74       */
75      public static MethodInfo getConstructorInfo(
76          final String constructorDesc,
77          final byte[] bytecode,
78          final ClassLoader loader) {
79          String className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
80          AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
81          ClassInfo classInfo = repository.getClassInfo(className);
82          if (classInfo == null) {
83              classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
84          }
85          return classInfo.getMethod(AsmHelper.calculateConstructorHash(constructorDesc));
86      }
87  
88      /***
89       * Returns the parameter types.
90       * 
91       * @return the parameter types
92       */
93      public ClassInfo[] getParameterTypes() {
94          if (m_parameterTypes == null) {
95              m_parameterTypes = new ClassInfo[m_parameterTypeNames.length];
96              for (int i = 0; i < m_parameterTypeNames.length; i++) {
97                  m_parameterTypes[i] = AsmClassInfo.getClassInfo(
98                          m_parameterTypeNames[i],
99                          (ClassLoader) m_loaderRef.get()
100                 );
101             }
102         }
103         return m_parameterTypes;
104     }
105 
106     /***
107      * Returns the exception types.
108      * 
109      * @return the exception types
110      */
111     public ClassInfo[] getExceptionTypes() {
112         if (m_exceptionTypes == null) {
113             m_exceptionTypes = new ClassInfo[m_exceptionTypeNames.length];
114             for (int i = 0; i < m_exceptionTypeNames.length; i++) {
115                 m_exceptionTypes[i] = AsmClassInfo.getClassInfo(
116                         m_exceptionTypeNames[i],
117                         (ClassLoader) m_loaderRef.get()
118                 );
119             }
120         }
121         return m_exceptionTypes;
122     }
123 
124     /***
125      * Returns the annotations.
126      *
127      * @return the annotations
128      */
129     public List getAnnotations() {
130         if (m_annotations == null) {
131             try {
132                 ClassReader cr = new ClassReader(((ClassLoader)m_loaderRef.get()).getResourceAsStream(m_declaringTypeName.replace('.','/')+".class"));
133                 List annotations = new ArrayList();
134                 cr.accept(
135                         new AsmAnnotationHelper.ConstructorAnnotationExtractor(annotations, m_member.desc, (ClassLoader)m_loaderRef.get()),
136                         AsmAnnotationHelper.ANNOTATIONS_ATTRIBUTES,
137                         true
138                 );
139                 m_annotations = annotations;
140             } catch (IOException e) {
141                 // unlikely to occur since ClassInfo relies on getResourceAsStream
142                 System.err.println("WARN - could not load " + m_declaringTypeName + " as a resource to retrieve annotations");
143                 m_annotations = AsmClassInfo.EMPTY_LIST;
144             }
145         }
146         return m_annotations;
147     }
148 
149     public boolean equals(Object o) {
150         if (this == o) {
151             return true;
152         }
153         if (!(o instanceof ConstructorInfo)) {
154             return false;
155         }
156         ConstructorInfo constructorInfo = (ConstructorInfo) o;
157         if (!m_declaringTypeName.equals(constructorInfo.getDeclaringType().getName())) {
158             return false;
159         }
160         if (!m_member.name.equals(constructorInfo.getName())) {
161             return false;
162         }
163         ClassInfo[] parameterTypes = constructorInfo.getParameterTypes();
164         if (m_parameterTypeNames.length != parameterTypes.length) {//check on names length for lazyness optim
165             return false;
166         }
167         for (int i = 0; i < m_parameterTypeNames.length; i++) {
168             if (!m_parameterTypeNames[i].equals(parameterTypes[i].getName())) {
169                 return false;
170             }
171         }
172         return true;
173     }
174 
175     public int hashCode() {
176         int result = 29;
177         result = (29 * result) + m_declaringTypeName.hashCode();
178         result = (29 * result) + m_member.name.hashCode();
179         for (int i = 0; i < m_parameterTypeNames.length; i++) {
180             result = (29 * result) + m_parameterTypeNames[i].hashCode();
181         }
182         return result;
183     }
184 
185     public String toString() {
186         StringBuffer sb = new StringBuffer(m_declaringTypeName);
187         sb.append('.').append(m_member.name);
188         sb.append(m_member.desc);
189         return sb.toString();
190     }
191 }