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
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
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) {
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 }