⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pathableclassloader.java

📁 comming logging 的源码 可以封装log4j等日志系统。 源码中使用了很多的设计模式
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.commons.logging;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * A ClassLoader which sees only specified classes, and which can be
 * set to do parent-first or child-first path lookup.
 * <p>
 * Note that this classloader is not "industrial strength"; users
 * looking for such a class may wish to look at the Tomcat sourcecode
 * instead. In particular, this class may not be threadsafe.
 * <p>
 * Note that the ClassLoader.getResources method isn't overloaded here.
 * It would be nice to ensure that when child-first lookup is set the
 * resources from the child are returned earlier in the list than the
 * resources from the parent. However overriding this method isn't possible
 * as the java 1.4 version of ClassLoader declares this method final
 * (though the java 1.5 version has removed the final qualifier). As the
 * ClassLoader javadoc doesn't specify the order in which resources
 * are returned, it's valid to return the resources in any order (just
 * untidy) so the inherited implementation is technically ok.
 */

public class PathableClassLoader extends URLClassLoader {
    
    private static final URL[] NO_URLS = new URL[0];
    
    /**
     * A map of package-prefix to ClassLoader. Any class which is in
     * this map is looked up via the specified classloader instead of
     * the classpath associated with this classloader or its parents.
     * <p>
     * This is necessary in order for the rest of the world to communicate
     * with classes loaded via a custom classloader. As an example, junit
     * testcases which are loaded via a custom classloader needs to see
     * the same junit classes as the code invoking the testcase, otherwise
     * they can't pass result objects back. 
     * <p>
     * Normally, only a classloader created with a null parent needs to
     * have any lookasides defined.
     */
    private HashMap lookasides = null;

    /**
     * See setParentFirst.
     */
    private boolean parentFirst = true;

    /**
     * Constructor.
     * <p>
     * Often, null is passed as the parent, ie the parent of the new
     * instance is the bootloader. This ensures that the classpath is
     * totally clean; nothing but the standard java library will be
     * present.
     * <p>
     * When using a null parent classloader with a junit testcase, it *is*
     * necessary for the junit library to also be visible. In this case, it
     * is recommended that the following code be used:
     * <pre>
     * pathableLoader.useExplicitLoader(
     *   "junit.",
     *   junit.framework.Test.class.getClassLoader());
     * </pre>
     * Note that this works regardless of whether junit is on the system
     * classpath, or whether it has been loaded by some test framework that
     * creates its own classloader to run unit tests in (eg maven2's
     * Surefire plugin).
     */
    public PathableClassLoader(ClassLoader parent) {
        super(NO_URLS, parent);
    }
    
    /**
     * Allow caller to explicitly add paths. Generally this not a good idea;
     * use addLogicalLib instead, then define the location for that logical
     * library in the build.xml file.
     */
    public void addURL(URL url) {
        super.addURL(url);
    }

    /**
     * Specify whether this classloader should ask the parent classloader
     * to resolve a class first, before trying to resolve it via its own
     * classpath.
     * <p> 
     * Checking with the parent first is the normal approach for java, but
     * components within containers such as servlet engines can use 
     * child-first lookup instead, to allow the components to override libs
     * which are visible in shared classloaders provided by the container.
     * <p>
     * Note that the method getResources always behaves as if parentFirst=true,
     * because of limitations in java 1.4; see the javadoc for method
     * getResourcesInOrder for details.
     * <p>
     * This value defaults to true.
     */
    public void setParentFirst(boolean state) {
        parentFirst = state;
    }

    /**
     * For classes with the specified prefix, get them from the system
     * classpath <i>which is active at the point this method is called</i>.
     * <p>
     * This method is just a shortcut for
     * <pre>
     * useExplicitLoader(prefix, ClassLoader.getSystemClassLoader());
     * </pre>
     * <p>
     * Of course, this assumes that the classes of interest are already
     * in the classpath of the system classloader.
     */
    public void useSystemLoader(String prefix) {
        useExplicitLoader(prefix, ClassLoader.getSystemClassLoader());
        
    }

    /**
     * Specify a classloader to use for specific java packages.
     * <p>
     * The specified classloader is normally a loader that is NOT
     * an ancestor of this classloader. In particular, this loader
     * may have the bootloader as its parent, but be configured to 
     * see specific other classes (eg the junit library loaded
     * via the system classloader).
     * <p>
     * The differences between using this method, and using
     * addLogicalLib are:
     * <ul>
     * <li>If code calls getClassLoader on a class loaded via
     * "lookaside", then traces up its inheritance chain, it
     * will see the "real" classloaders. When the class is remapped
     * into this classloader via addLogicalLib, the classloader
     * chain seen is this object plus ancestors.
     * <li>If two different jars contain classes in the same
     * package, then it is not possible to load both jars into
     * the same "lookaside" classloader (eg the system classloader)
     * then map one of those subsets from here. Of course they could
     * be loaded into two different "lookaside" classloaders and
     * then a prefix used to map from here to one of those classloaders.
     * </ul>
     */
    public void useExplicitLoader(String prefix, ClassLoader loader) {
        if (lookasides == null) {
            lookasides = new HashMap();
        }
        lookasides.put(prefix, loader);
    }

    /**
     * Specify a collection of logical libraries. See addLogicalLib.
     */
    public void addLogicalLib(String[] logicalLibs) {
        for(int i=0; i<logicalLibs.length; ++i) {
            addLogicalLib(logicalLibs[i]);
        }
    }

    /**
     * Specify a logical library to be included in the classpath used to
     * locate classes. 
     * <p>
     * The specified lib name is used as a key into the system properties;
     * there is expected to be a system property defined with that name
     * whose value is a url that indicates where that logical library can
     * be found. Typically this is the name of a jar file, or a directory
     * containing class files.
     * <p>
     * If there is no system property, but the classloader that loaded
     * this class is a URLClassLoader then the set of URLs that the
     * classloader uses for its classpath is scanned; any jar in the
     * URL set whose name starts with the specified string is added to
     * the classpath managed by this instance. 
     * <p>
     * Using logical library names allows the calling code to specify its
     * desired classpath without knowing the exact location of the necessary
     * classes. 
     */
    public void addLogicalLib(String logicalLib) {
        // first, check the system properties
        String filename = System.getProperty(logicalLib);
        if (filename != null) {
            try {
                URL libUrl = new File(filename).toURL();
                addURL(libUrl);
                return;
            } catch(java.net.MalformedURLException e) {
                throw new UnknownError(
                    "Invalid file [" + filename + "] for logical lib [" + logicalLib + "]");
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -