All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidpm.proxybuilder.VirtualProxyBuilder Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
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;
//  }


}