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