You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/01/20 14:48:55 UTC
svn commit: r370807 [4/22] - in /directory/sandbox/trustin/mina-spi: ./
core/src/main/java/org/apache/mina/common/
core/src/main/java/org/apache/mina/common/support/
core/src/main/java/org/apache/mina/common/support/discovery/
core/src/main/java/org/ap...
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/DiscoverSingleton.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/DiscoverSingleton.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/DiscoverSingleton.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/DiscoverSingleton.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,531 @@
+/*
+ * $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.mina.common.support.discovery.tools;
+
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.apache.mina.common.support.discovery.DiscoveryException;
+import org.apache.mina.common.support.discovery.jdk.JDKHooks;
+import org.apache.mina.common.support.discovery.resource.ClassLoaders;
+
+
+/**
+ * <p>Discover singleton service providers.
+ * This
+ * </p>
+ *
+ * <p>DiscoverSingleton instances are cached by the Discovery service,
+ * keyed by a combination of
+ * <ul>
+ * <li>thread context class loader,</li>
+ * <li>groupContext, and</li>
+ * <li>SPI.</li>
+ * </ul>
+ * This DOES allow multiple instances of a given <i>singleton</i> class
+ * to exist for different class loaders and different group contexts.
+ * </p>
+ *
+ * <p>In the context of this package, a service interface is defined by a
+ * Service Provider Interface (SPI). The SPI is expressed as a Java interface,
+ * abstract class, or (base) class that defines an expected programming
+ * interface.
+ * </p>
+ *
+ * <p>DiscoverSingleton provides the <code>find</code> methods for locating and
+ * instantiating a singleton instance of an implementation of a service (SPI).
+ * Each form of <code>find</code> varies slightly, but they all perform the
+ * same basic function.
+ *
+ * The simplest <code>find</code> methods are intended for direct use by
+ * components looking for a service. If you are not sure which finder(s)
+ * to use, you can narrow your search to one of these:
+ * <ul>
+ * <li>static Object find(Class spi);</li>
+ * <li>static Object find(Class spi, Properties properties);</li>
+ * <li>static Object find(Class spi, String defaultImpl);</li>
+ * <li>static Object find(Class spi,
+ * Properties properties, String defaultImpl);</li>
+ * <li>static Object find(Class spi,
+ * String propertiesFileName, String defaultImpl);</li>
+ * <li>static Object find(String groupContext, Class spi,
+ * Properties properties, String defaultImpl);</li>
+ * <li>static Object find(String groupContext, Class spi,
+ * String propertiesFileName, String defaultImpl);</li>
+ * </ul>
+ *
+ * The <code>DiscoverSingleton.find</code> methods proceed as follows:
+ * </p>
+ * <ul>
+ * <p><li>
+ * Examine an internal cache to determine if the desired service was
+ * previously identified and instantiated. If found in cache, return it.
+ * </li></p>
+ * <p><li>
+ * Get the name of an implementation class. The name is the first
+ * non-null value obtained from the following resources:
+ * <ul>
+ * <li>
+ * The value of the (scoped) system property whose name is the same as
+ * the SPI's fully qualified class name (as given by SPI.class.getName()).
+ * The <code>ScopedProperties</code> class provides a way to bind
+ * properties by classloader, in a secure hierarchy similar in concept
+ * to the way classloader find class and resource files.
+ * See <code>ScopedProperties</code> for more details.
+ * <p>If the ScopedProperties are not set by users, then behaviour
+ * is equivalent to <code>System.getProperty()</code>.
+ * </p>
+ * </li>
+ * <p><li>
+ * The value of a <code>Properties properties</code> property, if provided
+ * as a parameter, whose name is the same as the SPI's fully qualifed class
+ * name (as given by SPI.class.getName()).
+ * </li></p>
+ * <p><li>
+ * The value obtained using the JDK1.3+ 'Service Provider' specification
+ * (http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html) to locate a
+ * service named <code>SPI.class.getName()</code>. This is implemented
+ * internally, so there is not a dependency on JDK 1.3+.
+ * </li></p>
+ * </ul>
+ * </li></p>
+ * <p><li>
+ * If the name of the implementation class is non-null, load that class.
+ * The class loaded is the first class loaded by the following sequence
+ * of class loaders:
+ * <ul>
+ * <li>Thread Context Class Loader</li>
+ * <li>DiscoverSingleton's Caller's Class Loader</li>
+ * <li>SPI's Class Loader</li>
+ * <li>DiscoverSingleton's (this class or wrapper) Class Loader</li>
+ * <li>System Class Loader</li>
+ * </ul>
+ * An exception is thrown if the class cannot be loaded.
+ * </li></p>
+ * <p><li>
+ * If the name of the implementation class is null, AND the default
+ * implementation class (<code>defaultImpl</code>) is null,
+ * then an exception is thrown.
+ * </li></p>
+ * <p><li>
+ * If the name of the implementation class is null, AND the default
+ * implementation class (<code>defaultImpl</code>) is non-null,
+ * then load the default implementation class. The class loaded is the
+ * first class loaded by the following sequence of class loaders:
+ * <ul>
+ * <li>SPI's Class Loader</li>
+ * <li>DiscoverSingleton's (this class or wrapper) Class Loader</li>
+ * <li>System Class Loader</li>
+ * </ul>
+ * <p>
+ * This limits the scope in which the default class loader can be found
+ * to the SPI, DiscoverSingleton, and System class loaders. The assumption
+ * here is that the default implementation is closely associated with the SPI
+ * or system, and is not defined in the user's application space.
+ * </p>
+ * <p>
+ * An exception is thrown if the class cannot be loaded.
+ * </p>
+ * </li></p>
+ * <p><li>
+ * Verify that the loaded class implements the SPI: an exception is thrown
+ * if the loaded class does not implement the SPI.
+ * </li></p>
+ * <p><li>
+ * Create an instance of the class.
+ * </li></p>
+ * </ul>
+ *
+ * <p>
+ * Variances for various forms of the <code>find</code>
+ * methods are discussed with each such method.
+ * Variances include the following concepts:
+ * <ul>
+ * <li><b>rootFinderClass</b> - a wrapper encapsulating a finder method
+ * (factory or other helper class). The root finder class is used to
+ * determine the 'real' caller, and hence the caller's class loader -
+ * thereby preserving knowledge that is relevant to finding the
+ * correct/expected implementation class.
+ * </li>
+ * <li><b>propertiesFileName</b> - <code>Properties</code> may be specified
+ * directly, or by property file name. A property file is loaded using the
+ * same sequence of class loaders used to load the SPI implementation:
+ * <ul>
+ * <li>Thread Context Class Loader</li>
+ * <li>DiscoverSingleton's Caller's Class Loader</li>
+ * <li>SPI's Class Loader</li>
+ * <li>DiscoverSingleton's (this class) Class Loader</li>
+ * <li>System Class Loader</li>
+ * </ul>
+ * </li>
+ * <li><b>groupContext</b> - differentiates service providers for different
+ * logical groups of service users, that might otherwise be forced to share
+ * a common service and, more importantly, a common configuration of that
+ * service.
+ * <p>The groupContext is used to qualify the name of the property file
+ * name: <code>groupContext + '.' + propertiesFileName</code>. If that
+ * file is not found, then the unqualified propertyFileName is used.
+ * </p>
+ * <p>In addition, groupContext is used to qualify the name of the system
+ * property used to find the service implementation by prepending the value
+ * of <code>groupContext</code> to the property name:
+ * <code>groupContext> + '.' + SPI.class.getName()</code>.
+ * Again, if a system property cannot be found by that name, then the
+ * unqualified property name is used.
+ * </p>
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is modelled
+ * after the SAXParserFactory and DocumentBuilderFactory implementations
+ * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.
+ * </p>
+ *
+ * @author Richard A. Sitze
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ * @version $Revision$ $Date$
+ */
+public class DiscoverSingleton {
+ /********************** (RELATIVELY) SIMPLE FINDERS **********************
+ *
+ * These finders are suitable for direct use in components looking for a
+ * service. If you are not sure which finder(s) to use, you can narrow
+ * your search to one of these.
+ */
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(Class spiClass)
+ throws DiscoveryException
+ {
+ return find(null,
+ new SPInterface(spiClass),
+ DiscoverClass.nullProperties,
+ DiscoverClass.nullDefaultImpl);
+ }
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @param properties Used to determine name of SPI implementation,
+ * and passed to implementation.init() method if
+ * implementation implements Service interface.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(Class spiClass, Properties properties)
+ throws DiscoveryException
+ {
+ return find(null,
+ new SPInterface(spiClass),
+ new PropertiesHolder(properties),
+ DiscoverClass.nullDefaultImpl);
+ }
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @param defaultImpl Default implementation.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(Class spiClass, String defaultImpl)
+ throws DiscoveryException
+ {
+ return find(null,
+ new SPInterface(spiClass),
+ DiscoverClass.nullProperties,
+ new DefaultClassHolder(defaultImpl));
+ }
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @param properties Used to determine name of SPI implementation,
+ * and passed to implementation.init() method if
+ * implementation implements Service interface.
+ *
+ * @param defaultImpl Default implementation.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(Class spiClass,
+ Properties properties,
+ String defaultImpl)
+ throws DiscoveryException
+ {
+ return find(null,
+ new SPInterface(spiClass),
+ new PropertiesHolder(properties),
+ new DefaultClassHolder(defaultImpl));
+ }
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @param properties Used to determine name of SPI implementation,
+ * and passed to implementation.init() method if
+ * implementation implements Service interface.
+ *
+ * @param defaultImpl Default implementation.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(Class spiClass,
+ String propertiesFileName,
+ String defaultImpl)
+ throws DiscoveryException
+ {
+ return find(null,
+ new SPInterface(spiClass),
+ new PropertiesHolder(propertiesFileName),
+ new DefaultClassHolder(defaultImpl));
+ }
+
+ /*************** FINDERS FOR USE IN FACTORY/HELPER METHODS ***************
+ */
+
+
+ /**
+ * Find implementation of SPI.
+ *
+ * @param spiClass Service Provider Interface Class.
+ *
+ * @param properties Used to determine name of SPI implementation,
+ * and passed to implementation.init() method if
+ * implementation implements Service interface.
+ *
+ * @param defaultImpl Default implementation.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Object find(ClassLoaders loaders,
+ SPInterface spi,
+ PropertiesHolder properties,
+ DefaultClassHolder defaultImpl)
+ throws DiscoveryException
+ {
+ ClassLoader contextLoader = JDKHooks.getJDKHooks().getThreadContextClassLoader();
+
+ Object obj = get(contextLoader, spi.getSPName());
+
+ if (obj == null) {
+ try {
+ obj = DiscoverClass.newInstance(loaders, spi, properties, defaultImpl);
+
+ if (obj != null) {
+ put(contextLoader, spi.getSPName(), obj);
+ }
+ } catch (DiscoveryException de) {
+ throw de;
+ } catch (Exception e) {
+ throw new DiscoveryException("Unable to instantiate implementation class for " + spi.getSPName(), e);
+ }
+ }
+
+ return obj;
+ }
+
+ /********************** 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() {
+ EnvironmentCache.release();
+ }
+
+ /**
+ * 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(Class spiClass) {
+ HashMap spis = (HashMap)EnvironmentCache.get(JDKHooks.getJDKHooks().getThreadContextClassLoader());
+
+ if (spis != null) {
+ spis.remove(spiClass.getName());
+ }
+ }
+
+
+ /************************* SPI CACHE SUPPORT *************************
+ *
+ * Cache services by a 'key' unique to the requesting class/environment:
+ *
+ * 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 all cached entries to be released.
+ *
+ * We will manage synchronization directly, so all caches are implemented
+ * as HashMap (unsynchronized).
+ *
+ * - ClassLoader::groupContext::SPI::Instance Cache
+ * Cache : HashMap
+ * Key : Thread Context Class Loader (<code>ClassLoader</code>).
+ * Value : groupContext::SPI Cache (<code>HashMap</code>).
+ *
+ * - groupContext::SPI::Instance Cache
+ * Cache : HashMap
+ * Key : groupContext (<code>String</code>).
+ * Value : SPI Cache (<code>HashMap</code>).
+ *
+ * - SPI::Instance Cache
+ * Cache : HashMap
+ * Key : SPI Class Name (<code>String</code>).
+ * Value : SPI Instance/Implementation (<code>Object</code>.
+ */
+
+ /**
+ * Implements first two levels of the cache (loader & groupContext).
+ * Allows null keys, important as default groupContext is null.
+ */
+ // FIXME: Why is this here? All the methods used are static.
+ //private static final EnvironmentCache root_cache = new EnvironmentCache();
+
+ /**
+ * Get service keyed by spi & classLoader.
+ */
+ private static synchronized Object get(ClassLoader classLoader,
+ String spiName)
+ {
+ HashMap spis = (HashMap)EnvironmentCache.get(classLoader);
+
+ return (spis != null)
+ ? spis.get(spiName)
+ : null;
+ }
+
+ /**
+ * Put service keyed by spi & classLoader.
+ */
+ private static synchronized void put(ClassLoader classLoader,
+ String spiName,
+ Object service)
+ {
+ if (service != null)
+ {
+ HashMap spis = (HashMap)EnvironmentCache.get(classLoader);
+
+ if (spis == null) {
+ spis = new HashMap(EnvironmentCache.smallHashSize);
+ EnvironmentCache.put(classLoader, spis);
+ }
+
+ spis.put(spiName, service);
+ }
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/DiscoverSingleton.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/EnvironmentCache.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/EnvironmentCache.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/EnvironmentCache.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/EnvironmentCache.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,165 @@
+/*
+ * $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.mina.common.support.discovery.tools;
+
+import java.util.HashMap;
+
+import org.apache.mina.common.support.discovery.jdk.JDKHooks;
+
+
+/**
+ * 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.
+ *
+ * @author Richard A. Sitze
+ */
+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(ClassLoader classLoader)
+ {
+ /**
+ * 'null' (bootstrap/system class loader) thread context class loader
+ * is ok... Until we learn otherwise.
+ */
+ return root_cache.get(classLoader);
+ }
+
+ /**
+ * Put service keyed by spi & classLoader.
+ */
+ public static synchronized void put(ClassLoader classLoader, Object object)
+ {
+ /**
+ * 'null' (bootstrap/system class loader) thread context class loader
+ * is ok... Until we learn otherwise.
+ */
+ if (object != null) {
+ root_cache.put(classLoader, 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.
+ */
+ root_cache.remove(JDKHooks.getJDKHooks().getThreadContextClassLoader());
+ }
+
+
+ /**
+ * 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(ClassLoader classLoader) {
+ /**
+ * 'null' (bootstrap/system class loader) thread context class loader
+ * is ok... Until we learn otherwise.
+ */
+ root_cache.remove(classLoader);
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/EnvironmentCache.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ManagedProperties.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ManagedProperties.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ManagedProperties.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ManagedProperties.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,376 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Axis" 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 name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * 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.mina.common.support.discovery.tools;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.mina.common.support.discovery.jdk.JDKHooks;
+
+
+
+/**
+ * <p>This class may disappear in the future, or be moved to another project..
+ * </p>
+ *
+ * <p>Extend the concept of System properties to a hierarchical scheme
+ * based around class loaders. System properties are global in nature,
+ * so using them easily violates sound architectural and design principles
+ * for maintaining separation between components and runtime environments.
+ * Nevertheless, there is a need for properties broader in scope than
+ * class or class instance scope.
+ * </p>
+ *
+ * <p>This class is one solution.
+ * </p>
+ *
+ * <p>Manage properties according to a secure
+ * scheme similar to that used by classloaders:
+ * <ul>
+ * <li><code>ClassLoader</code>s are organized in a tree hierarchy.</li>
+ * <li>each <code>ClassLoader</code> has a reference
+ * to a parent <code>ClassLoader</code>.</li>
+ * <li>the root of the tree is the bootstrap <code>ClassLoader</code>er.</li>
+ * <li>the youngest decendent is the thread context class loader.</li>
+ * <li>properties are bound to a <code>ClassLoader</code> instance
+ * <ul>
+ * <li><i>non-default</i> properties bound to a parent <code>ClassLoader</code>
+ * instance take precedence over all properties of the same name bound
+ * to any decendent.
+ * Just to confuse the issue, this is the default case.</li>
+ * <li><i>default</i> properties bound to a parent <code>ClassLoader</code>
+ * instance may be overriden by (default or non-default) properties of
+ * the same name bound to any decendent.
+ * </li>
+ * </ul>
+ * </li>
+ * <li>System properties take precedence over all other properties</li>
+ * </ul>
+ * </p>
+ *
+ * <p>This is not a perfect solution, as it is possible that
+ * different <code>ClassLoader</code>s load different instances of
+ * <code>ScopedProperties</code>. The 'higher' this class is loaded
+ * within the <code>ClassLoader</code> hierarchy, the more usefull
+ * it will be.
+ * </p>
+ *
+ * @author Richard A. Sitze
+ */
+public class ManagedProperties {
+ /**
+ * Cache of Properties, keyed by (thread-context) class loaders.
+ * Use <code>HashMap</code> because it allows 'null' keys, which
+ * allows us to account for the (null) bootstrap classloader.
+ */
+ private static final HashMap propertiesCache = new HashMap();
+
+
+ /**
+ * Get value for property bound to the current thread context class loader.
+ *
+ * @param property property name.
+ * @return property value if found, otherwise default.
+ */
+ public static String getProperty(String propertyName) {
+ return getProperty(getThreadContextClassLoader(), propertyName);
+ }
+
+ /**
+ * Get value for property bound to the current thread context class loader.
+ * If not found, then return default.
+ *
+ * @param property property name.
+ * @param dephault default value.
+ * @return property value if found, otherwise default.
+ */
+ public static String getProperty(String propertyName, String dephault) {
+ return getProperty(getThreadContextClassLoader(), propertyName, dephault);
+ }
+
+ /**
+ * Get value for property bound to the class loader.
+ *
+ * @param classLoader
+ * @param property property name.
+ * @return property value if found, otherwise default.
+ */
+ public static String getProperty(ClassLoader classLoader, String propertyName) {
+ String value = System.getProperty(propertyName);
+ if (value == null) {
+ Value val = getValueProperty(classLoader, propertyName);
+ if (val != null) {
+ value = val.value;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Get value for property bound to the class loader.
+ * If not found, then return default.
+ *
+ * @param classLoader
+ * @param property property name.
+ * @param dephault default value.
+ * @return property value if found, otherwise default.
+ */
+ public static String getProperty(ClassLoader classLoader, String propertyName, String dephault) {
+ String value = getProperty(classLoader, propertyName);
+ return (value == null) ? dephault : value;
+ }
+
+ /**
+ * Set value for property bound to the current thread context class loader.
+ * @param property property name
+ * @param value property value (non-default) If null, remove the property.
+ */
+ public static void setProperty(String propertyName, String value) {
+ setProperty(propertyName, value, false);
+ }
+
+ /**
+ * Set value for property bound to the current thread context class loader.
+ * @param property property name
+ * @param value property value. If null, remove the property.
+ * @param isDefault determines if property is default or not.
+ * A non-default property cannot be overriden.
+ * A default property can be overriden by a property
+ * (default or non-default) of the same name bound to
+ * a decendent class loader.
+ */
+ public static void setProperty(String propertyName, String value, boolean isDefault) {
+ if (propertyName != null) {
+ synchronized (propertiesCache) {
+ ClassLoader classLoader = getThreadContextClassLoader();
+ HashMap properties = (HashMap)propertiesCache.get(classLoader);
+
+ if (value == null) {
+ properties.remove(propertyName);
+ } else {
+ if (properties == null) {
+ properties = new HashMap();
+ propertiesCache.put(classLoader, properties);
+ }
+
+ properties.put(propertyName, new Value(value, isDefault));
+ }
+ }
+ }
+ }
+
+ /**
+ * Set property values for <code>Properties</code> bound to the
+ * current thread context class loader.
+ *
+ * @param newProperties name/value pairs to be bound
+ */
+ public static void setProperties(Map newProperties) {
+ setProperties(newProperties, false);
+ }
+
+
+ /**
+ * Set property values for <code>Properties</code> bound to the
+ * current thread context class loader.
+ *
+ * @param newProperties name/value pairs to be bound
+ * @param isDefault determines if properties are default or not.
+ * A non-default property cannot be overriden.
+ * A default property can be overriden by a property
+ * (default or non-default) of the same name bound to
+ * a decendent class loader.
+ */
+ public static void setProperties(Map newProperties, boolean isDefault) {
+ java.util.Iterator it = newProperties.entrySet().iterator();
+
+ /**
+ * Each entry must be mapped to a Property.
+ * 'setProperty' does this for us.
+ */
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry)it.next();
+ setProperty( String.valueOf(entry.getKey()),
+ String.valueOf(entry.getValue()),
+ isDefault);
+ }
+ }
+
+
+ /**
+ * Return list of all property names. This is an expensive
+ * operation: ON EACH CALL it walks through all property lists
+ * associated with the current context class loader upto
+ * and including the bootstrap class loader.
+ */
+ public static Enumeration propertyNames() {
+ Hashtable allProps = new Hashtable();
+
+ ClassLoader classLoader = getThreadContextClassLoader();
+
+ /**
+ * Order doesn't matter, we are only going to use
+ * the set of all keys...
+ */
+ while (true) {
+ HashMap properties = null;
+
+ synchronized (propertiesCache) {
+ properties = (HashMap)propertiesCache.get(classLoader);
+ }
+
+ if (properties != null) {
+ allProps.putAll(properties);
+ }
+
+ if (classLoader == null) break;
+
+ classLoader = getParent(classLoader);
+ }
+
+ return allProps.keys();
+ }
+
+ /**
+ * This is an expensive operation.
+ * ON EACH CALL it walks through all property lists
+ * associated with the current context class loader upto
+ * and including the bootstrap class loader.
+ *
+ * @return Returns a <code>java.util.Properties</code> instance
+ * that is equivalent to the current state of the scoped
+ * properties, in that getProperty() will return the same value.
+ * However, this is a copy, so setProperty on the
+ * returned value will not effect the scoped properties.
+ */
+ public static Properties getProperties() {
+ Properties p = new Properties();
+
+ Enumeration names = propertyNames();
+ while (names.hasMoreElements()) {
+ String name = (String)names.nextElement();
+ p.put(name, getProperty(name));
+ }
+
+ return p;
+ }
+
+
+ /***************** INTERNAL IMPLEMENTATION *****************/
+
+ private static class Value {
+ final String value;
+ final boolean isDefault;
+
+ Value(String value, boolean isDefault) {
+ this.value = value;
+ this.isDefault = isDefault;
+ }
+ }
+
+ /**
+ * Get value for properties bound to the class loader.
+ * Explore up the tree first, as higher-level class
+ * loaders take precedence over lower-level class loaders.
+ */
+ private static final Value getValueProperty(ClassLoader classLoader, String propertyName) {
+ Value value = null;
+
+ if (propertyName != null) {
+ /**
+ * If classLoader isn't bootstrap loader (==null),
+ * then get up-tree value.
+ */
+ if (classLoader != null) {
+ value = getValueProperty(getParent(classLoader), propertyName);
+ }
+
+ if (value == null || value.isDefault) {
+ synchronized (propertiesCache) {
+ HashMap properties = (HashMap)propertiesCache.get(classLoader);
+
+ if (properties != null) {
+ Value altValue = (Value)properties.get(propertyName);
+
+ // set value only if override exists..
+ // otherwise pass default (or null) on..
+ if (altValue != null)
+ value = altValue;
+ }
+ }
+ }
+ }
+
+ return value;
+ }
+
+ private static final ClassLoader getThreadContextClassLoader() {
+ return JDKHooks.getJDKHooks().getThreadContextClassLoader();
+ }
+
+ private static final ClassLoader getParent(final ClassLoader classLoader) {
+ return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return classLoader.getParent();
+ }
+ });
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ManagedProperties.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/PropertiesHolder.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/PropertiesHolder.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/PropertiesHolder.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/PropertiesHolder.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,110 @@
+/*
+ * $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.mina.common.support.discovery.tools;
+
+import java.util.Properties;
+
+import org.apache.mina.common.support.discovery.resource.ClassLoaders;
+
+
+/**
+ * Holder for a default class.
+ *
+ * Class may be specified by name (String) or class (Class).
+ * Using the holder complicates the users job, but minimized # of API's.
+ *
+ * @author Richard A. Sitze
+ */
+public class PropertiesHolder {
+ private Properties properties;
+ private final String propertiesFileName;
+
+ public PropertiesHolder(Properties properties) {
+ this.properties = properties;
+ this.propertiesFileName = null;
+ }
+
+ public PropertiesHolder(String propertiesFileName) {
+ this.properties = null;
+ this.propertiesFileName = propertiesFileName;
+ }
+
+ /**
+ * @param spi Optional SPI (may be null).
+ * If provided, an attempt is made to load the
+ * property file as-per Class.getResource().
+ *
+ * @param loaders Used only if properties need to be loaded.
+ *
+ * @return Properties. Load the properties if necessary.
+ */
+ public Properties getProperties(SPInterface spi, ClassLoaders loaders) {
+ if (properties == null) {
+ properties = ResourceUtils.loadProperties(spi.getSPClass(), getPropertiesFileName(), loaders);
+ }
+ return properties;
+ }
+
+ public String getPropertiesFileName() {
+ return propertiesFileName;
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/PropertiesHolder.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ResourceUtils.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ResourceUtils.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ResourceUtils.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ResourceUtils.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,197 @@
+/*
+ * $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.mina.common.support.discovery.tools;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.mina.common.support.discovery.DiscoveryException;
+import org.apache.mina.common.support.discovery.Resource;
+import org.apache.mina.common.support.discovery.ResourceIterator;
+import org.apache.mina.common.support.discovery.resource.ClassLoaders;
+import org.apache.mina.common.support.discovery.resource.DiscoverResources;
+
+
+/**
+ * Mechanisms to locate and load a class.
+ * The load methods locate a class only.
+ * The find methods locate a class and verify that the
+ * class implements an given interface or extends a given class.
+ *
+ * @author Richard A. Sitze
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ */
+public class ResourceUtils {
+ /**
+ * Get package name.
+ * Not all class loaders 'keep' package information,
+ * in which case Class.getPackage() returns null.
+ * This means that calling Class.getPackage().getName()
+ * is unreliable at best.
+ */
+ public static String getPackageName(Class clazz) {
+ Package clazzPackage = clazz.getPackage();
+ String packageName;
+ if (clazzPackage != null) {
+ packageName = clazzPackage.getName();
+ } else {
+ String clazzName = clazz.getName();
+ packageName = new String(clazzName.toCharArray(), 0, clazzName.lastIndexOf('.'));
+ }
+ return packageName;
+ }
+
+
+ /**
+ * Load the resource <code>resourceName</code>.
+ * Try each classloader in succession,
+ * until first succeeds, or all fail.
+ * If all fail and <code>resouceName</code> is not absolute
+ * (doesn't start with '/' character), then retry with
+ * <code>packageName/resourceName</code> after changing all
+ * '.' to '/'.
+ *
+ * @param resourceName The name of the resource to load.
+ */
+ public static Resource getResource(Class spi,
+ String resourceName,
+ ClassLoaders loaders)
+ throws DiscoveryException
+ {
+ DiscoverResources explorer = new DiscoverResources(loaders);
+ ResourceIterator resources = explorer.findResources(resourceName);
+
+ if (spi != null &&
+ !resources.hasNext() &&
+ resourceName.charAt(0) != '/')
+ {
+ /**
+ * If we didn't find the resource, and if the resourceName
+ * isn't an 'absolute' path name, then qualify with
+ * package name of the spi.
+ */
+ resourceName = getPackageName(spi).replace('.','/') + "/" + resourceName;
+ resources = explorer.findResources(resourceName);
+ }
+
+ return resources.hasNext()
+ ? resources.nextResource()
+ : null;
+ }
+
+ /**
+ * Load named property file, optionally qualifed by spi's package name
+ * as per Class.getResource.
+ *
+ * A property file is loaded using the following sequence of class loaders:
+ * <ul>
+ * <li>Thread Context Class Loader</li>
+ * <li>DiscoverSingleton's Caller's Class Loader</li>
+ * <li>SPI's Class Loader</li>
+ * <li>DiscoverSingleton's (this class) Class Loader</li>
+ * <li>System Class Loader</li>
+ * </ul>
+ *
+ * @param
+ * @param propertiesFileName The property file name.
+ *
+ * @return Instance of a class implementing the SPI.
+ *
+ * @exception DiscoveryException Thrown if the name of a class implementing
+ * the SPI cannot be found, if the class cannot be loaded and
+ * instantiated, or if the resulting class does not implement
+ * (or extend) the SPI.
+ */
+ public static Properties loadProperties(Class spi,
+ String propertiesFileName,
+ ClassLoaders classLoaders)
+ throws DiscoveryException
+ {
+ Properties properties = null;
+
+ if (propertiesFileName != null) {
+ try {
+ Resource resource = getResource(spi, propertiesFileName, classLoaders);
+ if (resource != null) {
+ InputStream stream = resource.getResourceAsStream();
+
+ if (stream != null) {
+ properties = new Properties();
+ try {
+ properties.load(stream);
+ } finally {
+ stream.close();
+ }
+ }
+ }
+ } catch (IOException e) {
+ ; // ignore
+ } catch (SecurityException e) {
+ ; // ignore
+ }
+ }
+
+ return properties;
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/ResourceUtils.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/SPInterface.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/SPInterface.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/SPInterface.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/SPInterface.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,203 @@
+/*
+ * $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.mina.common.support.discovery.tools;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.mina.common.support.discovery.DiscoveryException;
+
+
+/**
+ * Represents a Service Programming Interface (spi).
+ * - SPI's name
+ * - SPI's (provider) class
+ * - SPI's (alternate) override property name
+ *
+ * In addition, while there are many cases where this is NOT
+ * usefull, for those in which it is:
+ *
+ * - expected constructor argument types and parameters values.
+ *
+ * @author Richard A. Sitze
+ */
+public class SPInterface {
+ /**
+ * The service programming interface: intended to be
+ * an interface or abstract class, but not limited
+ * to those two.
+ */
+ private final Class spi;
+
+ /**
+ * The property name to be used for finding the name of
+ * the SPI implementation class.
+ */
+ private final String propertyName;
+
+
+ private Class paramClasses[] = null;
+ private Object params[] = null;
+
+
+ /**
+ * Construct object representing Class <code>provider</code>.
+ *
+ * @param provider The SPI class
+ */
+ public SPInterface(Class provider) {
+ this(provider, provider.getName());
+ }
+
+ /**
+ * Construct object representing Class <code>provider</code>.
+ *
+ * @param provider The SPI class
+ *
+ * @param propertyName when looking for the name of a class implementing
+ * the provider class, a discovery strategy may involve looking for
+ * (system or other) properties having either the name of the class
+ * (provider) or the <code>propertyName</code>.
+ */
+ public SPInterface(Class spi, String propertyName) {
+ this.spi = spi;
+ this.propertyName = propertyName;
+ }
+
+ /**
+ * Construct object representing Class <code>provider</code>.
+ *
+ * @param provider The SPI class
+ *
+ * @param constructorParamClasses classes representing the
+ * constructor argument types.
+ *
+ * @param constructorParams objects representing the
+ * constructor arguments.
+ */
+ public SPInterface(Class provider,
+ Class constructorParamClasses[],
+ Object constructorParams[])
+ {
+ this(provider,
+ provider.getName(),
+ constructorParamClasses,
+ constructorParams);
+ }
+
+ /**
+ * Construct object representing Class <code>provider</code>.
+ *
+ * @param provider The SPI class
+ *
+ * @param propertyName when looking for the name of a class implementing
+ * the provider class, a discovery strategy may involve looking for
+ * (system or other) properties having either the name of the class
+ * (provider) or the <code>propertyName</code>.
+ *
+ * @param constructorParamClasses classes representing the
+ * constructor argument types.
+ *
+ * @param constructorParams objects representing the
+ * constructor arguments.
+ */
+ public SPInterface(Class spi,
+ String propertyName,
+ Class constructorParamClasses[],
+ Object constructorParams[])
+ {
+ this.spi = spi;
+ this.propertyName = propertyName;
+ this.paramClasses = constructorParamClasses;
+ this.params = constructorParams;
+ }
+
+ public String getSPName() {
+ return spi.getName();
+ }
+
+ public Class getSPClass() {
+ return spi;
+ }
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Instantiate a new
+ */
+ public Object newInstance(Class impl)
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
+ {
+ verifyAncestory(impl);
+
+ return ClassUtils.newInstance(impl, paramClasses, params);
+ }
+
+ public void verifyAncestory(Class impl) {
+ ClassUtils.verifyAncestory(spi, impl);
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/SPInterface.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision
Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/Service.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/Service.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/Service.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/Service.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,162 @@
+/*
+ * ====================================================================
+ *
+ * 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.mina.common.support.discovery.tools;
+
+import java.util.Enumeration;
+
+import org.apache.mina.common.support.discovery.ResourceClass;
+import org.apache.mina.common.support.discovery.ResourceClassIterator;
+import org.apache.mina.common.support.discovery.ResourceNameIterator;
+import org.apache.mina.common.support.discovery.resource.ClassLoaders;
+import org.apache.mina.common.support.discovery.resource.classes.DiscoverClasses;
+import org.apache.mina.common.support.discovery.resource.names.DiscoverServiceNames;
+
+
+/**
+ * [this was ServiceDiscovery12... the 1.1 versus 1.2 issue
+ * has been abstracted to org.apache.commons.discover.jdk.JDKHooks]
+ *
+ * <p>Implement the JDK1.3 'Service Provider' specification.
+ * ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html )
+ * </p>
+ *
+ * This class supports any VM, including JDK1.1, via
+ * org.apache.commons.discover.jdk.JDKHooks.
+ *
+ * The caller will first configure the discoverer by adding ( in the desired
+ * order ) all the places to look for the META-INF/services. Currently
+ * we support loaders.
+ *
+ * The findResources() method will check every loader.
+ *
+ * @author Richard A. Sitze
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ * @author James Strachan
+ */
+public class Service
+{
+ /** Construct a new service discoverer
+ */
+ protected Service() {
+ }
+
+ /**
+ * as described in
+ * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider,
+ * Except this uses <code>Enumeration</code>
+ * instead of <code>Interator</code>.
+ *
+ * @return Enumeration of class instances (<code>Object</code>)
+ */
+ public static Enumeration providers(Class spiClass) {
+ return providers(new SPInterface(spiClass), null);
+ }
+
+ /**
+ * This version lets you specify constructor arguments..
+ *
+ * @param spi SPI to look for and load.
+ * @param classLoaders loaders to use in search.
+ * If <code>null</code> then use ClassLoaders.getAppLoaders().
+ */
+ public static Enumeration providers(final SPInterface spi,
+ ClassLoaders loaders)
+ {
+ if (loaders == null) {
+ loaders = ClassLoaders.getAppLoaders(spi.getSPClass(),
+ Service.class,
+ true);
+ }
+
+ ResourceNameIterator servicesIter =
+ (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName());
+
+ final ResourceClassIterator services =
+ (new DiscoverClasses(loaders)).findResourceClasses(servicesIter);
+
+ return new Enumeration() {
+ private Object object = null;
+
+ public boolean hasMoreElements() {
+ if (object == null) {
+ object = getNextClassInstance();
+ }
+ return object != null;
+ }
+
+ public Object nextElement() {
+ Object obj = object;
+ object = null;
+ return obj;
+ }
+
+ private Object getNextClassInstance() {
+ while (services.hasNext()) {
+ ResourceClass info = services.nextResourceClass();
+ try {
+ return spi.newInstance(info.loadClass());
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ return null;
+ }
+ };
+ }
+}
Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/discovery/tools/Service.java
------------------------------------------------------------------------------
svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision