001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.discovery.tools;
018:
019: import java.util.HashMap;
020:
021: import org.apache.commons.discovery.jdk.JDKHooks;
022:
023: /**
024: * Cache by a 'key' unique to the environment:
025: *
026: * - ClassLoader::groupContext::Object Cache
027: * Cache : HashMap
028: * Key : Thread Context Class Loader (<code>ClassLoader</code>)
029: * Value : groupContext::SPI Cache (<code>HashMap</code>)
030: *
031: * //- groupContext::Object Cache
032: * // Cache : HashMap
033: * // Key : groupContext (<code>String</code>)
034: * // Value : <code>Object</code>
035: *
036: * When we 'release', it is expected that the caller of the 'release'
037: * have the same thread context class loader... as that will be used
038: * to identify cached entries to be released.
039: *
040: * @author Richard A. Sitze
041: */
042: public class EnvironmentCache {
043: /**
044: * Allows null key, important as default groupContext is null.
045: *
046: * We will manage synchronization directly, so all caches are implemented
047: * as HashMap (unsynchronized).
048: *
049: */
050: private static final HashMap root_cache = new HashMap();
051:
052: /**
053: * Initial hash size for SPI's, default just seem TO big today..
054: */
055: public static final int smallHashSize = 13;
056:
057: /**
058: * Get object keyed by classLoader.
059: */
060: public static synchronized Object get(ClassLoader classLoader) {
061: /**
062: * 'null' (bootstrap/system class loader) thread context class loader
063: * is ok... Until we learn otherwise.
064: */
065: return root_cache.get(classLoader);
066: }
067:
068: /**
069: * Put service keyed by spi & classLoader.
070: */
071: public static synchronized void put(ClassLoader classLoader,
072: Object object) {
073: /**
074: * 'null' (bootstrap/system class loader) thread context class loader
075: * is ok... Until we learn otherwise.
076: */
077: if (object != null) {
078: root_cache.put(classLoader, object);
079: }
080: }
081:
082: /********************** CACHE-MANAGEMENT SUPPORT **********************/
083:
084: /**
085: * Release all internal references to previously created service
086: * instances associated with the current thread context class loader.
087: * The <code>release()</code> method is called for service instances that
088: * implement the <code>Service</code> interface.
089: *
090: * This is useful in environments like servlet containers,
091: * which implement application reloading by throwing away a ClassLoader.
092: * Dangling references to objects in that class loader would prevent
093: * garbage collection.
094: */
095: public static synchronized void release() {
096: /**
097: * 'null' (bootstrap/system class loader) thread context class loader
098: * is ok... Until we learn otherwise.
099: */
100: root_cache.remove(JDKHooks.getJDKHooks()
101: .getThreadContextClassLoader());
102: }
103:
104: /**
105: * Release any internal references to a previously created service
106: * instance associated with the current thread context class loader.
107: * If the SPI instance implements <code>Service</code>, then call
108: * <code>release()</code>.
109: */
110: public static synchronized void release(ClassLoader classLoader) {
111: /**
112: * 'null' (bootstrap/system class loader) thread context class loader
113: * is ok... Until we learn otherwise.
114: */
115: root_cache.remove(classLoader);
116: }
117: }
|