View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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 }