Home » apache-ant-1.7.1-src » org.apache.tools » ant » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    *
   17    */
   18   
   19   package org.apache.tools.ant;
   20   
   21   import java.io.ByteArrayOutputStream;
   22   import java.io.File;
   23   import java.io.FileInputStream;
   24   import java.io.IOException;
   25   import java.io.InputStream;
   26   import java.io.InputStreamReader;
   27   import java.io.Reader;
   28   import java.lang.reflect.Constructor;
   29   import java.net.MalformedURLException;
   30   import java.net.URL;
   31   import java.util.Collections;
   32   import java.util.Enumeration;
   33   import java.util.HashMap;
   34   import java.util.Hashtable;
   35   import java.util.Map;
   36   import java.util.StringTokenizer;
   37   import java.util.Vector;
   38   import java.util.Locale;
   39   import java.util.jar.Attributes;
   40   import java.util.jar.Attributes.Name;
   41   import java.util.jar.JarFile;
   42   import java.util.jar.Manifest;
   43   import java.util.zip.ZipEntry;
   44   import java.util.zip.ZipFile;
   45   import org.apache.tools.ant.types.Path;
   46   import org.apache.tools.ant.util.CollectionUtils;
   47   import org.apache.tools.ant.util.FileUtils;
   48   import org.apache.tools.ant.util.JavaEnvUtils;
   49   import org.apache.tools.ant.util.LoaderUtils;
   50   import org.apache.tools.ant.launch.Locator;
   51   
   52   /**
   53    * Used to load classes within ant with a different classpath from
   54    * that used to start ant. Note that it is possible to force a class
   55    * into this loader even when that class is on the system classpath by
   56    * using the forceLoadClass method. Any subsequent classes loaded by that
   57    * class will then use this loader rather than the system class loader.
   58    *
   59    * <p>
   60    * Note that this classloader has a feature to allow loading
   61    * in reverse order and for "isolation".
   62    * Due to the fact that a number of
   63    * methods in java.lang.ClassLoader are final (at least
   64    * in java 1.4 getResources) this means that the
   65    * class has to fake the given parent.
   66    * </p>
   67    *
   68    */
   69   public class AntClassLoader extends ClassLoader implements SubBuildListener {
   70   
   71       private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
   72   
   73       /**
   74        * An enumeration of all resources of a given name found within the
   75        * classpath of this class loader. This enumeration is used by the
   76        * ClassLoader.findResources method, which is in
   77        * turn used by the ClassLoader.getResources method.
   78        *
   79        * @see AntClassLoader#findResources(String)
   80        * @see java.lang.ClassLoader#getResources(String)
   81        */
   82       private class ResourceEnumeration implements Enumeration {
   83           /**
   84            * The name of the resource being searched for.
   85            */
   86           private String resourceName;
   87   
   88           /**
   89            * The index of the next classpath element to search.
   90            */
   91           private int pathElementsIndex;
   92   
   93           /**
   94            * The URL of the next resource to return in the enumeration. If this
   95            * field is <code>null</code> then the enumeration has been completed,
   96            * i.e., there are no more elements to return.
   97            */
   98           private URL nextResource;
   99   
  100           /**
  101            * Constructs a new enumeration of resources of the given name found
  102            * within this class loader's classpath.
  103            *
  104            * @param name the name of the resource to search for.
  105            */
  106           ResourceEnumeration(String name) {
  107               this.resourceName = name;
  108               this.pathElementsIndex = 0;
  109               findNextResource();
  110           }
  111   
  112           /**
  113            * Indicates whether there are more elements in the enumeration to
  114            * return.
  115            *
  116            * @return <code>true</code> if there are more elements in the
  117            *         enumeration; <code>false</code> otherwise.
  118            */
  119           public boolean hasMoreElements() {
  120               return (this.nextResource != null);
  121           }
  122   
  123           /**
  124            * Returns the next resource in the enumeration.
  125            *
  126            * @return the next resource in the enumeration
  127            */
  128           public Object nextElement() {
  129               URL ret = this.nextResource;
  130               findNextResource();
  131               return ret;
  132           }
  133   
  134           /**
  135            * Locates the next resource of the correct name in the classpath and
  136            * sets <code>nextResource</code> to the URL of that resource. If no
  137            * more resources can be found, <code>nextResource</code> is set to
  138            * <code>null</code>.
  139            */
  140           private void findNextResource() {
  141               URL url = null;
  142               while ((pathElementsIndex < pathComponents.size())
  143                      && (url == null)) {
  144                   try {
  145                       File pathComponent
  146                           = (File) pathComponents.elementAt(pathElementsIndex);
  147                       url = getResourceURL(pathComponent, this.resourceName);
  148                       pathElementsIndex++;
  149                   } catch (BuildException e) {
  150                       // ignore path elements which are not valid relative to the
  151                       // project
  152                   }
  153               }
  154               this.nextResource = url;
  155           }
  156       }
  157   
  158       /**
  159        * The size of buffers to be used in this classloader.
  160        */
  161       private static final int BUFFER_SIZE = 8192;
  162       /**
  163        * Number of array elements in a test array of strings
  164        */
  165       private static final int NUMBER_OF_STRINGS = 256;
  166   
  167       /**
  168        * The components of the classpath that the classloader searches
  169        * for classes.
  170        */
  171       private Vector pathComponents  = new Vector();
  172   
  173       /**
  174        * The project to which this class loader belongs.
  175        */
  176       private Project project;
  177   
  178       /**
  179        * Indicates whether the parent class loader should be
  180        * consulted before trying to load with this class loader.
  181        */
  182       private boolean parentFirst = true;
  183   
  184       /**
  185        * These are the package roots that are to be loaded by the parent class
  186        * loader regardless of whether the parent class loader is being searched
  187        * first or not.
  188        */
  189       private Vector systemPackages = new Vector();
  190   
  191       /**
  192        * These are the package roots that are to be loaded by this class loader
  193        * regardless of whether the parent class loader is being searched first
  194        * or not.
  195        */
  196       private Vector loaderPackages = new Vector();
  197   
  198       /**
  199        * Whether or not this classloader will ignore the base
  200        * classloader if it can't find a class.
  201        *
  202        * @see #setIsolated(boolean)
  203        */
  204       private boolean ignoreBase = false;
  205   
  206       /**
  207        * The parent class loader, if one is given or can be determined.
  208        */
  209       private ClassLoader parent = null;
  210   
  211       /**
  212        * A hashtable of zip files opened by the classloader (File to ZipFile).
  213        */
  214       private Hashtable zipFiles = new Hashtable();
  215   
  216       /** Static map of jar file/time to manifest class-path entries */
  217       private static Map/*<String,String>*/ pathMap = Collections.synchronizedMap(new HashMap());
  218   
  219       /**
  220        * The context loader saved when setting the thread's current
  221        * context loader.
  222        */
  223       private ClassLoader savedContextLoader = null;
  224       /**
  225        * Whether or not the context loader is currently saved.
  226        */
  227       private boolean isContextLoaderSaved = false;
  228   
  229       /**
  230        * Create an Ant ClassLoader for a given project, with
  231        * a parent classloader and an initial classpath.
  232        * @since Ant 1.7.
  233        * @param parent the parent for this classloader.
  234        * @param project The project to which this classloader is to
  235        *                belong.
  236        * @param classpath The classpath to use to load classes.
  237        */
  238       public AntClassLoader(
  239           ClassLoader parent, Project project, Path classpath) {
  240           setParent(parent);
  241           setClassPath(classpath);
  242           setProject(project);
  243       }
  244   
  245       /**
  246        * Create an Ant Class Loader
  247        */
  248       public AntClassLoader() {
  249           setParent(null);
  250       }
  251   
  252       /**
  253        * Creates a classloader for the given project using the classpath given.
  254        *
  255        * @param project The project to which this classloader is to belong.
  256        *                Must not be <code>null</code>.
  257        * @param classpath The classpath to use to load the classes.  This
  258        *                is combined with the system classpath in a manner
  259        *                determined by the value of ${build.sysclasspath}.
  260        *                May be <code>null</code>, in which case no path
  261        *                elements are set up to start with.
  262        */
  263       public AntClassLoader(Project project, Path classpath) {
  264           setParent(null);
  265           setProject(project);
  266           setClassPath(classpath);
  267       }
  268   
  269       /**
  270        * Creates a classloader for the given project using the classpath given.
  271        *
  272        * @param parent The parent classloader to which unsatisfied loading
  273        *               attempts are delegated. May be <code>null</code>,
  274        *               in which case the classloader which loaded this
  275        *               class is used as the parent.
  276        * @param project The project to which this classloader is to belong.
  277        *                Must not be <code>null</code>.
  278        * @param classpath the classpath to use to load the classes.
  279        *                  May be <code>null</code>, in which case no path
  280        *                  elements are set up to start with.
  281        * @param parentFirst If <code>true</code>, indicates that the parent
  282        *                    classloader should be consulted  before trying to
  283        *                    load the a class through this loader.
  284        */
  285       public AntClassLoader(ClassLoader parent, Project project, Path classpath,
  286                             boolean parentFirst) {
  287           this(project, classpath);
  288           if (parent != null) {
  289               setParent(parent);
  290           }
  291           setParentFirst(parentFirst);
  292           addJavaLibraries();
  293       }
  294   
  295   
  296       /**
  297        * Creates a classloader for the given project using the classpath given.
  298        *
  299        * @param project The project to which this classloader is to belong.
  300        *                Must not be <code>null</code>.
  301        * @param classpath The classpath to use to load the classes. May be
  302        *                  <code>null</code>, in which case no path
  303        *                  elements are set up to start with.
  304        * @param parentFirst If <code>true</code>, indicates that the parent
  305        *                    classloader should be consulted before trying to
  306        *                    load the a class through this loader.
  307        */
  308       public AntClassLoader(Project project, Path classpath,
  309                             boolean parentFirst) {
  310           this(null, project, classpath, parentFirst);
  311       }
  312   
  313       /**
  314        * Creates an empty class loader. The classloader should be configured
  315        * with path elements to specify where the loader is to look for
  316        * classes.
  317        *
  318        * @param parent The parent classloader to which unsatisfied loading
  319        *               attempts are delegated. May be <code>null</code>,
  320        *               in which case the classloader which loaded this
  321        *               class is used as the parent.
  322        * @param parentFirst If <code>true</code>, indicates that the parent
  323        *                    classloader should be consulted before trying to
  324        *                    load the a class through this loader.
  325        */
  326       public AntClassLoader(ClassLoader parent, boolean parentFirst) {
  327           setParent(parent);
  328           project = null;
  329           this.parentFirst = parentFirst;
  330       }
  331   
  332       /**
  333        * Set the project associated with this class loader
  334        *
  335        * @param project the project instance
  336        */
  337       public void setProject(Project project) {
  338           this.project = project;
  339           if (project != null) {
  340               project.addBuildListener(this);
  341           }
  342       }
  343   
  344       /**
  345        * Set the classpath to search for classes to load. This should not be
  346        * changed once the classloader starts to server classes
  347        *
  348        * @param classpath the search classpath consisting of directories and
  349        *        jar/zip files.
  350        */
  351       public void setClassPath(Path classpath) {
  352           pathComponents.removeAllElements();
  353           if (classpath != null) {
  354               Path actualClasspath = classpath.concatSystemClasspath("ignore");
  355               String[] pathElements = actualClasspath.list();
  356               for (int i = 0; i < pathElements.length; ++i) {
  357                   try {
  358                       addPathElement(pathElements[i]);
  359                   } catch (BuildException e) {
  360                       // ignore path elements which are invalid
  361                       // relative to the project
  362                   }
  363               }
  364           }
  365       }
  366   
  367       /**
  368        * Set the parent for this class loader. This is the class loader to which
  369        * this class loader will delegate to load classes
  370        *
  371        * @param parent the parent class loader.
  372        */
  373       public void setParent(ClassLoader parent) {
  374           if (parent == null) {
  375               this.parent = AntClassLoader.class.getClassLoader();
  376           } else {
  377               this.parent = parent;
  378           }
  379       }
  380   
  381       /**
  382        * Control whether class lookup is delegated to the parent loader first
  383        * or after this loader. Use with extreme caution. Setting this to
  384        * false violates the class loader hierarchy and can lead to Linkage errors
  385        *
  386        * @param parentFirst if true, delegate initial class search to the parent
  387        *                    classloader.
  388        */
  389       public void setParentFirst(boolean parentFirst) {
  390           this.parentFirst = parentFirst;
  391       }
  392   
  393   
  394       /**
  395        * Logs a message through the project object if one has been provided.
  396        *
  397        * @param message The message to log.
  398        *                Should not be <code>null</code>.
  399        *
  400        * @param priority The logging priority of the message.
  401        */
  402       protected void log(String message, int priority) {
  403           if (project != null) {
  404               project.log(message, priority);
  405           }
  406           //         else {
  407           //             System.out.println(message);
  408           //         }
  409       }
  410   
  411       /**
  412        * Sets the current thread's context loader to this classloader, storing
  413        * the current loader value for later resetting.
  414        */
  415       public void setThreadContextLoader() {
  416           if (isContextLoaderSaved) {
  417               throw new BuildException("Context loader has not been reset");
  418           }
  419           if (LoaderUtils.isContextLoaderAvailable()) {
  420               savedContextLoader = LoaderUtils.getContextClassLoader();
  421               ClassLoader loader = this;
  422               if (project != null
  423                   && "only".equals(project.getProperty("build.sysclasspath"))) {
  424                   loader = this.getClass().getClassLoader();
  425               }
  426               LoaderUtils.setContextClassLoader(loader);
  427               isContextLoaderSaved = true;
  428           }
  429       }
  430   
  431       /**
  432        * Resets the current thread's context loader to its original value.
  433        */
  434       public void resetThreadContextLoader() {
  435           if (LoaderUtils.isContextLoaderAvailable()
  436               && isContextLoaderSaved) {
  437               LoaderUtils.setContextClassLoader(savedContextLoader);
  438               savedContextLoader = null;
  439               isContextLoaderSaved = false;
  440           }
  441       }
  442   
  443   
  444       /**
  445        * Adds an element to the classpath to be searched.
  446        *
  447        * @param pathElement The path element to add. Must not be
  448        *                    <code>null</code>.
  449        *
  450        * @exception BuildException if the given path element cannot be resolved
  451        *                           against the project.
  452        */
  453       public void addPathElement(String pathElement) throws BuildException {
  454           File pathComponent
  455               = project != null ? project.resolveFile(pathElement)
  456               : new File(pathElement);
  457           try {
  458               addPathFile(pathComponent);
  459           } catch (IOException e) {
  460               throw new BuildException(e);
  461           }
  462       }
  463   
  464       /**
  465        * Add a path component.
  466        * This simply adds the file, unlike addPathElement
  467        * it does not open jar files and load files from
  468        * their CLASSPATH entry in the manifest file.
  469        * @param file the jar file or directory to add.
  470        */
  471       public void addPathComponent(File file) {
  472           if (pathComponents.contains(file)) {
  473               return;
  474           }
  475           pathComponents.addElement(file);
  476       }
  477   
  478       /**
  479        * Add a file to the path.
  480        * Reads the manifest, if available, and adds any additional class path jars
  481        * specified in the manifest.
  482        *
  483        * @param pathComponent the file which is to be added to the path for
  484        *                      this class loader
  485        *
  486        * @throws IOException if data needed from the file cannot be read.
  487        */
  488       protected void addPathFile(File pathComponent) throws IOException {
  489           pathComponents.addElement(pathComponent);
  490           if (pathComponent.isDirectory()) {
  491               return;
  492           }
  493   
  494           String absPathPlusTimeAndLength =
  495               pathComponent.getAbsolutePath() + pathComponent.lastModified() + "-"
  496               + pathComponent.length();
  497           String classpath = (String) pathMap.get(absPathPlusTimeAndLength);
  498           if (classpath == null) {
  499               ZipFile jarFile = null;
  500               InputStream manifestStream = null;
  501               try {
  502                   jarFile = new ZipFile(pathComponent);
  503                   manifestStream
  504                       = jarFile.getInputStream(new ZipEntry("META-INF/MANIFEST.MF"));
  505   
  506                   if (manifestStream == null) {
  507                       return;
  508                   }
  509                   Reader manifestReader
  510                       = new InputStreamReader(manifestStream, "UTF-8");
  511                   org.apache.tools.ant.taskdefs.Manifest manifest
  512                       = new org.apache.tools.ant.taskdefs.Manifest(manifestReader);
  513                   classpath
  514                       = manifest.getMainSection().getAttributeValue("Class-Path");
  515   
  516               } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
  517                   // ignore
  518               } finally {
  519                   FileUtils.close(manifestStream);
  520                   if (jarFile != null) {
  521                       jarFile.close();
  522                   }
  523               }
  524               if (classpath == null) {
  525                   classpath = "";
  526               }
  527               pathMap.put(absPathPlusTimeAndLength, classpath);
  528           }
  529   
  530           if (!"".equals(classpath)) {
  531               URL baseURL = FILE_UTILS.getFileURL(pathComponent);
  532               StringTokenizer st = new StringTokenizer(classpath);
  533               while (st.hasMoreTokens()) {
  534                   String classpathElement = st.nextToken();
  535                   URL libraryURL = new URL(baseURL, classpathElement);
  536                   if (!libraryURL.getProtocol().equals("file")) {
  537                       log("Skipping jar library " + classpathElement
  538                           + " since only relative URLs are supported by this"
  539                           + " loader", Project.MSG_VERBOSE);
  540                       continue;
  541                   }
  542                   String decodedPath = Locator.decodeUri(libraryURL.getFile());
  543                   File libraryFile = new File(decodedPath);
  544                   if (libraryFile.exists() && !isInPath(libraryFile)) {
  545                       addPathFile(libraryFile);
  546                   }
  547               }
  548           }
  549       }
  550   
  551       /**
  552        * Returns the classpath this classloader will consult.
  553        *
  554        * @return the classpath used for this classloader, with elements
  555        *         separated by the path separator for the system.
  556        */
  557       public String getClasspath() {
  558           StringBuffer sb = new StringBuffer();
  559           boolean firstPass = true;
  560           Enumeration componentEnum = pathComponents.elements();
  561           while (componentEnum.hasMoreElements()) {
  562               if (!firstPass) {
  563                   sb.append(System.getProperty("path.separator"));
  564               } else {
  565                   firstPass = false;
  566               }
  567               sb.append(((File) componentEnum.nextElement()).getAbsolutePath());
  568           }
  569           return sb.toString();
  570       }
  571   
  572       /**
  573        * Sets whether this classloader should run in isolated mode. In
  574        * isolated mode, classes not found on the given classpath will
  575        * not be referred to the parent class loader but will cause a
  576        * ClassNotFoundException.
  577        *
  578        * @param isolated Whether or not this classloader should run in
  579        *                 isolated mode.
  580        */
  581       public synchronized void setIsolated(boolean isolated) {
  582           ignoreBase = isolated;
  583       }
  584   
  585       /**
  586        * Forces initialization of a class in a JDK 1.1 compatible, albeit hacky
  587        * way.
  588        *
  589        * @param theClass The class to initialize.
  590        *                 Must not be <code>null</code>.
  591        *
  592        * @deprecated since 1.6.x.
  593        *             Use Class.forName with initialize=true instead.
  594        */
  595       public static void initializeClass(Class theClass) {
  596           // ***HACK*** We ask the VM to create an instance
  597           // by voluntarily providing illegal arguments to force
  598           // the VM to run the class' static initializer, while
  599           // at the same time not running a valid constructor.
  600   
  601           final Constructor[] cons = theClass.getDeclaredConstructors();
  602           //At least one constructor is guaranteed to be there, but check anyway.
  603           if (cons != null) {
  604               if (cons.length > 0 && cons[0] != null) {
  605                   final String[] strs = new String[NUMBER_OF_STRINGS];
  606                   try {
  607                       cons[0].newInstance((Object[]) strs);
  608                       // Expecting an exception to be thrown by this call:
  609                       // IllegalArgumentException: wrong number of Arguments
  610                   } catch (Exception e) {
  611                       // Ignore - we are interested only in the side
  612                       // effect - that of getting the static initializers
  613                       // invoked.  As we do not want to call a valid
  614                       // constructor to get this side effect, an
  615                       // attempt is made to call a hopefully
  616                       // invalid constructor - come on, nobody
  617                       // would have a constructor that takes in
  618                       // 256 String arguments ;-)
  619                       // (In fact, they can't - according to JVM spec
  620                       // section 4.10, the number of method parameters is limited
  621                       // to 255 by the definition of a method descriptor.
  622                       // Constructors count as methods here.)
  623                   }
  624               }
  625           }
  626       }
  627   
  628       /**
  629        * Adds a package root to the list of packages which must be loaded on the
  630        * parent loader.
  631        *
  632        * All subpackages are also included.
  633        *
  634        * @param packageRoot The root of all packages to be included.
  635        *                    Should not be <code>null</code>.
  636        */
  637       public void addSystemPackageRoot(String packageRoot) {
  638           systemPackages.addElement(packageRoot
  639                                     + (packageRoot.endsWith(".") ? "" : "."));
  640       }
  641   
  642       /**
  643        * Adds a package root to the list of packages which must be loaded using
  644        * this loader.
  645        *
  646        * All subpackages are also included.
  647        *
  648        * @param packageRoot The root of all packages to be included.
  649        *                    Should not be <code>null</code>.
  650        */
  651       public void addLoaderPackageRoot(String packageRoot) {
  652           loaderPackages.addElement(packageRoot
  653                                     + (packageRoot.endsWith(".") ? "" : "."));
  654       }
  655   
  656       /**
  657        * Loads a class through this class loader even if that class is available
  658        * on the parent classpath.
  659        *
  660        * This ensures that any classes which are loaded by the returned class
  661        * will use this classloader.
  662        *
  663        * @param classname The name of the class to be loaded.
  664        *                  Must not be <code>null</code>.
  665        *
  666        * @return the required Class object
  667        *
  668        * @exception ClassNotFoundException if the requested class does not exist
  669        *                                   on this loader's classpath.
  670        */
  671       public Class forceLoadClass(String classname)
  672           throws ClassNotFoundException {
  673           log("force loading " + classname, Project.MSG_DEBUG);
  674   
  675           Class theClass = findLoadedClass(classname);
  676   
  677           if (theClass == null) {
  678               theClass = findClass(classname);
  679           }
  680   
  681           return theClass;
  682       }
  683   
  684       /**
  685        * Loads a class through this class loader but defer to the parent class
  686        * loader.
  687        *
  688        * This ensures that instances of the returned class will be compatible
  689        * with instances which have already been loaded on the parent
  690        * loader.
  691        *
  692        * @param classname The name of the class to be loaded.
  693        *                  Must not be <code>null</code>.
  694        *
  695        * @return the required Class object
  696        *
  697        * @exception ClassNotFoundException if the requested class does not exist
  698        * on this loader's classpath.
  699        */
  700       public Class forceLoadSystemClass(String classname)
  701           throws ClassNotFoundException {
  702           log("force system loading " + classname, Project.MSG_DEBUG);
  703   
  704           Class theClass = findLoadedClass(classname);
  705   
  706           if (theClass == null) {
  707               theClass = findBaseClass(classname);
  708           }
  709   
  710           return theClass;
  711       }
  712   
  713       /**
  714        * Returns a stream to read the requested resource name.
  715        *
  716        * @param name The name of the resource for which a stream is required.
  717        *             Must not be <code>null</code>.
  718        *
  719        * @return a stream to the required resource or <code>null</code> if the
  720        *         resource cannot be found on the loader's classpath.
  721        */
  722       public InputStream getResourceAsStream(String name) {
  723   
  724           InputStream resourceStream = null;
  725           if (isParentFirst(name)) {
  726               resourceStream = loadBaseResource(name);
  727               if (resourceStream != null) {
  728                   log("ResourceStream for " + name
  729                       + " loaded from parent loader", Project.MSG_DEBUG);
  730   
  731               } else {
  732                   resourceStream = loadResource(name);
  733                   if (resourceStream != null) {
  734                       log("ResourceStream for " + name
  735                           + " loaded from ant loader", Project.MSG_DEBUG);
  736                   }
  737               }
  738           } else {
  739               resourceStream = loadResource(name);
  740               if (resourceStream != null) {
  741                   log("ResourceStream for " + name
  742                       + " loaded from ant loader", Project.MSG_DEBUG);
  743   
  744               } else {
  745                   resourceStream = loadBaseResource(name);
  746                   if (resourceStream != null) {
  747                       log("ResourceStream for " + name
  748                           + " loaded from parent loader", Project.MSG_DEBUG);
  749                   }
  750               }
  751           }
  752   
  753           if (resourceStream == null) {
  754               log("Couldn't load ResourceStream for " + name,
  755                   Project.MSG_DEBUG);
  756           }
  757   
  758           return resourceStream;
  759       }
  760   
  761       /**
  762        * Returns a stream to read the requested resource name from this loader.
  763        *
  764        * @param name The name of the resource for which a stream is required.
  765        *             Must not be <code>null</code>.
  766        *
  767        * @return a stream to the required resource or <code>null</code> if
  768        *         the resource cannot be found on the loader's classpath.
  769        */
  770       private InputStream loadResource(String name) {
  771           // we need to search the components of the path to see if we can
  772           // find the class we want.
  773           InputStream stream = null;
  774   
  775           Enumeration e = pathComponents.elements();
  776           while (e.hasMoreElements() && stream == null) {
  777               File pathComponent = (File) e.nextElement();
  778               stream = getResourceStream(pathComponent, name);
  779           }
  780           return stream;
  781       }
  782   
  783       /**
  784        * Finds a system resource (which should be loaded from the parent
  785        * classloader).
  786        *
  787        * @param name The name of the system resource to load.
  788        *             Must not be <code>null</code>.
  789        *
  790        * @return a stream to the named resource, or <code>null</code> if
  791        *         the resource cannot be found.
  792        */
  793       private InputStream loadBaseResource(String name) {
  794           if (parent == null) {
  795               return getSystemResourceAsStream(name);
  796           } else {
  797               return parent.getResourceAsStream(name);
  798           }
  799       }
  800   
  801       /**
  802        * Returns an inputstream to a given resource in the given file which may
  803        * either be a directory or a zip file.
  804        *
  805        * @param file the file (directory or jar) in which to search for the
  806        *             resource. Must not be <code>null</code>.
  807        * @param resourceName The name of the resource for which a stream is
  808        *                     required. Must not be <code>null</code>.
  809        *
  810        * @return a stream to the required resource or <code>null</code> if
  811        *         the resource cannot be found in the given file.
  812        */
  813       private InputStream getResourceStream(File file, String resourceName) {
  814           try {
  815               ZipFile zipFile = (ZipFile) zipFiles.get(file);
  816               if (zipFile == null && file.isDirectory()) {
  817                   File resource = new File(file, resourceName);
  818   
  819                   if (resource.exists()) {
  820                       return new FileInputStream(resource);
  821                   }
  822               } else {
  823                   if (zipFile == null) {
  824                       if (file.exists()) {
  825   
  826                           zipFile = new ZipFile(file);
  827                           zipFiles.put(file, zipFile);
  828                       } else {
  829                           return null;
  830                       }
  831                       //to eliminate a race condition, retrieve the entry
  832                       //that is in the hash table under that filename
  833                       zipFile = (ZipFile) zipFiles.get(file);
  834                   }
  835                   ZipEntry entry = zipFile.getEntry(resourceName);
  836                   if (entry != null) {
  837                       return zipFile.getInputStream(entry);
  838                   }
  839               }
  840           } catch (Exception e) {
  841               log("Ignoring Exception " + e.getClass().getName() + ": "
  842                       + e.getMessage() + " reading resource " + resourceName
  843                       + " from " + file, Project.MSG_VERBOSE);
  844           }
  845   
  846           return null;
  847       }
  848   
  849       /**
  850        * Tests whether or not the parent classloader should be checked for a
  851        * resource before this one. If the resource matches both the "use parent
  852        * classloader first" and the "use this classloader first" lists, the latter
  853        * takes priority.
  854        *
  855        * @param resourceName
  856        *            The name of the resource to check. Must not be
  857        *            <code>null</code>.
  858        *
  859        * @return whether or not the parent classloader should be checked for a
  860        *         resource before this one is.
  861        */
  862       private boolean isParentFirst(String resourceName) {
  863           // default to the global setting and then see
  864           // if this class belongs to a package which has been
  865           // designated to use a specific loader first
  866           // (this one or the parent one)
  867   
  868           // XXX - shouldn't this always return false in isolated mode?
  869   
  870           boolean useParentFirst = parentFirst;
  871   
  872           for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) {
  873               String packageName = (String) e.nextElement();
  874               if (resourceName.startsWith(packageName)) {
  875                   useParentFirst = true;
  876                   break;
  877               }
  878           }
  879   
  880           for (Enumeration e = loaderPackages.elements(); e.hasMoreElements();) {
  881               String packageName = (String) e.nextElement();
  882               if (resourceName.startsWith(packageName)) {
  883                   useParentFirst = false;
  884                   break;
  885               }
  886           }
  887   
  888           return useParentFirst;
  889       }
  890   
  891       /**
  892        * Used for isolated resource seaching.
  893        * @return the root classloader of AntClassLoader.
  894        */
  895       private ClassLoader getRootLoader() {
  896           ClassLoader ret = getClass().getClassLoader();
  897           while (ret != null && ret.getParent() != null) {
  898               ret = ret.getParent();
  899           }
  900           return ret;
  901       }
  902   
  903       /**
  904        * Finds the resource with the given name. A resource is
  905        * some data (images, audio, text, etc) that can be accessed by class
  906        * code in a way that is independent of the location of the code.
  907        *
  908        * @param name The name of the resource for which a stream is required.
  909        *             Must not be <code>null</code>.
  910        *
  911        * @return a URL for reading the resource, or <code>null</code> if the
  912        *         resource could not be found or the caller doesn't have
  913        *         adequate privileges to get the resource.
  914        */
  915       public URL getResource(String name) {
  916           // we need to search the components of the path to see if
  917           // we can find the class we want.
  918           URL url = null;
  919           if (isParentFirst(name)) {
  920               url = (parent == null) ? super.getResource(name)
  921                   : parent.getResource(name);
  922           }
  923   
  924           if (url != null) {
  925               log("Resource " + name + " loaded from parent loader",
  926                   Project.MSG_DEBUG);
  927   
  928           } else {
  929               // try and load from this loader if the parent either didn't find
  930               // it or wasn't consulted.
  931               Enumeration e = pathComponents.elements();
  932               while (e.hasMoreElements() && url == null) {
  933                   File pathComponent = (File) e.nextElement();
  934                   url = getResourceURL(pathComponent, name);
  935                   if (url != null) {
  936                       log("Resource " + name
  937                           + " loaded from ant loader",
  938                           Project.MSG_DEBUG);
  939                   }
  940               }
  941           }
  942   
  943           if (url == null && !isParentFirst(name)) {
  944               // this loader was first but it didn't find it - try the parent
  945               if (ignoreBase) {
  946                   url = (getRootLoader() == null) ? null
  947                       : getRootLoader().getResource(name);
  948               } else {
  949                   url = (parent == null) ? super.getResource(name)
  950                       : parent.getResource(name);
  951               }
  952               if (url != null) {
  953                   log("Resource " + name + " loaded from parent loader",
  954                       Project.MSG_DEBUG);
  955               }
  956           }
  957   
  958           if (url == null) {
  959               log("Couldn't load Resource " + name, Project.MSG_DEBUG);
  960           }
  961   
  962           return url;
  963       }
  964   
  965       /**
  966        * Returns an enumeration of URLs representing all the resources with the
  967        * given name by searching the class loader's classpath.
  968        *
  969        * @param name The resource name to search for.
  970        *             Must not be <code>null</code>.
  971        * @return an enumeration of URLs for the resources
  972        * @exception IOException if I/O errors occurs (can't happen)
  973        */
  974       protected Enumeration/*<URL>*/ findResources(String name) throws IOException {
  975           Enumeration/*<URL>*/ mine = new ResourceEnumeration(name);
  976           Enumeration/*<URL>*/ base;
  977           if (parent != null && parent != getParent()) {
  978               // Delegate to the parent:
  979               base = parent.getResources(name);
  980               // Note: could cause overlaps in case ClassLoader.this.parent has matches.
  981           } else {
  982               // ClassLoader.this.parent is already delegated to from
  983               // ClassLoader.getResources, no need:
  984               base = new CollectionUtils.EmptyEnumeration();
  985           }
  986           if (isParentFirst(name)) {
  987               // Normal case.
  988               return CollectionUtils.append(base, mine);
  989           } else if (ignoreBase) {
  990               return getRootLoader() == null
  991                   ? mine
  992                   : CollectionUtils.append(
  993                       mine, getRootLoader().getResources(name));
  994           } else {
  995               // Inverted.
  996               return CollectionUtils.append(mine, base);
  997           }
  998       }
  999   
 1000       /**
 1001        * Returns the URL of a given resource in the given file which may
 1002        * either be a directory or a zip file.
 1003        *
 1004        * @param file The file (directory or jar) in which to search for
 1005        *             the resource. Must not be <code>null</code>.
 1006        * @param resourceName The name of the resource for which a stream
 1007        *                     is required. Must not be <code>null</code>.
 1008        *
 1009        * @return a stream to the required resource or <code>null</code> if the
 1010        *         resource cannot be found in the given file object.
 1011        */
 1012       protected URL getResourceURL(File file, String resourceName) {
 1013           try {
 1014               ZipFile zipFile = (ZipFile) zipFiles.get(file);
 1015               if (zipFile == null && file.isDirectory()) {
 1016                   File resource = new File(file, resourceName);
 1017   
 1018                   if (resource.exists()) {
 1019                       try {
 1020                           return FILE_UTILS.getFileURL(resource);
 1021                       } catch (MalformedURLException ex) {
 1022                           return null;
 1023                       }
 1024                   }
 1025               } else {
 1026                   if (zipFile == null) {
 1027                       if (file.exists()) {
 1028                           zipFile = new ZipFile(file);
 1029                           zipFiles.put(file, zipFile);
 1030                       } else {
 1031                           return null;
 1032                       }
 1033                   }
 1034                   ZipEntry entry = zipFile.getEntry(resourceName);
 1035                   if (entry != null) {
 1036                       try {
 1037                           return new URL("jar:" + FILE_UTILS.getFileURL(file)
 1038                                          + "!/" + entry);
 1039                       } catch (MalformedURLException ex) {
 1040                           return null;
 1041                       }
 1042                   }
 1043               }
 1044           } catch (Exception e) {
 1045               e.printStackTrace();
 1046           }
 1047   
 1048           return null;
 1049       }
 1050   
 1051       /**
 1052        * Loads a class with this class loader.
 1053        *
 1054        * This class attempts to load the class in an order determined by whether
 1055        * or not the class matches the system/loader package lists, with the
 1056        * loader package list taking priority. If the classloader is in isolated
 1057        * mode, failure to load the class in this loader will result in a
 1058        * ClassNotFoundException.
 1059        *
 1060        * @param classname The name of the class to be loaded.
 1061        *                  Must not be <code>null</code>.
 1062        * @param resolve <code>true</code> if all classes upon which this class
 1063        *                depends are to be loaded.
 1064        *
 1065        * @return the required Class object
 1066        *
 1067        * @exception ClassNotFoundException if the requested class does not exist
 1068        * on the system classpath (when not in isolated mode) or this loader's
 1069        * classpath.
 1070        */
 1071       protected synchronized Class loadClass(String classname, boolean resolve)
 1072           throws ClassNotFoundException {
 1073           // 'sync' is needed - otherwise 2 threads can load the same class
 1074           // twice, resulting in LinkageError: duplicated class definition.
 1075           // findLoadedClass avoids that, but without sync it won't work.
 1076   
 1077           Class theClass = findLoadedClass(classname);
 1078           if (theClass != null) {
 1079               return theClass;
 1080           }
 1081   
 1082           if (isParentFirst(classname)) {
 1083               try {
 1084                   theClass = findBaseClass(classname);
 1085                   log("Class " + classname + " loaded from parent loader "
 1086                       + "(parentFirst)", Project.MSG_DEBUG);
 1087               } catch (ClassNotFoundException cnfe) {
 1088                   theClass = findClass(classname);
 1089                   log("Class " + classname + " loaded from ant loader "
 1090                       + "(parentFirst)", Project.MSG_DEBUG);
 1091               }
 1092           } else {
 1093               try {
 1094                   theClass = findClass(classname);
 1095                   log("Class " + classname + " loaded from ant loader",
 1096                       Project.MSG_DEBUG);
 1097               } catch (ClassNotFoundException cnfe) {
 1098                   if (ignoreBase) {
 1099                       throw cnfe;
 1100                   }
 1101                   theClass = findBaseClass(classname);
 1102                   log("Class " + classname + " loaded from parent loader",
 1103                       Project.MSG_DEBUG);
 1104               }
 1105           }
 1106   
 1107           if (resolve) {
 1108               resolveClass(theClass);
 1109           }
 1110   
 1111           return theClass;
 1112       }
 1113   
 1114       /**
 1115        * Converts the class dot notation to a filesystem equivalent for
 1116        * searching purposes.
 1117        *
 1118        * @param classname The class name in dot format (eg java.lang.Integer).
 1119        *                  Must not be <code>null</code>.
 1120        *
 1121        * @return the classname in filesystem format (eg java/lang/Integer.class)
 1122        */
 1123       private String getClassFilename(String classname) {
 1124           return classname.replace('.', '/') + ".class";
 1125       }
 1126   
 1127       /**
 1128        * Define a class given its bytes
 1129        *
 1130        * @param container the container from which the class data has been read
 1131        *                  may be a directory or a jar/zip file.
 1132        *
 1133        * @param classData the bytecode data for the class
 1134        * @param classname the name of the class
 1135        *
 1136        * @return the Class instance created from the given data
 1137        *
 1138        * @throws IOException if the class data cannot be read.
 1139        */
 1140       protected Class defineClassFromData(File container, byte[] classData,
 1141                                           String classname) throws IOException {
 1142           definePackage(container, classname);
 1143           // XXX should instead make a new ProtectionDomain with a CodeSource
 1144           // corresponding to container.toURI().toURL() and the same
 1145           // PermissionCollection as Project.class.protectionDomain had
 1146           return defineClass(classname, classData, 0, classData.length,
 1147                              Project.class.getProtectionDomain());
 1148       }
 1149   
 1150       /**
 1151        * Define the package information associated with a class.
 1152        *
 1153        * @param container the file containing the class definition.
 1154        * @param className the class name of for which the package information
 1155        *        is to be determined.
 1156        *
 1157        * @exception IOException if the package information cannot be read from the
 1158        *            container.
 1159        */
 1160       protected void definePackage(File container, String className)
 1161           throws IOException {
 1162           int classIndex = className.lastIndexOf('.');
 1163           if (classIndex == -1) {
 1164               return;
 1165           }
 1166   
 1167           String packageName = className.substring(0, classIndex);
 1168           if (getPackage(packageName) != null) {
 1169               // already defined
 1170               return;
 1171           }
 1172   
 1173           // define the package now
 1174           Manifest manifest = getJarManifest(container);
 1175   
 1176           if (manifest == null) {
 1177               definePackage(packageName, null, null, null, null, null,
 1178                             null, null);
 1179           } else {
 1180               definePackage(container, packageName, manifest);
 1181           }
 1182       }
 1183   
 1184       /**
 1185        * Get the manifest from the given jar, if it is indeed a jar and it has a
 1186        * manifest
 1187        *
 1188        * @param container the File from which a manifest is required.
 1189        *
 1190        * @return the jar's manifest or null is the container is not a jar or it
 1191        *         has no manifest.
 1192        *
 1193        * @exception IOException if the manifest cannot be read.
 1194        */
 1195       private Manifest getJarManifest(File container) throws IOException {
 1196           if (container.isDirectory()) {
 1197               return null;
 1198           }
 1199           JarFile jarFile = null;
 1200           try {
 1201               jarFile = new JarFile(container);
 1202               return jarFile.getManifest();
 1203           } finally {
 1204               if (jarFile != null) {
 1205                   jarFile.close();
 1206               }
 1207           }
 1208       }
 1209   
 1210       /**
 1211        * Define the package information when the class comes from a
 1212        * jar with a manifest
 1213        *
 1214        * @param container the jar file containing the manifest
 1215        * @param packageName the name of the package being defined.
 1216        * @param manifest the jar's manifest
 1217        */
 1218       protected void definePackage(File container, String packageName,
 1219                                    Manifest manifest) {
 1220           String sectionName = packageName.replace('.', '/') + "/";
 1221   
 1222           String specificationTitle = null;
 1223           String specificationVendor = null;
 1224           String specificationVersion = null;
 1225           String implementationTitle = null;
 1226           String implementationVendor = null;
 1227           String implementationVersion = null;
 1228           String sealedString = null;
 1229           URL sealBase = null;
 1230   
 1231           Attributes sectionAttributes = manifest.getAttributes(sectionName);
 1232           if (sectionAttributes != null) {
 1233               specificationTitle
 1234                   = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
 1235               specificationVendor
 1236                   = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
 1237               specificationVersion
 1238                   = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
 1239               implementationTitle
 1240                   = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
 1241               implementationVendor
 1242                   = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
 1243               implementationVersion
 1244                   = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
 1245               sealedString
 1246                   = sectionAttributes.getValue(Name.SEALED);
 1247           }
 1248   
 1249           Attributes mainAttributes = manifest.getMainAttributes();
 1250           if (mainAttributes != null) {
 1251               if (specificationTitle == null) {
 1252                   specificationTitle
 1253                       = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
 1254               }
 1255               if (specificationVendor == null) {
 1256                   specificationVendor
 1257                       = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
 1258               }
 1259               if (specificationVersion == null) {
 1260                   specificationVersion
 1261                       = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
 1262               }
 1263               if (implementationTitle == null) {
 1264                   implementationTitle
 1265                       = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
 1266               }
 1267               if (implementationVendor == null) {
 1268                   implementationVendor
 1269                       = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
 1270               }
 1271               if (implementationVersion == null) {
 1272                   implementationVersion
 1273                       = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
 1274               }
 1275               if (sealedString == null) {
 1276                   sealedString
 1277                       = mainAttributes.getValue(Name.SEALED);
 1278               }
 1279           }
 1280   
 1281           if (sealedString != null
 1282                   && sealedString.toLowerCase(Locale.ENGLISH).equals("true")) {
 1283               try {
 1284                   sealBase = new URL(FileUtils.getFileUtils().toURI(container.getAbsolutePath()));
 1285               } catch (MalformedURLException e) {
 1286                   // ignore
 1287               }
 1288           }
 1289   
 1290           definePackage(packageName, specificationTitle, specificationVersion,
 1291                         specificationVendor, implementationTitle,
 1292                         implementationVersion, implementationVendor, sealBase);
 1293       }
 1294   
 1295   
 1296       /**
 1297        * Reads a class definition from a stream.
 1298        *
 1299        * @param stream The stream from which the class is to be read.
 1300        *               Must not be <code>null</code>.
 1301        * @param classname The name of the class in the stream.
 1302        *                  Must not be <code>null</code>.
 1303        * @param container the file or directory containing the class.
 1304        *
 1305        * @return the Class object read from the stream.
 1306        *
 1307        * @exception IOException if there is a problem reading the class from the
 1308        * stream.
 1309        * @exception SecurityException if there is a security problem while
 1310        * reading the class from the stream.
 1311        */
 1312       private Class getClassFromStream(InputStream stream, String classname,
 1313                                        File container)
 1314           throws IOException, SecurityException {
 1315           ByteArrayOutputStream baos = new ByteArrayOutputStream();
 1316           int bytesRead = -1;
 1317           byte[] buffer = new byte[BUFFER_SIZE];
 1318   
 1319           while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
 1320               baos.write(buffer, 0, bytesRead);
 1321           }
 1322   
 1323           byte[] classData = baos.toByteArray();
 1324           return defineClassFromData(container, classData, classname);
 1325       }
 1326   
 1327       /**
 1328        * Searches for and load a class on the classpath of this class loader.
 1329        *
 1330        * @param name The name of the class to be loaded. Must not be
 1331        *             <code>null</code>.
 1332        *
 1333        * @return the required Class object
 1334        *
 1335        * @exception ClassNotFoundException if the requested class does not exist
 1336        *                                   on this loader's classpath.
 1337        */
 1338       public Class findClass(String name) throws ClassNotFoundException {
 1339           log("Finding class " + name, Project.MSG_DEBUG);
 1340   
 1341           return findClassInComponents(name);
 1342       }
 1343   
 1344       /**
 1345        * Indicate if the given file is in this loader's path
 1346        *
 1347        * @param component the file which is to be checked
 1348        *
 1349        * @return true if the file is in the class path
 1350        */
 1351       protected boolean isInPath(File component) {
 1352           for (Enumeration e = pathComponents.elements(); e.hasMoreElements();) {
 1353               File pathComponent = (File) e.nextElement();
 1354               if (pathComponent.equals(component)) {
 1355                   return true;
 1356               }
 1357           }
 1358           return false;
 1359       }
 1360   
 1361   
 1362       /**
 1363        * Finds a class on the given classpath.
 1364        *
 1365        * @param name The name of the class to be loaded. Must not be
 1366        *             <code>null</code>.
 1367        *
 1368        * @return the required Class object
 1369        *
 1370        * @exception ClassNotFoundException if the requested class does not exist
 1371        * on this loader's classpath.
 1372        */
 1373       private Class findClassInComponents(String name)
 1374           throws ClassNotFoundException {
 1375           // we need to search the components of the path to see if
 1376           // we can find the class we want.
 1377           InputStream stream = null;
 1378           String classFilename = getClassFilename(name);
 1379           try {
 1380               Enumeration e = pathComponents.elements();
 1381               while (e.hasMoreElements()) {
 1382                   File pathComponent = (File) e.nextElement();
 1383                   try {
 1384                       stream = getResourceStream(pathComponent, classFilename);
 1385                       if (stream != null) {
 1386                           log("Loaded from " + pathComponent + " "
 1387                               + classFilename, Project.MSG_DEBUG);
 1388                           return getClassFromStream(stream, name, pathComponent);
 1389                       }
 1390                   } catch (SecurityException se) {
 1391                       throw se;
 1392                   } catch (IOException ioe) {
 1393                       // ioe.printStackTrace();
 1394                       log("Exception reading component " + pathComponent
 1395                           + " (reason: " + ioe.getMessage() + ")",
 1396                           Project.MSG_VERBOSE);
 1397                   }
 1398               }
 1399   
 1400               throw new ClassNotFoundException(name);
 1401           } finally {
 1402           	FileUtils.close(stream);
 1403           }
 1404       }
 1405   
 1406       /**
 1407        * Finds a system class (which should be loaded from the same classloader
 1408        * as the Ant core).
 1409        *
 1410        * For JDK 1.1 compatibility, this uses the findSystemClass method if
 1411        * no parent classloader has been specified.
 1412        *
 1413        * @param name The name of the class to be loaded.
 1414        *             Must not be <code>null</code>.
 1415        *
 1416        * @return the required Class object
 1417        *
 1418        * @exception ClassNotFoundException if the requested class does not exist
 1419        * on this loader's classpath.
 1420        */
 1421       private Class findBaseClass(String name) throws ClassNotFoundException {
 1422           if (parent == null) {
 1423               return findSystemClass(name);
 1424           } else {
 1425               return parent.loadClass(name);
 1426           }
 1427       }
 1428   
 1429       /**
 1430        * Cleans up any resources held by this classloader. Any open archive
 1431        * files are closed.
 1432        */
 1433       public synchronized void cleanup() {
 1434           for (Enumeration e = zipFiles.elements(); e.hasMoreElements();) {
 1435               ZipFile zipFile = (ZipFile) e.nextElement();
 1436               try {
 1437                   zipFile.close();
 1438               } catch (IOException ioe) {
 1439                   // ignore
 1440               }
 1441           }
 1442           zipFiles = new Hashtable();
 1443           if (project != null) {
 1444               project.removeBuildListener(this);
 1445           }
 1446           project = null;
 1447       }
 1448   
 1449       /**
 1450        * Empty implementation to satisfy the BuildListener interface.
 1451        *
 1452        * @param event the buildStarted event
 1453        */
 1454       public void buildStarted(BuildEvent event) {
 1455           // Not significant for the class loader.
 1456       }
 1457   
 1458       /**
 1459        * Cleans up any resources held by this classloader at the end
 1460        * of a build.
 1461        *
 1462        * @param event the buildFinished event
 1463        */
 1464       public void buildFinished(BuildEvent event) {
 1465           cleanup();
 1466       }
 1467   
 1468       /**
 1469        * Cleans up any resources held by this classloader at the end of
 1470        * a subbuild if it has been created for the subbuild's project
 1471        * instance.
 1472        *
 1473        * @param event the buildFinished event
 1474        *
 1475        * @since Ant 1.6.2
 1476        */
 1477       public void subBuildFinished(BuildEvent event) {
 1478           if (event.getProject() == project) {
 1479               cleanup();
 1480           }
 1481       }
 1482   
 1483       /**
 1484        * Empty implementation to satisfy the BuildListener interface.
 1485        *
 1486        * @param event the buildStarted event
 1487        *
 1488        * @since Ant 1.6.2
 1489        */
 1490       public void subBuildStarted(BuildEvent event) {
 1491           // Not significant for the class loader.
 1492       }
 1493   
 1494       /**
 1495        * Empty implementation to satisfy the BuildListener interface.
 1496        *
 1497        * @param event the targetStarted event
 1498        */
 1499       public void targetStarted(BuildEvent event) {
 1500           // Not significant for the class loader.
 1501       }
 1502   
 1503       /**
 1504        * Empty implementation to satisfy the BuildListener interface.
 1505        *
 1506        * @param event the targetFinished event
 1507        */
 1508       public void targetFinished(BuildEvent event) {
 1509           // Not significant for the class loader.
 1510       }
 1511   
 1512       /**
 1513        * Empty implementation to satisfy the BuildListener interface.
 1514        *
 1515        * @param event the taskStarted event
 1516        */
 1517       public void taskStarted(BuildEvent event) {
 1518           // Not significant for the class loader.
 1519       }
 1520   
 1521       /**
 1522        * Empty implementation to satisfy the BuildListener interface.
 1523        *
 1524        * @param event the taskFinished event
 1525        */
 1526       public void taskFinished(BuildEvent event) {
 1527           // Not significant for the class loader.
 1528       }
 1529   
 1530       /**
 1531        * Empty implementation to satisfy the BuildListener interface.
 1532        *
 1533        * @param event the messageLogged event
 1534        */
 1535       public void messageLogged(BuildEvent event) {
 1536           // Not significant for the class loader.
 1537       }
 1538   
 1539       /**
 1540        * add any libraries that come with different java versions
 1541        * here
 1542        */
 1543       public void addJavaLibraries() {
 1544           Vector packages = JavaEnvUtils.getJrePackages();
 1545           Enumeration e = packages.elements();
 1546           while (e.hasMoreElements()) {
 1547               String packageName = (String) e.nextElement();
 1548               addSystemPackageRoot(packageName);
 1549           }
 1550       }
 1551   
 1552       /**
 1553        * Returns a <code>String</code> representing this loader.
 1554        * @return the path that this classloader has.
 1555        */
 1556       public String toString() {
 1557           return "AntClassLoader[" + getClasspath() + "]";
 1558       }
 1559   
 1560   }

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » [javadoc | source]