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.FieldInfo;
12 import org.codehaus.aspectwerkz.transform.AsmHelper;
13 import org.codehaus.aspectwerkz.transform.AsmHelper;
14 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
15
16 import org.objectweb.asm.Type;
17 import org.objectweb.asm.ClassReader;
18
19 import java.util.List;
20 import java.util.ArrayList;
21 import java.io.IOException;
22
23 /***
24 * ASM implementation of the FieldInfo interface.
25 *
26 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
27 */
28 public class AsmFieldInfo extends AsmMemberInfo implements FieldInfo {
29
30 /***
31 * The field type name.
32 */
33 private String m_typeName;
34
35 /***
36 * The field type.
37 */
38 private ClassInfo m_type = null;
39
40 /***
41 * Creates a new field java instance.
42 *
43 * @param field
44 * @param declaringType
45 * @param loader
46 */
47 AsmFieldInfo(final FieldStruct field, final String declaringType, final ClassLoader loader) {
48 super(field, declaringType, loader);
49 m_typeName = Type.getType(field.desc).getClassName();
50 }
51
52 /***
53 * Returns the field info for the field specified.
54 *
55 * @param fieldName
56 * @param fieldDesc
57 * @param bytecode
58 * @param loader
59 * @return the field info
60 */
61 public static FieldInfo getFieldInfo(
62 final String fieldName,
63 final String fieldDesc,
64 final byte[] bytecode,
65 final ClassLoader loader) {
66 String className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
67 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
68 ClassInfo classInfo = repository.getClassInfo(className);
69 if (classInfo == null) {
70 classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
71 }
72 return classInfo.getField(AsmHelper.calculateFieldHash(fieldName, fieldDesc));
73 }
74
75 /***
76 * Returns the type.
77 *
78 * @return the type
79 */
80 public ClassInfo getType() {
81 if (m_type == null) {
82 m_type = AsmClassInfo.getClassInfo(m_typeName, (ClassLoader) m_loaderRef.get());
83 }
84 return m_type;
85 }
86
87 /***
88 * Returns the annotations.
89 *
90 * @return the annotations
91 */
92 public List getAnnotations() {
93 if (m_annotations == null) {
94 try {
95 ClassReader cr = new ClassReader(((ClassLoader)m_loaderRef.get()).getResourceAsStream(m_declaringTypeName.replace('.','/')+".class"));
96 List annotations = new ArrayList();
97 cr.accept(
98 new AsmAnnotationHelper.FieldAnnotationExtractor(annotations, m_member.name, (ClassLoader)m_loaderRef.get()),
99 AsmAnnotationHelper.ANNOTATIONS_ATTRIBUTES,
100 true
101 );
102 m_annotations = annotations;
103 } catch (IOException e) {
104
105 System.err.println("WARN - could not load " + m_declaringTypeName + " as a resource to retrieve annotations");
106 m_annotations = AsmClassInfo.EMPTY_LIST;
107 }
108 }
109 return m_annotations;
110 }
111
112 public boolean equals(Object o) {
113 if (this == o) {
114 return true;
115 }
116 if (!(o instanceof FieldInfo)) {
117 return false;
118 }
119 FieldInfo fieldInfo = (FieldInfo) o;
120 if (!m_declaringTypeName.equals(fieldInfo.getDeclaringType().getName())) {
121 return false;
122 }
123 if (!m_member.name.equals(fieldInfo.getName())) {
124 return false;
125 }
126 if (!m_typeName.equals(fieldInfo.getType().getName())) {
127 return false;
128 }
129 return true;
130 }
131
132 public int hashCode() {
133 int result = 29;
134 result = (29 * result) + m_declaringTypeName.hashCode();
135 result = (29 * result) + m_member.name.hashCode();
136 result = (29 * result) + m_typeName.hashCode();
137 return result;
138 }
139
140 public String toString() {
141 StringBuffer sb = new StringBuffer(m_declaringTypeName);
142 sb.append('.').append(m_member.name).append(' ');
143 sb.append(m_member.desc);
144 return sb.toString();
145 }
146 }