net.e6tech.elements.common.interceptor.JoinClassLoader Maven / Gradle / Ivy
// Copyright 2010 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
// www.source-code.biz, www.inventec.ch/chdh
//
// This module is multi-licensed and may be used under the terms
// of any of the following licenses:
//
// LGPL, GNU Lesser General Public License, V2 or later, http://www.gnu.org/licenses/lgpl.html
// AL, Apache License, V2.0 or later, http://www.apache.org/licenses
//
// Please contact the author if you need another license.
// This module is provided "as is", without warranties of any kind.
package net.e6tech.elements.common.interceptor;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
/**
* A class loader that combines multiple class loaders into one.
* The classes loaded by this class loader are associated with this class loader,
* i.e. Class.getClassLoader() points to this class loader.
*/
public class JoinClassLoader extends ClassLoader {
private ClassLoader[] delegateClassLoaders;
public JoinClassLoader(ClassLoader parent, ClassLoader... delegateClassLoaders) {
super(parent);
this.delegateClassLoaders = delegateClassLoaders;
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
// It would be easier to call the loadClass() methods of the delegateClassLoaders
// here, but we have to load the class from the byte code ourselves, because we
// need it to be associated with our class loader.
String path = name.replace('.', '/') + ".class";
URL url = findResource(path);
if (url == null) {
throw new ClassNotFoundException(name);
}
ByteBuffer byteCode;
try {
byteCode = loadResource(url);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
return defineClass(name, byteCode, null);
}
private ByteBuffer loadResource(URL url) throws IOException {
InputStream stream = null;
try {
stream = url.openStream();
int initialBufferCapacity = Math.min(0x40000, stream.available() + 1);
if (initialBufferCapacity <= 2) {
initialBufferCapacity = 0x10000;
} else {
initialBufferCapacity = Math.max(initialBufferCapacity, 0x200);
}
ByteBuffer buf = ByteBuffer.allocate(initialBufferCapacity);
while (true) {
if (!buf.hasRemaining()) {
ByteBuffer newBuf = ByteBuffer.allocate(2 * buf.capacity());
buf.flip();
newBuf.put(buf);
buf = newBuf;
}
int len = stream.read(buf.array(), buf.position(), buf.remaining());
if (len <= 0) {
break;
}
buf.position(buf.position() + len);
}
buf.flip();
return buf;
} finally {
if (stream != null) {
stream.close();
}
}
}
@Override
protected URL findResource(String name) {
for (ClassLoader delegate : delegateClassLoaders) {
URL resource = delegate.getResource(name);
if (resource != null) {
return resource;
}
}
return null;
}
@Override
protected Enumeration findResources(String name) throws IOException {
List list = new ArrayList<>();
for (ClassLoader delegate : delegateClassLoaders) {
Enumeration enumeration = delegate.getResources(name);
while (enumeration.hasMoreElements()) {
list.add(enumeration.nextElement());
}
}
return Collections.enumeration(list);
}
} // end class JoinClassLoader