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.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          // FIXME: how to do exceptions?
    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                 // unlikely to occur since ClassInfo relies on getResourceAsStream
    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) {//check on names length for lazyness optim
    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 }