You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rs...@apache.org on 2002/08/15 21:33:25 UTC
cvs commit: jakarta-commons/discovery/src/java/org/apache/commons/discovery DiscoverSingleton.java
rsitze 2002/08/15 12:33:25
Modified: discovery/src/java/org/apache/commons/discovery
DiscoverSingleton.java
Added: discovery/src/java/org/apache/commons/discovery/tools
EnvironmentCache.java
Log:
Factored portions of caching out to tools package.
Revision Changes Path
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/tools/EnvironmentCache.java
Index: EnvironmentCache.java
===================================================================
/*
* $Header$
* $Revision$
* $Date$
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.commons.discovery.tools;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import org.apache.commons.discovery.base.Environment;
import org.apache.commons.discovery.base.ImplClass;
import org.apache.commons.discovery.base.SPInterface;
import org.apache.commons.discovery.load.ClassLoaderUtils;
/**
* Cache by a 'key' unique to the environment:
*
* - ClassLoader::groupContext::Object Cache
* Cache : HashMap
* Key : Thread Context Class Loader (<code>ClassLoader</code>)
* Value : groupContext::SPI Cache (<code>HashMap</code>)
*
* - groupContext::Object Cache
* Cache : HashMap
* Key : groupContext (<code>String</code>)
* Value : <code>Object</code>
*
* When we 'release', it is expected that the caller of the 'release'
* have the same thread context class loader... as that will be used
* to identify cached entries to be released.
*
*/
public class EnvironmentCache {
/**
* Allows null key, important as default groupContext is null.
*
* We will manage synchronization directly, so all caches are implemented
* as HashMap (unsynchronized).
*
*/
private static final HashMap root_cache = new HashMap();
/**
* Initial hash size for SPI's, default just seem TO big today..
*/
public static final int smallHashSize = 13;
/**
* Get object keyed by classLoader.
*/
public static synchronized Object get(Environment env)
{
/**
* 'null' (bootstrap/system class loader) thread context class loader
* is ok... Until we learn otherwise.
*/
HashMap groups =
(HashMap)root_cache.get(env.getThreadContextClassLoader());
return (groups != null)
? (HashMap)groups.get(env.getGroupContext())
: null;
}
/**
* Put service keyed by spi & classLoader.
*/
public static synchronized void put(Environment env, Object object)
{
/**
* 'null' (bootstrap/system class loader) thread context class loader
* is ok... Until we learn otherwise.
*/
if (object != null)
{
HashMap groups =
(HashMap)root_cache.get(env.getThreadContextClassLoader());
if (groups == null) {
groups = new HashMap(smallHashSize);
root_cache.put(env.getThreadContextClassLoader(), groups);
}
groups.put(env.getGroupContext(), object);
}
}
/********************** CACHE-MANAGEMENT SUPPORT **********************/
/**
* Release all internal references to previously created service
* instances associated with the current thread context class loader.
* The <code>release()</code> method is called for service instances that
* implement the <code>Service</code> interface.
*
* This is useful in environments like servlet containers,
* which implement application reloading by throwing away a ClassLoader.
* Dangling references to objects in that class loader would prevent
* garbage collection.
*/
public static synchronized void release() {
/**
* 'null' (bootstrap/system class loader) thread context class loader
* is ok... Until we learn otherwise.
*/
ClassLoader threadContextClassLoader =
ClassLoaderUtils.getThreadContextClassLoader();
HashMap groups = (HashMap)root_cache.get(threadContextClassLoader);
if (groups != null) {
Iterator groupIter = groups.values().iterator();
while (groupIter.hasNext()) {
Object object = groupIter.next();
}
groups.clear();
}
root_cache.remove(threadContextClassLoader);
}
/**
* Release any internal references to a previously created service
* instance associated with the current thread context class loader.
* If the SPI instance implements <code>Service</code>, then call
* <code>release()</code>.
*/
public static synchronized void release(Environment env) {
/**
* 'null' (bootstrap/system class loader) thread context class loader
* is ok... Until we learn otherwise.
*/
HashMap groups =
(HashMap)root_cache.get(env.getThreadContextClassLoader());
if (groups != null) {
groups.remove(env.getGroupContext());
}
}
}
1.5 +40 -134 jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoverSingleton.java
Index: DiscoverSingleton.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoverSingleton.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- DiscoverSingleton.java 15 Aug 2002 17:45:46 -0000 1.4
+++ DiscoverSingleton.java 15 Aug 2002 19:33:25 -0000 1.5
@@ -70,6 +70,7 @@
import org.apache.commons.discovery.base.ImplClass;
import org.apache.commons.discovery.base.SPInterface;
import org.apache.commons.discovery.load.ClassLoaderUtils;
+import org.apache.commons.discovery.tools.EnvironmentCache;
/**
@@ -498,9 +499,7 @@
* Return previously registered service object (not class)
* for this spi, bound only to current thread context class loader.
*/
- Object service = get(env.getThreadContextClassLoader(),
- env.getGroupContext(),
- spi.getSPName());
+ Object service = get(env, spi.getSPName());
if (service == null) {
try {
@@ -508,10 +507,7 @@
DiscoverClass.newInstance(env, spi, properties, defaultImpl);
if (service != null) {
- put(env.getThreadContextClassLoader(),
- env.getGroupContext(),
- spi.getSPName(),
- service);
+ put(env, spi.getSPName(), service);
}
} catch (DiscoveryException de) {
throw de;
@@ -557,9 +553,7 @@
* Return previously registered service object (not class)
* for this spi, bound only to current thread context class loader.
*/
- Object service = get(env.getThreadContextClassLoader(),
- env.getGroupContext(),
- spi.getSPName());
+ Object service = get(env, spi.getSPName());
if (service == null) {
try {
@@ -569,10 +563,7 @@
defaultImpl);
if (service != null) {
- put(env.getThreadContextClassLoader(),
- env.getGroupContext(),
- spi.getSPName(),
- service);
+ put(env, spi.getSPName(), service);
}
} catch (DiscoveryException de) {
throw de;
@@ -598,31 +589,8 @@
* Dangling references to objects in that class loader would prevent
* garbage collection.
*/
- public static void release() {
- ClassLoader threadContextClassLoader =
- ClassLoaderUtils.getThreadContextClassLoader();
-
- /**
- * 'null' (bootstrap/system class loader) thread context class loader
- * is ok... Until we learn otherwise.
- */
- synchronized (root_cache) {
- HashMap groups = (HashMap)root_cache.get(threadContextClassLoader);
-
- if (groups != null) {
- Iterator groupIter = groups.values().iterator();
-
- while (groupIter.hasNext()) {
- HashMap spis = (HashMap)groupIter.next();
-
- if (spis != null) {
- spis.clear();
- }
- }
- groups.clear();
- }
- root_cache.remove(threadContextClassLoader);
- }
+ public static synchronized void release() {
+ root_cache.release();
}
@@ -632,27 +600,14 @@
* If the SPI instance implements <code>Service</code>, then call
* <code>release()</code>.
*/
- public static void release(String groupContext) {
- ClassLoader threadContextClassLoader =
- ClassLoaderUtils.getThreadContextClassLoader();
-
- /**
- * 'null' (bootstrap/system class loader) thread context class loader
- * is ok... Until we learn otherwise.
- */
- synchronized (root_cache) {
- HashMap groups = (HashMap)root_cache.get(threadContextClassLoader);
-
- if (groups != null) {
- HashMap spis = (HashMap)groups.get(groupContext);
-
- if (spis != null) {
- spis.clear();
- }
- groups.remove(groupContext);
- }
- root_cache.remove(threadContextClassLoader);
+ public static synchronized void release(String groupContext) {
+ HashMap spis = (HashMap)root_cache.get(new Environment(groupContext));
+
+ if (spis != null) {
+ spis.clear();
}
+
+ root_cache.release(new Environment(groupContext));
}
/**
@@ -661,26 +616,11 @@
* If the SPI instance implements <code>Service</code>, then call
* <code>release()</code>.
*/
- public static void release(String groupContext, Class spiClass) {
- ClassLoader threadContextClassLoader =
- ClassLoaderUtils.getThreadContextClassLoader();
-
- /**
- * 'null' (bootstrap/system class loader) thread context class loader
- * is ok... Until we learn otherwise.
- */
- if (spiClass != null) {
- synchronized (root_cache) {
- HashMap groups = (HashMap)root_cache.get(threadContextClassLoader);
-
- if (groups != null) {
- HashMap spis = (HashMap)groups.get(groupContext);
-
- if (spis != null) {
- spis.remove(spiClass.getName());
- }
- }
- }
+ public static synchronized void release(String groupContext, Class spiClass) {
+ HashMap spis = (HashMap)root_cache.get(new Environment(groupContext));
+
+ if (spis != null) {
+ spis.remove(spiClass.getName());
}
}
@@ -690,7 +630,7 @@
* If the SPI instance implements <code>Service</code>, then call
* <code>release()</code>.
*/
- public static void release(Class spiClass) {
+ public static synchronized void release(Class spiClass) {
release(Environment.defaultGroupContext, spiClass);
}
@@ -723,75 +663,41 @@
*/
/**
- * Allows null key, important as default groupContext is null.
+ * Implements first two levels of the cache (loader & groupContext).
+ * Allows null keys, important as default groupContext is null.
*/
- private static final HashMap root_cache = new HashMap();
+ private static final EnvironmentCache root_cache = new EnvironmentCache();
/**
- * Initial hash size for SPI's, default just seem TO big today..
- */
- private static final int smallHashSize = 13;
-
- /**
* Get service keyed by spi & classLoader.
*/
- static Object get(ClassLoader loader, String groupContext, String spiName)
+ private static synchronized Object get(Environment env,
+ String spiName)
{
- Object service = null;
-
- /**
- * 'null' (bootstrap/system class loader) thread context class loader
- * is ok... Until we learn otherwise.
- */
- synchronized (root_cache) {
- HashMap groups =
- (HashMap)root_cache.get(loader);
-
- if (groups != null) {
- HashMap spis =
- (HashMap)groups.get(groupContext);
-
- if (spis != null) {
-
- service = (Object)spis.get(spiName);
- }
- }
- }
-
- return service;
+ HashMap spis = (HashMap)root_cache.get(env);
+
+ return (spis != null)
+ ? spis.get(spiName)
+ : null;
}
/**
* Put service keyed by spi & classLoader.
*/
- static void put(ClassLoader loader, String groupContext, String spiName,
- Object service)
+ private static synchronized void put(Environment env,
+ String spiName,
+ Object service)
{
- /**
- * 'null' (bootstrap/system class loader) thread context class loader
- * is ok... Until we learn otherwise.
- */
if (service != null)
{
- synchronized (root_cache) {
- HashMap groups =
- (HashMap)root_cache.get(loader);
-
- if (groups == null) {
- groups = new HashMap(smallHashSize);
- root_cache.put(loader, groups);
- }
-
- HashMap spis =
- (HashMap)groups.get(groupContext);
-
- if (spis == null) {
- spis = new HashMap(smallHashSize);
- groups.put(groupContext, spis);
- }
-
- spis.put(spiName, service);
+ HashMap spis = (HashMap)root_cache.get(env);
+
+ if (spis == null) {
+ spis = new HashMap(root_cache.smallHashSize);
+ root_cache.put(env, spis);
}
+
+ spis.put(spiName, service);
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>