org.simpleflatmapper.reflect.asm.FactoryClassLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sfm-reflect Show documentation
Show all versions of sfm-reflect Show documentation
Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.
package org.simpleflatmapper.reflect.asm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class FactoryClassLoader extends ClassLoader {
private class ClassInfo {
private final byte[] bytes;
private final Class> clazz;
private ClassInfo(byte[] bytes, Class> clazz) {
super();
this.bytes = bytes;
this.clazz = clazz;
}
}
private final Map classes = new HashMap();
private final List delegateClassLoader = new ArrayList();
private final Lock lock = new ReentrantLock();
public FactoryClassLoader(final ClassLoader parent) {
super(parent);
}
public Class> registerClass(final String name, final byte[] bytes, ClassLoader classLoader) {
lock.lock();
try {
ClassInfo info = classes.get(name);
if (info != null) {
if (!Arrays.equals(info.bytes, bytes)) {
throw new LinkageError("Class " + name + " is defined with different bytecodes");
}
} else {
Class> clazz = defineClass(name, bytes, 0, bytes.length);
info = new ClassInfo(bytes, clazz);
classes.put(name, info);
if (classLoader != null && !isAlreadyAccessible(classLoader)) {
delegateClassLoader.add(classLoader);
}
}
return info.clazz;
} finally {
lock.unlock();
}
}
private boolean isAlreadyAccessible(ClassLoader classLoader) {
if (isAccessibleFrom(classLoader, getParent())) {
return true;
}
for(ClassLoader cl : delegateClassLoader) {
if (isAccessibleFrom(classLoader, cl)) {
return true;
}
}
return false;
}
private boolean isAccessibleFrom(ClassLoader classLoader, ClassLoader from) {
ClassLoader parent = from;
while(parent != null) {
if (parent.equals(classLoader)) {
return true;
}
parent = parent.getParent();
}
return false;
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
try {
return super.findClass(name);
} catch(ClassNotFoundException e) {
for(ClassLoader cl : delegateClassLoader) {
try {
return cl.loadClass(name);
} catch(ClassNotFoundException e2) {
///
}
}
throw e;
}
}
}