001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.reflect.impl.asm;
008:
009: import org.codehaus.aspectwerkz.reflect.ClassInfo;
010: import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
011: import org.codehaus.aspectwerkz.reflect.MethodInfo;
012: import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
013: import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
014: import org.codehaus.aspectwerkz.proxy.ProxyCompiler;
015: import org.objectweb.asm.Type;
016: import org.objectweb.asm.ClassReader;
017: import org.objectweb.asm.attrs.Attributes;
018:
019: import java.util.List;
020: import java.util.ArrayList;
021: import java.io.IOException;
022: import java.io.InputStream;
023:
024: /**
025: * ASM implementation of the ConstructorInfo interface.
026: *
027: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
028: */
029: public class AsmConstructorInfo extends AsmMemberInfo implements
030: ConstructorInfo {
031:
032: /**
033: * A list with the parameter type names.
034: */
035: private String[] m_parameterTypeNames = null;
036:
037: /**
038: * A list with the exception type names.
039: */
040: private String[] m_exceptionTypeNames = null;
041:
042: /**
043: * A list with the parameter types.
044: */
045: private ClassInfo[] m_parameterTypes = null;
046:
047: /**
048: * A list with the exception types.
049: */
050: private ClassInfo[] m_exceptionTypes = null;
051:
052: /**
053: * Creates a new method meta data instance.
054: *
055: * @param method
056: * @param declaringType
057: * @param loader
058: */
059: AsmConstructorInfo(final MethodStruct method,
060: final String declaringType, final ClassLoader loader) {
061: super (method, declaringType, loader);
062: Type[] argTypes = Type.getArgumentTypes(method.desc);
063: m_parameterTypeNames = new String[argTypes.length];
064: for (int i = 0; i < argTypes.length; i++) {
065: m_parameterTypeNames[i] = argTypes[i].getClassName();
066: }
067: // FIXME: how to do exceptions?
068: m_exceptionTypeNames = new String[] {};
069: }
070:
071: /**
072: * Returns the constructor info for the constructor specified.
073: *
074: * @param constructorDesc
075: * @param bytecode
076: * @param loader
077: * @return the constructor info
078: */
079: public static ConstructorInfo getConstructorInfo(
080: final String constructorDesc, final byte[] bytecode,
081: final ClassLoader loader) {
082: String className = AsmClassInfo
083: .retrieveClassNameFromBytecode(bytecode);
084: AsmClassInfoRepository repository = AsmClassInfoRepository
085: .getRepository(loader);
086: ClassInfo classInfo = repository.getClassInfo(className);
087: if (classInfo == null) {
088: classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
089: }
090: return classInfo.getConstructor(AsmHelper
091: .calculateConstructorHash(constructorDesc));
092: }
093:
094: /**
095: * Returns the signature for the element.
096: *
097: * @return the signature for the element
098: */
099: public String getSignature() {
100: return AsmHelper.getConstructorDescriptor(this );
101: }
102:
103: /**
104: * Returns the parameter types.
105: *
106: * @return the parameter types
107: */
108: public ClassInfo[] getParameterTypes() {
109: if (m_parameterTypes == null) {
110: m_parameterTypes = new ClassInfo[m_parameterTypeNames.length];
111: for (int i = 0; i < m_parameterTypeNames.length; i++) {
112: m_parameterTypes[i] = AsmClassInfo.getClassInfo(
113: m_parameterTypeNames[i],
114: (ClassLoader) m_loaderRef.get());
115: }
116: }
117: return m_parameterTypes;
118: }
119:
120: /**
121: * Returns the exception types.
122: *
123: * @return the exception types
124: */
125: public ClassInfo[] getExceptionTypes() {
126: if (m_exceptionTypes == null) {
127: m_exceptionTypes = new ClassInfo[m_exceptionTypeNames.length];
128: for (int i = 0; i < m_exceptionTypeNames.length; i++) {
129: m_exceptionTypes[i] = AsmClassInfo.getClassInfo(
130: m_exceptionTypeNames[i],
131: (ClassLoader) m_loaderRef.get());
132: }
133: }
134: return m_exceptionTypes;
135: }
136:
137: /**
138: * Returns the annotations.
139: *
140: * @return the annotations
141: */
142: public List getAnnotations() {
143: if (m_annotations == null) {
144: try {
145: InputStream in = null;
146: ClassReader cr = null;
147: try {
148: if ((ClassLoader) m_loaderRef.get() != null) {
149: in = ((ClassLoader) m_loaderRef.get())
150: .getResourceAsStream(m_declaringTypeName
151: .replace('.', '/')
152: + ".class");
153: } else {
154: in = ClassLoader.getSystemClassLoader()
155: .getResourceAsStream(
156: m_declaringTypeName.replace(
157: '.', '/')
158: + ".class");
159: }
160: if (in == null) {
161: in = ProxyCompiler.getProxyResourceAsStream(
162: (ClassLoader) m_loaderRef.get(),
163: m_declaringTypeName);
164: }
165: cr = new ClassReader(in);
166: } finally {
167: try {
168: in.close();
169: } catch (Exception e) {
170: ;
171: }
172: }
173: List annotations = new ArrayList();
174: cr
175: .accept(
176: new AsmAnnotationHelper.ConstructorAnnotationExtractor(
177: annotations, m_member.desc,
178: (ClassLoader) m_loaderRef.get()),
179: Attributes.getDefaultAttributes(), true);
180: m_annotations = annotations;
181: } catch (IOException e) {
182: // unlikely to occur since ClassInfo relies on getResourceAsStream
183: System.err.println("WARN - could not load "
184: + m_declaringTypeName
185: + " as a resource to retrieve annotations");
186: m_annotations = AsmClassInfo.EMPTY_LIST;
187: }
188: }
189: return m_annotations;
190: }
191:
192: public boolean equals(Object o) {
193: if (this == o) {
194: return true;
195: }
196: if (!(o instanceof ConstructorInfo)) {
197: return false;
198: }
199: ConstructorInfo constructorInfo = (ConstructorInfo) o;
200: if (!m_declaringTypeName.equals(constructorInfo
201: .getDeclaringType().getName())) {
202: return false;
203: }
204: if (!m_member.name.equals(constructorInfo.getName())) {
205: return false;
206: }
207: ClassInfo[] parameterTypes = constructorInfo
208: .getParameterTypes();
209: if (m_parameterTypeNames.length != parameterTypes.length) {//check on names length for lazyness optim
210: return false;
211: }
212: for (int i = 0; i < m_parameterTypeNames.length; i++) {
213: if (!m_parameterTypeNames[i].equals(parameterTypes[i]
214: .getName())) {
215: return false;
216: }
217: }
218: return true;
219: }
220:
221: public int hashCode() {
222: int result = 29;
223: result = (29 * result) + m_declaringTypeName.hashCode();
224: result = (29 * result) + m_member.name.hashCode();
225: for (int i = 0; i < m_parameterTypeNames.length; i++) {
226: result = (29 * result) + m_parameterTypeNames[i].hashCode();
227: }
228: return result;
229: }
230:
231: public String toString() {
232: StringBuffer sb = new StringBuffer(m_declaringTypeName);
233: sb.append('.').append(m_member.name);
234: sb.append(m_member.desc);
235: return sb.toString();
236: }
237: }
|