📄 antclassloader.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */package org.apache.tools.ant;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.Reader;import java.lang.reflect.Constructor;import java.net.MalformedURLException;import java.net.URL;import java.util.Collections;import java.util.Enumeration;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;import java.util.StringTokenizer;import java.util.Vector;import java.util.Locale;import java.util.jar.Attributes;import java.util.jar.Attributes.Name;import java.util.jar.JarFile;import java.util.jar.Manifest;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import org.apache.tools.ant.types.Path;import org.apache.tools.ant.util.CollectionUtils;import org.apache.tools.ant.util.FileUtils;import org.apache.tools.ant.util.JavaEnvUtils;import org.apache.tools.ant.util.LoaderUtils;import org.apache.tools.ant.launch.Locator;/** * Used to load classes within ant with a different classpath from * that used to start ant. Note that it is possible to force a class * into this loader even when that class is on the system classpath by * using the forceLoadClass method. Any subsequent classes loaded by that * class will then use this loader rather than the system class loader. * * <p> * Note that this classloader has a feature to allow loading * in reverse order and for "isolation". * Due to the fact that a number of * methods in java.lang.ClassLoader are final (at least * in java 1.4 getResources) this means that the * class has to fake the given parent. * </p> * */public class AntClassLoader extends ClassLoader implements SubBuildListener { private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); /** * An enumeration of all resources of a given name found within the * classpath of this class loader. This enumeration is used by the * ClassLoader.findResources method, which is in * turn used by the ClassLoader.getResources method. * * @see AntClassLoader#findResources(String) * @see java.lang.ClassLoader#getResources(String) */ private class ResourceEnumeration implements Enumeration { /** * The name of the resource being searched for. */ private String resourceName; /** * The index of the next classpath element to search. */ private int pathElementsIndex; /** * The URL of the next resource to return in the enumeration. If this * field is <code>null</code> then the enumeration has been completed, * i.e., there are no more elements to return. */ private URL nextResource; /** * Constructs a new enumeration of resources of the given name found * within this class loader's classpath. * * @param name the name of the resource to search for. */ ResourceEnumeration(String name) { this.resourceName = name; this.pathElementsIndex = 0; findNextResource(); } /** * Indicates whether there are more elements in the enumeration to * return. * * @return <code>true</code> if there are more elements in the * enumeration; <code>false</code> otherwise. */ public boolean hasMoreElements() { return (this.nextResource != null); } /** * Returns the next resource in the enumeration. * * @return the next resource in the enumeration */ public Object nextElement() { URL ret = this.nextResource; findNextResource(); return ret; } /** * Locates the next resource of the correct name in the classpath and * sets <code>nextResource</code> to the URL of that resource. If no * more resources can be found, <code>nextResource</code> is set to * <code>null</code>. */ private void findNextResource() { URL url = null; while ((pathElementsIndex < pathComponents.size()) && (url == null)) { try { File pathComponent = (File) pathComponents.elementAt(pathElementsIndex); url = getResourceURL(pathComponent, this.resourceName); pathElementsIndex++; } catch (BuildException e) { // ignore path elements which are not valid relative to the // project } } this.nextResource = url; } } /** * The size of buffers to be used in this classloader. */ private static final int BUFFER_SIZE = 8192; /** * Number of array elements in a test array of strings */ private static final int NUMBER_OF_STRINGS = 256; /** * The components of the classpath that the classloader searches * for classes. */ private Vector pathComponents = new Vector(); /** * The project to which this class loader belongs. */ private Project project; /** * Indicates whether the parent class loader should be * consulted before trying to load with this class loader. */ private boolean parentFirst = true; /** * These are the package roots that are to be loaded by the parent class * loader regardless of whether the parent class loader is being searched * first or not. */ private Vector systemPackages = new Vector(); /** * These are the package roots that are to be loaded by this class loader * regardless of whether the parent class loader is being searched first * or not. */ private Vector loaderPackages = new Vector(); /** * Whether or not this classloader will ignore the base * classloader if it can't find a class. * * @see #setIsolated(boolean) */ private boolean ignoreBase = false; /** * The parent class loader, if one is given or can be determined. */ private ClassLoader parent = null; /** * A hashtable of zip files opened by the classloader (File to ZipFile). */ private Hashtable zipFiles = new Hashtable(); /** Static map of jar file/time to manifest class-path entries */ private static Map/*<String,String>*/ pathMap = Collections.synchronizedMap(new HashMap()); /** * The context loader saved when setting the thread's current * context loader. */ private ClassLoader savedContextLoader = null; /** * Whether or not the context loader is currently saved. */ private boolean isContextLoaderSaved = false; /** * Create an Ant ClassLoader for a given project, with * a parent classloader and an initial classpath. * @since Ant 1.7. * @param parent the parent for this classloader. * @param project The project to which this classloader is to * belong. * @param classpath The classpath to use to load classes. */ public AntClassLoader( ClassLoader parent, Project project, Path classpath) { setParent(parent); setClassPath(classpath); setProject(project); } /** * Create an Ant Class Loader */ public AntClassLoader() { setParent(null); } /** * Creates a classloader for the given project using the classpath given. * * @param project The project to which this classloader is to belong. * Must not be <code>null</code>. * @param classpath The classpath to use to load the classes. This * is combined with the system classpath in a manner * determined by the value of ${build.sysclasspath}. * May be <code>null</code>, in which case no path * elements are set up to start with. */ public AntClassLoader(Project project, Path classpath) { setParent(null); setProject(project); setClassPath(classpath); } /** * Creates a classloader for the given project using the classpath given. * * @param parent The parent classloader to which unsatisfied loading * attempts are delegated. May be <code>null</code>, * in which case the classloader which loaded this * class is used as the parent. * @param project The project to which this classloader is to belong. * Must not be <code>null</code>. * @param classpath the classpath to use to load the classes. * May be <code>null</code>, in which case no path * elements are set up to start with. * @param parentFirst If <code>true</code>, indicates that the parent * classloader should be consulted before trying to * load the a class through this loader. */ public AntClassLoader(ClassLoader parent, Project project, Path classpath, boolean parentFirst) { this(project, classpath); if (parent != null) { setParent(parent); } setParentFirst(parentFirst); addJavaLibraries(); } /** * Creates a classloader for the given project using the classpath given. * * @param project The project to which this classloader is to belong. * Must not be <code>null</code>. * @param classpath The classpath to use to load the classes. May be * <code>null</code>, in which case no path * elements are set up to start with. * @param parentFirst If <code>true</code>, indicates that the parent * classloader should be consulted before trying to * load the a class through this loader. */ public AntClassLoader(Project project, Path classpath, boolean parentFirst) { this(null, project, classpath, parentFirst); } /** * Creates an empty class loader. The classloader should be configured * with path elements to specify where the loader is to look for * classes. * * @param parent The parent classloader to which unsatisfied loading * attempts are delegated. May be <code>null</code>, * in which case the classloader which loaded this * class is used as the parent. * @param parentFirst If <code>true</code>, indicates that the parent * classloader should be consulted before trying to * load the a class through this loader. */ public AntClassLoader(ClassLoader parent, boolean parentFirst) { setParent(parent); project = null; this.parentFirst = parentFirst; } /** * Set the project associated with this class loader * * @param project the project instance */ public void setProject(Project project) { this.project = project; if (project != null) { project.addBuildListener(this); } } /** * Set the classpath to search for classes to load. This should not be * changed once the classloader starts to server classes * * @param classpath the search classpath consisting of directories and * jar/zip files. */ public void setClassPath(Path classpath) { pathComponents.removeAllElements(); if (classpath != null) { Path actualClasspath = classpath.concatSystemClasspath("ignore"); String[] pathElements = actualClasspath.list(); for (int i = 0; i < pathElements.length; ++i) { try { addPathElement(pathElements[i]); } catch (BuildException e) { // ignore path elements which are invalid // relative to the project } } } } /** * Set the parent for this class loader. This is the class loader to which * this class loader will delegate to load classes * * @param parent the parent class loader. */ public void setParent(ClassLoader parent) { if (parent == null) { this.parent = AntClassLoader.class.getClassLoader(); } else { this.parent = parent; } } /** * Control whether class lookup is delegated to the parent loader first * or after this loader. Use with extreme caution. Setting this to * false violates the class loader hierarchy and can lead to Linkage errors * * @param parentFirst if true, delegate initial class search to the parent * classloader. */ public void setParentFirst(boolean parentFirst) { this.parentFirst = parentFirst; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -