/* * Copyright 2013 Alex Lin. * * Licensed 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.opoo.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; /** * @author Alex Lin * */ public class ChainingClassLoader extends URLClassLoader { private static final Logger log = LoggerFactory.getLogger(ChainingClassLoader.class); private final ClassLoader parent; private final Collection<ClassLoader> loaders; private static final URL NULL_URL_ARRAY[] = new URL[0]; private static Map<String, Object> classLookupCache = new HashMap<String, Object>(); public ChainingClassLoader(ClassLoader parent, Collection<ClassLoader> loaders) { super(NULL_URL_ARRAY, parent); this.parent = parent; this.loaders = loaders; } public Class<?> loadClass(String string) throws ClassNotFoundException { Object cls = classLookupCache.get(string); if (cls != null) { if (cls instanceof ClassNotFoundException) { throw (ClassNotFoundException) cls; } else { return (Class<?>) cls; } } ClassNotFoundException ex = null; Class<?> clazz = null; try { clazz = parent.loadClass(string); } catch (ClassNotFoundException e) { ex = e; } if (clazz == null) { for (ClassLoader l : loaders) { try { clazz = l.loadClass(string); break; } catch (ClassNotFoundException e) { } } } if (clazz == null) { classLookupCache.put(string, ex); throw ex; } else { classLookupCache.put(string, clazz); return clazz; } } public URL getResource(String string) { URL url = parent.getResource(string); if (url == null) { for (ClassLoader l : loaders) { url = l.getResource(string); if (url != null) { break; } } } return url; } public Enumeration<URL> getResources(String string) throws IOException { Enumeration<URL> enumeration = parent.getResources(string); if (enumeration == null || !enumeration.hasMoreElements()) { for (ClassLoader l : loaders) { enumeration = l.getResources(string); if (enumeration != null && enumeration.hasMoreElements()) { break; } } } return enumeration; } public InputStream getResourceAsStream(String string) { InputStream stream = parent.getResourceAsStream(string); if (stream == null) { for (ClassLoader l : loaders) { stream = l.getResourceAsStream(string); if (stream != null) { break; } } } return stream; } public URL[] getURLs() { if (parent instanceof URLClassLoader) try { URL resource[] = ((URLClassLoader) parent).getURLs(); if (resource != null) { return resource; } } catch (Exception e) { log.error(e.getMessage(), e); } return super.getURLs(); } public URL findResource(String string) { if (parent instanceof URLClassLoader) try { URL resource = ((URLClassLoader) parent).findResource(string); if (resource != null) return resource; } catch (Exception e) { log.error(e.getMessage(), e); } return super.findResource(string); } public Enumeration<URL> findResources(String string) throws IOException { if (parent instanceof URLClassLoader) try { Enumeration<URL> resource = ((URLClassLoader) parent).findResources(string); if (resource != null) return resource; } catch (Exception e) { log.error(e.getMessage(), e); } return super.findResources(string); } public static void clearCache() { classLookupCache.clear(); } public ClassLoader getWrappedClassLoader() { return parent; } }