1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.discovery.tools;
18
19 import java.util.HashMap;
20
21 import org.apache.commons.discovery.jdk.JDKHooks;
22
23
24 /***
25 * Cache by a 'key' unique to the environment:
26 *
27 * - ClassLoader::groupContext::Object Cache
28 * Cache : HashMap
29 * Key : Thread Context Class Loader (<code>ClassLoader</code>)
30 * Value : groupContext::SPI Cache (<code>HashMap</code>)
31 *
32 * //- groupContext::Object Cache
33 * // Cache : HashMap
34 * // Key : groupContext (<code>String</code>)
35 * // Value : <code>Object</code>
36 *
37 * When we 'release', it is expected that the caller of the 'release'
38 * have the same thread context class loader... as that will be used
39 * to identify cached entries to be released.
40 *
41 * @author Richard A. Sitze
42 */
43 public class EnvironmentCache {
44 /***
45 * Allows null key, important as default groupContext is null.
46 *
47 * We will manage synchronization directly, so all caches are implemented
48 * as HashMap (unsynchronized).
49 *
50 */
51 private static final HashMap root_cache = new HashMap();
52
53 /***
54 * Initial hash size for SPI's, default just seem TO big today..
55 */
56 public static final int smallHashSize = 13;
57
58 /***
59 * Get object keyed by classLoader.
60 */
61 public static synchronized Object get(ClassLoader classLoader)
62 {
63 /***
64 * 'null' (bootstrap/system class loader) thread context class loader
65 * is ok... Until we learn otherwise.
66 */
67 return root_cache.get(classLoader);
68 }
69
70 /***
71 * Put service keyed by spi & classLoader.
72 */
73 public static synchronized void put(ClassLoader classLoader, Object object)
74 {
75 /***
76 * 'null' (bootstrap/system class loader) thread context class loader
77 * is ok... Until we learn otherwise.
78 */
79 if (object != null) {
80 root_cache.put(classLoader, object);
81 }
82 }
83
84
85 /*********************** CACHE-MANAGEMENT SUPPORT **********************/
86
87 /***
88 * Release all internal references to previously created service
89 * instances associated with the current thread context class loader.
90 * The <code>release()</code> method is called for service instances that
91 * implement the <code>Service</code> interface.
92 *
93 * This is useful in environments like servlet containers,
94 * which implement application reloading by throwing away a ClassLoader.
95 * Dangling references to objects in that class loader would prevent
96 * garbage collection.
97 */
98 public static synchronized void release() {
99 /***
100 * 'null' (bootstrap/system class loader) thread context class loader
101 * is ok... Until we learn otherwise.
102 */
103 root_cache.remove(JDKHooks.getJDKHooks().getThreadContextClassLoader());
104 }
105
106
107 /***
108 * Release any internal references to a previously created service
109 * instance associated with the current thread context class loader.
110 * If the SPI instance implements <code>Service</code>, then call
111 * <code>release()</code>.
112 */
113 public static synchronized void release(ClassLoader classLoader) {
114 /***
115 * 'null' (bootstrap/system class loader) thread context class loader
116 * is ok... Until we learn otherwise.
117 */
118 root_cache.remove(classLoader);
119 }
120 }