
com.rbkmoney.woody.api.proxy.ProxyInvocationHandler Maven / Gradle / Ivy
package com.rbkmoney.woody.api.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.BiFunction;
public final class ProxyInvocationHandler implements InvocationHandler {
private final Map callMap;
private final InvocationTargetProvider targetProvider;
public ProxyInvocationHandler(Class iface, InvocationTargetProvider targetProvider, MethodCallerFactory callerFactory, MethodCallInterceptor callInterceptor) {
this.targetProvider = targetProvider;
this.callMap = createCallMap(callInterceptor, targetProvider, iface, callerFactory);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
CallerBundle methodCallerBundle = callMap.get(method);
if (methodCallerBundle != null) {
return methodCallerBundle.interceptor.intercept(proxy, args, methodCallerBundle.caller);
} else {
return method.invoke(targetProvider.getTarget(), args);
}
}
private Map createCallMap(MethodCallInterceptor callInterceptor, InvocationTargetProvider targetProvider, Class iface, MethodCallerFactory callerFactory) {
Class targetType = targetProvider.getTargetType();
if (!iface.isAssignableFrom(targetType)) {
throw new IllegalArgumentException("Target object class doesn't implement referred interface");
}
Map callerMap = new TreeMap<>(MethodShadow.METHOD_COMPARATOR);
Method[] targetIfaceMethods = MethodShadow.getShadowedMethods(targetType, iface);
for (Method method : targetIfaceMethods) {
callerMap.put(MethodShadow.getSameMethod(method, iface), new CallerBundle(callerFactory.getInstance(targetProvider, method), callInterceptor));
}
return addObjectMethods(iface, callerFactory, callerMap);
}
private Map addObjectMethods(Class iface, MethodCallerFactory callerFactory, Map callerMap) {
SingleTargetProvider objTargetProvider = new SingleTargetProvider(Object.class, this);//ref leak on init, assume it's a trusted code
MethodCallInterceptor directCallInterceptor = MethodCallInterceptors.directCallInterceptor();
BiFunction
© 2015 - 2025 Weber Informatics LLC | Privacy Policy