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/14 23:46:22 UTC
cvs commit: jakarta-commons/discovery/src/java/org/apache/commons/discovery/tools ManagedProperties.java
rsitze 2002/08/14 14:46:22
Modified: discovery/src/java/org/apache/commons/discovery/strategy
LoadStrategy.java DefaultLoadStrategy.java
discovery/src/java/org/apache/commons/discovery
DiscoverSingleton.java DiscoverClass.java
discovery/src/java/org/apache/commons/discovery/load
ClassLoaderUtils.java Loaders.java
Added: discovery/src/java/org/apache/commons/discovery/strategy
DiscoverStrategy.java DefaultDiscoverStrategy.java
discovery/src/java/org/apache/commons/discovery/base
SPInterface.java Environment.java ImplClass.java
discovery/src/java/org/apache/commons/discovery/tools
ManagedProperties.java
Removed: discovery/src/java/org/apache/commons/discovery/strategy
Utils.java
discovery/src/java/org/apache/commons/discovery Service.java
ManagedProperties.java SingletonService.java
discovery/src/java/org/apache/commons/discovery/types
SPInterface.java Environment.java ImplClass.java
Log:
Take 1: Got rid of lifecycle management, left caching & newInstance...
others recognized some value there... Comments, and I can take
another (and another :-) stab at it if needed.
Revision Changes Path
1.3 +2 -13 jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/LoadStrategy.java
Index: LoadStrategy.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/LoadStrategy.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- LoadStrategy.java 12 Aug 2002 22:06:39 -0000 1.2
+++ LoadStrategy.java 14 Aug 2002 21:46:21 -0000 1.3
@@ -61,28 +61,17 @@
package org.apache.commons.discovery.strategy;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.discovery.DiscoveryException;
-import org.apache.commons.discovery.types.ImplClass;
-import org.apache.commons.discovery.types.SPInterface;
-import org.apache.commons.discovery.load.Loaders;
+import org.apache.commons.discovery.base.ImplClass;
/**
- * <p>Implement the search strategy. Someday this might be pluggable..
- * </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>The strategy for loading resources. Someday this might be pluggable..
* </p>
*
* @author Richard A. Sitze
- * @author Craig R. McClanahan
- * @author Costin Manolache
* @version $Revision$ $Date$
*/
public interface LoadStrategy {
1.3 +15 -54 jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/DefaultLoadStrategy.java
Index: DefaultLoadStrategy.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/DefaultLoadStrategy.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DefaultLoadStrategy.java 12 Aug 2002 22:06:39 -0000 1.2
+++ DefaultLoadStrategy.java 14 Aug 2002 21:46:21 -0000 1.3
@@ -66,9 +66,9 @@
import java.util.Properties;
import org.apache.commons.discovery.DiscoveryException;
-import org.apache.commons.discovery.types.Environment;
-import org.apache.commons.discovery.types.ImplClass;
-import org.apache.commons.discovery.types.SPInterface;
+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.Loaders;
@@ -87,6 +87,9 @@
* @version $Revision$ $Date$
*/
public class DefaultLoadStrategy implements LoadStrategy {
+ private static final DiscoverStrategy discoverStrategy =
+ new DefaultDiscoverStrategy();
+
private final Environment env;
private final SPInterface spi;
private final Loaders loaders;
@@ -104,18 +107,8 @@
* </p>
* <ul>
* <p><li>
- * Get the name of an implementation class. The name is the first
- * non-null value obtained from the following resources:
- * <ul>
- * <li>ManagedProperty.getProperty(SPI.class.getName());</li>
- * <li>properties.getProperty(SPI.class.getName());</li>
- * <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>
- * </ul>
+ * Get the name of an implementation class using the discover strategy
+ * (@see DiscoverStrategy).
* </li></p>
* <p><li>
* If the name of the implementation class is non-null, load that class.
@@ -157,9 +150,7 @@
* </li></p>
* </ul>
*
- * @param properties Used to determine name of SPI implementation,
- * and passed to implementation.init() method if
- * implementation implements Service interface.
+ * @param properties Used to determine name of SPI implementation.
*
* @param defaultImpl Default implementation.
*
@@ -171,40 +162,8 @@
public ImplClass loadClass(Properties properties, ImplClass defaultImpl)
throws DiscoveryException
{
- String spiName = spi.getSPName();
- String propertyName = spi.getPropertyName();
-
- // First, try the (managed) system property spiName
- String className = Utils.getManagedProperty(spiName);
- if (className == null) {
- if (spiName.equals(propertyName)) {
- if (properties != null) {
- // Second, try the properties parameter spiName
- className = properties.getProperty(spiName);
- }
- } else {
- // Second, try the (managed) system property propertyName
- className = Utils.getManagedProperty(propertyName);
- if (className == null) {
- if (properties != null) {
- // Third, try the properties parameter spiName
- className = properties.getProperty(spiName);
-
- if (className == null) {
- // Fourth, try the properties parameter propertyName
- className = properties.getProperty(propertyName);
- }
- }
- }
- }
-
- if (className == null) {
- // Last, try to find a service by using the JDK1.3 jar
- // discovery mechanism.
- className = Utils.getJDK13ClassName(
- env.getThreadContextClassLoader(), spiName);
- }
- }
+ String className =
+ discoverStrategy.discoverClassName(env, spi, properties);
ImplClass implClass = null;
@@ -222,8 +181,10 @@
}
}
- if (implClass == null || implClass.getImplClass() == null) {
- throw new DiscoveryException("No implementation defined for " + spiName);
+ if (implClass == null || // class name couldn't be found
+ implClass.getImplClass() == null) // class couldn't be loaded
+ {
+ throw new DiscoveryException("No implementation defined for " + spi.getSPName());
}
return implClass;
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/DiscoverStrategy.java
Index: DiscoverStrategy.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.strategy;
import java.util.Properties;
import org.apache.commons.discovery.base.Environment;
import org.apache.commons.discovery.base.SPInterface;
/**
* <p>The strategy for discovering the class name. Someday this might be pluggable..
* </p>
*
* @author Richard A. Sitze
* @version $Revision$ $Date$
*/
public interface DiscoverStrategy {
/**
* Discover names of SPI implementation Classes.
*
* @param properties Properties that may define the implementation
* class name(s).
*
* @return String[] Name of classes implementing the SPI.
*
* @exception DiscoveryException Thrown if the name of a class implementing
* the SPI cannot be found.
*/
public String discoverClassName(Environment env,
SPInterface spi,
Properties properties);
/**
* Discover names of SPI implementation Classes.
*
* @param properties Properties that may define the implementation
* class name(s).
*
* @return String[] Name of classes implementing the SPI.
*
* @exception DiscoveryException Thrown if the name of a class implementing
* the SPI cannot be found.
*/
public String[] discoverClassNames(Environment env,
SPInterface spi,
Properties properties);
}
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy/DefaultDiscoverStrategy.java
Index: DefaultDiscoverStrategy.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.strategy;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Vector;
import org.apache.commons.discovery.base.Environment;
import org.apache.commons.discovery.base.SPInterface;
import org.apache.commons.discovery.tools.ManagedProperties;
/**
* <p>Implement the search strategy. Someday this might be pluggable..
* </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 DefaultDiscoverStrategy
implements DiscoverStrategy
{
/**
* JDK1.3+ 'Service Provider' specification
* ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html )
*/
private static final String SERVICE_HOME = "META-INF/services/";
/**
* <p>Discover names of SPI implementation Classes.
* The names are the non-null values, in order, obtained from the following
* resources:
* <ul>
* <li>ManagedProperty.getProperty(SPI.class.getName());</li>
* <li>properties.getProperty(SPI.class.getName());</li>
* <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>
* </ul>
*
* @param properties Properties that may define the implementation
* class name(s).
*
* @return String[] Name of classes implementing the SPI.
*
* @exception DiscoveryException Thrown if the name of a class implementing
* the SPI cannot be found.
*/
public String discoverClassName(Environment env,
SPInterface spi,
Properties properties)
{
Vector names = new Vector();
String spiName = spi.getSPName();
String propertyName = spi.getPropertyName();
boolean includeAltProperty = !spiName.equals(propertyName);
// Try the (managed) system property spiName
String className = getManagedProperty(spiName);
if (className != null) return className;
if (includeAltProperty) {
// Try the (managed) system property propertyName
className = getManagedProperty(propertyName);
if (className != null) return className;
}
if (properties != null) {
// Try the properties parameter spiName
className = properties.getProperty(spiName);
if (className != null) return className;
if (includeAltProperty) {
// Try the properties parameter propertyName
className = properties.getProperty(propertyName);
if (className != null) return className;
}
}
// Last, try to find a service by using the JDK1.3 jar
// discovery mechanism.
className = getJDK13ClassName(env.getThreadContextClassLoader(), spiName);
if (className != null) return className;
return null;
}
/**
* <p>Discover names of SPI implementation Classes.
* The names are the non-null values, in order, obtained from the following
* resources:
* <ul>
* <li>ManagedProperty.getProperty(SPI.class.getName());</li>
* <li>properties.getProperty(SPI.class.getName());</li>
* <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>
* </ul>
*
* @param properties Properties that may define the implementation
* class name(s).
*
* @return String[] Name of classes implementing the SPI.
*
* @exception DiscoveryException Thrown if the name of a class implementing
* the SPI cannot be found.
*/
public String[] discoverClassNames(Environment env,
SPInterface spi,
Properties properties)
{
Vector names = new Vector();
String spiName = spi.getSPName();
String propertyName = spi.getPropertyName();
boolean includeAltProperty = !spiName.equals(propertyName);
// Try the (managed) system property spiName
String className = getManagedProperty(spiName);
if (className != null) names.addElement(className);
if (includeAltProperty) {
// Try the (managed) system property propertyName
className = getManagedProperty(propertyName);
if (className != null) names.addElement(className);
}
if (properties != null) {
// Try the properties parameter spiName
className = properties.getProperty(spiName);
if (className != null) names.addElement(className);
if (includeAltProperty) {
// Try the properties parameter propertyName
className = properties.getProperty(propertyName);
if (className != null) names.addElement(className);
}
}
// Last, try to find a service by using the JDK1.3 jar
// discovery mechanism.
className = getJDK13ClassName(env.getThreadContextClassLoader(), spiName);
if (className != null) names.addElement(className);
String[] results = new String[names.size()];
names.copyInto(results);
return results;
}
/**
* Load the class whose name is given by the value of a (Managed)
* System Property.
*
* @see ManagedProperties
*
* @param attribute the name of the system property whose value is
* the name of the class to load.
*/
public static String getManagedProperty(String propertyName) {
String value;
try {
value = ManagedProperties.getProperty(propertyName);
} catch (SecurityException e) {
value = null;
}
return value;
}
/**
* Find the name of a service using the JDK 1.3 jar discovery mechanism.
* This will allow users to plug a service implementation by just
* placing it in the META-INF/services directory of the webapp
* (or in CLASSPATH or equivalent).
*/
public static String getJDK13ClassName(ClassLoader classLoader, String spiName) {
String serviceImplName = null;
// Name of J2EE application file that identifies the service implementation.
String servicePropertyFile = SERVICE_HOME + spiName;
InputStream is = (classLoader == null
? ClassLoader.getSystemResourceAsStream(servicePropertyFile)
: classLoader.getResourceAsStream(servicePropertyFile));
if( is != null ) {
try {
try {
// This code is needed by EBCDIC and other strange systems.
// It's a fix for bugs reported in xerces
BufferedReader rd;
try {
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
} catch (java.io.UnsupportedEncodingException e) {
rd = new BufferedReader(new InputStreamReader(is));
}
try {
serviceImplName = rd.readLine();
} finally {
rd.close();
}
} finally {
is.close();
}
} catch (IOException ioe) {
; // ignore
}
}
return serviceImplName;
}
}
1.3 +106 -151 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.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DiscoverSingleton.java 12 Aug 2002 22:06:39 -0000 1.2
+++ DiscoverSingleton.java 14 Aug 2002 21:46:21 -0000 1.3
@@ -61,23 +61,24 @@
package org.apache.commons.discovery;
+import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
-import org.apache.commons.discovery.types.Environment;
-import org.apache.commons.discovery.types.ImplClass;
-import org.apache.commons.discovery.types.SPInterface;
+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;
/**
- * <p>Discover singleton service providers, with discovery and configuration features
- * similar to that employed by standard Java APIs such as JAXP.
+ * <p>Discover singleton service providers.
+ * This
* </p>
*
- * <p>DiscoverSingleton instances are managed (life-cycle) by the Discovery
- * service, which maintains a cache keyed by a combination of
+ * <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>
@@ -105,8 +106,10 @@
* <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(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,
@@ -178,8 +181,8 @@
* </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
+ * 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>
@@ -193,11 +196,6 @@
* <p><li>
* Create an instance of the class.
* </li></p>
- * <p><li>
- * If the loaded class implements the <code>Service</code> interface,
- * then invoke the <code>init(Properties)</code> method, passing in the
- * <code>Properties properties</code> parameter, if provided.
- * </li></p>
* </ul>
*
* <p>
@@ -342,7 +340,10 @@
String defaultImpl)
throws DiscoveryException
{
- return find(DiscoverSingleton.class, spiClass, properties, defaultImpl);
+ return find(DiscoverSingleton.class,
+ spiClass,
+ properties,
+ defaultImpl);
}
/**
@@ -366,7 +367,10 @@
String defaultImpl)
throws DiscoveryException
{
- return find(DiscoverSingleton.class, spiClass, propertiesFileName, defaultImpl);
+ return find(DiscoverSingleton.class,
+ spiClass,
+ propertiesFileName,
+ defaultImpl);
}
/**
@@ -398,7 +402,11 @@
String defaultImpl)
throws DiscoveryException
{
- return find(DiscoverSingleton.class, groupContext, spiClass, properties, defaultImpl);
+ return find(DiscoverSingleton.class,
+ groupContext,
+ spiClass,
+ properties,
+ defaultImpl);
}
/**
@@ -428,15 +436,19 @@
String defaultImpl)
throws DiscoveryException
{
- return find(DiscoverSingleton.class, groupContext, spiClass, propertiesFileName, defaultImpl);
+ return find(DiscoverSingleton.class,
+ groupContext,
+ spiClass,
+ propertiesFileName,
+ defaultImpl);
}
/*************** FINDERS FOR USE IN FACTORY/HELPER METHODS ***************
*
* These finders provide a rootFinderClass. The root finder is the wrapper
- * class (factories or helper classes) that invoke the DiscoverSingleton find
- * methods, presumably providing (default) values for propertiesFileName
+ * class (factories or helper classes) that invoke the DiscoverSingleton
+ * find methods, presumably providing (default) values for propertiesFileName
* and defaultImpl. Having access to this wrapper class provides a
* way to determine the 'real' caller, and hence the caller's class loader.
* Thus preserving knowledge that is relevant to finding the
@@ -461,7 +473,10 @@
public static Object find(Class rootFinderClass, Class spiClass)
throws DiscoveryException
{
- return find(rootFinderClass, spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
+ return find(rootFinderClass,
+ spiClass,
+ DiscoverClass.nullProperties,
+ DiscoverClass.nullDefaultImpl);
}
/**
@@ -486,7 +501,10 @@
public static Object find(Class rootFinderClass, Class spiClass, Properties properties)
throws DiscoveryException
{
- return find(rootFinderClass, spiClass, properties, DiscoverClass.nullDefaultImpl);
+ return find(rootFinderClass,
+ spiClass,
+ properties,
+ DiscoverClass.nullDefaultImpl);
}
/**
@@ -509,7 +527,10 @@
public static Object find(Class rootFinderClass, Class spiClass, String defaultImpl)
throws DiscoveryException
{
- return find(rootFinderClass, spiClass, DiscoverClass.nullProperties, defaultImpl);
+ return find(rootFinderClass,
+ spiClass,
+ DiscoverClass.nullProperties,
+ defaultImpl);
}
/**
@@ -539,7 +560,11 @@
String defaultImpl)
throws DiscoveryException
{
- return find(rootFinderClass, DiscoverClass.nullGroupContext, spiClass, properties, defaultImpl);
+ return find(rootFinderClass,
+ DiscoverClass.nullGroupContext,
+ spiClass,
+ properties,
+ defaultImpl);
}
/**
@@ -567,8 +592,11 @@
String defaultImpl)
throws DiscoveryException
{
- return find(rootFinderClass, DiscoverClass.nullGroupContext,
- spiClass, propertiesFileName, defaultImpl);
+ return find(rootFinderClass,
+ DiscoverClass.nullGroupContext,
+ spiClass,
+ propertiesFileName,
+ defaultImpl);
}
/**
@@ -603,13 +631,16 @@
String defaultImpl)
throws DiscoveryException
{
- /**
- * Env can change between calls... so we don't cache this.
- */
- return find(new Environment(groupContext, rootFinderClass),
- new SPInterface(spiClass),
- properties,
- new ImplClass(defaultImpl));
+ try {
+ return find(new Environment(groupContext, rootFinderClass),
+ new SPInterface(spiClass),
+ properties,
+ new ImplClass(defaultImpl));
+ } catch (DiscoveryException de) {
+ throw de;
+ } catch (Exception e) {
+ throw new DiscoveryException("Unable to create class " + spiClass.getName(), e);
+ }
}
/**
@@ -642,93 +673,16 @@
String defaultImpl)
throws DiscoveryException
{
- /**
- * Env can change between calls... so we don't cache this.
- */
- return find(new Environment(groupContext, rootFinderClass),
- new SPInterface(spiClass),
- propertiesFileName,
- new ImplClass(defaultImpl));
- }
-
- /**
- * Find implementation of SPI.
- *
- * @param rootFinderClass Wrapper class used by end-user, that ultimately
- * calls this finder method.
- *
- * @param groupContext qualifier for the property file name and for
- * the system property name used to find the service implementation.
- * If not found, the unqualified names are used.
- *
- * @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 rootFinderClass,
- String groupContext,
- SPInterface spi,
- Properties properties,
- ImplClass defaultImpl)
- throws DiscoveryException
- {
- /**
- * Env can change between calls... so we don't cache this.
- */
- return find(new Environment(groupContext, rootFinderClass),
- spi,
- properties,
- defaultImpl);
- }
-
- /**
- * Find implementation of SPI.
- *
- * @param rootFinderClass Wrapper class used by end-user, that ultimately
- * calls this finder method.
- *
- * @param groupContext qualifier for the property file name and for
- * the system property name used to find the service implementation.
- * If not found, the unqualified names are used.
- *
- * @param spiClass Service Provider Interface Class.
- *
- * @param propertiesFileName The property file name.
- *
- * @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 rootFinderClass,
- String groupContext,
- SPInterface spi,
- String propertiesFileName,
- ImplClass defaultImpl)
- throws DiscoveryException
- {
- /**
- * Env can change between calls... so we don't cache this.
- */
- return find(new Environment(groupContext, rootFinderClass),
- spi,
- propertiesFileName,
- defaultImpl);
+ try {
+ return find(new Environment(groupContext, rootFinderClass),
+ new SPInterface(spiClass),
+ propertiesFileName,
+ new ImplClass(defaultImpl));
+ } catch (DiscoveryException de) {
+ throw de;
+ } catch (Exception e) {
+ throw new DiscoveryException("Unable to create class " + spiClass.getName(), e);
+ }
}
/**
@@ -760,19 +714,29 @@
SPInterface spi,
Properties properties,
ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
/**
* 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.getThreadContextClassLoader(),
+ env.getGroupContext(),
+ spi.getSPName());
if (service == null) {
- service = DiscoverClass.newInstance(env, spi, properties, defaultImpl);
+ service =
+ DiscoverClass.newInstance(env, spi, properties, defaultImpl);
if (service != null) {
- put(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName(), service);
+ put(env.getThreadContextClassLoader(),
+ env.getGroupContext(),
+ spi.getSPName(),
+ service);
}
}
@@ -806,19 +770,31 @@
SPInterface spi,
String propertiesFileName,
ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
/**
* 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.getThreadContextClassLoader(),
+ env.getGroupContext(),
+ spi.getSPName());
if (service == null) {
- service = DiscoverClass.newInstance(env, spi, propertiesFileName, defaultImpl);
+ service = DiscoverClass.newInstance(env,
+ spi,
+ propertiesFileName,
+ defaultImpl);
if (service != null) {
- put(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName(), service);
+ put(env.getThreadContextClassLoader(),
+ env.getGroupContext(),
+ spi.getSPName(),
+ service);
}
}
@@ -857,14 +833,6 @@
HashMap spis = (HashMap)groupIter.next();
if (spis != null) {
- Iterator spiIter = spis.values().iterator();
-
- while (spiIter.hasNext()) {
- Object service = (Object)spiIter.next();
-
- if (service instanceof SingletonService)
- ((SingletonService)service).release();
- }
spis.clear();
}
}
@@ -896,14 +864,6 @@
HashMap spis = (HashMap)groups.get(groupContext);
if (spis != null) {
- Iterator spiIter = spis.values().iterator();
-
- while (spiIter.hasNext()) {
- Object service = (Object)spiIter.next();
-
- if (service instanceof SingletonService)
- ((SingletonService)service).release();
- }
spis.clear();
}
groups.remove(groupContext);
@@ -934,11 +894,6 @@
HashMap spis = (HashMap)groups.get(groupContext);
if (spis != null) {
- Object service = (Object)spis.get(spiClass.getName());
-
- if (service instanceof SingletonService)
- ((SingletonService)service).release();
-
spis.remove(spiClass.getName());
}
}
1.3 +61 -36 jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoverClass.java
Index: DiscoverClass.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoverClass.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DiscoverClass.java 12 Aug 2002 22:06:39 -0000 1.2
+++ DiscoverClass.java 14 Aug 2002 21:46:21 -0000 1.3
@@ -61,11 +61,12 @@
package org.apache.commons.discovery;
+import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
-import org.apache.commons.discovery.types.Environment;
-import org.apache.commons.discovery.types.ImplClass;
-import org.apache.commons.discovery.types.SPInterface;
+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.strategy.DefaultLoadStrategy;
import org.apache.commons.discovery.strategy.LoadStrategy;
@@ -177,23 +178,23 @@
/**
* Readable placeholder for a null value.
*/
- static final String nullGroupContext = null;
+ public static final String nullGroupContext = null;
/**
* Readable placeholder for a null value.
*/
- static final String nullDefaultImpl = null;
+ public static final String nullDefaultImpl = null;
/**
* Readable placeholder for a null value.
*/
- static final Properties nullProperties = null;
+ public static final Properties nullProperties = null;
private final String groupContext;
private final Class rootDiscoveryClass;
private final Environment env;
- private Environment getEnvironment() {
+ protected Environment getEnvironment() {
/**
* The environment may change between calls, so
* we cache it if it was 'given' to us, otherwise
@@ -298,7 +299,7 @@
public Class find(Class spiClass)
throws DiscoveryException
{
- return find(spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
+ return find(spiClass, nullProperties, nullDefaultImpl);
}
/**
@@ -317,7 +318,7 @@
public Class find(Class spiClass, Properties properties)
throws DiscoveryException
{
- return find(spiClass, properties, DiscoverClass.nullDefaultImpl);
+ return find(spiClass, properties, nullDefaultImpl);
}
/**
@@ -336,7 +337,7 @@
public Class find(Class spiClass, String defaultImpl)
throws DiscoveryException
{
- return find(spiClass, DiscoverClass.nullProperties, defaultImpl);
+ return find(spiClass, nullProperties, defaultImpl);
}
/**
@@ -527,9 +528,13 @@
* (or extend) the SPI.
*/
public Object newInstance(Class spiClass)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
- return newInstance(spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
+ return newInstance(spiClass, nullProperties, nullDefaultImpl);
}
/**
@@ -549,9 +554,13 @@
* (or extend) the SPI.
*/
public Object newInstance(Class spiClass, Properties properties)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
- return newInstance(spiClass, properties, DiscoverClass.nullDefaultImpl);
+ return newInstance(spiClass, properties, nullDefaultImpl);
}
/**
@@ -569,9 +578,13 @@
* (or extend) the SPI.
*/
public Object newInstance(Class spiClass, String defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
- return newInstance(spiClass, DiscoverClass.nullProperties, defaultImpl);
+ return newInstance(spiClass, nullProperties, defaultImpl);
}
/**
@@ -593,7 +606,11 @@
* (or extend) the SPI.
*/
public Object newInstance(Class spiClass, Properties properties, String defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
return newInstance(getEnvironment(),
new SPInterface(spiClass),
@@ -627,7 +644,11 @@
* (or extend) the SPI.
*/
public Object newInstance(Class spiClass, String propertiesFileName, String defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
return newInstance(getEnvironment(),
new SPInterface(spiClass),
@@ -657,7 +678,11 @@
* (or extend) the SPI.
*/
public Object newInstance(SPInterface spi, Properties properties, ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
return newInstance(getEnvironment(), spi, properties, defaultImpl);
}
@@ -691,7 +716,11 @@
* (or extend) the SPI.
*/
public Object newInstance(SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
return newInstance(getEnvironment(), spi, propertiesFileName, defaultImpl);
}
@@ -719,16 +748,14 @@
* (or extend) the SPI.
*/
public static Object newInstance(Environment env, SPInterface spi, Properties properties, ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
LoadStrategy strategy = new DefaultLoadStrategy(env, spi);
- Object service = strategy.loadClass(properties, defaultImpl).newInstance();
-
- if (service instanceof Service) {
- ((Service)service).init(env.getGroupContext(), properties);
- }
-
- return service;
+ return strategy.loadClass(properties, defaultImpl).newInstance();
}
/**
@@ -760,16 +787,14 @@
* (or extend) the SPI.
*/
public static Object newInstance(Environment env, SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
- throws DiscoveryException
+ throws DiscoveryException,
+ InstantiationException,
+ IllegalAccessException,
+ NoSuchMethodException,
+ InvocationTargetException
{
LoadStrategy strategy = new DefaultLoadStrategy(env, spi);
Properties properties = strategy.loadProperties(propertiesFileName);
- Object service = strategy.loadClass(properties, defaultImpl).newInstance();
-
- if (service instanceof Service) {
- ((Service)service).init(env.getGroupContext(), properties);
- }
-
- return service;
+ return strategy.loadClass(properties, defaultImpl).newInstance();
}
}
1.5 +0 -12 jakarta-commons/discovery/src/java/org/apache/commons/discovery/load/ClassLoaderUtils.java
Index: ClassLoaderUtils.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/load/ClassLoaderUtils.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ClassLoaderUtils.java 12 Aug 2002 22:09:37 -0000 1.4
+++ ClassLoaderUtils.java 14 Aug 2002 21:46:21 -0000 1.5
@@ -167,18 +167,6 @@
return loadClass(serviceImplName, loaders, loaders.length);
}
-// /**
-// * Load the class <code>serviceImplName</code> using the
-// * class loaders associated with the SPI's context.
-// *
-// * @param serviceImplName The name of the class to load.
-// */
-// public static Class loadClass(String serviceImplName, EnvContext spi)
-// throws DiscoveryException
-// {
-// return loadClass(serviceImplName, spi.getClassLoaders());
-// }
-
/**
* Load the resource <code>resourceName</code>.
1.4 +2 -2 jakarta-commons/discovery/src/java/org/apache/commons/discovery/load/Loaders.java
Index: Loaders.java
===================================================================
RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/load/Loaders.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Loaders.java 12 Aug 2002 22:06:38 -0000 1.3
+++ Loaders.java 14 Aug 2002 21:46:21 -0000 1.4
@@ -64,8 +64,8 @@
import java.io.InputStream;
import org.apache.commons.discovery.DiscoveryException;
-import org.apache.commons.discovery.types.Environment;
-import org.apache.commons.discovery.types.SPInterface;
+import org.apache.commons.discovery.base.Environment;
+import org.apache.commons.discovery.base.SPInterface;
/**
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/base/SPInterface.java
Index: SPInterface.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.base;
/**
* 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 name
*/
private final String name;
/**
* The service programming interface: intended to be
* an interface or abstract class, but not limited
* to those two.
*/
private final Class provider;
/**
* 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 provider, String propertyName) {
this.name = provider.getName();
this.provider = provider;
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 provider,
String propertyName,
Class constructorParamClasses[],
Object constructorParams[])
{
this.name = provider.getName();
this.provider = provider;
this.propertyName = propertyName;
this.paramClasses = constructorParamClasses;
this.params = constructorParams;
}
public String getSPName() {
return name;
}
public Class getSPClass() {
return provider;
}
public String getPropertyName() {
return propertyName;
}
/**
* Create an ImplClass representing the SPI and,
* if set, the constructor type/object arguments.
*/
public ImplClass createImplClass(String className) {
return new ImplClass(className, paramClasses, params);
}
}
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/base/Environment.java
Index: Environment.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.base;
import org.apache.commons.discovery.load.ClassLoaderUtils;
/**
* Represents a environment context:
* the Thread Context Class Loader, the group context id, and the
* root discovery class (class representing the discovery front-door).
*
* @author Richard A. Sitze
*/
public class Environment {
/**
* Thread context class loader or null if not available (JDK 1.1).
* Wrapped bootstrap classloader if classLoader == null.
*/
private final ClassLoader threadContextClassLoader =
ClassLoaderUtils.getThreadContextClassLoader();
private final String groupContext;
private final Class rootDiscoveryClass;
public Environment(String groupContext, Class rootDiscoveryClass) {
this.groupContext = groupContext;
this.rootDiscoveryClass = rootDiscoveryClass;
}
public ClassLoader getThreadContextClassLoader() {
return threadContextClassLoader;
}
public String getGroupContext() {
return groupContext;
}
public Class getRootDiscoveryClass() {
return rootDiscoveryClass;
}
}
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/base/ImplClass.java
Index: ImplClass.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.base;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.discovery.DiscoveryException;
import org.apache.commons.discovery.load.Loaders;
/**
* @author Richard A. Sitze
*/
public class ImplClass {
private final String implName;
private Class implClass;
private Class paramClasses[] = null;
private Object params[] = null;
/**
* Construct object representing implementation
* Class whose name is <code>implName</code>.
*
* @param implName The SPI class name
*/
public ImplClass(String implName) {
this.implName = implName;
this.implClass = null;
}
/**
* Construct object representing implementation
* Class <code>implClass</code>.
*
* @param implClass The SPI class
*/
public ImplClass(Class implClass) {
this.implName = (implClass != null) ? implClass.getName() : null;
this.implClass = implClass;
}
/**
* Construct object representing implementation
* Class whose name is <code>implName</code>.
*
* @param implName The SPI class name
*
* @param constructorParamClasses classes representing the
* constructor argument types.
*
* @param constructorParams objects representing the
* constructor arguments.
*/
public ImplClass(String implName,
Class constructorParamClasses[],
Object constructorParams[])
{
this(implName);
this.paramClasses = constructorParamClasses;
this.params = constructorParams;
}
/**
* Construct object representing implementation
* Class <code>implClass</code>.
*
* @param implClass The SPI class
*
* @param constructorParamClasses classes representing the
* constructor argument types.
*
* @param constructorParams objects representing the
* constructor arguments.
*/
public ImplClass(Class implClass,
Class constructorParamClasses[],
Object constructorParams[])
{
this(implClass);
this.paramClasses = constructorParamClasses;
this.params = constructorParams;
}
public String getImplName() {
return implName;
}
/**
* The implementation's Class.
* If the original constructor specified the class using a
* <code>String implName</code>, then this will return <code>null</code>.
* Resolution of the class is defered until it is
* <ul>
* <li>required, and</li>
* <li>loaded by <code>loadImplClass</code></li>.
* </ul>
*
* @return implementation class or null.
*/
public Class getImplClass() {
return implClass;
}
/**
* Load and return the class using the list of class loaders
* specified by <code>loaders</code>.
*
* @param loaders
*
* @param systemOnly Use system loaders, as opposed to application
* class loaders. System loaders do not include
* the thread context class loader.
*/
public Class loadImplClass(Loaders loaders, boolean systemOnly) {
if (implClass == null) {
implClass = loaders.loadClass(getImplName(), systemOnly);
}
return implClass;
}
/**
* Instantiate a new
*/
public Object newInstance()
throws DiscoveryException,
InstantiationException,
IllegalAccessException,
NoSuchMethodException,
InvocationTargetException
{
if (getImplClass() == null)
throw new DiscoveryException("Class " + getImplName() + " not loaded!");
if (paramClasses == null || params == null) {
return getImplClass().newInstance();
} else {
Constructor constructor = getImplClass().getConstructor(paramClasses);
return constructor.newInstance(params);
}
}
}
1.1 jakarta-commons/discovery/src/java/org/apache/commons/discovery/tools/ManagedProperties.java
Index: ManagedProperties.java
===================================================================
/*
* 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.commons.discovery.tools;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
/**
* <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 = classLoader.getParent();
}
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(classLoader.getParent(), 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 Thread.currentThread().getContextClassLoader();
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>