Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2.util » [javadoc | source]
    1   /*
    2    * Copyright (c) 2002-2003 by OpenSymphony
    3    * All rights reserved.
    4    */
    5   package com.opensymphony.xwork2.util;
    6   
    7   import java.io.IOException;
    8   import java.io.InputStream;
    9   
   10   import java.net.URL;
   11   import java.util;
   12   
   13   
   14   /**
   15    * This class is extremely useful for loading resources and classes in a fault tolerant manner
   16    * that works across different applications servers.
   17    *
   18    * It has come out of many months of frustrating use of multiple application servers at Atlassian,
   19    * please don't change things unless you're sure they're not going to break in one server or another!
   20    * 
   21    * It was brought in from oscore trunk revision 147.
   22    *
   23    * @author $Author: hani $
   24    * @version $Revision: 117 $
   25    */
   26   public class ClassLoaderUtil {
   27       //~ Methods ////////////////////////////////////////////////////////////////
   28   
   29       /**
   30        * Load all resources with a given name, potentially aggregating all results 
   31        * from the searched classloaders.  If no results are found, the resource name
   32        * is prepended by '/' and tried again.
   33        *
   34        * This method will try to load the resources using the following methods (in order):
   35        * <ul>
   36        *  <li>From Thread.currentThread().getContextClassLoader()
   37        *  <li>From ClassLoaderUtil.class.getClassLoader()
   38        *  <li>callingClass.getClassLoader()
   39        * </ul>
   40        *
   41        * @param resourceName The name of the resources to load
   42        * @param callingClass The Class object of the calling object
   43        */
   44        public static Iterator<URL> getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {
   45   
   46            AggregateIterator<URL> iterator = new AggregateIterator<URL>();
   47   
   48            iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
   49   
   50            if (!iterator.hasNext() || aggregate) {
   51                iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
   52            }
   53   
   54            if (!iterator.hasNext() || aggregate) {
   55                ClassLoader cl = callingClass.getClassLoader();
   56   
   57                if (cl != null) {
   58                    iterator.addEnumeration(cl.getResources(resourceName));
   59                }
   60            }
   61   
   62            if (!iterator.hasNext() && (resourceName != null) && (resourceName.charAt(0) != '/')) {
   63                return getResources('/' + resourceName, callingClass, aggregate);
   64            }
   65   
   66            return iterator;
   67        }
   68   
   69       /**
   70       * Load a given resource.
   71       *
   72       * This method will try to load the resource using the following methods (in order):
   73       * <ul>
   74       *  <li>From Thread.currentThread().getContextClassLoader()
   75       *  <li>From ClassLoaderUtil.class.getClassLoader()
   76       *  <li>callingClass.getClassLoader()
   77       * </ul>
   78       *
   79       * @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
   80       * @param callingClass The Class object of the calling object
   81       */
   82       public static URL getResource(String resourceName, Class callingClass) {
   83           URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
   84   
   85           if (url == null) {
   86               url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
   87           }
   88   
   89           if (url == null) {
   90               ClassLoader cl = callingClass.getClassLoader();
   91   
   92               if (cl != null) {
   93                   url = cl.getResource(resourceName);
   94               }
   95           }
   96   
   97           if ((url == null) && (resourceName != null) && (resourceName.charAt(0) != '/')) {
   98               return getResource('/' + resourceName, callingClass);
   99           }
  100   
  101           return url;
  102       }
  103   
  104       /**
  105       * This is a convenience method to load a resource as a stream.
  106       *
  107       * The algorithm used to find the resource is given in getResource()
  108       *
  109       * @param resourceName The name of the resource to load
  110       * @param callingClass The Class object of the calling object
  111       */
  112       public static InputStream getResourceAsStream(String resourceName, Class callingClass) {
  113           URL url = getResource(resourceName, callingClass);
  114   
  115           try {
  116               return (url != null) ? url.openStream() : null;
  117           } catch (IOException e) {
  118               return null;
  119           }
  120       }
  121   
  122       /**
  123       * Load a class with a given name.
  124       *
  125       * It will try to load the class in the following order:
  126       * <ul>
  127       *  <li>From Thread.currentThread().getContextClassLoader()
  128       *  <li>Using the basic Class.forName()
  129       *  <li>From ClassLoaderUtil.class.getClassLoader()
  130       *  <li>From the callingClass.getClassLoader()
  131       * </ul>
  132       *
  133       * @param className The name of the class to load
  134       * @param callingClass The Class object of the calling object
  135       * @throws ClassNotFoundException If the class cannot be found anywhere.
  136       */
  137       public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {
  138           try {
  139               return Thread.currentThread().getContextClassLoader().loadClass(className);
  140           } catch (ClassNotFoundException e) {
  141               try {
  142                   return Class.forName(className);
  143               } catch (ClassNotFoundException ex) {
  144                   try {
  145                       return ClassLoaderUtil.class.getClassLoader().loadClass(className);
  146                   } catch (ClassNotFoundException exc) {
  147                       return callingClass.getClassLoader().loadClass(className);
  148                   }
  149               }
  150           }
  151       }
  152   
  153       /**
  154        * Aggregates Enumeration instances into one iterator and filters out duplicates.  Always keeps one
  155        * ahead of the enumerator to protect against returning duplicates.
  156        */
  157       protected static class AggregateIterator<E> implements Iterator<E> {
  158   
  159           LinkedList<Enumeration<E>> enums = new LinkedList<Enumeration<E>>();
  160           Enumeration<E> cur = null;
  161           E next = null;
  162           Set<E> loaded = new HashSet<E>();
  163   
  164           public AggregateIterator addEnumeration(Enumeration<E> e) {
  165               if (e.hasMoreElements()) {
  166                   if (cur == null) {
  167                       cur = e;
  168                       next = e.nextElement();
  169                       loaded.add(next);
  170                   } else {
  171                       enums.add(e);
  172                   }
  173               }
  174               return this;
  175           }
  176   
  177           public boolean hasNext() {
  178               return (next != null);
  179           }
  180   
  181           public E next() {
  182               if (next != null) {
  183                   E prev = next;
  184                   next = loadNext();
  185                   return prev;
  186               } else {
  187                   throw new NoSuchElementException();
  188               }
  189           }
  190   
  191           private Enumeration<E> determineCurrentEnumeration() {
  192               if (cur != null && !cur.hasMoreElements()) {
  193                   if (enums.size() > 0) {
  194                       cur = enums.removeLast();
  195                   } else {
  196                       cur = null;
  197                   }
  198               }
  199               return cur;
  200           }
  201   
  202           private E loadNext() {
  203               if (determineCurrentEnumeration() != null) {
  204                   E tmp = cur.nextElement();
  205                   while (loaded.contains(tmp)) {
  206                       tmp = loadNext();
  207                       if (tmp == null) {
  208                           break;
  209                       }
  210                   }
  211                   if (tmp != null) {
  212                       loaded.add(tmp);
  213                   }
  214                   return tmp;
  215               }
  216               return null;
  217   
  218           }
  219   
  220           public void remove() {
  221               throw new UnsupportedOperationException();
  222           }
  223       }
  224   }

Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2.util » [javadoc | source]