You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/05/29 19:39:09 UTC

[isis] branch master updated: ISIS-1950: codegen-bytebuddy plugin: first give-it-a-try implementation

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 <ah...@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
ahuber@apache.org.