commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rsi...@apache.org
Subject cvs commit: jakarta-commons/discovery/src/java/org/apache/commons/discovery/strategy DefaultLoadStrategy.java LoadStrategy.java
Date Mon, 12 Aug 2002 22:06:39 GMT
rsitze      2002/08/12 15:06:39

  Modified:    discovery/src/java/org/apache/commons/discovery/load
                        Loaders.java ClassLoaderUtils.java
               discovery/src/java/org/apache/commons/discovery
                        DiscoverSingleton.java DiscoveryException.java
                        DiscoverClass.java
               discovery/src/java/org/apache/commons/discovery/strategy
                        DefaultLoadStrategy.java LoadStrategy.java
  Added:       discovery/src/java/org/apache/commons/discovery/types
                        SPInterface.java Environment.java ImplClass.java
               discovery/src/java/org/apache/commons/discovery/load
                        PsuedoSystemClassLoader.java
  Removed:     discovery/src/java/org/apache/commons/discovery/load
                        BootstrapLoader.java SPIContext.java
  Log:
  More cleanup.  (hopeful) performance enhancements, cleanup
  around conceptual use of boot-strap loader (it's in every hierarchy,
  right?), improved for system class loader in early JVMs.
  Introduced (internally used) objects to represent SPInterface,
  current runtime Environment, and ImplClass.  These are
  also exposed to help optimize use of the discovery pattern.
  For example, SPInterface can be used to declare the interface,
  optional 'property name' for finding the impl, constructor arguments
  to be used in instantiating the impl...
  Bottom line: more flexibility if you want it, or simple interface
  if that's all you need.
  
  Revision  Changes    Path
  1.1                  jakarta-commons/discovery/src/java/org/apache/commons/discovery/types/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.types;
  
  
  /**
   * Represents a Service Programming Interface (spi) context,
   * to include an spi and the Thread Context Class Loader for
   * the thread that created an instance of this object.
   * 
   * @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;
  
  
      public SPInterface(Class provider) {
          this(provider, provider.getName());
      }
      
      public SPInterface(Class provider, String propertyName) {
          this.name = provider.getName();
          this.provider = provider;
          this.propertyName = propertyName;
      }
  
      public SPInterface(Class provider, Class paramClasses[], Object params[]) {
          this(provider, provider.getName(), paramClasses, params);
      }
      
      public SPInterface(Class provider, String propertyName, Class paramClasses[], Object params[]) {
          this.name = provider.getName();
          this.provider = provider;
          this.propertyName = propertyName;
          this.paramClasses = paramClasses;
          this.params = params;
      }
      
      public String getSPName() {
          return name;
      }
      
      public Class getSPClass() {
          return provider;
      }
      
      public String getPropertyName() {
          return propertyName;
      }
      
      public ImplClass createImplClass(String className) {
          return new ImplClass(className, paramClasses, params);
      }
  }
  
  
  
  1.1                  jakarta-commons/discovery/src/java/org/apache/commons/discovery/types/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.types;
  
  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/types/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.types;
  
  import java.lang.reflect.Constructor;
  
  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;
  
  
      public ImplClass(String implName) {
          this.implName = implName;
          this.implClass = null;
      }
      
      public ImplClass(Class implClass) {
          this.implName = (implClass != null) ? implClass.getName() : null;
          this.implClass = implClass;
      }
      
  
      public ImplClass(String implName, Class paramClasses[], Object params[]) {
          this(implName);
          this.paramClasses = paramClasses;
          this.params = params;
      }
      
      public ImplClass(Class implClass, Class paramClasses[], Object params[]) {
          this(implClass);
          this.paramClasses = paramClasses;
          this.params = params;
      }
  
  
      public String getImplName() {
          return implName;
      }
      
      public Class getImplClass() {
          return implClass;
      }
      
      public Class loadImplClass(Loaders loaders, boolean systemOnly) {
          if (implClass == null) {
              implClass = loaders.loadClass(getImplName(), systemOnly);
          }
  
          return implClass;
      }
      
      public Object newInstance()
          throws DiscoveryException
      {
          try {
              if (paramClasses == null || params == null) {
                  return getImplClass().newInstance();
              } else {
                  Constructor constructor = getImplClass().getConstructor(paramClasses);
                  return constructor.newInstance(params);
             }
          } catch (Exception e) {
              throw new DiscoveryException("Unable to instantiate " + getImplName(), e);
          }
      }
  }
  
  
  
  1.3       +38 -39    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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Loaders.java	9 Aug 2002 19:42:04 -0000	1.2
  +++ Loaders.java	12 Aug 2002 22:06:38 -0000	1.3
  @@ -64,6 +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;
   
   
   /**
  @@ -74,11 +76,8 @@
    * @author Costin Manolache
    */
   public class Loaders {
  -    /**
  -     * The SPI (and thread context) for which we are (presumably)
  -     * looking for an implementation of.
  -     */
  -    private final SPIContext spiContext;
  +    private final Environment env;
  +    private final Class      spiClass;
       
       /**
        * System ClassLoaders only
  @@ -88,23 +87,23 @@
        */
       private final ClassLoader[] systemLoaders;
       
  -    private final ClassLoader[] allLoaders;
  +    private final ClassLoader[] appLoaders;
   
   
  -    /**
  -     * @param rootFinderClass a wrapper class encapsulating use of DiscoverSingleton.
  -     *   If DiscoverSingleton is used directly, then this would be DiscoverSingleton itself.
  -     *   The root finder class is used to determine the 'real' caller, and
  -     *   hence the caller's class loader - thereby preserving knowledge that
  -     *   is relevant to finding the correct/expected implementation class.
  -     */
  -    public Loaders(SPIContext spiContext, Class rootFinderClass)
  +    public Loaders(Environment env, SPInterface spi)
       {
  -        this.spiContext = spiContext;
  -        this.systemLoaders = getSystemLoaders(spiContext, rootFinderClass);
  -        this.allLoaders = getAllLoaders(spiContext, rootFinderClass);
  -
  -        //System.out.println("Finding '" + groupContext + "::" + spiContext.getSPI().getName() + "'");
  +        this.env = env;
  +        this.spiClass = spi.getSPClass();
  +        this.systemLoaders = createSystemLoaders();
  +        this.appLoaders = createAppLoaders();
  +    }
  +    
  +    public ClassLoader[] getSystemLoaders() {
  +        return systemLoaders;
  +    }
  +    
  +    public ClassLoader[] getAppLoaders() {
  +        return appLoaders;
       }
       
       /**
  @@ -127,11 +126,11 @@
           throws DiscoveryException
       {
           Class clazz = ClassLoaderUtils.loadClass(className,
  -                           systemOnly ? systemLoaders : allLoaders);
  +                           systemOnly ? systemLoaders : appLoaders);
               
  -        if (clazz != null  &&  !spiContext.getSPI().isAssignableFrom(clazz)) {
  +        if (clazz != null  &&  !spiClass.isAssignableFrom(clazz)) {
               throw new DiscoveryException("Class " + className +
  -                          " does not implement " + spiContext.getSPI().getName());
  +                          " does not implement " + spiClass.getName());
           }
           
           return clazz;
  @@ -156,19 +155,19 @@
       public InputStream loadResourceAsStream(String resourceName)
           throws DiscoveryException
       {
  -        String packageName = ClassLoaderUtils.getPackageName(spiContext.getSPI());
  +        String packageName = ClassLoaderUtils.getPackageName(spiClass);
   
           InputStream stream =
  -            (spiContext.getGroupContext() == null)
  +            (env.getGroupContext() == null)
                   ? null
                   : ClassLoaderUtils.getResourceAsStream(packageName,
  -                          spiContext.getGroupContext() + "." + resourceName,
  -                          allLoaders);
  +                          env.getGroupContext() + "." + resourceName,
  +                          appLoaders);
   
           if (stream == null)
               stream = ClassLoaderUtils.getResourceAsStream(packageName,
                                                             resourceName,
  -                                                          allLoaders);
  +                                                          appLoaders);
   
           return stream;
       }
  @@ -186,28 +185,28 @@
        * 
        */
       private static final ClassLoader getCallerClassLoader(Class rootFinderClass) {
  -        return BootstrapLoader.wrap(null);
  +        return null;
       }
   
       /**
  -     * List of 'system' class loaders to the SPI
  +     * List of 'system' class loaders to the SPI.
  +     * The last should always return a non-null loader, so we
  +     * always (?!) have a list of at least one classloader.
        */
  -    private static final ClassLoader[] getSystemLoaders(SPIContext spiContext,
  -                                                        Class rootFinderClass) {
  +    private final ClassLoader[] createSystemLoaders() {
           return ClassLoaderUtils.compactUniq(
  -                new ClassLoader[] {BootstrapLoader.wrap(spiContext.getSPI().getClassLoader()),
  -                                   BootstrapLoader.wrap(rootFinderClass.getClassLoader()),
  +                new ClassLoader[] {spiClass.getClassLoader(),
  +                                   env.getRootDiscoveryClass().getClassLoader(),
                                      ClassLoaderUtils.getSystemClassLoader()
                                     });
       }
       
  -    private static final ClassLoader[] getAllLoaders(SPIContext spiContext,
  -                                                     Class rootFinderClass) {
  +    private final ClassLoader[] createAppLoaders() {
           return ClassLoaderUtils.compactUniq(
  -                new ClassLoader[] {spiContext.getThreadContextClassLoader(),
  -                                   getCallerClassLoader(rootFinderClass),
  -                                   BootstrapLoader.wrap(spiContext.getSPI().getClassLoader()),
  -                                   BootstrapLoader.wrap(rootFinderClass.getClassLoader()),
  +                new ClassLoader[] {env.getThreadContextClassLoader(),
  +                                   getCallerClassLoader(env.getRootDiscoveryClass()),
  +                                   spiClass.getClassLoader(),
  +                                   env.getRootDiscoveryClass().getClassLoader(),
                                      ClassLoaderUtils.getSystemClassLoader()
                                     });
       }
  
  
  
  1.3       +34 -35    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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ClassLoaderUtils.java	9 Aug 2002 19:42:04 -0000	1.2
  +++ ClassLoaderUtils.java	12 Aug 2002 22:06:38 -0000	1.3
  @@ -167,17 +167,17 @@
           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, SPIContext spiContext)
  -        throws DiscoveryException
  -    {
  -        return loadClass(serviceImplName, spiContext.getClassLoaders());
  -    }
  +//    /**
  +//     * 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());
  +//    }
   
   
       /**
  @@ -221,17 +221,17 @@
           return getResourceAsStream(resourceName, loaders, loaders.length);
       }
       
  -    /**
  -     * Load the resource resourceName using the
  -     * class loaders associated with the SPI's context.
  -     * 
  -     * @param resourceName The name of the resource to load.
  -     */
  -    public static InputStream getResourceAsStream(String resourceName, SPIContext spiContext)
  -        throws DiscoveryException
  -    {
  -        return getResourceAsStream(resourceName, spiContext.getClassLoaders());
  -    }
  +//    /**
  +//     * Load the resource resourceName using the
  +//     * class loaders associated with the SPI's context.
  +//     * 
  +//     * @param resourceName The name of the resource to load.
  +//     */
  +//    public static InputStream getResourceAsStream(String resourceName, SPSpec spiContext)
  +//        throws DiscoveryException
  +//    {
  +//        return getResourceAsStream(resourceName, spiContext.getClassLoaders());
  +//    }
   
       /**
        * Load the resource <code>resourceName</code>.
  @@ -292,13 +292,13 @@
        * 
        * @param resourceName The name of the resource to load.
        */
  -    public static InputStream getResourceAsStream(String packageName,
  -                                                  String resourceName,
  -                                                  SPIContext spiContext)
  -        throws DiscoveryException
  -    {
  -        return getResourceAsStream(packageName, resourceName, spiContext.getClassLoaders());
  -    }
  +//    public static InputStream getResourceAsStream(String packageName,
  +//                                                  String resourceName,
  +//                                                  SPSpec spiContext)
  +//        throws DiscoveryException
  +//    {
  +//        return getResourceAsStream(packageName, resourceName, spiContext.getClassLoaders());
  +//    }
   
       
       /**
  @@ -310,7 +310,7 @@
       public static final boolean wouldUseClassLoader(ClassLoader thisClassLoader,
                                                       ClassLoader classLoader) {
           /* bootstrap classloader, at root of all trees! */
  -        if (BootstrapLoader.isBootstrapLoader(classLoader))
  +        if (classLoader == null)
               return true;
           
           while (thisClassLoader != null) {
  @@ -370,6 +370,7 @@
       public static final ClassLoader[] compactUniq(ClassLoader[] array) {        
           ClassLoader[] uniqLoaders = new ClassLoader[array.length];
           int length = uniq(array, uniqLoaders);
  +        
           return copy(uniqLoaders, 0, length);
       }
       
  @@ -409,8 +410,7 @@
       
               // Get the thread context class loader (if there is one)
               try {
  -                classLoader =
  -                    BootstrapLoader.wrap((ClassLoader)method.invoke(Thread.currentThread(), null));
  +                classLoader = (ClassLoader)method.invoke(Thread.currentThread(), null);
               } catch (IllegalAccessException e) {
                   throw new DiscoveryException("Unexpected IllegalAccessException", e);
               } catch (InvocationTargetException e) {
  @@ -494,8 +494,7 @@
       
               // Get the system class loader (if there is one)
               try {
  -                classLoader =
  -                    BootstrapLoader.wrap((ClassLoader)method.invoke(null, null));
  +                classLoader = (ClassLoader)method.invoke(null, null);
               } catch (IllegalAccessException e) {
                   throw new DiscoveryException("Unexpected IllegalAccessException", e);
               } catch (InvocationTargetException e) {
  @@ -519,7 +518,7 @@
               }
           } catch (NoSuchMethodException e) {
               // Assume we are running on JDK 1.1
  -            classLoader = null;
  +            classLoader = new PsuedoSystemClassLoader();
           }
       
           // Return the selected class loader
  
  
  
  1.1                  jakarta-commons/discovery/src/java/org/apache/commons/discovery/load/PsuedoSystemClassLoader.java
  
  Index: PsuedoSystemClassLoader.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.load;
  
  import java.io.InputStream;
  import java.net.URL;
  
  
  /**
   * JDK 1.1.x compatible?
   * There is no direct way to get the system class loader
   * in 1.1.x, but this should be a good work around...
   */
  public class PsuedoSystemClassLoader extends ClassLoader {
      protected Class loadClass(String className, boolean resolve)
          throws ClassNotFoundException
      {
          return findSystemClass(className);
      }
      
      public URL getResource(String resName) {
          return getSystemResource(resName);
      }
      
      public InputStream getResourceAsStream(String resName) {
          return getSystemResourceAsStream(resName);
      }
  }
  
  
  
  1.2       +260 -125  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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DiscoverSingleton.java	9 Aug 2002 14:57:59 -0000	1.1
  +++ DiscoverSingleton.java	12 Aug 2002 22:06:39 -0000	1.2
  @@ -65,8 +65,10 @@
   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.load.ClassLoaderUtils;
  -import org.apache.commons.discovery.load.SPIContext;
   
   
   /**
  @@ -102,13 +104,13 @@
    * <ul>
    * <li>static Object find(Class spi);</li>
    * <li>static Object find(Class spi, Properties properties);</li>
  - * <li>static Object find(Class spi, String defaultImplName);</li>
  - * <li>static Object find(Class spi, Properties properties, String defaultImplName);</li>
  - * <li>static Object find(Class spi, String propertiesFileName, String defaultImplName);</li>
  + * <li>static Object find(Class spi, String defaultImpl);</li>
  + * <li>static Object find(Class spi, Properties properties, String defaultImpl);</li>
  + * <li>static Object find(Class spi, String propertiesFileName, String defaultImpl);</li>
    * <li>static Object find(String groupContext, Class spi,
  - *                        Properties properties, String defaultImplName);</li>
  + *                        Properties properties, String defaultImpl);</li>
    * <li>static Object find(String groupContext, Class spi,
  - *                        String propertiesFileName, String defaultImplName);</li>
  + *                        String propertiesFileName, String defaultImpl);</li>
    * </ul>
    * 
    * The <code>DiscoverSingleton.find</code> methods proceed as follows:
  @@ -161,12 +163,12 @@
    *   </li></p>
    *   <p><li>
    *   If the name of the implementation class is null, AND the default
  - *   implementation class name (<code>defaultImplName</code>) is null,
  + *   implementation class (<code>defaultImpl</code>) is null,
    *   then an exception is thrown.
    *   </li></p>
    *   <p><li>
    *   If the name of the implementation class is null, AND the default
  - *   implementation class name (<code>defaultImplName</code>) is non-null,
  + *   implementation class (<code>defaultImpl</code>) is non-null,
    *   then load the default implementation class.  The class loaded is the
    *   first class loaded by the following sequence of class loaders:
    *   <ul>
  @@ -250,22 +252,6 @@
    * @version $Revision$ $Date$
    */
   public class DiscoverSingleton {
  -    /**
  -     * Readable placeholder for a null value.
  -     */
  -    static final String     nullGroupContext = null;
  -    
  -    /**
  -     * Readable placeholder for a null value.
  -     */
  -    static final Properties nullProperties = null;
  -    
  -    /**
  -     * Readable placeholder for a null value.
  -     */
  -    static final String     nullDefaultImplName = null;
  -    
  -    
       /********************** (RELATIVELY) SIMPLE FINDERS **********************
        * 
        * These finders are suitable for direct use in components looking for a
  @@ -276,7 +262,7 @@
       /**
        * Find implementation of SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -285,16 +271,16 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class spi)
  +    public static Object find(Class spiClass)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, spi);
  +        return find(DiscoverSingleton.class, spiClass);
       }
   
       /**
        * Find implementation of SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param properties Used to determine name of SPI implementation,
        *                   and passed to implementation.init() method if
  @@ -307,18 +293,18 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class spi, Properties properties)
  +    public static Object find(Class spiClass, Properties properties)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, spi, properties);
  +        return find(DiscoverSingleton.class, spiClass, properties);
       }
   
       /**
        * Find implementation of SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -327,22 +313,22 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class spi, String defaultImplName)
  +    public static Object find(Class spiClass, String defaultImpl)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, spi, defaultImplName);
  +        return find(DiscoverSingleton.class, spiClass, defaultImpl);
       }
   
       /**
        * Find implementation of SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @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 defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -351,22 +337,22 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class spi,
  +    public static Object find(Class spiClass,
                                 Properties properties,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, spi, properties, defaultImplName);
  +        return find(DiscoverSingleton.class, spiClass, properties, defaultImpl);
       }
       
       /**
        * Find implementation of SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param propertiesFileName The property file name.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -375,12 +361,12 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */    
  -    public static Object find(Class spi,
  +    public static Object find(Class spiClass,
                                 String propertiesFileName,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, spi, propertiesFileName, defaultImplName);
  +        return find(DiscoverSingleton.class, spiClass, propertiesFileName, defaultImpl);
       }
   
       /**
  @@ -391,13 +377,13 @@
        *        cannot be found by that name, then the unqualified property
        *        name is used.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @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 defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -407,12 +393,12 @@
        *            (or extend) the SPI.
        */
       public static Object find(String groupContext,
  -                              Class spi,
  +                              Class spiClass,
                                 Properties properties,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, groupContext, spi, properties, defaultImplName);
  +        return find(DiscoverSingleton.class, groupContext, spiClass, properties, defaultImpl);
       }
       
       /**
  @@ -422,12 +408,12 @@
        *        the system property name used to find the service implementation.
        *        If not found, the unqualified names are used.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param propertiesFileName The (qualified and unqualified) property file
        *        name.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -437,12 +423,12 @@
        *            (or extend) the SPI.
        */    
       public static Object find(String groupContext,
  -                              Class spi,
  +                              Class spiClass,
                                 String propertiesFileName,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(DiscoverSingleton.class, groupContext, spi, propertiesFileName, defaultImplName);
  +        return find(DiscoverSingleton.class, groupContext, spiClass, propertiesFileName, defaultImpl);
       }
   
       
  @@ -451,7 +437,7 @@
        * 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
  -     * and defaultImplName.  Having access to this wrapper class provides a
  +     * 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
        * correct/expected implementation class.
  @@ -464,7 +450,7 @@
        * @param rootFinderClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -472,10 +458,10 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement the SPI.
        */
  -    public static Object find(Class rootFinderClass, Class spi)
  +    public static Object find(Class rootFinderClass, Class spiClass)
           throws DiscoveryException
       {
  -        return find(rootFinderClass, spi, nullProperties, nullDefaultImplName);
  +        return find(rootFinderClass, spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
  @@ -484,7 +470,7 @@
        * @param rootFinderClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param properties Used to determine name of SPI implementation,
        *                   and passed to implementation.init() method if
  @@ -497,10 +483,10 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class rootFinderClass, Class spi, Properties properties)
  +    public static Object find(Class rootFinderClass, Class spiClass, Properties properties)
           throws DiscoveryException
       {
  -        return find(rootFinderClass, spi, properties, nullDefaultImplName);
  +        return find(rootFinderClass, spiClass, properties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
  @@ -509,9 +495,9 @@
        * @param rootFinderClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation name.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -520,10 +506,10 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public static Object find(Class rootFinderClass, Class spi, String defaultImplName)
  +    public static Object find(Class rootFinderClass, Class spiClass, String defaultImpl)
           throws DiscoveryException
       {
  -        return find(rootFinderClass, spi, nullProperties, defaultImplName);
  +        return find(rootFinderClass, spiClass, DiscoverClass.nullProperties, defaultImpl);
       }
   
       /**
  @@ -532,13 +518,13 @@
        * @param rootFinderClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @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 defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -548,12 +534,12 @@
        *            (or extend) the SPI.
        */
       public static Object find(Class rootFinderClass,
  -                              Class spi,
  +                              Class spiClass,
                                 Properties properties,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(rootFinderClass, nullGroupContext, spi, properties, defaultImplName);
  +        return find(rootFinderClass, DiscoverClass.nullGroupContext, spiClass, properties, defaultImpl);
       }
       
       /**
  @@ -562,11 +548,46 @@
        * @param rootFinderClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param propertiesFileName The property file name.
        * 
  -     * @param defaultImplName Default implementation 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,
  +                              Class spiClass,
  +                              String propertiesFileName,
  +                              String defaultImpl)
  +        throws DiscoveryException
  +    {
  +        return find(rootFinderClass, DiscoverClass.nullGroupContext,
  +                    spiClass, propertiesFileName, 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.
        * 
  @@ -576,13 +597,58 @@
        *            (or extend) the SPI.
        */    
       public static Object find(Class rootFinderClass,
  -                              Class spi,
  +                              String groupContext,
  +                              Class spiClass,
  +                              Properties properties,
  +                              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));
  +    }
  +
  +    /**
  +     * 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,
  +                              Class  spiClass,
                                 String propertiesFileName,
  -                              String defaultImplName)
  +                              String defaultImpl)
           throws DiscoveryException
       {
  -        return find(rootFinderClass, nullGroupContext,
  -                    spi, propertiesFileName, defaultImplName);
  +        /**
  +         * Env can change between calls... so we don't cache this.
  +         */
  +        return find(new Environment(groupContext, rootFinderClass),
  +                    new SPInterface(spiClass),
  +                    propertiesFileName,
  +                    new ImplClass(defaultImpl));
       }
   
       /**
  @@ -595,13 +661,13 @@
        *        the system property name used to find the service implementation.
        *        If not found, the unqualified names are used.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @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 defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -612,25 +678,101 @@
        */    
       public static Object find(Class rootFinderClass,
                                 String groupContext,
  -                              Class spi,
  +                              SPInterface spi,
                                 Properties properties,
  -                              String defaultImplName)
  +                              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
       {
  -        SPIContext spiContext = new SPIContext(groupContext, spi);
  +        /**
  +         * Env can change between calls... so we don't cache this.
  +         */
  +        return find(new Environment(groupContext, rootFinderClass),
  +                    spi,
  +                    propertiesFileName,
  +                    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(Environment env,
  +                              SPInterface spi,
  +                              Properties properties,
  +                              ImplClass defaultImpl)
  +        throws DiscoveryException
  +    {
           /**
            * Return previously registered service object (not class)
            * for this spi, bound only to current thread context class loader.
            */
  -        Object service = get(spiContext);
  +        Object service = get(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName());
   
           if (service == null) {
  -            DiscoverClass discoverClass = new DiscoverClass(rootFinderClass, groupContext);
  -            service = discoverClass.newInstance(spi, properties, defaultImplName);
  +            service = DiscoverClass.newInstance(env, spi, properties, defaultImpl);
   
               if (service != null) {
  -                put(spiContext, service);
  +                put(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName(), service);
               }
           }
   
  @@ -647,11 +789,11 @@
        *        the system property name used to find the service implementation.
        *        If not found, the unqualified names are used.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param propertiesFileName The property file name.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -660,27 +802,23 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */    
  -    public static Object find(Class  rootFinderClass,
  -                              String groupContext,
  -                              Class  spi,
  +    public static Object find(Environment env,
  +                              SPInterface spi,
                                 String propertiesFileName,
  -                              String defaultImplName)
  +                              ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        SPIContext spiContext = new SPIContext(groupContext, spi);
  -
           /**
            * Return previously registered service object (not class)
            * for this spi, bound only to current thread context class loader.
            */
  -        Object service = get(spiContext);
  +        Object service = get(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName());
   
           if (service == null) {
  -            DiscoverClass discoverClass = new DiscoverClass(rootFinderClass, groupContext);
  -            service = discoverClass.newInstance(spi, propertiesFileName, defaultImplName);
  +            service = DiscoverClass.newInstance(env, spi, propertiesFileName, defaultImpl);
   
               if (service != null) {
  -                put(spiContext, service);
  +                put(env.getThreadContextClassLoader(), env.getGroupContext(), spi.getSPName(), service);
               }
           }
   
  @@ -780,7 +918,7 @@
        * If the SPI instance implements <code>Service</code>, then call
        * <code>release()</code>.
        */
  -    public static void release(String groupContext, Class spi) {
  +    public static void release(String groupContext, Class spiClass) {
           ClassLoader threadContextClassLoader =
               ClassLoaderUtils.getThreadContextClassLoader();
   
  @@ -788,7 +926,7 @@
            * 'null' (bootstrap/system class loader) thread context class loader
            * is ok...  Until we learn otherwise.
            */
  -        if (spi != null) {
  +        if (spiClass != null) {
               synchronized (root_cache) {
                   HashMap groups = (HashMap)root_cache.get(threadContextClassLoader);
   
  @@ -796,12 +934,12 @@
                       HashMap spis = (HashMap)groups.get(groupContext);
   
                       if (spis != null) {
  -                        Object service = (Object)spis.get(spi.getName());
  +                        Object service = (Object)spis.get(spiClass.getName());
                           
                           if (service instanceof SingletonService)
                               ((SingletonService)service).release();
                           
  -                        spis.remove(spi.getName());
  +                        spis.remove(spiClass.getName());
                       }
                   }
               }
  @@ -814,8 +952,8 @@
        * If the SPI instance implements <code>Service</code>, then call
        * <code>release()</code>.
        */
  -    public static void release(Class spi) {
  -        release(nullGroupContext, spi);
  +    public static void release(Class spiClass) {
  +        release(DiscoverClass.nullGroupContext, spiClass);
       }
       
       
  @@ -859,7 +997,7 @@
       /**
        * Get service keyed by spi & classLoader.
        */
  -    static Object get(SPIContext spiContext)
  +    static Object get(ClassLoader loader, String groupContext, String spiName)
       {
           Object service = null;
   
  @@ -867,20 +1005,17 @@
            * 'null' (bootstrap/system class loader) thread context class loader
            * is ok...  Until we learn otherwise.
            */
  -        if (spiContext.getSPI() != null)
  -        {
  -            synchronized (root_cache) {
  -                HashMap groups =
  -                    (HashMap)root_cache.get(spiContext.getThreadContextClassLoader());
  +        synchronized (root_cache) {
  +            HashMap groups =
  +                (HashMap)root_cache.get(loader);
   
  -                if (groups != null) {
  -                    HashMap spis =
  -                        (HashMap)groups.get(spiContext.getGroupContext());
  -    
  -                    if (spis != null) {
  -                        
  -                        service = (Object)spis.get(spiContext.getSPI().getName());
  -                    }
  +            if (groups != null) {
  +                HashMap spis =
  +                    (HashMap)groups.get(groupContext);
  +
  +                if (spis != null) {
  +                    
  +                    service = (Object)spis.get(spiName);
                   }
               }
           }
  @@ -891,33 +1026,33 @@
       /**
        * Put service keyed by spi & classLoader.
        */
  -    static void put(SPIContext spiContext, Object service)
  +    static void put(ClassLoader loader, String groupContext, String spiName,
  +                    Object service)
       {
           /**
            * 'null' (bootstrap/system class loader) thread context class loader
            * is ok...  Until we learn otherwise.
            */
  -        if (spiContext.getSPI() != null  &&
  -            service != null)
  +        if (service != null)
           {
               synchronized (root_cache) {
                   HashMap groups =
  -                    (HashMap)root_cache.get(spiContext.getThreadContextClassLoader());
  +                    (HashMap)root_cache.get(loader);
                       
                   if (groups == null) {
                       groups = new HashMap(smallHashSize);
  -                    root_cache.put(spiContext.getThreadContextClassLoader(), groups);
  +                    root_cache.put(loader, groups);
                   }
   
                   HashMap spis =
  -                    (HashMap)groups.get(spiContext.getGroupContext());
  +                    (HashMap)groups.get(groupContext);
   
                   if (spis == null) {
                       spis = new HashMap(smallHashSize);
  -                    groups.put(spiContext.getGroupContext(), spis);
  +                    groups.put(groupContext, spis);
                   }
   
  -                spis.put(spiContext.getSPI().getName(), service);
  +                spis.put(spiName, service);
               }
           }
       }
  
  
  
  1.2       +0 -1      jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoveryException.java
  
  Index: DiscoveryException.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/DiscoveryException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DiscoveryException.java	18 Jul 2002 18:32:34 -0000	1.1
  +++ DiscoveryException.java	12 Aug 2002 22:06:39 -0000	1.2
  @@ -71,7 +71,6 @@
    * @author Craig R. McClanahan
    * @version $Revision$ $Date$
    */
  -
   public class DiscoveryException extends RuntimeException {
   
   
  
  
  
  1.2       +332 -72   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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DiscoverClass.java	9 Aug 2002 14:57:59 -0000	1.1
  +++ DiscoverClass.java	12 Aug 2002 22:06:39 -0000	1.2
  @@ -63,9 +63,11 @@
   
   import java.util.Properties;
   
  -import org.apache.commons.discovery.load.SPIContext;
  -import org.apache.commons.discovery.strategy.LoadStrategy;
  +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.strategy.DefaultLoadStrategy;
  +import org.apache.commons.discovery.strategy.LoadStrategy;
   
   
   /**
  @@ -131,12 +133,12 @@
    *   </li></p>
    *   <p><li>
    *   If the name of the implementation class is null, AND the default
  - *   implementation class name (<code>defaultImplName</code>) is null,
  + *   implementation class name (<code>defaultImpl</code>) is null,
    *   then an exception is thrown.
    *   </li></p>
    *   <p><li>
    *   If the name of the implementation class is null, AND the default
  - *   implementation class name (<code>defaultImplName</code>) is non-null,
  + *   implementation class (<code>defaultImpl</code>) is non-null,
    *   then load the default implementation class.  The class loaded is the
    *   first class loaded by the following sequence of class loaders:
    *   <ul>
  @@ -172,22 +174,50 @@
    * @version $Revision$ $Date$
    */
   public class DiscoverClass {
  -    private final Class  rootFinderClass;
  +    /**
  +     * Readable placeholder for a null value.
  +     */
  +    static final String     nullGroupContext = null;
  +
  +    /**
  +     * Readable placeholder for a null value.
  +     */
  +    static final String     nullDefaultImpl = null;
  +
  +    /**
  +     * Readable placeholder for a null value.
  +     */
  +    static final Properties nullProperties = null;
  +
       private final String groupContext;
  +    private final Class  rootDiscoveryClass;
  +    private final Environment env;
  +    
  +    private Environment getEnvironment() {
  +        /**
  +         * The environment may change between calls, so
  +         * we cache it if it was 'given' to us, otherwise
  +         * we recompute on each call.
  +         */
  +        return (env != null)
  +               ? env
  +               : new Environment(groupContext, rootDiscoveryClass);
  +    }
  +
       
  -    DiscoverClass() {
  -        this(DiscoverClass.class, DiscoverSingleton.nullGroupContext);
  +    public DiscoverClass() {
  +        this(DiscoverClass.class, DiscoverClass.nullGroupContext);
       }
       
       /**
  -     * @param rootFinderClass Wrapper class used by end-user, that ultimately
  +     * @param rootDiscoveryClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.  The root finder class is used to
        *        determine the 'real' caller, and hence the caller's class loader -
        *        thereby preserving knowledge that is relevant to finding the
        *        correct/expected implementation class.
        */
  -    DiscoverClass(Class rootFinderClass) {
  -        this(rootFinderClass, DiscoverSingleton.nullGroupContext);
  +    public DiscoverClass(Class rootDiscoveryClass) {
  +        this(rootDiscoveryClass, DiscoverClass.nullGroupContext);
       }
       
       /**
  @@ -211,12 +241,12 @@
        *        unqualified property name is used.
        *        </p>
        */
  -    DiscoverClass(String groupContext) {
  +    public DiscoverClass(String groupContext) {
           this(DiscoverClass.class, groupContext);
       }
       
       /**
  -     * @param rootFinderClass Wrapper class used by end-user, that ultimately
  +     * @param rootDiscoveryClass Wrapper class used by end-user, that ultimately
        *        calls this finder method.  The root finder class is used to
        *        determine the 'real' caller, and hence the caller's class loader -
        *        thereby preserving knowledge that is relevant to finding the
  @@ -242,15 +272,22 @@
        *        unqualified property name is used.
        *        </p>
        */
  -    DiscoverClass(Class rootFinderClass, String groupContext) {
  -        this.rootFinderClass = rootFinderClass;
  +    public DiscoverClass(Class rootDiscoveryClass, String groupContext) {
           this.groupContext = groupContext;
  +        this.rootDiscoveryClass = rootDiscoveryClass;
  +        this.env = null;
       }
       
  +    public DiscoverClass(Environment env) {
  +        this.groupContext = env.getGroupContext();
  +        this.rootDiscoveryClass = env.getRootDiscoveryClass();
  +        this.env = env;
  +    }
  +
       /**
        * Find class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @return Class implementing the SPI.
        * 
  @@ -258,16 +295,16 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement (or extend) the SPI.
        */
  -    public Class find(Class spi)
  +    public Class find(Class spiClass)
           throws DiscoveryException
       {
  -        return find(spi, DiscoverSingleton.nullProperties, DiscoverSingleton.nullDefaultImplName);
  +        return find(spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
        * Find class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param properties Used to determine name of SPI implementation.
        * 
  @@ -277,18 +314,18 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement (or extend) the SPI.
        */
  -    public Class find(Class spi, Properties properties)
  +    public Class find(Class spiClass, Properties properties)
           throws DiscoveryException
       {
  -        return find(spi, properties, DiscoverSingleton.nullDefaultImplName);
  +        return find(spiClass, properties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
        * Find class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation name.
        * 
        * @return Class implementing the SPI.
        * 
  @@ -296,20 +333,20 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement (or extend) the SPI.
        */
  -    public Class find(Class spi, String defaultImplName)
  +    public Class find(Class spiClass, String defaultImpl)
           throws DiscoveryException
       {
  -        return find(spi, DiscoverSingleton.nullProperties, defaultImplName);
  +        return find(spiClass, DiscoverClass.nullProperties, defaultImpl);
       }
   
       /**
        * Find class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param properties Used to determine name of SPI implementation,.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation class.
        * 
        * @return Class implementing the SPI.
        * 
  @@ -317,12 +354,70 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement (or extend) the SPI.
        */
  -    public Class find(Class spi, Properties properties, String defaultImplName)
  +    public Class find(Class spiClass, Properties properties, String defaultImpl)
           throws DiscoveryException
       {
  -        SPIContext spiContext = new SPIContext(groupContext, spi);
  -        LoadStrategy strategy = new DefaultLoadStrategy(spiContext, rootFinderClass);
  -        return strategy.loadClass(properties, defaultImplName);
  +        return find(getEnvironment(),
  +                    new SPInterface(spiClass),
  +                    properties,
  +                    new ImplClass(defaultImpl));
  +    }
  +    
  +    /**
  +     * Find class implementing SPI.
  +     * 
  +     * @param spiClass Service Provider Interface Class.
  +     * 
  +     * @param propertiesFileName The property file name.
  +     *        A property file is loaded using the following sequence of class
  +     *        loaders:
  +     *        <ul>
  +     *          <li>Thread Context Class Loader</li>
  +     *          <li>DiscoverSingleton's Caller's Class Loader</li>
  +     *          <li>SPI's Class Loader</li>
  +     *          <li>DiscoverSingleton's (this class) Class Loader</li>
  +     *          <li>System Class Loader</li>
  +     *        </ul>
  +     * 
  +     * @param defaultImpl Default implementation.
  +     * 
  +     * @return 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, or if
  +     *            the resulting class does not implement (or extend) the SPI.
  +     */    
  +    public Class find(Class spiClass, String propertiesFileName, String defaultImpl)
  +        throws DiscoveryException
  +    {
  +        return find(getEnvironment(),
  +                    new SPInterface(spiClass),
  +                    propertiesFileName,
  +                    new ImplClass(defaultImpl));
  +    }
  +
  +    /**
  +     * Find class implementing SPI.
  +     * 
  +     * @param spi Service Provider Interface Class.
  +     * 
  +     * @param properties Used to determine name of SPI implementation.
  +     * 
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
  +     * 
  +     * @return 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, or if
  +     *            the resulting class does not implement (or extend) the SPI.
  +     */
  +    public Class find(SPInterface spi, Properties properties, ImplClass defaultImpl)
  +        throws DiscoveryException
  +    {
  +        return find(getEnvironment(), spi, properties, defaultImpl);
       }
       
       /**
  @@ -341,7 +436,10 @@
        *          <li>System Class Loader</li>
        *        </ul>
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
        * 
        * @return Class implementing the SPI.
        * 
  @@ -349,20 +447,78 @@
        *            the SPI cannot be found, if the class cannot be loaded, or if
        *            the resulting class does not implement (or extend) the SPI.
        */    
  -    public Class find(Class spi, String propertiesFileName, String defaultImplName)
  +    public Class find(SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        SPIContext spiContext = new SPIContext(groupContext, spi);
  -        LoadStrategy strategy = new DefaultLoadStrategy(spiContext, rootFinderClass);
  -        return strategy.loadClass(strategy.loadProperties(propertiesFileName), defaultImplName);
  +        return find(getEnvironment(), spi, propertiesFileName, defaultImpl);
       }
   
  +
  +    /**
  +     * Find class implementing SPI.
  +     * 
  +     * @param spi Service Provider Interface Class.
  +     * 
  +     * @param properties Used to determine name of SPI implementation.
  +     * 
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
  +     * 
  +     * @return 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, or if
  +     *            the resulting class does not implement (or extend) the SPI.
  +     */
  +    public static Class find(Environment env, SPInterface spi, Properties properties, ImplClass defaultImpl)
  +        throws DiscoveryException
  +    {
  +        LoadStrategy strategy = new DefaultLoadStrategy(env, spi);
  +        return strategy.loadClass(properties, defaultImpl).getImplClass();
  +    }
       
       /**
  -     * Create new instance of class implementing SPI.
  +     * Find class implementing SPI.
        * 
        * @param spi Service Provider Interface Class.
        * 
  +     * @param propertiesFileName The property file name.
  +     *        A property file is loaded using the following sequence of class
  +     *        loaders:
  +     *        <ul>
  +     *          <li>Thread Context Class Loader</li>
  +     *          <li>DiscoverSingleton's Caller's Class Loader</li>
  +     *          <li>SPI's Class Loader</li>
  +     *          <li>DiscoverSingleton's (this class) Class Loader</li>
  +     *          <li>System Class Loader</li>
  +     *        </ul>
  +     * 
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
  +     * 
  +     * @return 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, or if
  +     *            the resulting class does not implement (or extend) the SPI.
  +     */    
  +    public static Class find(Environment env, SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
  +        throws DiscoveryException
  +    {
  +        LoadStrategy strategy = new DefaultLoadStrategy(env, spi);
  +        return strategy.loadClass(strategy.loadProperties(propertiesFileName),
  +                                  defaultImpl).getImplClass();
  +    }
  +    
  +    /**
  +     * Create new instance of class implementing SPI.
  +     * 
  +     * @param spiClass Service Provider Interface Class.
  +     * 
        * @return Instance of a class implementing the SPI.
        * 
        * @exception DiscoveryException Thrown if the name of a class implementing
  @@ -370,16 +526,16 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public Object newInstance(Class spi)
  +    public Object newInstance(Class spiClass)
           throws DiscoveryException
       {
  -        return newInstance(spi, DiscoverSingleton.nullProperties, DiscoverSingleton.nullDefaultImplName);
  +        return newInstance(spiClass, DiscoverClass.nullProperties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
        * Create new instance of class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
        * @param properties Used to determine name of SPI implementation,
        *                   and passed to implementation.init() method if
  @@ -392,18 +548,18 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public Object newInstance(Class spi, Properties properties)
  +    public Object newInstance(Class spiClass, Properties properties)
           throws DiscoveryException
       {
  -        return newInstance(spi, properties, DiscoverSingleton.nullDefaultImplName);
  +        return newInstance(spiClass, properties, DiscoverClass.nullDefaultImpl);
       }
   
       /**
        * Create new instance of class implementing SPI.
        * 
  -     * @param spi Service Provider Interface Class.
  +     * @param spiClass Service Provider Interface Class.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -412,10 +568,71 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public Object newInstance(Class spi, String defaultImplName)
  +    public Object newInstance(Class spiClass, String defaultImpl)
           throws DiscoveryException
       {
  -        return newInstance(spi, DiscoverSingleton.nullProperties, defaultImplName);
  +        return newInstance(spiClass, DiscoverClass.nullProperties, defaultImpl);
  +    }
  +
  +    /**
  +     * Create new instance of class implementing SPI.
  +     * 
  +     * @param spiClass Service Provider Interface Class.
  +     * 
  +     * @param properties Used to determine name of SPI implementation,
  +     *                   and passed to implementation.init() method if
  +     *                   implementation implements Service interface.
  +     * 
  +     * @param defaultImpl Default implementation.
  +     * 
  +     * @return Instance of a class implementing the SPI.
  +     * 
  +     * @exception DiscoveryException Thrown if the name of a class implementing
  +     *            the SPI cannot be found, if the class cannot be loaded and
  +     *            instantiated, or if the resulting class does not implement
  +     *            (or extend) the SPI.
  +     */
  +    public Object newInstance(Class spiClass, Properties properties, String defaultImpl)
  +        throws DiscoveryException
  +    {
  +        return newInstance(getEnvironment(),
  +                           new SPInterface(spiClass),
  +                           properties,
  +                           new ImplClass(defaultImpl));
  +    }
  +    
  +    /**
  +     * Create new instance of class implementing SPI.
  +     * 
  +     * @param spiClass Service Provider Interface Class.
  +     * 
  +     * @param propertiesFileName The property file name.
  +     *        A property file is loaded using the following sequence of class
  +     *       loaders:
  +     *      <ul>
  +     *        <li>Thread Context Class Loader</li>
  +     *        <li>DiscoverSingleton's Caller's Class Loader</li>
  +     *        <li>SPI's Class Loader</li>
  +     *        <li>DiscoverSingleton's (this class) Class Loader</li>
  +     *        <li>System Class Loader</li>
  +     *      </ul>
  +     * 
  +     * @param 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 Object newInstance(Class spiClass, String propertiesFileName, String defaultImpl)
  +        throws DiscoveryException
  +    {
  +        return newInstance(getEnvironment(),
  +                           new SPInterface(spiClass),
  +                           propertiesFileName,
  +                           new ImplClass(defaultImpl));
       }
   
       /**
  @@ -427,7 +644,10 @@
        *                   and passed to implementation.init() method if
        *                   implementation implements Service interface.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -436,10 +656,10 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */
  -    public Object newInstance(Class spi, Properties properties, String defaultImplName)
  +    public Object newInstance(SPInterface spi, Properties properties, ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        return newInstance(spi, find(spi, properties, defaultImplName), properties);
  +        return newInstance(getEnvironment(), spi, properties, defaultImpl);
       }
       
       /**
  @@ -458,7 +678,10 @@
        *        <li>System Class Loader</li>
        *      </ul>
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @param defaultImpl Default implementation.
        * 
        * @return Instance of a class implementing the SPI.
        * 
  @@ -467,49 +690,86 @@
        *            instantiated, or if the resulting class does not implement
        *            (or extend) the SPI.
        */    
  -    public Object newInstance(Class spi, String propertiesFileName, String defaultImplName)
  +    public Object newInstance(SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        SPIContext spiContext = new SPIContext(groupContext, spi);
  -        LoadStrategy strategy = new DefaultLoadStrategy(spiContext, rootFinderClass);
  -        Properties properties = strategy.loadProperties(propertiesFileName);
  -        return newInstance(spi,
  -                           strategy.loadClass(properties, defaultImplName),
  -                           properties);
  +        return newInstance(getEnvironment(), spi, propertiesFileName, defaultImpl);
       }
  -    
  +
  +
       /**
  -     * Instantiate SPI.
  -     *   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.
  +     * Create new instance of class implementing SPI.
        * 
        * @param spi Service Provider Interface Class.
        * 
  -     * @param impl Class implementing SPI, class to instantiate.
  +     * @param properties Used to determine name of SPI implementation,
  +     *                   and passed to implementation.init() method if
  +     *                   implementation implements Service interface.
  +     * 
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
        * 
  -     * @param properties if impl implements Service, call impl.init(properties).
  +     * @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.
        */
  -    private Object newInstance(Class spi, Class impl, Properties properties)
  +    public static Object newInstance(Environment env, SPInterface spi, Properties properties, ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        Object service = null;
  -    
  -        try {
  -            service = impl.newInstance();
  -        } catch (Exception e) {
  -            throw new DiscoveryException("Unable to instantiate " + impl.getName() + " for " + spi.getName(), e);
  -        }
  +        LoadStrategy strategy = new DefaultLoadStrategy(env, spi);
  +        Object service = strategy.loadClass(properties, defaultImpl).newInstance();
   
           if (service instanceof Service) {
  -            ((Service)service).init(groupContext, properties);
  +            ((Service)service).init(env.getGroupContext(), properties);
           }
  +        
  +        return service;
  +    }
  +    
  +    /**
  +     * Create new instance of class implementing SPI.
  +     * 
  +     * @param spi Service Provider Interface Class.
  +     * 
  +     * @param propertiesFileName The property file name.
  +     *        A property file is loaded using the following sequence of class
  +     *       loaders:
  +     *      <ul>
  +     *        <li>Thread Context Class Loader</li>
  +     *        <li>DiscoverSingleton's Caller's Class Loader</li>
  +     *        <li>SPI's Class Loader</li>
  +     *        <li>DiscoverSingleton's (this class) Class Loader</li>
  +     *        <li>System Class Loader</li>
  +     *      </ul>
  +     * 
  +     * @param propertyName Alternate propertyName for value of name of
  +     *                     SPI implementation.
  +     * 
  +     * @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 newInstance(Environment env, SPInterface spi, String propertiesFileName, ImplClass defaultImpl)
  +        throws DiscoveryException
  +    {
  +        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;
       }
   }
  
  
  
  1.2       +50 -32    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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultLoadStrategy.java	9 Aug 2002 14:58:00 -0000	1.1
  +++ DefaultLoadStrategy.java	12 Aug 2002 22:06:39 -0000	1.2
  @@ -66,8 +66,10 @@
   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.load.Loaders;
  -import org.apache.commons.discovery.load.SPIContext;
   
   
   /**
  @@ -85,12 +87,14 @@
    * @version $Revision$ $Date$
    */
   public class DefaultLoadStrategy implements LoadStrategy {
  -    private final SPIContext spiContext;
  +    private final Environment env;
  +    private final SPInterface spi;
       private final Loaders loaders;
       
  -    public DefaultLoadStrategy(SPIContext spiContext, Class rootFinderClass) {
  -        this.spiContext = spiContext;
  -        this.loaders = new Loaders(spiContext, rootFinderClass);
  +    public DefaultLoadStrategy(Environment env, SPInterface spi) {
  +        this.env = env;
  +        this.spi = spi;
  +        this.loaders = new Loaders(env, spi);
       }
       
       /**
  @@ -128,12 +132,12 @@
        *   </li></p>
        *   <p><li>
        *   If the name of the implementation class is null, AND the default
  -     *   implementation class name (<code>defaultImplName</code>) is null,
  +     *   implementation class (<code>defaultImpl</code>) is null,
        *   then an exception is thrown.
        *   </li></p>
        *   <p><li>
        *   If the name of the implementation class is null, AND the default
  -     *   implementation class name (<code>defaultImplName</code>) is non-null,
  +     *   implementation class (<code>defaultImpl</code>) is non-null,
        *   then load the default implementation class.  The class loaded is the
        *   first class loaded by the following sequence of class loaders:
        *   <ul>
  @@ -153,59 +157,76 @@
        *   </li></p>
        * </ul>
        * 
  -     * @param ClassFinder  Represents the spiContext, class loaders
  -     *        (including root finder class), and the groupContext.
  -     * 
        * @param properties Used to determine name of SPI implementation,
        *                   and passed to implementation.init() method if
        *                   implementation implements Service interface.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Class class implementing the SPI.
        * 
        * @exception DiscoveryException Thrown if the name of a class implementing
        *            the SPI cannot be found, or if the class cannot be loaded.
        */
  -    public Class loadClass(Properties properties, String defaultImplName)
  +    public ImplClass loadClass(Properties properties, ImplClass defaultImpl)
           throws DiscoveryException
       {
  -        String spiName = spiContext.getSPI().getName();
  -        Object service = null;
  +        String spiName = spi.getSPName();
  +        String propertyName = spi.getPropertyName();
   
  -        // First, try the (managed) system property
  +        // First, try the (managed) system property spiName
           String className = Utils.getManagedProperty(spiName);
  -
           if (className == null) {
  -            // Second, try the properties parameter
  -            if (properties != null)
  -                className = properties.getProperty(spiName);
  -        
  +            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) {
  -                // Third, try to find a service by using the JDK1.3 jar
  +                // Last, try to find a service by using the JDK1.3 jar
                   // discovery mechanism.
                   className = Utils.getJDK13ClassName(
  -                    spiContext.getThreadContextClassLoader(), spiName);
  +                    env.getThreadContextClassLoader(), spiName);
               }
           }
   
  -        Class clazz = null;
  +        ImplClass implClass = null;
   
           if (className != null) {
  -            clazz = loaders.loadClass(className, false);
  -        } else {        
  -            // Fourth, try the fallback implementation class,
  +            implClass = spi.createImplClass(className);
  +            implClass.loadImplClass(loaders, false);
  +        } else {
  +            // All else fails: try the fallback implementation class,
               // but limit loaders to 'system' loaders, in an
               // attempt to ensure that the default picked up is
               // the one that was intended.
  -            clazz = loaders.loadClass(defaultImplName, true);
  +            implClass = defaultImpl;
  +            if (implClass != null) {
  +                implClass.loadImplClass(loaders, true);
  +            }
           }
   
  -        if (clazz == null) {
  +        if (implClass == null  ||  implClass.getImplClass() == null) {
               throw new DiscoveryException("No implementation defined for " + spiName);
           }
   
  -        return clazz;
  +        return implClass;
       }
       
       /**
  @@ -219,9 +240,6 @@
        *     <li>DiscoverSingleton's (this class) Class Loader</li>
        *     <li>System Class Loader</li>
        *   </ul>
  -     * 
  -     * @param ClassFinder  Represents the spiContext, class loaders
  -     *        (including root finder class), and the groupContext.
        * 
        * @param propertiesFileName The property file name.
        * 
  
  
  
  1.2       +4 -3      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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LoadStrategy.java	9 Aug 2002 14:58:00 -0000	1.1
  +++ LoadStrategy.java	12 Aug 2002 22:06:39 -0000	1.2
  @@ -66,8 +66,9 @@
   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.load.SPIContext;
   
   
   /**
  @@ -91,14 +92,14 @@
        * @param properties May use, but must pass to implementation.init() method
        *                   if implementation implements Service interface.
        * 
  -     * @param defaultImplName Default implementation name.
  +     * @param defaultImpl Default implementation.
        * 
        * @return Class class implementing the SPI.
        * 
        * @exception DiscoveryException Thrown if the name of a class implementing
        *            the SPI cannot be found, or if the class cannot be loaded.
        */
  -    public Class loadClass(Properties properties, String defaultImplName)
  +    public ImplClass loadClass(Properties properties, ImplClass defaultImpl)
           throws DiscoveryException;
       
       /**
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message