org.rapidpm.proxybuilder.VirtualProxyBuilder Maven / Gradle / Ivy
package org.rapidpm.proxybuilder;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry;
import org.rapidpm.proxybuilder.type.metrics.MetricsRegistry;
import org.rapidpm.proxybuilder.type.virtual.Concurrency;
import org.rapidpm.proxybuilder.type.virtual.ProxyGenerator;
import org.rapidpm.proxybuilder.type.virtual.ProxyType;
import org.rapidpm.proxybuilder.type.virtual.dynamic.DefaultConstructorServiceFactory;
import org.rapidpm.proxybuilder.type.virtual.dynamic.ServiceStrategyFactoryNotThreadSafe;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by sven on 28.04.15.
*/
public class VirtualProxyBuilder {
private T original;
private Class clazz;
private List securityRules = new ArrayList<>();
private VirtualProxyBuilder() {
}
public static VirtualProxyBuilder createBuilder(Class clazz, T original) {
final VirtualProxyBuilder virtualProxyBuilder = new VirtualProxyBuilder<>();
virtualProxyBuilder.original = original;
virtualProxyBuilder.clazz = clazz;
return virtualProxyBuilder;
}
/**
* Hier noch die Kombinationen abfangen zwischen Dynamic und Concurrent
*
* @param clazz
* @param original
* @param concurrency
* @param
* @param
*
* @return
*/
public static VirtualProxyBuilder createBuilder(Class clazz, Class original, Concurrency concurrency) {
final VirtualProxyBuilder virtualProxyBuilder = new VirtualProxyBuilder<>();
final I proxy = ProxyGenerator.newBuilder()
.withSubject(clazz)
.withRealClass(original)
.withConcurrency(concurrency)
.withServiceFactory(new DefaultConstructorServiceFactory<>(original))
.withServiceStrategyFactory(new ServiceStrategyFactoryNotThreadSafe())
.withType(ProxyType.DYNAMIC)
.build()
.make();
virtualProxyBuilder.original = (T) proxy;
virtualProxyBuilder.clazz = clazz;
return virtualProxyBuilder;
}
public VirtualProxyBuilder addSecurityRule(SecurityRule rule) {
securityRules.add(rule);
return this;
}
//die originalReihenfolge behalten in der die Methoden aufgerufen worden sind.
public I build() {
Collections.reverse(securityRules);
securityRules.forEach(this::buildAddSecurityRule);
return this.original;
}
private VirtualProxyBuilder buildAddSecurityRule(SecurityRule rule) {
final InvocationHandler invocationHandler = new InvocationHandler() {
private T original = VirtualProxyBuilder.this.original;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final boolean checkRule = rule.checkRule();
if (checkRule) {
return method.invoke(original, args);
} else {
return null;
}
}
};
createProxy(invocationHandler);
return this;
}
private void createProxy(InvocationHandler invocationHandler) {
final ClassLoader classLoader = original.getClass().getClassLoader();
final Class[] interfaces = {clazz};
final Object nextProxy = Proxy.newProxyInstance(
classLoader,
interfaces,
invocationHandler);
original = (T) clazz.cast(nextProxy);
}
//wo die Metriken ablegen ?
public VirtualProxyBuilder addMetrics() {
final MetricRegistry metrics = MetricsRegistry.getInstance().getMetrics();
final InvocationHandler invocationHandler = new InvocationHandler() {
private final T original = VirtualProxyBuilder.this.original;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final long start = System.nanoTime();
final Object invoke = method.invoke(original, args);
final long stop = System.nanoTime();
Histogram methodCalls = metrics.histogram(clazz.getSimpleName() + "." + method.getName());
methodCalls.update((stop - start));
return invoke;
}
};
createProxy(invocationHandler);
return this;
}
public VirtualProxyBuilder addIPreAction(PreAction preAction) {
final InvocationHandler invocationHandler = new InvocationHandler() {
private final T original = VirtualProxyBuilder.this.original;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
preAction.execute(original, method, args);
final Object invoke = method.invoke(original, args);
return invoke;
}
};
createProxy(invocationHandler);
return this;
}
public VirtualProxyBuilder addIPostAction(PreAction postAction) {
final InvocationHandler invocationHandler = new InvocationHandler() {
private final T original = VirtualProxyBuilder.this.original;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final Object invoke = method.invoke(original, args);
postAction.execute(original, method, args);
return invoke;
}
};
createProxy(invocationHandler);
return this;
}
public interface PreAction {
void execute(T original, Method method, Object[] args) throws Throwable;
}
public interface PostAction {
void execute(T original, Method method, Object[] args) throws Throwable;
}
// public ProxyBuilder addLogging() {
//
// final InvocationHandler invocationHandler = new InvocationHandler() {
//
// private final T original = ProxyBuilder.this.original;
//
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// final long start = System.nanoTime();
// final Object invoke = method.invoke(original, args);
// final long stop = System.nanoTime();
//// methodCalls.update((stop - start));
// return invoke;
// }
// };
//
//
// createProxy(invocationHandler);
// return this;
// }
}