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.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                 // unlikely to occur since ClassInfo relies on getResourceAsStream
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 }