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.inlining.AsmHelper;
14 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
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;
21 import java.util.ArrayList;
22 import java.io.IOException;
23 import java.io.InputStream;
24
25 /***
26 * ASM implementation of the ConstructorInfo interface.
27 *
28 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
29 */
30 public class AsmConstructorInfo extends AsmMemberInfo implements ConstructorInfo {
31
32 /***
33 * A list with the parameter type names.
34 */
35 private String[] m_parameterTypeNames = null;
36
37 /***
38 * A list with the exception type names.
39 */
40 private String[] m_exceptionTypeNames = null;
41
42 /***
43 * A list with the parameter types.
44 */
45 private ClassInfo[] m_parameterTypes = null;
46
47 /***
48 * A list with the exception types.
49 */
50 private ClassInfo[] m_exceptionTypes = null;
51
52 /***
53 * Creates a new method meta data instance.
54 *
55 * @param method
56 * @param declaringType
57 * @param loader
58 */
59 AsmConstructorInfo(final MethodStruct method, final String declaringType, final ClassLoader loader) {
60 super(method, declaringType, loader);
61 Type[] argTypes = Type.getArgumentTypes(method.desc);
62 m_parameterTypeNames = new String[argTypes.length];
63 for (int i = 0; i < argTypes.length; i++) {
64 m_parameterTypeNames[i] = argTypes[i].getClassName();
65 }
66
67 m_exceptionTypeNames = new String[]{};
68 }
69
70 /***
71 * Returns the constructor info for the constructor specified.
72 *
73 * @param constructorDesc
74 * @param bytecode
75 * @param loader
76 * @return the constructor info
77 */
78 public static ConstructorInfo getConstructorInfo(final String constructorDesc,
79 final byte[] bytecode,
80 final ClassLoader loader) {
81 String className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
82 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
83 ClassInfo classInfo = repository.getClassInfo(className);
84 if (classInfo == null) {
85 classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
86 }
87 return classInfo.getConstructor(AsmHelper.calculateConstructorHash(constructorDesc));
88 }
89
90 /***
91 * Returns the signature for the element.
92 *
93 * @return the signature for the element
94 */
95 public String getSignature() {
96 return AsmHelper.getConstructorDescriptor(this);
97 }
98
99 /***
100 * Returns the parameter types.
101 *
102 * @return the parameter types
103 */
104 public ClassInfo[] getParameterTypes() {
105 if (m_parameterTypes == null) {
106 m_parameterTypes = new ClassInfo[m_parameterTypeNames.length];
107 for (int i = 0; i < m_parameterTypeNames.length; i++) {
108 m_parameterTypes[i] = AsmClassInfo.getClassInfo(
109 m_parameterTypeNames[i],
110 (ClassLoader) m_loaderRef.get()
111 );
112 }
113 }
114 return m_parameterTypes;
115 }
116
117 /***
118 * Returns the exception types.
119 *
120 * @return the exception types
121 */
122 public ClassInfo[] getExceptionTypes() {
123 if (m_exceptionTypes == null) {
124 m_exceptionTypes = new ClassInfo[m_exceptionTypeNames.length];
125 for (int i = 0; i < m_exceptionTypeNames.length; i++) {
126 m_exceptionTypes[i] = AsmClassInfo.getClassInfo(
127 m_exceptionTypeNames[i],
128 (ClassLoader) m_loaderRef.get()
129 );
130 }
131 }
132 return m_exceptionTypes;
133 }
134
135 /***
136 * Returns the annotations.
137 *
138 * @return the annotations
139 */
140 public List getAnnotations() {
141 if (m_annotations == null) {
142 try {
143 InputStream in = null;
144 ClassReader cr = null;
145 try {
146 if ((ClassLoader) m_loaderRef.get() != null) {
147 in = ((ClassLoader) m_loaderRef.get()).getResourceAsStream(
148 m_declaringTypeName.replace('.', '/') + ".class"
149 );
150 } else {
151 in = ClassLoader.getSystemClassLoader().getResourceAsStream(
152 m_declaringTypeName.replace('.', '/') + ".class"
153 );
154 }
155 if (in == null) {
156 in = ProxyCompiler.getProxyResourceAsStream((ClassLoader) m_loaderRef.get(), m_declaringTypeName);
157 }
158 cr = new ClassReader(in);
159 } finally {
160 try {
161 in.close();
162 } catch (Exception e) {
163 ;
164 }
165 }
166 List annotations = new ArrayList();
167 cr.accept(
168 new AsmAnnotationHelper.ConstructorAnnotationExtractor(
169 annotations, m_member.desc, (ClassLoader) m_loaderRef.get()
170 ),
171 Attributes.getDefaultAttributes(),
172 true
173 );
174 m_annotations = annotations;
175 } catch (IOException e) {
176
177 System.err.println(
178 "WARN - could not load " + m_declaringTypeName + " as a resource to retrieve annotations"
179 );
180 m_annotations = AsmClassInfo.EMPTY_LIST;
181 }
182 }
183 return m_annotations;
184 }
185
186 public boolean equals(Object o) {
187 if (this == o) {
188 return true;
189 }
190 if (!(o instanceof ConstructorInfo)) {
191 return false;
192 }
193 ConstructorInfo constructorInfo = (ConstructorInfo) o;
194 if (!m_declaringTypeName.equals(constructorInfo.getDeclaringType().getName())) {
195 return false;
196 }
197 if (!m_member.name.equals(constructorInfo.getName())) {
198 return false;
199 }
200 ClassInfo[] parameterTypes = constructorInfo.getParameterTypes();
201 if (m_parameterTypeNames.length != parameterTypes.length) {
202 return false;
203 }
204 for (int i = 0; i < m_parameterTypeNames.length; i++) {
205 if (!m_parameterTypeNames[i].equals(parameterTypes[i].getName())) {
206 return false;
207 }
208 }
209 return true;
210 }
211
212 public int hashCode() {
213 int result = 29;
214 result = (29 * result) + m_declaringTypeName.hashCode();
215 result = (29 * result) + m_member.name.hashCode();
216 for (int i = 0; i < m_parameterTypeNames.length; i++) {
217 result = (29 * result) + m_parameterTypeNames[i].hashCode();
218 }
219 return result;
220 }
221
222 public String toString() {
223 StringBuffer sb = new StringBuffer(m_declaringTypeName);
224 sb.append('.').append(m_member.name);
225 sb.append(m_member.desc);
226 return sb.toString();
227 }
228 }