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.FieldInfo;
12  import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
13  import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
14  import org.codehaus.aspectwerkz.proxy.ProxyCompiler;
15  
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 FieldInfo interface.
27   *
28   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
29   */
30  public class AsmFieldInfo extends AsmMemberInfo implements FieldInfo {
31  
32      /***
33       * The field type name.
34       */
35      private String m_typeName;
36  
37      /***
38       * The field type.
39       */
40      private ClassInfo m_type = null;
41  
42      /***
43       * Creates a new field java instance.
44       *
45       * @param field
46       * @param declaringType
47       * @param loader
48       */
49      AsmFieldInfo(final FieldStruct field, final String declaringType, final ClassLoader loader) {
50          super(field, declaringType, loader);
51          m_typeName = Type.getType(field.desc).getClassName();
52      }
53  
54      /***
55       * Returns the field info for the field specified.
56       *
57       * @param fieldName
58       * @param fieldDesc
59       * @param bytecode
60       * @param loader
61       * @return the field info
62       */
63      public static FieldInfo getFieldInfo(final String fieldName,
64                                           final String fieldDesc,
65                                           final byte[] bytecode,
66                                           final ClassLoader loader) {
67          String className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
68          AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
69          ClassInfo classInfo = repository.getClassInfo(className);
70          if (classInfo == null) {
71              classInfo = AsmClassInfo.getClassInfo(bytecode, loader);
72          }
73          return classInfo.getField(AsmHelper.calculateFieldHash(fieldName, fieldDesc));
74      }
75  
76      /***
77       * Returns the signature for the element.
78       *
79       * @return the signature for the element
80       */
81      public String getSignature() {
82          return AsmHelper.getFieldDescriptor(this);
83      }
84  
85      /***
86       * Returns the type.
87       *
88       * @return the type
89       */
90      public ClassInfo getType() {
91          if (m_type == null) {
92              m_type = AsmClassInfo.getClassInfo(m_typeName, (ClassLoader) m_loaderRef.get());
93          }
94          return m_type;
95      }
96  
97      /***
98       * Returns the annotations.
99       *
100      * @return the annotations
101      */
102     public List getAnnotations() {
103         if (m_annotations == null) {
104             try {
105                 InputStream in = null;
106                 ClassReader cr = null;
107                 try {
108                     if ((ClassLoader) m_loaderRef.get() != null) {
109                         in = ((ClassLoader) m_loaderRef.get()).getResourceAsStream(
110                                 m_declaringTypeName.replace('.', '/') + ".class"
111                         );
112                     } else {
113                         in = ClassLoader.getSystemClassLoader().getResourceAsStream(
114                                 m_declaringTypeName.replace('.', '/') + ".class"
115                         );
116                     }
117                     if (in == null) {
118                         in = ProxyCompiler.getProxyResourceAsStream((ClassLoader) m_loaderRef.get(), m_declaringTypeName);
119                     }
120                     cr = new ClassReader(in);
121                 } finally {
122                     try {
123                         in.close();
124                     } catch (Exception e) {
125                         ;
126                     }
127                 }
128                 List annotations = new ArrayList();
129                 cr.accept(
130                         new AsmAnnotationHelper.FieldAnnotationExtractor(
131                                 annotations, m_member.name, (ClassLoader) m_loaderRef.get()
132                         ),
133                         Attributes.getDefaultAttributes(),
134                         true
135                 );
136                 m_annotations = annotations;
137             } catch (IOException e) {
138                 // unlikely to occur since ClassInfo relies on getResourceAsStream
139                 System.err.println(
140                         "WARN - could not load " + m_declaringTypeName + " as a resource to retrieve annotations"
141                 );
142                 m_annotations = AsmClassInfo.EMPTY_LIST;
143             }
144         }
145         return m_annotations;
146     }
147 
148     public boolean equals(Object o) {
149         if (this == o) {
150             return true;
151         }
152         if (!(o instanceof FieldInfo)) {
153             return false;
154         }
155         FieldInfo fieldInfo = (FieldInfo) o;
156         if (!m_declaringTypeName.equals(fieldInfo.getDeclaringType().getName())) {
157             return false;
158         }
159         if (!m_member.name.equals(fieldInfo.getName())) {
160             return false;
161         }
162         if (!m_typeName.equals(fieldInfo.getType().getName())) {
163             return false;
164         }
165         return true;
166     }
167 
168     public int hashCode() {
169         int result = 29;
170         result = (29 * result) + m_declaringTypeName.hashCode();
171         result = (29 * result) + m_member.name.hashCode();
172         result = (29 * result) + m_typeName.hashCode();
173         return result;
174     }
175 
176     public String toString() {
177         StringBuffer sb = new StringBuffer(m_declaringTypeName);
178         sb.append('.').append(m_member.name).append(' ');
179         sb.append(m_member.desc);
180         return sb.toString();
181     }
182 }