KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > reflect > impl > asm > AsmClassInfoRepository


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5
6 package com.tc.aspectwerkz.reflect.impl.asm;
7
8 import com.tc.aspectwerkz.exception.DefinitionException;
9 import com.tc.aspectwerkz.reflect.ClassInfo;
10
11 import java.io.IOException JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.lang.ref.Reference JavaDoc;
14 import java.lang.ref.SoftReference JavaDoc;
15 import java.lang.ref.WeakReference JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Properties JavaDoc;
18
19 /**
20  * A repository for the class info hierarchy. Is class loader aware.
21  *
22  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
23  */

24 public class AsmClassInfoRepository {
25   /**
26    * Map with all the class info repositories mapped to their class loader.
27    */

28   private static final HashMap JavaDoc s_repositories = new HashMap JavaDoc();
29
30   /**
31    * Map with all the class info mapped to their class names.
32    */

33   private final HashMap JavaDoc m_repository = new HashMap JavaDoc();
34
35   /**
36    * Class loader for the class repository.
37    */

38   private transient final WeakReference JavaDoc m_loaderRef;
39
40   /**
41    * The annotation properties file.
42    */

43   private final Properties JavaDoc m_annotationProperties;
44
45   /**
46    * Creates a new repository.
47    *
48    * @param loader
49    */

50   private AsmClassInfoRepository(final ClassLoader JavaDoc loader) {
51     m_loaderRef = new WeakReference JavaDoc(loader);
52     m_annotationProperties = new Properties JavaDoc();
53     if (loader != null) {
54       try {
55         InputStream JavaDoc stream = loader.getResourceAsStream("annotation.properties");
56         if (stream != null) {
57           try {
58             m_annotationProperties.load(stream);
59           } finally {
60             try {
61               stream.close();
62             } catch (Exception JavaDoc e) {
63               //
64
}
65           }
66         }
67       } catch (IOException JavaDoc e) {
68         throw new DefinitionException("could not find resource [annotation.properties] on classpath");
69       }
70     }
71   }
72
73   /**
74    * Returns the class info repository for the specific class loader
75    *
76    * @param loader
77    * @return
78    */

79   public static AsmClassInfoRepository getRepository(final ClassLoader JavaDoc loader) {
80     Integer JavaDoc hash = new Integer JavaDoc(loader == null ? 0 : loader.hashCode()); // boot cl
81

82     synchronized (s_repositories) {
83       AsmClassInfoRepository repository = lookup(hash);
84
85       // normal return case for existing repositories
86
if (repository != null) { return repository; }
87     }
88
89     // Construct the repo outside of the lock (see CDV-116)
90
AsmClassInfoRepository repo = new AsmClassInfoRepository(loader);
91
92     // check again
93
synchronized (s_repositories) {
94       AsmClassInfoRepository repository = lookup(hash);
95
96       // another thread won, don't replace the mapping
97
if (repository != null) { return repository; }
98
99       s_repositories.put(hash, new SoftReference JavaDoc(repo));
100     }
101
102     return repo;
103
104   }
105
106   private static AsmClassInfoRepository lookup(Integer JavaDoc hash) {
107     Reference JavaDoc repositoryRef = (Reference JavaDoc) s_repositories.get(hash);
108     return ((repositoryRef == null) ? null : (AsmClassInfoRepository) repositoryRef.get());
109   }
110
111   /**
112    * Remove a class from the repository.
113    *
114    * @param className the name of the class
115    */

116   public static void removeClassInfoFromAllClassLoaders(final String JavaDoc className) {
117     // TODO - fix algorithm
118
throw new UnsupportedOperationException JavaDoc("fix algorithm");
119   }
120
121   /**
122    * Returns the class info.
123    *
124    * @param className
125    * @return
126    */

127   public ClassInfo getClassInfo(final String JavaDoc className) {
128     Reference JavaDoc classInfoRef = ((Reference JavaDoc) m_repository.get(new Integer JavaDoc(className.hashCode())));
129     ClassInfo info = classInfoRef == null ? null : (ClassInfo) classInfoRef.get();
130     if (info == null) { return checkParentClassRepository(className, (ClassLoader JavaDoc) m_loaderRef.get()); }
131     return info;
132   }
133
134   /**
135    * Adds a new class info.
136    *
137    * @param classInfo
138    */

139   public void addClassInfo(final ClassInfo classInfo) {
140     // is the class loaded by a class loader higher up in the hierarchy?
141
if (checkParentClassRepository(classInfo.getName(), (ClassLoader JavaDoc) m_loaderRef.get()) == null) {
142       m_repository.put(new Integer JavaDoc(classInfo.getName().hashCode()), new SoftReference JavaDoc(classInfo));
143     } else {
144       // TODO: remove class in child class repository and add it for the
145
// current (parent) CL
146
}
147   }
148
149   /**
150    * Checks if the class info for a specific class exists.
151    *
152    * @param name
153    * @return
154    */

155   public boolean hasClassInfo(final String JavaDoc name) {
156     Reference JavaDoc classInfoRef = (Reference JavaDoc) m_repository.get(new Integer JavaDoc(name.hashCode()));
157     return (classInfoRef == null) ? false : (classInfoRef.get() != null);
158   }
159
160   /**
161    * Removes the class from the repository (since it has been modified and needs to be rebuild).
162    *
163    * @param className
164    */

165   public void removeClassInfo(final String JavaDoc className) {
166     m_repository.remove(new Integer JavaDoc(className.hashCode()));
167   }
168
169   /**
170    * Returns the annotation properties for the specific class loader.
171    *
172    * @return the annotation properties
173    */

174   public Properties JavaDoc getAnnotationProperties() {
175     return m_annotationProperties;
176   }
177
178   /**
179    * Searches for a class info up in the class loader hierarchy.
180    *
181    * @param className
182    * @param loader
183    * @return the class info
184    * @TODO might clash for specific class loader lookup algorithms, user need to override this class and implement this
185    * method
186    */

187   public ClassInfo checkParentClassRepository(final String JavaDoc className, final ClassLoader JavaDoc loader) {
188     if (loader == null) { return null; }
189     ClassLoader JavaDoc parent = loader.getParent();
190     if (parent == null) {
191       return null;
192     } else {
193       AsmClassInfoRepository parentRep = AsmClassInfoRepository.getRepository(parent);
194
195       Reference JavaDoc classInfoRef = ((Reference JavaDoc) parentRep.m_repository.get(new Integer JavaDoc(className.hashCode())));
196       ClassInfo info = classInfoRef == null ? null : (ClassInfo) classInfoRef.get();
197       if (info != null) {
198         return info;
199       } else {
200         return checkParentClassRepository(className, parent);
201       }
202     }
203   }
204
205   /*
206    * public ClassInfo checkParentClassRepository(final String className, final ClassLoader loader) { if (loader == null) {
207    * return null; } ClassLoader parent = loader.getParent(); if (parent == null) { return null; } else { ClassInfo info =
208    * AsmClassInfoRepository.getRepository(parent).getClassInfo(className); if (info != null) { return info; } else {
209    * return checkParentClassRepository(className, parent); } } }
210    */

211
212 }
Popular Tags