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>