/* * Capsule * Copyright (c) 2014-2015, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are licensed under the terms * of the Eclipse Public License v1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package co.paralleluniverse.common; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; /** * * @author pron */ public abstract class FlexibleClassLoader extends ClassLoader { private final boolean childFirst; private final ThreadLocal<Boolean> inGetResourceAsStream = new ThreadLocal<Boolean>(); public FlexibleClassLoader(ClassLoader parent, boolean childFirst) { super(parent); this.childFirst = childFirst; } public FlexibleClassLoader(boolean childFirst) { this.childFirst = childFirst; } @Override public URL getResource(String name) { if (!childFirst) return super.getResource(name); URL url = findResource(name); if (url == null) url = super.getResource(name); return url; } @Override public InputStream getResourceAsStream(String name) { inGetResourceAsStream.set(Boolean.TRUE); try { InputStream is = null; if (!childFirst) is = super.getResourceAsStream(name); if (is == null) is = findResourceAsStream(name); if (is == null && childFirst) is = super.getResourceAsStream(name); return is; } finally { inGetResourceAsStream.remove(); } } @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { if (!childFirst) return super.loadClass(name, resolve); Class c; try { c = findClass(name); if (resolve) resolveClass(c); return c; } catch (ClassNotFoundException e) { } return super.loadClass(name, resolve); } @Override public Enumeration<URL> getResources(String name) throws IOException { Enumeration[] tmp = new Enumeration[2]; tmp[childFirst ? 1 : 0] = super.getResources(name); tmp[childFirst ? 0 : 1] = findResources1(name); return new sun.misc.CompoundEnumeration<URL>(tmp); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> clazz = findLoadedClass(name); if (clazz == null) { final byte[] buf = readResource(name.replace('.', '/') + ".class"); if (buf == null) throw new ClassNotFoundException(name); clazz = defineClass(name, buf, 0, buf.length); } return clazz; } @Override protected URL findResource(String name) { if (inGetResourceAsStream.get() == Boolean.TRUE) return null; return findResource1(name); } protected abstract URL findResource1(String name); protected abstract Enumeration<URL> findResources1(String name); protected abstract InputStream findResourceAsStream(String name); protected abstract byte[] readResource(String name); }