On Fri, Apr 24, 2015 at 1:15 PM, <[email protected]> wrote:

> Repository: isis
> Updated Branches:
>   refs/heads/master 69d559486 -> ee834d9a3
>
>
> ISIS-1137: Now cache a ProxyFactory instance by class (allowing reuse of
> the enhanced class for all instances of that type) rather than creating a
> newly enhanced class as currently.
>
>
> Project: http://git-wip-us.apache.org/repos/asf/isis/repo
> Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/a4f924b1
> Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/a4f924b1
> Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/a4f924b1
>
> Branch: refs/heads/master
> Commit: a4f924b11cf614535e2faf2fb4f7aacdb4c7e1e0
> Parents: 69d5594
> Author: Dan Haywood <[email protected]>
> Authored: Fri Apr 24 10:29:16 2015 +0100
> Committer: Dan Haywood <[email protected]>
> Committed: Fri Apr 24 10:29:16 2015 +0100
>
> ----------------------------------------------------------------------
>  .../isis/core/commons/lang/ArrayExtensions.java |  4 +-
>  .../core/wrapper/WrapperFactoryAbstract.java    |  6 +-
>  .../proxy/ProxyInstantiatorForJavassist.java    | 71 +++++++++++++++-----
>  3 files changed, 61 insertions(+), 20 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/isis/blob/a4f924b1/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
> ----------------------------------------------------------------------
> diff --git
> a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
> b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
> index 25a6f88..df7238b 100644
> ---
> a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
> +++
> b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
> @@ -27,6 +27,8 @@ import java.util.Arrays;
>  import java.util.Collection;
>  import java.util.List;
>
> +import com.google.common.collect.Lists;
> +
>  import org.apache.isis.core.commons.exceptions.IsisException;
>
>  public final class ArrayExtensions {
> @@ -71,7 +73,7 @@ public final class ArrayExtensions {
>      }
>
>      public static <T> T[] combine(final T[]... arrays) {
> -        final List<T> combinedList = new ArrayList<T>();
> +        final List<T> combinedList = Lists.newArrayList();
>          for (final T[] array : arrays) {
>              for (final T t : array) {
>                  combinedList.add(t);
>
>
> http://git-wip-us.apache.org/repos/asf/isis/blob/a4f924b1/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
> ----------------------------------------------------------------------
> diff --git
> a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
> b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
> index ceea4a5..2d251ed 100644
> ---
> a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
> +++
> b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
> @@ -51,11 +51,11 @@ public abstract class WrapperFactoryAbstract
> implements WrapperFactory, Authenti
>      private AdapterManager adapterManager;
>      private ObjectPersistor objectPersistor;
>
> -    private final ProxyContextHandler proxy;
> +    private final ProxyContextHandler proxyContextHandler;
>
>      public WrapperFactoryAbstract(final ProxyInstantiator
> proxyInstantiator) {
>
> -        proxy = new ProxyContextHandler(proxyInstantiator);
> +        proxyContextHandler = new ProxyContextHandler(proxyInstantiator);
>
>          dispatchersByEventClass.put(ObjectTitleEvent.class, new
> InteractionEventDispatcherTypeSafe<ObjectTitleEvent>() {
>              @Override
> @@ -221,7 +221,7 @@ public abstract class WrapperFactoryAbstract
> implements WrapperFactory, Authenti
>      }
>
>      protected <T> T createProxy(final T domainObject, final ExecutionMode
> mode) {
> -        return proxy.proxy(domainObject, this, mode,
> getAuthenticationSessionProvider(), getSpecificationLookup(),
> getAdapterManager(), getObjectPersistor());
> +        return proxyContextHandler.proxy(domainObject, this, mode,
> getAuthenticationSessionProvider(), getSpecificationLookup(),
> getAdapterManager(), getObjectPersistor());
>      }
>
>      @Override
>
>
> http://git-wip-us.apache.org/repos/asf/isis/blob/a4f924b1/core/wrapper/src/main/java/org/apache/isis/core/wrapper/proxy/ProxyInstantiatorForJavassist.java
> ----------------------------------------------------------------------
> diff --git
> a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/proxy/ProxyInstantiatorForJavassist.java
> b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/proxy/ProxyInstantiatorForJavassist.java
> index 3d2b838..cc0ee19 100644
> ---
> a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/proxy/ProxyInstantiatorForJavassist.java
> +++
> b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/proxy/ProxyInstantiatorForJavassist.java
> @@ -19,21 +19,38 @@
>
>  package org.apache.isis.core.wrapper.proxy;
>
> -import java.lang.reflect.InvocationHandler;
>  import java.lang.reflect.Method;
> +import java.util.Map;
>
> -import javassist.util.proxy.MethodFilter;
> -import javassist.util.proxy.MethodHandler;
> -import javassist.util.proxy.ProxyFactory;
> -import javassist.util.proxy.ProxyObject;
> +import com.google.common.collect.MapMaker;
>
>  import org.apache.isis.applib.services.wrapper.WrapperObject;
> +import org.apache.isis.applib.services.wrapper.WrappingObject;
>  import org.apache.isis.core.commons.lang.ArrayExtensions;
> +import
> org.apache.isis.core.metamodel.specloader.classsubstitutor.JavassistEnhanced;
>  import org.apache.isis.core.wrapper.handlers.DelegatingInvocationHandler;
>  import org.apache.isis.core.wrapper.internal.util.Util;
>
> +import javassist.util.proxy.MethodFilter;
> +import javassist.util.proxy.MethodHandler;
> +import javassist.util.proxy.Proxy;
> +import javassist.util.proxy.ProxyFactory;
> +
>  public class ProxyInstantiatorForJavassist implements ProxyInstantiator {
>
> +    /**
> +     * Lazily constructed cache.
> +     */
> +    private final Map<Class, ProxyFactory> proxyFactoryByClass;
> +
>



> +    public ProxyInstantiatorForJavassist() {
> +        this(new MapMaker().concurrencyLevel(10).<Class,
> ProxyFactory>makeMap());
>

I think this should use weak keys to prevent classloader leaks and allow
class unloading.


> +    }
> +
> +    public ProxyInstantiatorForJavassist(Map<Class, ProxyFactory>
> proxyFactoryByClass) {
> +        this.proxyFactoryByClass = proxyFactoryByClass;
> +    }
> +
>      @SuppressWarnings("unchecked")
>      public <T> T instantiateProxy(final DelegatingInvocationHandler<T>
> handler) {
>
> @@ -44,24 +61,40 @@ public class ProxyInstantiatorForJavassist implements
> ProxyInstantiator {
>          if (clazz.isInterface()) {
>              return Util.createInstance(clazz, handler,
> WrapperObject.class);
>          } else {
> -            final Class<T> enhancedClass = createEnhancedClass(clazz,
> handler, WrapperObject.class);
> -            ProxyObject proxyObject = (ProxyObject)
> Util.createInstance(enhancedClass);
> -            proxyObject.setHandler(new MethodHandler() {
> +            final ProxyFactory proxyFactory = proxyFactoryFor(clazz);
> +
> +            final Class<T> enhancedClass = proxyFactory.createClass();
> +            final Proxy proxy = (Proxy)
> Util.createInstance(enhancedClass);
> +
> +            proxy.setHandler(new MethodHandler() {
>                  @Override
>                  public Object invoke(Object self, Method thisMethod,
> Method proceed, Object[] args) throws Throwable {
>                      return handler.invoke(self, thisMethod, args);
>                  }
>              });
> -            return (T) proxyObject;
> +
> +            return (T) proxy;
>          }
>      }
> -
> -    @SuppressWarnings("unchecked")
> -    private static <T> Class<T> createEnhancedClass(final Class<T>
> toProxyClass, final InvocationHandler handler, final Class<?>...
> auxiliaryTypes) {
> -
> +
> +    private <T> ProxyFactory proxyFactoryFor(final Class<T> toProxyClass)
> {
> +        ProxyFactory proxyFactory = proxyFactoryByClass.get(toProxyClass);
> +        if(proxyFactory == null) {
> +            proxyFactory = createProxyFactoryFor(toProxyClass);
> +            proxyFactoryByClass.put(toProxyClass, proxyFactory);
> +        }
> +        return proxyFactory;
> +    }
> +
> +    private <T> ProxyFactory createProxyFactoryFor(final Class<T>
> toProxyClass) {
> +
>          final ProxyFactory proxyFactory = new ProxyFactory();
> +
>          proxyFactory.setSuperclass(toProxyClass);
> -
> proxyFactory.setInterfaces(ArrayExtensions.combine(toProxyClass.getInterfaces(),
> new
> Class<?>[]{org.apache.isis.core.metamodel.specloader.classsubstitutor.JavassistEnhanced.class},
> auxiliaryTypes));
> +        final Class[] types = ArrayExtensions.combine(
> +                toProxyClass.getInterfaces(),
> +                new Class<?>[] { JavassistEnhanced.class,
> WrappingObject.class });
> +        proxyFactory.setInterfaces(types);
>
>          proxyFactory.setFilter(new MethodFilter() {
>              @Override
> @@ -70,8 +103,14 @@ public class ProxyInstantiatorForJavassist implements
> ProxyInstantiator {
>                  return !m.getName().equals("finalize") || m.isBridge();
>              }
>          });
> -
> -        return proxyFactory.createClass();
> +
> +        // this is the default, I believe
> +        // calling it here only because I know that it will throw an
> exception if the code were
> +        // in the future changed such that caching is invalid
> +        // (ie fail fast if future change could introduce a bug)
> +        proxyFactory.setUseCache(true);
> +
> +        return proxyFactory;
>      }
>
>  }
>
>

Reply via email to