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) {
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
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
101 if (checkParentClassRepository(classInfo.getName(), (ClassLoader) m_loaderRef.get()) == null) {
102
103 m_repository.put(new String(classInfo.getName()), classInfo);
104 } else {
105
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 }