package jenkins;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
/**
* Reflective access to various {@link ClassLoader} methods which are otherwise {@code protected}.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class ClassLoaderReflectionToolkit {
private static final Method FIND_CLASS, FIND_LOADED_CLASS, FIND_RESOURCE, FIND_RESOURCES, GET_CLASS_LOADING_LOCK;
static {
try {
FIND_CLASS = ClassLoader.class.getDeclaredMethod("findClass",String.class);
FIND_CLASS.setAccessible(true);
FIND_LOADED_CLASS = ClassLoader.class.getDeclaredMethod("findLoadedClass",String.class);
FIND_LOADED_CLASS.setAccessible(true);
FIND_RESOURCE = ClassLoader.class.getDeclaredMethod("findResource",String.class);
FIND_RESOURCE.setAccessible(true);
FIND_RESOURCES = ClassLoader.class.getDeclaredMethod("findResources",String.class);
FIND_RESOURCES.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
Method gCLL = null;
try {
gCLL = ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class);
gCLL.setAccessible(true);
} catch (NoSuchMethodException x) {
throw new AssertionError(x);
}
GET_CLASS_LOADING_LOCK = gCLL;
}
private static <T extends Exception> Object invoke(Method method, Class<T> exception, Object obj, Object... args) throws T {
try {
return method.invoke(obj, args);
} catch (IllegalAccessException x) {
throw new AssertionError(x);
} catch (InvocationTargetException x) {
Throwable x2 = x.getCause();
if (x2 instanceof RuntimeException) {
throw (RuntimeException) x2;
} else if (x2 instanceof Error) {
throw (Error) x2;
} else if (exception.isInstance(x2)) {
throw exception.cast(x2);
} else {
throw new AssertionError(x2);
}
}
}
private static Object getClassLoadingLock(ClassLoader cl, String name) {
return invoke(GET_CLASS_LOADING_LOCK, RuntimeException.class, cl, name);
}
/**
* Calls {@link ClassLoader#findLoadedClass} while holding {@link ClassLoader#getClassLoadingLock}.
* @since 1.553
*/
public static @CheckForNull Class<?> _findLoadedClass(ClassLoader cl, String name) {
synchronized (getClassLoadingLock(cl, name)) {
return (Class) invoke(FIND_LOADED_CLASS, RuntimeException.class, cl, name);
}
}
/**
* Calls {@link ClassLoader#findClass} while holding {@link ClassLoader#getClassLoadingLock}.
* @since 1.553
*/
public static @Nonnull Class<?> _findClass(ClassLoader cl, String name) throws ClassNotFoundException {
synchronized (getClassLoadingLock(cl, name)) {
return (Class) invoke(FIND_CLASS, ClassNotFoundException.class, cl, name);
}
}
/**
* Calls {@link ClassLoader#findResource}.
* @since 1.553
*/
public static @CheckForNull URL _findResource(ClassLoader cl, String name) {
return (URL) invoke(FIND_RESOURCE, RuntimeException.class, cl, name);
}
/**
* Calls {@link ClassLoader#findResources}.
* @since 1.553
*/
public static @Nonnull Enumeration<URL> _findResources(ClassLoader cl, String name) throws IOException {
return (Enumeration<URL>) invoke(FIND_RESOURCES, IOException.class, cl, name);
}
/** @deprecated unsafe */
@Deprecated public ClassLoaderReflectionToolkit() {}
/** @deprecated unsafe */
@Deprecated
public Class findLoadedClass(ClassLoader cl, String name) throws InvocationTargetException {
try {
return (Class)FIND_LOADED_CLASS.invoke(cl,name);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
/** @deprecated unsafe */
@Deprecated
public Class findClass(ClassLoader cl, String name) throws InvocationTargetException {
try {
return (Class)FIND_CLASS.invoke(cl,name);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
/** @deprecated unsafe */
@Deprecated
public URL findResource(ClassLoader cl, String name) throws InvocationTargetException {
try {
return (URL)FIND_RESOURCE.invoke(cl,name);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
/** @deprecated unsafe */
@Deprecated
public Enumeration<URL> findResources(ClassLoader cl, String name) throws InvocationTargetException {
try {
return (Enumeration<URL>)FIND_RESOURCES.invoke(cl,name);
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
}