use of io.quarkus.deployment.proxy.ProxyFactory in project quarkus by quarkusio.
the class BytecodeRecorderImpl method getRecordingProxy.
public <T> T getRecordingProxy(Class<T> theClass) {
if (existingProxyClasses.containsKey(theClass)) {
return theClass.cast(existingProxyClasses.get(theClass));
}
NewRecorder newRecorder = new NewRecorder(theClass);
existingRecorderValues.put(theClass, newRecorder);
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (staticInit) {
for (int i = 0; i < args.length; ++i) {
if (args[i] instanceof ReturnedProxy) {
ReturnedProxy p = (ReturnedProxy) args[i];
if (!p.__static$$init()) {
throw new RuntimeException("Invalid proxy passed to recorder. Parameter " + i + " of type " + method.getParameterTypes()[i] + " was created in a runtime recorder method, while this recorder is for a static init method. The object will not have been created at the time this method is run.");
}
}
}
}
StoredMethodCall storedMethodCall = new StoredMethodCall(theClass, method, args);
storedMethodCalls.add(storedMethodCall);
Class<?> returnType = method.getReturnType();
if (method.getName().equals("toString") && method.getParameterCount() == 0 && returnType.equals(String.class)) {
return proxy.getClass().getName();
}
boolean voidMethod = method.getReturnType().equals(void.class);
if (!voidMethod && !isProxiable(method.getReturnType())) {
throw new RuntimeException("Cannot use " + method + " as a recorder method as the return type cannot be proxied. Use RuntimeValue to wrap the return value instead.");
}
if (voidMethod) {
return null;
}
ProxyInstance instance = getProxyInstance(returnType);
if (instance == null) {
return null;
}
storedMethodCall.returnedProxy = instance.proxy;
storedMethodCall.proxyId = instance.key;
return instance.proxy;
}
};
try {
if (recordingProxyFactories.containsKey(theClass)) {
return (T) recordingProxyFactories.get(theClass).newInstance(invocationHandler);
}
String proxyNameSuffix = "$$RecordingProxyProxy" + COUNT.incrementAndGet();
ProxyConfiguration<T> proxyConfiguration = new ProxyConfiguration<T>().setSuperClass(theClass).setClassLoader(classLoader).setAnchorClass(getClass()).setProxyNameSuffix(proxyNameSuffix);
ProxyFactory<T> factory = new ProxyFactory<T>(proxyConfiguration);
T recordingProxy = factory.newInstance(invocationHandler);
existingProxyClasses.put(theClass, recordingProxy);
recordingProxyFactories.put(theClass, factory);
if (theClass.getClassLoader() instanceof QuarkusClassLoader) {
((QuarkusClassLoader) theClass.getClassLoader()).addCloseTask(new Runnable() {
@Override
public void run() {
recordingProxyFactories.remove(theClass);
}
});
}
return recordingProxy;
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
}
use of io.quarkus.deployment.proxy.ProxyFactory in project quarkus by quarkusio.
the class BytecodeRecorderImpl method getProxyInstance.
private ProxyInstance getProxyInstance(Class<?> returnType) throws InstantiationException, IllegalAccessException {
boolean returnInterface = returnType.isInterface();
ProxyFactory<?> proxyFactory = returnValueProxy.get(returnType);
if (proxyFactory == null) {
ProxyConfiguration<Object> proxyConfiguration = new ProxyConfiguration<Object>().setSuperClass(returnInterface ? Object.class : (Class) returnType).setClassLoader(classLoader).addAdditionalInterface(ReturnedProxy.class).setAnchorClass(getClass()).setProxyNameSuffix("$$ReturnValueProxy" + COUNT.incrementAndGet());
if (returnInterface) {
proxyConfiguration.addAdditionalInterface(returnType);
}
returnValueProxy.put(returnType, proxyFactory = new ProxyFactory<>(proxyConfiguration));
}
String key = PROXY_KEY + COUNT.incrementAndGet();
Object proxyInstance = proxyFactory.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("__returned$proxy$key")) {
return key;
}
if (method.getName().equals("__static$$init")) {
return staticInit;
}
if (method.getName().equals("toString") && method.getParameterCount() == 0 && method.getReturnType().equals(String.class)) {
return "Runtime proxy of " + returnType + " with id " + key;
}
if (method.getName().equals("hashCode") && method.getParameterCount() == 0 && method.getReturnType().equals(int.class)) {
return System.identityHashCode(proxy);
}
if (method.getName().equals("equals") && method.getParameterCount() == 1 && method.getParameterTypes()[0] == Object.class && method.getReturnType().equals(boolean.class)) {
return proxy == args[0];
}
throw new RuntimeException("You cannot invoke " + method.getName() + "() directly on an object returned from the bytecode recorder, you can only pass it back into the recorder as a parameter");
}
});
return new ProxyInstance(proxyInstance, key);
}
Aggregations