io.github.toolfactory.jvm.Driver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jvm-driver Show documentation
Show all versions of jvm-driver Show documentation
A driver to allow deep interaction with the JVM without any restrictions
/*
* This file is part of ToolFactory JVM driver.
*
* Hosted at: https://github.com/toolfactory/jvm-driver
*
* --
*
* The MIT License (MIT)
*
* Copyright (c) 2021-2023 Luke Hutchison, Roberto Gentili
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
* EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.toolfactory.jvm;
import java.io.Closeable;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import io.github.toolfactory.jvm.util.CleanableSupplier;
import io.github.toolfactory.jvm.util.Properties;
public interface Driver extends Closeable {
public D init();
public T allocateInstance(Class> cls);
public ClassLoader convertToBuiltinClassLoader(ClassLoader classLoader);
public Class> defineHookClass(Class> clientClass, byte[] byteCode);
public Class> getBuiltinClassLoaderClass();
public Class> getClassLoaderDelegateClass();
public Class> getClassByName(String className, Boolean initialize, ClassLoader classLoader, Class> caller);
public MethodHandles.Lookup getConsulter(Class> cls);
public Constructor[] getDeclaredConstructors(Class cls);
public Field[] getDeclaredFields(Class> cls);
public Method[] getDeclaredMethods(Class> cls);
public T getFieldValue(Object target, Field field);
public Package getPackage(ClassLoader classLoader, String packageName);
public Collection getResources(String resourceRelativePath, boolean findFirst, ClassLoader... classLoaders);
public Collection getResources(String resourceRelativePath, boolean findFirst, Collection classLoaders);
public T invoke(Object target, Method method, Object[] params);
public boolean isBuiltinClassLoader(ClassLoader classLoader);
public boolean isClassLoaderDelegate(ClassLoader classLoader);
public T newInstance(Constructor ctor, Object[] params);
public CleanableSupplier>> getLoadedClassesRetriever(ClassLoader classLoader);
public Map retrieveLoadedPackages(ClassLoader classLoader);
public void setAccessible(AccessibleObject object, boolean flag);
public void setFieldValue(Object target, Field field, Object value);
public T throwException(String message, Object... placeHolderReplacements);
public T throwException(Throwable exception);
@Deprecated(since="9.4.0")
public void stop(Thread thread);
@Override
public void close();
@SuppressWarnings("unchecked")
public static class Factory {
private static Map> driverConstructors;
static {
try {
Set classLoaders = new HashSet<>();
classLoaders.add(Factory.class.getClassLoader());
classLoaders.add(Thread.currentThread().getContextClassLoader());
java.util.Properties configuration = Properties.loadFromResourcesAndMerge(
"jvm-driver.properties",
"priority-of-this-configuration",
classLoaders
);
driverConstructors = new ConcurrentHashMap<>();
setDriverClass("defaultDriverClass", configuration.getProperty("driver-factory.default-driver.class"));
setDriverClass("dynamicDriverClass", configuration.getProperty("driver-factory.dynamic-driver.class"));
setDriverClass("hybridDriverClass", configuration.getProperty("driver-factory.hybrid-driver.class"));
setDriverClass("nativeDriverClass", configuration.getProperty("driver-factory.native-driver.class"));
} catch (Throwable exc) {
throw new FactoryException(exc);
}
}
public static Driver getNew() {
try {
try {
return getNewDefault().init();
} catch (InitializeException exc) {
return getNewHybrid().init();
}
} catch (InitializeException exc) {
return getNewNative().init();
}
}
public static D getNew(String className) throws Throwable {
return (D)Class.forName(className).getDeclaredConstructor().newInstance();
}
private static void setDriverClass(String name, String className) {
try {
setDriverClass(name, Class.forName(className));
} catch (ClassNotFoundException exc) {
throw new FactoryException(exc);
}
}
private static void setDriverClass(String name, Class> cls) {
try {
driverConstructors.put(
name,
(Constructor extends Driver>)cls.getDeclaredConstructor()
);
} catch (NoSuchMethodException | SecurityException exc) {
throw new FactoryException(exc);
}
}
public static void setDefaultDriverClass(Class extends Driver> cls) {
setDriverClass("defaultDriverClass", cls);
}
public static void setDefaultDriverClass(String className) {
setDriverClass("defaultDriverClass", className);
}
public static void setHybridDriverClass(Class extends Driver> cls) {
setDriverClass("hybridDriverClass", cls);
}
public static void setHybridDriverClass(String className) {
setDriverClass("hybridDriverClass", className);
}
public static void setDynamicDriverClass(Class extends Driver> cls) {
setDriverClass("dynamicDriverClass", cls);
}
public static void setDynamicDriverClass(String className) {
setDriverClass("dynamicDriverClass", className);
}
public static void setNativeDriverClass(Class extends Driver> cls) {
setDriverClass("nativeDriverClass", cls);
}
public static void setNativeDriverClass(String className) {
setDriverClass("nativeDriverClass", className);
}
public static D getNewDefault() {
try {
return ((D)driverConstructors.get("defaultDriverClass").newInstance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException exc) {
throw new InstantiateException(exc);
}
}
public static D getNewDynamic() {
try {
return ((D)driverConstructors.get("dynamicDriverClass").newInstance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException exc) {
throw new InstantiateException(exc);
}
}
public static D getNewHybrid() {
try {
return ((D)driverConstructors.get("hybridDriverClass").newInstance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException exc) {
throw new InstantiateException(exc);
}
}
public static D getNewNative() {
try {
return ((D)driverConstructors.get("nativeDriverClass").newInstance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException exc) {
throw new InstantiateException(exc);
}
}
public static class FactoryException extends RuntimeException {
private static final long serialVersionUID = 6332920978175279534L;
public FactoryException(Throwable cause) {
super(cause);
}
}
}
public static class InitializeException extends RuntimeException {
private static final long serialVersionUID = -1351844562568567842L;
public InitializeException(String message, Throwable cause) {
super(message, cause);
}
public InitializeException(String message) {
super(message);
}
}
public static class InstantiateException extends RuntimeException {
private static final long serialVersionUID = 558903509767014098L;
public InstantiateException(Throwable cause) {
super(cause);
}
}
}