This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push: new 3008d7b ISIS-1950: codegen-bytebuddy plugin: first give-it-a-try implementation 3008d7b is described below commit 3008d7ba01afcb4274daab5257f14b054c088b40 Author: Andi Huber <ahu...@apache.org> AuthorDate: Tue May 29 21:38:44 2018 +0200 ISIS-1950: codegen-bytebuddy plugin: first give-it-a-try implementation Task-Url: https://issues.apache.org/jira/browse/ISIS-1950 --- core/plugins/codegen-bytebuddy/pom.xml | 5 + .../codegen/ProxyFactoryPluginUsingByteBuddy.java | 107 +++++++++++++++++++-- 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/core/plugins/codegen-bytebuddy/pom.xml b/core/plugins/codegen-bytebuddy/pom.xml index 0732c78..02c58e3 100644 --- a/core/plugins/codegen-bytebuddy/pom.xml +++ b/core/plugins/codegen-bytebuddy/pom.xml @@ -61,6 +61,11 @@ <artifactId>byte-buddy</artifactId> <version>${bytebuddy.version}</version> </dependency> + + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + </dependency> <dependency> <groupId>org.apache.isis.core</groupId> diff --git a/core/plugins/codegen-bytebuddy/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingByteBuddy.java b/core/plugins/codegen-bytebuddy/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingByteBuddy.java index dbe3da7..e9fdf46 100644 --- a/core/plugins/codegen-bytebuddy/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingByteBuddy.java +++ b/core/plugins/codegen-bytebuddy/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingByteBuddy.java @@ -1,11 +1,24 @@ package org.apache.isis.core.plugins.codegen; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.function.Function; import java.util.function.Predicate; -import org.apache.isis.commons.internal.exceptions._Exceptions; -import org.apache.isis.core.plugins.codegen.ProxyFactory; -import org.apache.isis.core.plugins.codegen.ProxyFactoryPlugin; +import javax.annotation.Nullable; + +import org.apache.isis.commons.internal._Constants; +import org.apache.isis.commons.internal.base._Casts; +import org.apache.isis.commons.internal.base._NullSafe; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; + +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.NamingStrategy; +import net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ImplementationDefinition; +import net.bytebuddy.implementation.InvocationHandlerAdapter; +import net.bytebuddy.matcher.ElementMatchers; public class ProxyFactoryPluginUsingByteBuddy implements ProxyFactoryPlugin { @@ -16,9 +29,91 @@ public class ProxyFactoryPluginUsingByteBuddy implements ProxyFactoryPlugin { Predicate<Method> methodFilter, Class<?>[] constructorArgTypes) { - _Exceptions.throwNotImplemented(); - // TODO Auto-generated method stub - return null; + final Objenesis objenesis = new ObjenesisStd(); + + final ImplementationDefinition<T> proxyDef = new ByteBuddy() + .with(new NamingStrategy.SuffixingRandom("bb")) + .subclass(base) + .implement(interfaces) + .method(ElementMatchers.any()); + + final Function<InvocationHandler, Class<? extends T>> proxyClassFactory = handler-> + proxyDef.intercept(InvocationHandlerAdapter.of(handler)) + .make() + .load(base.getClassLoader()) + .getLoaded(); + + return new ProxyFactory<T>() { + + @Override + public T createInstance(InvocationHandler handler, boolean initialize) { + + try { + + if(initialize) { + ensureSameSize(constructorArgTypes, null); + return _Casts.uncheckedCast( createUsingConstructor(handler, null) ); + } else { + return _Casts.uncheckedCast( createNotUsingConstructor(handler) ); + } + + } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | + IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + + } + + @Override + public T createInstance(InvocationHandler handler, Object[] constructorArgs) { + + ensureNonEmtpy(constructorArgs); + ensureSameSize(constructorArgTypes, constructorArgs); + + try { + return _Casts.uncheckedCast( createUsingConstructor(handler, constructorArgs) ); + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | + IllegalArgumentException | InvocationTargetException | SecurityException e) { + throw new RuntimeException(e); + } + } + + // -- HELPER (create w/o initialize) + + private Object createNotUsingConstructor(InvocationHandler invocationHandler) { + final Class<? extends T> proxyClass = proxyClassFactory.apply(invocationHandler); + final Object object = objenesis.newInstance(proxyClass); + return object; + } + + // -- HELPER (create with initialize) + + private Object createUsingConstructor(InvocationHandler invocationHandler, @Nullable Object[] constructorArgs) + throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + final Class<? extends T> proxyClass = proxyClassFactory.apply(invocationHandler); + return proxyClass + .getConstructor(constructorArgTypes==null ? _Constants.emptyClasses : constructorArgTypes) + .newInstance(constructorArgs==null ? _Constants.emptyObjects : constructorArgs); + } + + }; + + } + + // -- HELPER + + private static void ensureSameSize(Class<?>[] a, Object[] b) { + if(_NullSafe.size(a) != _NullSafe.size(b)) { + throw new IllegalArgumentException(String.format("Constructor arg count expected %d, got %d.", + _NullSafe.size(a), _NullSafe.size(b) )); + } + } + + private static void ensureNonEmtpy(Object[] a) { + if(_NullSafe.isEmpty(a)) { + throw new IllegalArgumentException(String.format("Contructor args count expected > 0, got %d.", + _NullSafe.size(a) )); + } } } -- To stop receiving notification emails like this one, please contact ahu...@apache.org.