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