Home » apache-tomcat-6.0.26-src » org.apache » tomcat » util » [javadoc | source]

    1   /*
    2    * $Header: /u/cvs/Projects/EnhydraOrg/enhydra3x/Enhydra/modules/Tomcat/src/share/org/apache/tomcat/util/Attic/NetworkClassLoader.java,v 1.2.2.1.2.1 2001/02/09 09:53:01 markd Exp $
    3    * $Revision: 1.2.2.1.2.1 $
    4    * $Date: 2001/02/09 09:53:01 $
    5    *
    6    * ====================================================================
    7    *
    8    * The Apache Software License, Version 1.1
    9    *
   10    * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   11    * reserved.
   12    *
   13    * Redistribution and use in source and binary forms, with or without
   14    * modification, are permitted provided that the following conditions
   15    * are met:
   16    *
   17    * 1. Redistributions of source code must retain the above copyright
   18    *    notice, this list of conditions and the following disclaimer. 
   19    *
   20    * 2. Redistributions in binary form must reproduce the above copyright
   21    *    notice, this list of conditions and the following disclaimer in
   22    *    the documentation and/or other materials provided with the
   23    *    distribution.
   24    *
   25    * 3. The end-user documentation included with the redistribution, if
   26    *    any, must include the following acknowlegement:  
   27    *       "This product includes software developed by the 
   28    *        Apache Software Foundation (http://www.apache.org/)."
   29    *    Alternately, this acknowlegement may appear in the software itself,
   30    *    if and wherever such third-party acknowlegements normally appear.
   31    *
   32    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   33    *    Foundation" must not be used to endorse or promote products derived
   34    *    from this software without prior written permission. For written 
   35    *    permission, please contact apache@apache.org.
   36    *
   37    * 5. Products derived from this software may not be called "Apache"
   38    *    nor may "Apache" appear in their names without prior written
   39    *    permission of the Apache Group.
   40    *
   41    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   42    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   43    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   44    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   45    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   46    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   47    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   48    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   49    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   50    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   51    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   52    * SUCH DAMAGE.
   53    * ====================================================================
   54    *
   55    * This software consists of voluntary contributions made by many
   56    * individuals on behalf of the Apache Software Foundation.  For more
   57    * information on the Apache Software Foundation, please see
   58    * <http://www.apache.org/>.
   59    *
   60    * [Additional notices, if required by prior licensing conditions]
   61    *
   62    */ 
   63   
   64   package org.apache.tomcat.util;
   65   
   66   import java.util.zip;
   67   import java.net;
   68   import java.util;
   69   import java.io;
   70   
   71   /**
   72    * The correct name for this class should be URLClassLoader.
   73    * But there is already a class by that name in JDK1.2.
   74    *
   75    * I have had quite a few problems with URLClassLoader in
   76    * past, so I ended up writing this ClassLoader. I found that
   77    * the Java 2's URLClassLoader, does not close the Jar file once
   78    * opened. It is a pretty good optimization step, but if you
   79    * modify the class in the jar file, it does not pick it up. Some
   80    * operating systems may not let you modify the jar file while it is
   81    * still open. IMHO, it does make sense to close the jar file
   82    * after you are done reading the class data. But this approach may not
   83    * get you the performance of the URLClassLoader, but it works in all
   84    * cases and also runs on JDK1.1. I have enhanced this class loader
   85    * to read all the zip/jar entries once & cache the data, so that
   86    * there is no overhead of opening/closing jar file to pick up
   87    * each entry.
   88    *
   89    *
   90    * @author Harish Prabandham
   91    */
   92   public class NetworkClassLoader extends ClassLoader {
   93       private ClassLoader parent = null; // parent classloader
   94       private Hashtable classCache = new Hashtable();
   95       private Hashtable urlset = new Hashtable();
   96   
   97       /**
   98        * Creates a new instance of the class loader.
   99        * @param delegate/parent class loader.
  100        */
  101       public NetworkClassLoader(ClassLoader parent) {
  102           setParent(parent);
  103       }
  104   
  105       /**
  106        * Sets the parent/delegate class loader.
  107        * @param delegate/parent class loader.
  108        */
  109       protected final void setParent(ClassLoader parent) {
  110           this.parent = parent;
  111       }
  112   
  113       /**
  114        * Adds the given URL to this class loader. If the URL
  115        * ends with "/", then it is assumed to be a directory
  116        * otherwise, it is assumed to be a zip/jar file. If the
  117        * same URL is added again, the URL is re-opened and this
  118        * zip/jar file is used for serving any future class requests.
  119        * @param URL where to look for the classes.
  120        */
  121       public synchronized void addURL(URL url) {
  122           // System.out.println("Adding url: " + url);
  123           if(!urlset.containsKey(url)) {
  124               try {
  125                   urlset.put(url, new URLResourceReader(url));
  126               }catch(IOException ioe){
  127                   // Probably a bad url...
  128               }
  129           } else {
  130               // remove the old one & add a new one...
  131               try{
  132                   URLResourceReader newu = new URLResourceReader(url);
  133                   URLResourceReader oldu = (URLResourceReader) urlset.get(url);
  134                   oldu.close();
  135                   urlset.remove(url);
  136                   urlset.put(url, newu);
  137               } catch (IOException ioe) {
  138               }
  139           }
  140       }
  141   
  142       /**
  143        * @return An enumeration of  URLs where this class loader
  144        * looks for classes.
  145        */
  146       public Enumeration getURLs() {
  147           return urlset.keys();
  148       }
  149   
  150       private byte[] loadResource(URL url, String resourceName)
  151           throws IOException {
  152           URLResourceReader urr = (URLResourceReader) urlset.get(url);
  153           if(urr != null) {
  154               return urr.getResource(resourceName);
  155           }
  156   
  157           return null;
  158       }
  159   
  160       private byte[] loadResource(String resource) {
  161           byte[] barray = null;
  162           for(Enumeration e = urlset.keys(); e.hasMoreElements();) {
  163               URL url = (URL) e.nextElement();
  164   
  165               try {
  166                   barray = loadResource(url, resource);
  167               } catch(Exception ex) {
  168               } finally {
  169                   if(barray != null)
  170                       break;
  171               }
  172           }
  173   
  174           return barray;
  175       }
  176   
  177       private byte[] loadClassData(String classname) {
  178           String resourceName = classname.replace('.', '/') + ".class";
  179           return loadResource(resourceName);
  180       }
  181   
  182       /**
  183        * @return The resource as the input stream if such a resource
  184        * exists, otherwise returns null.
  185        */
  186       public InputStream getResourceAsStream(String name) {
  187           InputStream istream = null;
  188           
  189           // Algorithm:
  190           //
  191           // 1. first check the system path for the resource
  192           // 2. next  check the  delegate/parent class loader for the resource
  193           // 3. then attempt to get the resource from the url set.
  194           //
  195   
  196           // Lets check the system path for the resource.
  197           istream = getSystemResourceAsStream(name);
  198           if(istream != null)
  199               return istream;
  200   
  201           // Lets check the parent/delegate class loader for the resource.
  202           if(parent != null) {
  203               istream = parent.getResourceAsStream(name);
  204               if(istream != null)
  205                   return istream;
  206           }
  207   
  208           // Lets load it ourselves.
  209           byte[] data = loadResource(name);
  210           if(data != null) {
  211               istream = new ByteArrayInputStream(data);
  212           }
  213   
  214           return istream;
  215       }
  216   
  217       /**
  218        * java.lang.ClassLoader's defineClass method is final, so the
  219        * its subclasses cannot override this method. But, this class
  220        * calls this method in the loadClass() instead.
  221        * @param The name of the class without ".class" extension.
  222        * @param The class data bytes.
  223        * @return The class object.
  224        */
  225       protected Class defineClass(String classname, byte[] classdata) {
  226           return defineClass(classname, classdata, 0, classdata.length);
  227       }
  228   
  229       protected synchronized Class loadClass(String name, boolean resolve)
  230           throws ClassNotFoundException {
  231           Class c = null;
  232   
  233           // Algorithm: (Please do not change the order; unless you
  234           // have a good reason to do so).
  235           //
  236           // 1. first check the system class loader.
  237           // 2. next  check the  delegate/parent class loader.
  238           // 3. next  check the class cache
  239           // 4. then attempt to load classes from the URL set.
  240           //
  241           
  242           // Lets see if the class is in system class loader.
  243           try {
  244               c = findSystemClass(name);
  245           }catch(ClassNotFoundException cnfe) {
  246           }finally {
  247               if(c != null)
  248                   return c;
  249           }
  250   
  251           // Lets see if the class is in parent class loader.
  252           try {
  253               if(parent != null)
  254                   c = parent.loadClass(name);
  255           }catch(ClassNotFoundException cnfe) {
  256           }finally {
  257               if(c != null)
  258                   return c;
  259           }
  260   
  261           // Lets see if the class is in the cache..
  262           c = (Class) classCache.get(name);
  263   
  264           if(c != null)
  265               return c;
  266   
  267   
  268           // Lets see if we find the class all by ourselves.
  269           byte[] data = loadClassData(name);
  270   
  271           if(data != null) {
  272               // we did !!
  273               c = defineClass(name, data);
  274               classCache.put(name, c);
  275               if(resolve)
  276                   resolveClass(c);
  277           } else {
  278               // We are out of luck at this point...
  279               throw new ClassNotFoundException(name);
  280           }
  281   
  282           return c;
  283       }
  284   
  285       /**
  286        * This method resets this ClassLoader's state. It completely
  287        * removes all the URLs and classes in this class loader cache. 
  288        */
  289       protected final void clear() {
  290           urlset.clear();
  291           classCache.clear();
  292       }
  293   
  294       /**
  295        * This method resets this ClassLoader's state and resets the
  296        * references for garbage collection.
  297        */
  298       protected void finalize() throws Throwable {
  299           // Cleanup real well. Otherwise, this can be
  300           // a major source of memory leaks...
  301   
  302           // remove all the urls & class entries.
  303           clear();
  304           
  305           parent = null;
  306           urlset = null;
  307           classCache = null;
  308       }
  309   
  310   
  311       // Added for enhydra:
  312   
  313       /**
  314        * @see ClassLoader#findResource(String)
  315        */
  316       protected URL findResource(String name) {
  317           for(Enumeration e = urlset.keys(); e.hasMoreElements();) {
  318               URL url = (URL) e.nextElement();
  319               
  320               try {
  321                   URL realURL = new URL(url.getProtocol(), url.getHost(),
  322                                     url.getFile() + name);
  323                   File urlFile = new File(realURL.getFile());
  324                   if (urlFile.exists()) {
  325                       return realURL;
  326                   }
  327               } catch (MalformedURLException except) {
  328                   // Ignore invalid CLASSPATH entries 
  329               }
  330           }
  331   
  332           return null;
  333       }
  334   
  335   }
  336   
  337   
  338   
  339   
  340   
  341   
  342   
  343   
  344   
  345   
  346   
  347   

Home » apache-tomcat-6.0.26-src » org.apache » tomcat » util » [javadoc | source]