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;
    9
    10  import gnu.trove.TIntObjectHashMap;
    11
    12  import java.lang.ref.WeakReference;
    13  import java.util.Map;
    14  import java.util.WeakHashMap;
    15
    16  /***
    17   * A repository for the class info hierarchy. Is class loader aware.
    18   *
    19   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    20   */
    21  public class ClassInfoRepository {
    22      /***
    23       * Map with all the class info repositories mapped to their class loader.
    24       */
    25      private static final TIntObjectHashMap s_repositories = new TIntObjectHashMap();
    26
    27      /***
    28       * Map with all the class info mapped to their class names.
    29       */
    30      private final Map m_repository = new WeakHashMap();
    31
    32      /***
    33       * Class loader for the class repository.
    34       */
    35      private transient final WeakReference m_loaderRef;
    36
    37      /***
    38       * Creates a new repository.
    39       *
    40       * @param loader
    41       */
    42      private ClassInfoRepository(final ClassLoader loader) {
    43          m_loaderRef = new WeakReference(loader);
    44      }
    45
    46      /***
    47       * Returns the class info repository for the specific class loader
    48       *
    49       * @param loader
    50       * @return
    51       */
    52      public static synchronized ClassInfoRepository getRepository(final ClassLoader loader) {
    53          int hash;
    54          if (loader == null) { // boot cl
    55              hash = 0;
    56          } else {
    57              hash = loader.hashCode();
    58          }
    59          WeakReference repositoryRef = (WeakReference) s_repositories.get(hash);
    60          ClassInfoRepository repository = ((repositoryRef == null) ? null : (ClassInfoRepository) repositoryRef.get());
    61          if (repository != null) {
    62              return repository;
    63          } else {
    64              ClassInfoRepository repo = new ClassInfoRepository(loader);
    65              s_repositories.put(hash, new WeakReference(repo));
    66              return repo;
    67          }
    68      }
    69
    70      /***
    71       * Remove a class from the repository.
    72       *
    73       * @param className the name of the class
    74       */
    75      public static void removeClassInfoFromAllClassLoaders(final String className) {
    76          //TODO - fix algorithm
    77          throw new UnsupportedOperationException("fix algorithm");
    78      }
    79
    80      /***
    81       * Returns the class info.
    82       *
    83       * @param className
    84       * @return
    85       */
    86      public ClassInfo getClassInfo(final String className) {
    87          ClassInfo info = (ClassInfo) m_repository.get(className);
    88          if (info == null) {
    89              return checkParentClassRepository(className, (ClassLoader) m_loaderRef.get());
    90          }
    91          return (ClassInfo) m_repository.get(className);
    92      }
    93
    94      /***
    95       * Adds a new class info.
    96       *
    97       * @param classInfo
    98       */
    99      public void addClassInfo(final ClassInfo classInfo) {
    100         // is the class loaded by a class loader higher up in the hierarchy?
    101         if (checkParentClassRepository(classInfo.getName(), (ClassLoader) m_loaderRef.get()) == null) {
    102             // need to create new String instance to avoid using the original reference
    103             m_repository.put(new String(classInfo.getName()), classInfo);
    104         } else {
    105             // TODO: remove class in child class repository and add it for the current (parent) CL
    106         }
    107     }
    108
    109     /***
    110      * Checks if the class info for a specific class exists.
    111      *
    112      * @param name
    113      * @return
    114      */
    115     public boolean hasClassInfo(final String name) {
    116         return m_repository.containsKey(name);
    117     }
    118
    119     /***
    120      * Searches for a class info up in the class loader hierarchy.
    121      *
    122      * @param className
    123      * @param loader
    124      * @return the class info
    125      * @TODO might clash for specific class loader lookup algorithms, user need to override this class and implement
    126      * this method
    127      */
    128     public ClassInfo checkParentClassRepository(final String className, final ClassLoader loader) {
    129         if (loader == null) {
    130             return null;
    131         }
    132         ClassInfo info;
    133         ClassLoader parent = loader.getParent();
    134         if (parent == null) {
    135             return null;
    136         } else {
    137             info = ClassInfoRepository.getRepository(parent).getClassInfo(className);
    138             if (info != null) {
    139                 return info;
    140             } else {
    141                 return checkParentClassRepository(className, parent);
    142             }
    143         }
    144     }
    145 }