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 gnu.trove.TIntObjectHashMap;
    11  import org.codehaus.aspectwerkz.reflect.ClassInfo;
    12  import org.codehaus.aspectwerkz.exception.DefinitionException;
    13
    14  import java.lang.ref.WeakReference;
    15  import java.lang.ref.SoftReference;
    16  import java.lang.ref.Reference;
    17  import java.util.Properties;
    18  import java.io.InputStream;
    19  import java.io.IOException;
    20
    21  /***
    22   * A repository for the class info hierarchy. Is class loader aware.
    23   *
    24   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    25   */
    26  public class AsmClassInfoRepository {
    27      /***
    28       * Map with all the class info repositories mapped to their class loader.
    29       */
    30      private static final TIntObjectHashMap s_repositories = new TIntObjectHashMap();
    31
    32      /***
    33       * Map with all the class info mapped to their class names.
    34       */
    35      private final TIntObjectHashMap m_repository = new TIntObjectHashMap();
    36
    37      /***
    38       * Class loader for the class repository.
    39       */
    40      private transient final WeakReference m_loaderRef;
    41
    42      /***
    43       * The annotation properties file.
    44       */
    45      private final Properties m_annotationProperties;
    46
    47      /***
    48       * Creates a new repository.
    49       *
    50       * @param loader
    51       */
    52      private AsmClassInfoRepository(final ClassLoader loader) {
    53          m_loaderRef = new WeakReference(loader);
    54          m_annotationProperties = new Properties();
    55          if (loader != null) {
    56              try {
    57                  InputStream stream = loader.getResourceAsStream("annotation.properties");
    58                  if (stream != null) {
    59                      try {
    60                          m_annotationProperties.load(stream);
    61                      } finally {
    62                          try {
    63                              stream.close();
    64                          } catch (Exception e) {
    65                              ;
    66                          }
    67                      }
    68                  }
    69              } catch (IOException e) {
    70                  throw new DefinitionException("could not find resource [annotation.properties] on classpath");
    71              }
    72          }
    73      }
    74
    75      /***
    76       * Returns the class info repository for the specific class loader
    77       *
    78       * @param loader
    79       * @return
    80       */
    81      public static synchronized AsmClassInfoRepository getRepository(final ClassLoader loader) {
    82          int hash;
    83          if (loader == null) { // boot cl
    84              hash = 0;
    85          } else {
    86              hash = loader.hashCode();
    87          }
    88          Reference repositoryRef = (Reference) s_repositories.get(hash);
    89          AsmClassInfoRepository repository = ((repositoryRef == null) ? null : (AsmClassInfoRepository) repositoryRef
    90                  .get());
    91          if (repository != null) {
    92              return repository;
    93          } else {
    94              AsmClassInfoRepository repo = new AsmClassInfoRepository(loader);
    95              s_repositories.put(hash, new SoftReference(repo));
    96              return repo;
    97          }
    98      }
    99
    100     /***
    101      * Remove a class from the repository.
    102      *
    103      * @param className the name of the class
    104      */
    105     public static void removeClassInfoFromAllClassLoaders(final String className) {
    106         //TODO - fix algorithm
    107         throw new UnsupportedOperationException("fix algorithm");
    108     }
    109
    110     /***
    111      * Returns the class info.
    112      *
    113      * @param className
    114      * @return
    115      */
    116     public ClassInfo getClassInfo(final String className) {
    117         Reference classInfoRef = ((Reference) m_repository.get(className.hashCode()));
    118         ClassInfo info = (classInfoRef == null) ? null : (ClassInfo) (classInfoRef.get());
    119         if (info == null) {
    120             return checkParentClassRepository(className, (ClassLoader) m_loaderRef.get());
    121         }
    122         return info;
    123     }
    124
    125     /***
    126      * Adds a new class info.
    127      *
    128      * @param classInfo
    129      */
    130     public void addClassInfo(final ClassInfo classInfo) {
    131         // is the class loaded by a class loader higher up in the hierarchy?
    132         if (checkParentClassRepository(classInfo.getName(), (ClassLoader) m_loaderRef.get()) == null) {
    133             m_repository.put(classInfo.getName().hashCode(), new SoftReference(classInfo));
    134         } else {
    135             // TODO: remove class in child class repository and add it for the
    136             // current (parent) CL
    137         }
    138     }
    139
    140     /***
    141      * Checks if the class info for a specific class exists.
    142      *
    143      * @param name
    144      * @return
    145      */
    146     public boolean hasClassInfo(final String name) {
    147         Reference classInfoRef = (Reference) m_repository.get(name.hashCode());
    148         return (classInfoRef == null) ? false : (classInfoRef.get() != null);
    149     }
    150
    151     /***
    152      * Removes the class from the repository (since it has been modified and needs to be rebuild).
    153      *
    154      * @param className
    155      */
    156     public void removeClassInfo(final String className) {
    157         m_repository.remove(className.hashCode());
    158     }
    159
    160     /***
    161      * Returns the annotation properties for the specific class loader.
    162      *
    163      * @return the annotation properties
    164      */
    165     public Properties getAnnotationProperties() {
    166         return m_annotationProperties;
    167     }
    168
    169     /***
    170      * Searches for a class info up in the class loader hierarchy.
    171      *
    172      * @param className
    173      * @param loader
    174      * @return the class info
    175      * @TODO might clash for specific class loader lookup algorithms, user need to override this class and implement
    176      * this method
    177      */
    178     public ClassInfo checkParentClassRepository(final String className, final ClassLoader loader) {
    179         if (loader == null) {
    180             return null;
    181         }
    182         ClassInfo info;
    183         ClassLoader parent = loader.getParent();
    184         if (parent == null) {
    185             return null;
    186         } else {
    187             info = AsmClassInfoRepository.getRepository(parent).getClassInfo(className);
    188             if (info != null) {
    189                 return info;
    190             } else {
    191                 return checkParentClassRepository(className, parent);
    192             }
    193         }
    194     }
    195 }