001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.reflect.impl.java;
008:
009: import gnu.trove.TIntObjectHashMap;
010: import org.codehaus.aspectwerkz.reflect.ClassInfo;
011:
012: import java.lang.ref.WeakReference;
013: import java.util.Map;
014: import java.util.WeakHashMap;
015:
016: /**
017: * A repository for the class info hierarchy. Is class loader aware. <p/>TODO refactor some with
018: * ASMClassInfoRepository but keep em separate for system runtime sake in AOPC (WLS)
019: *
020: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
021: */
022: public class JavaClassInfoRepository {
023: /**
024: * Map with all the class info repositories mapped to their class loader.
025: */
026: private static final TIntObjectHashMap s_repositories = new TIntObjectHashMap();
027:
028: /**
029: * Map with all the class info mapped to their class names.
030: */
031: private final Map m_repository = new WeakHashMap();
032:
033: /**
034: * Class loader for the class repository.
035: */
036: private transient final WeakReference m_loaderRef;
037:
038: /**
039: * Creates a new repository.
040: *
041: * @param loader
042: */
043: private JavaClassInfoRepository(final ClassLoader loader) {
044: m_loaderRef = new WeakReference(loader);
045: }
046:
047: /**
048: * Returns the class info repository for the specific class loader
049: *
050: * @param loader
051: * @return
052: */
053: public static synchronized JavaClassInfoRepository getRepository(
054: final ClassLoader loader) {
055: int hash;
056: if (loader == null) { // boot cl
057: hash = 0;
058: } else {
059: hash = loader.hashCode();
060: }
061: WeakReference repositoryRef = (WeakReference) s_repositories
062: .get(hash);
063: JavaClassInfoRepository repository = ((repositoryRef == null) ? null
064: : (JavaClassInfoRepository) repositoryRef.get());
065: if (repository != null) {
066: return repository;
067: } else {
068: JavaClassInfoRepository repo = new JavaClassInfoRepository(
069: loader);
070: s_repositories.put(hash, new WeakReference(repo));
071: return repo;
072: }
073: }
074:
075: /**
076: * Remove a class from the repository.
077: *
078: * @param className the name of the class
079: */
080: public static void removeClassInfoFromAllClassLoaders(
081: final String className) {
082: //TODO - fix algorithm
083: throw new UnsupportedOperationException("fix algorithm");
084: }
085:
086: /**
087: * Returns the class info.
088: *
089: * @param className
090: * @return
091: */
092: public ClassInfo getClassInfo(final String className) {
093: ClassInfo info = (ClassInfo) m_repository.get(className);
094: if (info == null) {
095: return checkParentClassRepository(className,
096: (ClassLoader) m_loaderRef.get());
097: }
098: return (ClassInfo) m_repository.get(className);
099: }
100:
101: /**
102: * Adds a new class info.
103: *
104: * @param classInfo
105: */
106: public void addClassInfo(final ClassInfo classInfo) {
107: // is the class loaded by a class loader higher up in the hierarchy?
108: if (checkParentClassRepository(classInfo.getName(),
109: (ClassLoader) m_loaderRef.get()) == null) {
110: m_repository
111: .put(new String(classInfo.getName()), classInfo);
112: } else {
113: // TODO: remove class in child class repository and add it for the current (parent) CL
114: }
115: }
116:
117: /**
118: * Checks if the class info for a specific class exists.
119: *
120: * @param name
121: * @return
122: */
123: public boolean hasClassInfo(final String name) {
124: return m_repository.containsKey(name);
125: }
126:
127: /**
128: * Searches for a class info up in the class loader hierarchy.
129: *
130: * @param className
131: * @param loader
132: * @return the class info
133: * @TODO might clash for specific class loader lookup algorithms, user need to override this class and implement
134: * this method
135: */
136: public ClassInfo checkParentClassRepository(final String className,
137: final ClassLoader loader) {
138: if (loader == null) {
139: return null;
140: }
141: ClassInfo info;
142: ClassLoader parent = loader.getParent();
143: if (parent == null) {
144: return null;
145: } else {
146: info = JavaClassInfoRepository.getRepository(parent)
147: .getClassInfo(className);
148: if (info != null) {
149: return info;
150: } else {
151: return checkParentClassRepository(className, parent);
152: }
153: }
154: }
155: }
|