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

📄 pathableclassloader.java

📁 comming logging 的源码 可以封装log4j等日志系统。 源码中使用了很多的设计模式
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        }

        // now check the classpath for a similar-named lib
        URL libUrl = libFromClasspath(logicalLib);
        if (libUrl != null) {
            addURL(libUrl);
            return;
        }

        // lib not found
        throw new UnknownError(
            "Logical lib [" + logicalLib + "] is not defined"
            + " as a System property.");
    }

    /**
     * If the classloader that loaded this class has this logical lib in its
     * path, then return the matching URL otherwise return null.
     * <p>
     * This only works when the classloader loading this class is an instance
     * of URLClassLoader and thus has a getURLs method that returns the classpath
     * it uses when loading classes. However in practice, the vast majority of the
     * time this type is the classloader used.
     * <p>
     * The classpath of the classloader for this instance is scanned, and any
     * jarfile in the path whose name starts with the logicalLib string is
     * considered a match. For example, passing "foo" will match a url
     * of <code>file:///some/where/foo-2.7.jar</code>.
     * <p>
     * When multiple classpath entries match the specified logicalLib string,
     * the one with the shortest filename component is returned. This means that
     * if "foo-1.1.jar" and "foobar-1.1.jar" are in the path, then a logicalLib
     * name of "foo" will match the first entry above.
     */
    private URL libFromClasspath(String logicalLib) {
        ClassLoader cl = this.getClass().getClassLoader();
        if (cl instanceof URLClassLoader == false) {
            return null;
        }
        
        URLClassLoader ucl = (URLClassLoader) cl;
        URL[] path = ucl.getURLs();
        URL shortestMatch = null;
        int shortestMatchLen = Integer.MAX_VALUE;
        for(int i=0; i<path.length; ++i) {
            URL u = path[i];
            
            // extract the filename bit on the end of the url
            String filename = u.toString();
            if (!filename.endsWith(".jar")) {
                // not a jarfile, ignore it
                continue;
            }

            int lastSlash = filename.lastIndexOf('/');
            if (lastSlash >= 0) {
                filename = filename.substring(lastSlash+1);
            }
            
            if (filename.startsWith(logicalLib)) {
                // ok, this is a candidate
                if (filename.length() < shortestMatchLen) {
                    shortestMatch = u;
                    shortestMatchLen = filename.length();
                }
            }
        }
        
        return shortestMatch;
    }

    /**
     * Override ClassLoader method.
     * <p>
     * For each explicitly mapped package prefix, if the name matches the 
     * prefix associated with that entry then attempt to load the class via 
     * that entries' classloader.
     */
    protected Class loadClass(String name, boolean resolve) 
    throws ClassNotFoundException {
        // just for performance, check java and javax
        if (name.startsWith("java.") || name.startsWith("javax.")) {
            return super.loadClass(name, resolve);
        }

        if (lookasides != null) {
            for(Iterator i = lookasides.entrySet().iterator(); i.hasNext(); ) {
                Map.Entry entry = (Map.Entry) i.next();
                String prefix = (String) entry.getKey();
                if (name.startsWith(prefix) == true) {
                    ClassLoader loader = (ClassLoader) entry.getValue();
                    Class clazz = Class.forName(name, resolve, loader);
                    return clazz;
                }
            }
        }
        
        if (parentFirst) {
            return super.loadClass(name, resolve);
        } else {
            // Implement child-first. 
            //
            // It appears that the findClass method doesn't check whether the
            // class has already been loaded. This seems odd to me, but without
            // first checking via findLoadedClass we can get java.lang.LinkageError
            // with message "duplicate class definition" which isn't good.
            
            try {
                Class clazz = findLoadedClass(name);
                if (clazz == null) {
                    clazz = super.findClass(name);
                }
                if (resolve) {
                    resolveClass(clazz);
                }
                return clazz;
            } catch(ClassNotFoundException e) {
                return super.loadClass(name, resolve);
            }
        }
    }
    
    /**
     * Same as parent class method except that when parentFirst is false
     * the resource is looked for in the local classpath before the parent
     * loader is consulted.
     */
    public URL getResource(String name) {
        if (parentFirst) {
            return super.getResource(name);
        } else {
            URL local = super.findResource(name);
            if (local != null) {
                return local;
            }
            return super.getResource(name);
        }
    }
    
    /**
     * Emulate a proper implementation of getResources which respects the
     * setting for parentFirst.
     * <p>
     * Note that it's not possible to override the inherited getResources, as
     * it's declared final in java1.4 (thought that's been removed for 1.5).
     * The inherited implementation always behaves as if parentFirst=true.
     */
    public Enumeration getResourcesInOrder(String name) throws IOException {
        if (parentFirst) {
            return super.getResources(name);
        } else {
            Enumeration localUrls = super.findResources(name);
            
            ClassLoader parent = getParent();
            if (parent == null) {
                // Alas, there is no method to get matching resources
                // from a null (BOOT) parent classloader. Calling
                // ClassLoader.getSystemClassLoader isn't right. Maybe
                // calling Class.class.getResources(name) would do?
                //
                // However for the purposes of unit tests, we can
                // simply assume that no relevant resources are
                // loadable from the parent; unit tests will never be
                // putting any of their resources in a "boot" classloader
                // path!
                return localUrls;
            }
            Enumeration parentUrls = parent.getResources(name);

            ArrayList localItems = toList(localUrls);
            ArrayList parentItems = toList(parentUrls);
            localItems.addAll(parentItems);
            return Collections.enumeration(localItems);
        }
    }
    
    /**
     * 
     * Clean implementation of list function of 
     * {@link java.utils.Collection} added in JDK 1.4 
     * @param en <code>Enumeration</code>, possibly null
     * @return <code>ArrayList</code> containing the enumerated
     * elements in the enumerated order, not null
     */
    private ArrayList toList(Enumeration en) {
        ArrayList results = new ArrayList();
        if (en != null) {
            while (en.hasMoreElements()){
                Object element = en.nextElement();
                results.add(element);
            }
        }
        return results;
    }
    
    /**
     * Same as parent class method except that when parentFirst is false
     * the resource is looked for in the local classpath before the parent
     * loader is consulted.
     */
    public InputStream getResourceAsStream(String name) {
        if (parentFirst) {
            return super.getResourceAsStream(name);
        } else {
            URL local = super.findResource(name);
            if (local != null) {
                try {
                    return local.openStream();
                } catch(IOException e) {
                    // TODO: check if this is right or whether we should
                    // fall back to trying parent. The javadoc doesn't say...
                    return null;
                }
            }
            return super.getResourceAsStream(name);
        }
    }
}

⌨️ 快捷键说明

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