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