You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rs...@apache.org on 2002/07/18 00:03:06 UTC

cvs commit: jakarta-commons/discovery/src/java/org/apache/commons/discovery BootstrapLoader.java SPIContext.java ServiceFinder.java ServiceCache.java ClassFinder.java ClassLoaderUtils.java

rsitze      2002/07/17 15:03:06

  Modified:    discovery/src/java/org/apache/commons/discovery
                        SPIContext.java ServiceFinder.java
                        ServiceCache.java ClassFinder.java
                        ClassLoaderUtils.java
  Added:       discovery/src/java/org/apache/commons/discovery
                        BootstrapLoader.java
  Log:
  Handle JDK 1.2 bootstrap loader (classLoader == null).  Basically,
  we pass every loader through BootstrapLoader.wrap(loader).
  This method returns the loader (load != null) or a wrapper class (loader == null).
  The wrapper class today is a 1.1.x compatible (we hope) ClassLoader
  that invokes the system class loader.  In future, this could be expanded
  to use the REAL bootstrap class loader (fun fun fun) for 1.2 JVMs.
  
  Revision  Changes    Path
  1.2       +6 -120    jakarta-commons/discovery/src/java/org/apache/commons/discovery/SPIContext.java
  
  Index: SPIContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/SPIContext.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SPIContext.java	9 Jul 2002 18:03:23 -0000	1.1
  +++ SPIContext.java	17 Jul 2002 22:03:06 -0000	1.2
  @@ -82,15 +82,17 @@
   public class SPIContext {
       /**
        * Thread context class loader or null if not available (JDK 1.1).
  +     * Wrapped bootstrap classloader if classLoader == null.
        */
       private final ClassLoader threadContextClassLoader =
  -        findThreadContextClassLoader();
  +        ClassLoaderUtils.findThreadContextClassLoader();
   
       /**
        * System class loader or null if not available (JDK 1.1).
  +     * Wrapped bootstrap classloader if classLoader == null.
        */
       private final ClassLoader systemClassLoader =
  -        findSystemClassLoader();
  +        ClassLoaderUtils.findSystemClassLoader();
   
       /**
        * List of class loaders
  @@ -108,8 +110,8 @@
           this.spi = spi;
           this.loaders = ClassLoaderUtils.compactUniq(
               new ClassLoader[] { threadContextClassLoader,
  -                           spi.getClassLoader(),
  -                           systemClassLoader });
  +                                BootstrapLoader.wrap(spi.getClassLoader()),
  +                                systemClassLoader });
       }
       
       public ClassLoader getThreadContextClassLoader() {
  @@ -126,121 +128,5 @@
       
       public Class getSPI() {
           return spi;
  -    }
  -
  -    /**
  -     * Return the thread context class loader if available.
  -     * Otherwise return null.
  -     * 
  -     * The thread context class loader is available for JDK 1.2
  -     * or later, if certain security conditions are met.
  -     * 
  -     * @exception ServiceException if a suitable class loader
  -     * cannot be identified.
  -     */
  -    private static ClassLoader findThreadContextClassLoader()
  -        throws ServiceException
  -    {
  -        ClassLoader classLoader = null;
  -        
  -        try {
  -            // Are we running on a JDK 1.2 or later system?
  -            Method method = Thread.class.getMethod("getContextClassLoader", null);
  -    
  -            // Get the thread context class loader (if there is one)
  -            try {
  -                classLoader =
  -                    (ClassLoader)method.invoke(Thread.currentThread(), null);
  -            } catch (IllegalAccessException e) {
  -                throw new ServiceException("Unexpected IllegalAccessException", e);
  -            } catch (InvocationTargetException e) {
  -                /**
  -                 * InvocationTargetException is thrown by 'invoke' when
  -                 * the method being invoked (Thread.getContextClassLoader)
  -                 * throws an exception.
  -                 * 
  -                 * Thread.getContextClassLoader() throws SecurityException
  -                 * when the context class loader isn't an ancestor of the
  -                 * calling class's class loader, or if security permissions
  -                 * are restricted.
  -                 * 
  -                 * In the first case (the context class loader isn't an
  -                 * ancestor of the calling class's class loader), we want
  -                 * to ignore and keep going.  We cannot help but also ignore
  -                 * the second case (restricted security permissions) with
  -                 * the logic below, but other calls elsewhere (to obtain
  -                 * a class loader) will re-trigger this exception where
  -                 * we can make a distinction.
  -                 */
  -                if (e.getTargetException() instanceof SecurityException) {
  -                    classLoader = null;  // ignore
  -                } else {
  -                    // Capture 'e.getTargetException()' exception for details
  -                    // alternate: log 'e.getTargetException()', and pass back 'e'.
  -                    throw new ServiceException
  -                        ("Unexpected InvocationTargetException",
  -                         e.getTargetException());
  -                }
  -            }
  -        } catch (NoSuchMethodException e) {
  -            // Assume we are running on JDK 1.1
  -            classLoader = null;
  -        }
  -    
  -        // Return the selected class loader
  -        return classLoader;
  -    }
  -
  -    /**
  -     * Return the system class loader if available.
  -     * Otherwise return null.
  -     * 
  -     * The system class loader is available for JDK 1.2
  -     * or later, if certain security conditions are met.
  -     * 
  -     * @exception ServiceException if a suitable class loader
  -     * cannot be identified.
  -     */
  -    private static ClassLoader findSystemClassLoader()
  -        throws ServiceException
  -    {
  -        ClassLoader classLoader = null;
  -        
  -        try {
  -            // Are we running on a JDK 1.2 or later system?
  -            Method method = ClassLoader.class.getMethod("getSystemClassLoader", null);
  -    
  -            // Get the system class loader (if there is one)
  -            try {
  -                classLoader =
  -                    (ClassLoader)method.invoke(null, null);
  -            } catch (IllegalAccessException e) {
  -                throw new ServiceException("Unexpected IllegalAccessException", e);
  -            } catch (InvocationTargetException e) {
  -                /**
  -                 * InvocationTargetException is thrown by 'invoke' when
  -                 * the method being invoked (ClassLoader.getSystemClassLoader)
  -                 * throws an exception.
  -                 * 
  -                 * ClassLoader.getSystemClassLoader() throws SecurityException
  -                 * if security permissions are restricted.
  -                 */
  -                if (e.getTargetException() instanceof SecurityException) {
  -                    classLoader = null;  // ignore
  -                } else {
  -                    // Capture 'e.getTargetException()' exception for details
  -                    // alternate: log 'e.getTargetException()', and pass back 'e'.
  -                    throw new ServiceException
  -                        ("Unexpected InvocationTargetException",
  -                         e.getTargetException());
  -                }
  -            }
  -        } catch (NoSuchMethodException e) {
  -            // Assume we are running on JDK 1.1
  -            classLoader = null;
  -        }
  -    
  -        // Return the selected class loader
  -        return classLoader;
       }
   }
  
  
  
  1.4       +4 -2      jakarta-commons/discovery/src/java/org/apache/commons/discovery/ServiceFinder.java
  
  Index: ServiceFinder.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/ServiceFinder.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ServiceFinder.java	9 Jul 2002 21:12:01 -0000	1.3
  +++ ServiceFinder.java	17 Jul 2002 22:03:06 -0000	1.4
  @@ -498,10 +498,11 @@
       
       /**
        * Get service keyed by spi & classLoader.
  +     * Special cases null bootstrap classloader (classLoader == null).
        */
       private static Object get(String spi, ClassLoader classLoader)
       {
  -        ServiceCache cache = (spi == null  ||  classLoader == null)
  +        ServiceCache cache = (spi == null)
                                ? null
                                : (ServiceCache)service_caches.get(spi);
           
  @@ -512,10 +513,11 @@
       
       /**
        * Put service keyed by spi & classLoader.
  +     * Special cases null bootstrap classloader (classLoader == null).
        */
       private static void put(String spi, ClassLoader classLoader, Object service)
       {
  -        if (spi != null  &&  classLoader != null  &&  service != null) {
  +        if (spi != null  &&  service != null) {
               ServiceCache cache = (ServiceCache)service_caches.get(spi);
               
               if (cache == null) {
  
  
  
  1.2       +6 -0      jakarta-commons/discovery/src/java/org/apache/commons/discovery/ServiceCache.java
  
  Index: ServiceCache.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/ServiceCache.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ServiceCache.java	9 Jul 2002 18:03:23 -0000	1.1
  +++ ServiceCache.java	17 Jul 2002 22:03:06 -0000	1.2
  @@ -81,9 +81,12 @@
       
       /**
        * Get service keyed by classLoader.
  +     * Special cases null bootstrap classloader (classLoader == null).
        */
       public Object get(ClassLoader classLoader)
       {
  +        classLoader = BootstrapLoader.wrap(classLoader);
  +
           return (classLoader == null)
                   ? null
                   : services.get(classLoader);
  @@ -91,9 +94,12 @@
       
       /**
        * Put service keyed by classLoader.
  +     * Special cases null bootstrap classloader (classLoader == null).
        */
       public void put(ClassLoader classLoader, Object service)
       {
  +        classLoader = BootstrapLoader.wrap(classLoader);
  +
           if (classLoader != null  &&  service != null) {
               services.put(classLoader, service);
           }
  
  
  
  1.3       +18 -12    jakarta-commons/discovery/src/java/org/apache/commons/discovery/ClassFinder.java
  
  Index: ClassFinder.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/ClassFinder.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ClassFinder.java	9 Jul 2002 21:12:01 -0000	1.2
  +++ ClassFinder.java	17 Jul 2002 22:03:06 -0000	1.3
  @@ -277,9 +277,15 @@
        * SecurityManager.getClassContext() is out of reach at best,
        * and getting to it in a J2EE environment is likely to be beyond
        * hopeless....
  +     * 
  +     * If the caller class loader is the bootstrap classloader, then
  +     * it is 'wrapped' (see BootstrapLoader).  Therefore this method
  +     * only returns 'null' if a caller class loader could not
  +     * be identified.
  +     * 
        */
       private static final ClassLoader getCallerClassLoader(Class rootFinderClass) {
  -        return null;
  +        return BootstrapLoader.wrap(null);
       }
   
       /**
  @@ -290,20 +296,20 @@
        */
       private static final ClassLoader[] getLocalLoaders(SPIContext spiContext,
                                                          Class rootFinderClass) {
  -        return ClassLoaderUtils.compactUniq(new ClassLoader[] {    
  -                                rootFinderClass.getClassLoader(),
  -                                spiContext.getSystemClassLoader()
  -                          });
  +        return ClassLoaderUtils.compactUniq(
  +                new ClassLoader[] {BootstrapLoader.wrap(rootFinderClass.getClassLoader()),
  +                                   spiContext.getSystemClassLoader()
  +                                  });
       }
       
       private static final ClassLoader[] getAllLoaders(SPIContext spiContext,
                                                        Class rootFinderClass) {
  -        return ClassLoaderUtils.compactUniq(new ClassLoader[] {    
  -                                spiContext.getThreadContextClassLoader(),
  -                                getCallerClassLoader(rootFinderClass),
  -                                spiContext.getSPI().getClassLoader(),
  -                                rootFinderClass.getClassLoader(),
  -                                spiContext.getSystemClassLoader()
  -                            });
  +        return ClassLoaderUtils.compactUniq(
  +                new ClassLoader[] {spiContext.getThreadContextClassLoader(),
  +                                   getCallerClassLoader(rootFinderClass),
  +                                   BootstrapLoader.wrap(spiContext.getSPI().getClassLoader()),
  +                                   BootstrapLoader.wrap(rootFinderClass.getClassLoader()),
  +                                   spiContext.getSystemClassLoader()
  +                                  });
       }
   }
  
  
  
  1.2       +130 -2    jakarta-commons/discovery/src/java/org/apache/commons/discovery/ClassLoaderUtils.java
  
  Index: ClassLoaderUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/discovery/src/java/org/apache/commons/discovery/ClassLoaderUtils.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ClassLoaderUtils.java	9 Jul 2002 18:03:23 -0000	1.1
  +++ ClassLoaderUtils.java	17 Jul 2002 22:03:06 -0000	1.2
  @@ -67,6 +67,8 @@
   import java.io.InputStreamReader;
   import java.util.Properties;
   import java.lang.reflect.Array;
  +import java.lang.reflect.InvocationTargetException;
  +import java.lang.reflect.Method;
   
   
   /**
  @@ -285,15 +287,17 @@
        */
       public static final boolean wouldUseClassLoader(ClassLoader thisClassLoader,
                                                       ClassLoader classLoader) {
  -        if (classLoader == null)
  +        /* bootstrap classloader, at root of all trees! */
  +        if (BootstrapLoader.isBootstrapLoader(classLoader))
               return true;
  -            
  +        
           while (thisClassLoader != null) {
               if (thisClassLoader == classLoader) {
                   return true;
               }
               thisClassLoader = thisClassLoader.getParent();
           }
  +        
           return false;
       }
   
  @@ -356,5 +360,129 @@
           return (name.charAt(0)=='/')
                  ? null
                  : packageName.replace('.','/') + "/" + name;
  +    }
  +
  +    /**
  +     * Return the system class loader if available.
  +     * Otherwise return null.  If the system class loader
  +     * is the bootstrap classloader, then it is 'wrapped'
  +     * (see BootstrapLoader).  Therefore this method only
  +     * returns 'null' if a system class loader could not
  +     * be identified.
  +     * 
  +     * The system class loader is available for JDK 1.2
  +     * or later, if certain security conditions are met.
  +     * 
  +     * @exception ServiceException if a suitable class loader
  +     *            cannot be identified.
  +     */
  +    public static ClassLoader findSystemClassLoader()
  +        throws ServiceException
  +    {
  +        ClassLoader classLoader = null;
  +        
  +        try {
  +            // Are we running on a JDK 1.2 or later system?
  +            Method method = ClassLoader.class.getMethod("getSystemClassLoader", null);
  +    
  +            // Get the system class loader (if there is one)
  +            try {
  +                classLoader =
  +                    BootstrapLoader.wrap((ClassLoader)method.invoke(null, null));
  +            } catch (IllegalAccessException e) {
  +                throw new ServiceException("Unexpected IllegalAccessException", e);
  +            } catch (InvocationTargetException e) {
  +                /**
  +                 * InvocationTargetException is thrown by 'invoke' when
  +                 * the method being invoked (ClassLoader.getSystemClassLoader)
  +                 * throws an exception.
  +                 * 
  +                 * ClassLoader.getSystemClassLoader() throws SecurityException
  +                 * if security permissions are restricted.
  +                 */
  +                if (e.getTargetException() instanceof SecurityException) {
  +                    classLoader = null;  // ignore
  +                } else {
  +                    // Capture 'e.getTargetException()' exception for details
  +                    // alternate: log 'e.getTargetException()', and pass back 'e'.
  +                    throw new ServiceException
  +                        ("Unexpected InvocationTargetException",
  +                         e.getTargetException());
  +                }
  +            }
  +        } catch (NoSuchMethodException e) {
  +            // Assume we are running on JDK 1.1
  +            classLoader = null;
  +        }
  +    
  +        // Return the selected class loader
  +        return classLoader;
  +    }
  +
  +    /**
  +     * Return the thread context class loader if available.
  +     * Otherwise return null.  If the thread context class
  +     * loader is the bootstrap classloader, then it is 'wrapped'
  +     * (see BootstrapLoader).  Therefore this method only
  +     * returns 'null' if a thread context class loader could not
  +     * be identified.
  +     * 
  +     * The thread context class loader is available for JDK 1.2
  +     * or later, if certain security conditions are met.
  +     * 
  +     * @exception ServiceException if a suitable class loader
  +     * cannot be identified.
  +     */
  +    public static ClassLoader findThreadContextClassLoader()
  +        throws ServiceException
  +    {
  +        ClassLoader classLoader = null;
  +        
  +        try {
  +            // Are we running on a JDK 1.2 or later system?
  +            Method method = Thread.class.getMethod("getContextClassLoader", null);
  +    
  +            // Get the thread context class loader (if there is one)
  +            try {
  +                classLoader =
  +                    BootstrapLoader.wrap((ClassLoader)method.invoke(Thread.currentThread(), null));
  +            } catch (IllegalAccessException e) {
  +                throw new ServiceException("Unexpected IllegalAccessException", e);
  +            } catch (InvocationTargetException e) {
  +                /**
  +                 * InvocationTargetException is thrown by 'invoke' when
  +                 * the method being invoked (Thread.getContextClassLoader)
  +                 * throws an exception.
  +                 * 
  +                 * Thread.getContextClassLoader() throws SecurityException
  +                 * when the context class loader isn't an ancestor of the
  +                 * calling class's class loader, or if security permissions
  +                 * are restricted.
  +                 * 
  +                 * In the first case (the context class loader isn't an
  +                 * ancestor of the calling class's class loader), we want
  +                 * to ignore and keep going.  We cannot help but also ignore
  +                 * the second case (restricted security permissions) with
  +                 * the logic below, but other calls elsewhere (to obtain
  +                 * a class loader) will re-trigger this exception where
  +                 * we can make a distinction.
  +                 */
  +                if (e.getTargetException() instanceof SecurityException) {
  +                    classLoader = null;  // ignore
  +                } else {
  +                    // Capture 'e.getTargetException()' exception for details
  +                    // alternate: log 'e.getTargetException()', and pass back 'e'.
  +                    throw new ServiceException
  +                        ("Unexpected InvocationTargetException",
  +                         e.getTargetException());
  +                }
  +            }
  +        } catch (NoSuchMethodException e) {
  +            // Assume we are running on JDK 1.1
  +            classLoader = null;
  +        }
  +    
  +        // Return the selected class loader
  +        return classLoader;
       }
   }
  
  
  
  1.1                  jakarta-commons/discovery/src/java/org/apache/commons/discovery/BootstrapLoader.java
  
  Index: BootstrapLoader.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;
  
  
  /**
   * A wrapper class that gives us a "bootstrap" loader.
   * For the moment, we cheat and return the system class loader.
   * Getting a wrapper for the bootstrap loader that works
   * in JDK 1.1.x may require a bit more work...
   */
  public class BootstrapLoader {
      private static ClassLoader bootstrapLoader =
          null;
      
      private BootstrapLoader() {
      }
      
      public static ClassLoader wrap(ClassLoader incoming) {
          return (incoming == null) ? getBootstrapLoader() : incoming;
      }
      
      public static boolean isBootstrapLoader(ClassLoader incoming) {
          return incoming == null  ||  incoming == getBootstrapLoader();
      }
      
      public static ClassLoader getBootstrapLoader() {
          return bootstrapLoader;
      }
      
      /**
       * JDK 1.1.x compatible?
       * There is no direct way to get the system class loader
       * in 1.1.x, so work around...
       */
      private class SystemClassLoader extends ClassLoader {
          protected Class loadClass(String className, boolean resolve)
              throws ClassNotFoundException
          {
              return findSystemClass(className);
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>