You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ta...@apache.org on 2017/06/26 18:13:45 UTC
[2/2] deltaspike git commit: DELTASPIKE-1274 Refactor proxy-module /
improve performance
DELTASPIKE-1274 Refactor proxy-module / improve performance
Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/b4c2ed26
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/b4c2ed26
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/b4c2ed26
Branch: refs/heads/master
Commit: b4c2ed26341a732f475db440c1b16f6a77115617
Parents: cdb8650
Author: Thomas Andraschko <ta...@apache.org>
Authored: Mon Jun 26 20:13:35 2017 +0200
Committer: Thomas Andraschko <ta...@apache.org>
Committed: Mon Jun 26 20:13:35 2017 +0200
----------------------------------------------------------------------
.../core/api/provider/BeanProvider.java | 14 +-
.../deltaspike/core/util/ReflectionUtils.java | 8 +
.../api/DeltaSpikeProxyContextualLifecycle.java | 89 +--
.../proxy/api/DeltaSpikeProxyFactory.java | 86 +--
.../deltaspike/proxy/spi/DeltaSpikeProxy.java | 12 +
.../spi/DeltaSpikeProxyClassGenerator.java | 51 ++
.../DeltaSpikeProxyClassGeneratorHolder.java | 63 +++
.../proxy/spi/ProxyClassGenerator.java | 49 --
.../DeltaSpikeProxyInterceptorLookup.java | 112 ++++
.../DeltaSpikeProxyInvocationContext.java | 125 +++++
.../DeltaSpikeProxyInvocationHandler.java | 131 +++++
...ltaSpikeProxyInvocationWrapperException.java | 31 ++
.../util/EnableInterceptorsProxyFactory.java | 17 +-
.../DeltaSpikeProxyClassGeneratorHolder.xml | 24 +
.../main/resources/OSGI-INF/GeneratorHolder.xml | 24 -
.../impl/AsmDeltaSpikeProxyClassGenerator.java | 548 +++++++++++++++++++
.../proxy/impl/AsmProxyClassGenerator.java | 494 -----------------
.../AbstractManualInvocationHandler.java | 72 ---
.../DelegateManualInvocationHandler.java | 49 --
.../InterceptManualInvocationHandler.java | 56 --
.../impl/invocation/InterceptorLookup.java | 109 ----
.../invocation/ManualInvocationContext.java | 136 -----
...nualInvocationThrowableWrapperException.java | 31 --
...pike.proxy.spi.DeltaSpikeProxyClassGenerator | 96 ++++
...che.deltaspike.proxy.spi.ProxyClassGenerator | 96 ----
.../AsmDeltaSpikeProxyClassGenerator.xml | 25 +
.../OSGI-INF/AsmProxyClassGenerator.xml | 25 -
.../proxy/impl/AsmProxyClassGeneratorTest.java | 2 +-
28 files changed, 1337 insertions(+), 1238 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
index e5674ce..7e9b05b 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java
@@ -398,7 +398,19 @@ public final class BeanProvider
return getBeanDefinitions(type, optional, includeDefaultScopedBeans, beanManager);
}
- private static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type,
+ /**
+ * Get a set of {@link Bean} definitions by type, regardless of qualifiers.
+ *
+ * @param type the type of the bean in question
+ * @param optional if <code>true</code> it will return an empty set if no bean could be found.
+ * Otherwise it will throw an {@code IllegalStateException}
+ * @param includeDefaultScopedBeans specifies whether dependent scoped beans should be included in the result
+ * @param <T> target type
+ * @param beanManager the {@link BeanManager} to use
+ *
+ * @return the resolved set of {@link Bean} definitions or an empty set if optional is true
+ */
+ public static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type,
boolean optional,
boolean includeDefaultScopedBeans,
BeanManager beanManager)
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
index baab6a5..bfbe873 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
@@ -504,4 +504,12 @@ public abstract class ReflectionUtils
return typeHash;
}
+
+ public static boolean hasSameSignature(Method a, Method b)
+ {
+ return a.getName().equals(b.getName())
+ && a.getReturnType().equals(b.getReturnType())
+ && Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
+ }
+
}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
index a58e2e7..c06aeef 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java
@@ -18,8 +18,8 @@
*/
package org.apache.deltaspike.proxy.api;
-import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
import java.util.Set;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
@@ -28,10 +28,11 @@ import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.PassivationCapable;
-import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.core.util.ExceptionUtils;
import org.apache.deltaspike.core.util.metadata.builder.ContextualLifecycle;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
/**
* {@link ContextualLifecycle} which handles a complete lifecycle of a proxy:
@@ -47,9 +48,14 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
{
private final Class<T> proxyClass;
private final Class<H> delegateInvocationHandlerClass;
+ private final Method[] delegateMethods;
private final Class<T> targetClass;
+ private final BeanManager beanManager;
+
+ private DeltaSpikeProxyInvocationHandler deltaSpikeProxyInvocationHandler;
private InjectionTarget<T> injectionTarget;
+ private Bean<H> handlerBean;
private CreationalContext<?> creationalContextOfDependentHandler;
public DeltaSpikeProxyContextualLifecycle(Class<T> targetClass,
@@ -60,7 +66,9 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
this.targetClass = targetClass;
this.delegateInvocationHandlerClass = delegateInvocationHandlerClass;
this.proxyClass = proxyFactory.getProxyClass(beanManager, targetClass);
-
+ this.delegateMethods = proxyFactory.getDelegateMethods(targetClass);
+ this.beanManager = beanManager;
+
if (!targetClass.isInterface())
{
AnnotatedType<T> annotatedType = beanManager.createAnnotatedType(this.targetClass);
@@ -70,20 +78,22 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
@Override
public T create(Bean bean, CreationalContext creationalContext)
- {
+ {
try
{
- T instance;
+ lazyInit();
+
+ T instance = proxyClass.newInstance();
- if (delegateInvocationHandlerClass == null)
- {
- instance = proxyClass.newInstance();
- }
- else
+ DeltaSpikeProxy deltaSpikeProxy = ((DeltaSpikeProxy) instance);
+ deltaSpikeProxy.setInvocationHandler(deltaSpikeProxyInvocationHandler);
+
+ // optional
+ if (delegateInvocationHandlerClass != null)
{
H delegateInvocationHandler = instantiateDelegateInvocationHandler();
- Constructor<T> constructor = proxyClass.getConstructor(InvocationHandler.class);
- instance = constructor.newInstance(delegateInvocationHandler);
+ deltaSpikeProxy.setDelegateInvocationHandler(delegateInvocationHandler);
+ deltaSpikeProxy.setDelegateMethods(delegateMethods);
}
if (this.injectionTarget != null)
@@ -119,34 +129,49 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler>
creationalContext.release();
}
- protected H instantiateDelegateInvocationHandler()
+ private void lazyInit()
{
- Set<Bean<H>> handlerBeans = BeanProvider.getBeanDefinitions(this.delegateInvocationHandlerClass, false, true);
-
- if (handlerBeans.size() != 1)
+ if (this.deltaSpikeProxyInvocationHandler == null)
{
- StringBuilder beanInfo = new StringBuilder();
- for (Bean<H> bean : handlerBeans)
+ init();
+ }
+ }
+
+ private synchronized void init()
+ {
+ if (this.deltaSpikeProxyInvocationHandler == null)
+ {
+ this.deltaSpikeProxyInvocationHandler = BeanProvider.getContextualReference(
+ beanManager, DeltaSpikeProxyInvocationHandler.class, false);
+
+ Set<Bean<H>> handlerBeans = BeanProvider.getBeanDefinitions(
+ delegateInvocationHandlerClass, false, true, beanManager);
+ if (handlerBeans.size() != 1)
{
- if (beanInfo.length() != 0)
+ StringBuilder beanInfo = new StringBuilder();
+ for (Bean<H> bean : handlerBeans)
{
- beanInfo.append(", ");
- }
- beanInfo.append(bean);
+ if (beanInfo.length() != 0)
+ {
+ beanInfo.append(", ");
+ }
+ beanInfo.append(bean);
- if (bean instanceof PassivationCapable)
- {
- beanInfo.append(" bean-id: ").append(((PassivationCapable)bean).getId());
+ if (bean instanceof PassivationCapable)
+ {
+ beanInfo.append(" bean-id: ").append(((PassivationCapable) bean).getId());
+ }
}
- }
- throw new IllegalStateException(handlerBeans.size() + " beans found for "
- + this.delegateInvocationHandlerClass + " found beans: " + beanInfo.toString());
+ throw new IllegalStateException(handlerBeans.size() + " beans found for "
+ + delegateInvocationHandlerClass + " found beans: " + beanInfo.toString());
+ }
+ this.handlerBean = handlerBeans.iterator().next();
}
-
- Bean<H> handlerBean = handlerBeans.iterator().next();
-
- BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+ }
+
+ protected H instantiateDelegateInvocationHandler()
+ {
CreationalContext<?> creationalContext = beanManager.createCreationalContext(handlerBean);
H handlerInstance = (H) beanManager.getReference(handlerBean,
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
index 19a8099..dd41c83 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java
@@ -22,7 +22,6 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.enterprise.inject.spi.BeanManager;
@@ -30,54 +29,15 @@ import javax.enterprise.inject.spi.BeanManager;
import javax.interceptor.InterceptorBinding;
import org.apache.deltaspike.core.util.ClassUtils;
-import org.apache.deltaspike.core.util.ServiceUtils;
-import org.apache.deltaspike.proxy.spi.ProxyClassGenerator;
+import org.apache.deltaspike.core.util.ReflectionUtils;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGeneratorHolder;
public abstract class DeltaSpikeProxyFactory
{
private static final String SUPER_ACCESSOR_METHOD_SUFFIX = "$super";
-
- public static class GeneratorHolder
- {
- private static ProxyClassGenerator generator;
-
- /**
- * Setter invoked by OSGi Service Component Runtime.
- *
- * @param generator
- * generator service
- */
- public void setGenerator(ProxyClassGenerator generator)
- {
- GeneratorHolder.generator = generator;
- }
- }
-
- /**
- * Looks up a unique service implementation.
- *
- * @return ProxyClassGenerator service
- */
- private static ProxyClassGenerator lookupService()
- {
- if (GeneratorHolder.generator == null)
- {
- List<ProxyClassGenerator> proxyClassGeneratorList = ServiceUtils
- .loadServiceImplementations(ProxyClassGenerator.class);
-
- if (proxyClassGeneratorList.size() != 1)
- {
- throw new IllegalStateException(proxyClassGeneratorList.size()
- + " implementations of " + ProxyClassGenerator.class.getName()
- + " found. Expected exactly one implementation.");
- }
- GeneratorHolder.generator = proxyClassGeneratorList.get(0);
- }
- return GeneratorHolder.generator;
- }
-
- public <T> Class<T> resolveAlreadyDefinedProxyClass(Class<T> targetClass)
+ private <T> Class<T> resolveAlreadyDefinedProxyClass(Class<T> targetClass)
{
Class<T> proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass),
targetClass,
@@ -106,7 +66,7 @@ public abstract class DeltaSpikeProxyFactory
{
ArrayList<Method> allMethods = collectAllMethods(targetClass);
ArrayList<Method> interceptMethods = filterInterceptMethods(targetClass, allMethods);
- ArrayList<Method> delegateMethods = getDelegateMethods(targetClass, allMethods);
+ Method[] delegateMethods = getDelegateMethods(targetClass);
// check if a interceptor is defined on class level. if not, skip interceptor methods
if (interceptMethods != null
@@ -126,15 +86,14 @@ public abstract class DeltaSpikeProxyFactory
}
}
- ProxyClassGenerator proxyClassGenerator = lookupService();
+ DeltaSpikeProxyClassGenerator proxyClassGenerator = DeltaSpikeProxyClassGeneratorHolder.lookup();
proxyClass = proxyClassGenerator.generateProxyClass(classLoader,
targetClass,
getProxyClassSuffix(),
SUPER_ACCESSOR_METHOD_SUFFIX,
getAdditionalInterfacesToImplement(targetClass),
- delegateMethods == null ? new Method[0]
- : delegateMethods.toArray(new Method[delegateMethods.size()]),
+ delegateMethods,
interceptMethods == null ? new Method[0]
: interceptMethods.toArray(new Method[interceptMethods.size()]));
}
@@ -142,7 +101,7 @@ public abstract class DeltaSpikeProxyFactory
return proxyClass;
}
- protected boolean containsInterceptorBinding(BeanManager beanManager, Annotation[] annotations)
+ private boolean containsInterceptorBinding(BeanManager beanManager, Annotation[] annotations)
{
for (Annotation annotation : annotations)
{
@@ -169,12 +128,12 @@ public abstract class DeltaSpikeProxyFactory
return false;
}
- protected String constructProxyClassName(Class<?> clazz)
+ private String constructProxyClassName(Class<?> clazz)
{
return clazz.getName() + getProxyClassSuffix();
}
- protected static String constructSuperAccessorMethodName(Method method)
+ private static String constructSuperAccessorMethodName(Method method)
{
return method.getName() + SUPER_ACCESSOR_METHOD_SUFFIX;
}
@@ -197,14 +156,7 @@ public abstract class DeltaSpikeProxyFactory
return clazz.getName().endsWith(getProxyClassSuffix());
}
- protected boolean hasSameSignature(Method a, Method b)
- {
- return a.getName().equals(b.getName())
- && a.getReturnType().equals(b.getReturnType())
- && Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
- }
-
- protected boolean ignoreMethod(Method method, List<Method> methods)
+ private boolean ignoreMethod(Method method, List<Method> methods)
{
// we have no interest in generics bridge methods
if (method.isBridge())
@@ -227,7 +179,7 @@ public abstract class DeltaSpikeProxyFactory
// check if a method with the same signature is already available
for (Method currentMethod : methods)
{
- if (hasSameSignature(currentMethod, method))
+ if (ReflectionUtils.hasSameSignature(currentMethod, method))
{
return true;
}
@@ -338,5 +290,19 @@ public abstract class DeltaSpikeProxyFactory
protected abstract ArrayList<Method> getDelegateMethods(Class<?> targetClass, ArrayList<Method> allMethods);
protected abstract String getProxyClassSuffix();
+
+
+ public Method[] getDelegateMethods(Class<?> targetClass)
+ {
+ ArrayList<Method> allMethods = collectAllMethods(targetClass);
+ ArrayList<Method> delegateMethods = getDelegateMethods(targetClass, allMethods);
+
+ if (delegateMethods == null)
+ {
+ return new Method[0];
+ }
+
+ return delegateMethods.toArray(new Method[delegateMethods.size()]);
+ }
}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
index d58b87d..774ca2b 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxy.java
@@ -19,13 +19,25 @@
package org.apache.deltaspike.proxy.spi;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
/**
* Interface which will automatically be implemented by the proxy instance.
*/
public interface DeltaSpikeProxy
{
+ void setInvocationHandler(DeltaSpikeProxyInvocationHandler invocationHandler);
+
+ DeltaSpikeProxyInvocationHandler getInvocationHandler();
+
+
void setDelegateInvocationHandler(InvocationHandler delegateInvocationHandler);
InvocationHandler getDelegateInvocationHandler();
+
+
+ void setDelegateMethods(Method[] methods);
+
+ Method[] getDelegateMethods();
}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
new file mode 100644
index 0000000..cbef5df
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi;
+
+public interface DeltaSpikeProxyClassGenerator
+{
+ /**
+ * Generates a proxy class from the given source class, which also implements {@link DeltaSpikeProxy}.
+ * The proxy class will be generated in the same package as the original class
+ * and the suffix will be appended to the name of the class.
+ *
+ * @param <T> The target class.
+ * @param classLoader The {@link ClassLoader} to be used to define the proxy class.
+ * @param targetClass The class to proxy.
+ * @param suffix The classname suffix.
+ * @param superAccessorMethodSuffix It's required to generate methods which just invokes the original method.
+ * We generate them with the same name as the original method
+ * and append the suffix.
+ * @param additionalInterfaces Additional interfaces which should be implemented.
+ * Please note that you must also pass new methods via <c>delegateMethods</c>.
+ * @param delegateMethods Methods which should be delegated to the
+ * {@link DeltaSpikeProxy#getDelegateInvocationHandler()}
+ * instead of invoking the original method.
+ * @param interceptMethods Methods which should be intercepted (to call interceptors or decorators)
+ * before invoking the original method.
+ * @return The generated proxy class.
+ */
+ <T> Class<T> generateProxyClass(ClassLoader classLoader,
+ Class<T> targetClass,
+ String suffix,
+ String superAccessorMethodSuffix,
+ Class<?>[] additionalInterfaces,
+ java.lang.reflect.Method[] delegateMethods,
+ java.lang.reflect.Method[] interceptMethods);
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
new file mode 100644
index 0000000..6f04d59
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/DeltaSpikeProxyClassGeneratorHolder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi;
+
+import java.util.List;
+import org.apache.deltaspike.core.util.ServiceUtils;
+
+// TODO it would be great if we could just rewrite it to an AppScoped bean
+public class DeltaSpikeProxyClassGeneratorHolder
+{
+ private static DeltaSpikeProxyClassGenerator generator;
+
+ /**
+ * Setter invoked by OSGi Service Component Runtime.
+ *
+ * @param generator generator service
+ */
+ public void setGenerator(DeltaSpikeProxyClassGenerator generator)
+ {
+ this.generator = generator;
+ }
+
+ /**
+ * Looks up a unique service implementation.
+ *
+ * @return ProxyClassGenerator service
+ */
+ public static DeltaSpikeProxyClassGenerator lookup()
+ {
+ if (generator == null)
+ {
+ List<DeltaSpikeProxyClassGenerator> proxyClassGeneratorList =
+ ServiceUtils.loadServiceImplementations(DeltaSpikeProxyClassGenerator.class);
+
+ if (proxyClassGeneratorList.size() != 1)
+ {
+ throw new IllegalStateException(proxyClassGeneratorList.size()
+ + " implementations of " + DeltaSpikeProxyClassGenerator.class.getName()
+ + " found. Expected exactly one implementation.");
+ }
+
+ generator = proxyClassGeneratorList.get(0);
+ }
+
+ return generator;
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
deleted file mode 100644
index cc9ffa6..0000000
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/ProxyClassGenerator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.proxy.spi;
-
-public interface ProxyClassGenerator
-{
- /**
- * Generates a proxy class from the given source class.
- * The proxy class will be generated in the same package as the original class
- * and the suffix will be appended to the name of the class.
- *
- * @param <T> The target class.
- * @param classLoader The {@link ClassLoader} to be used to define the proxy class.
- * @param targetClass The class to proxy.
- * @param suffix The classname suffix.
- * @param superAccessorMethodSuffix It's required to generate methods which just invokes the original method.
- * We generate them with the same name as the original method
- * and append the suffix.
- * @param additionalInterfaces Additional interfaces which should be implemented.
- * @param delegateMethods Methods which should be delegated to the {@code delegateInvocationHandlerClass}
- * instead of invoking the original method.
- * @param interceptMethods Methods which should be intercepted (to call interceptors or decorators)
- * before invoking the original method.
- * @return The generated proxy class.
- */
- <T> Class<T> generateProxyClass(ClassLoader classLoader,
- Class<T> targetClass,
- String suffix,
- String superAccessorMethodSuffix,
- Class<?>[] additionalInterfaces,
- java.lang.reflect.Method[] delegateMethods,
- java.lang.reflect.Method[] interceptMethods);
-}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
new file mode 100644
index 0000000..58e8e1b
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInterceptorLookup.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InterceptionType;
+import javax.enterprise.inject.spi.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+
+/**
+ * Utility which stores the information about configured interceptors for each method.
+ */
+@ApplicationScoped
+class DeltaSpikeProxyInterceptorLookup
+{
+ private final Map<Method, List<Interceptor<?>>> cache = new HashMap<Method, List<Interceptor<?>>>();
+
+ public List<Interceptor<?>> lookup(Object instance, Method method)
+ {
+ List<Interceptor<?>> interceptors = cache.get(method);
+
+ if (interceptors == null)
+ {
+ interceptors = resolveInterceptors(instance, method);
+ cache.put(method, interceptors);
+ }
+
+ return interceptors;
+ }
+
+ private List<Interceptor<?>> resolveInterceptors(Object instance, Method method)
+ {
+ BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
+
+ Annotation[] interceptorBindings = extractInterceptorBindings(beanManager, instance, method);
+ if (interceptorBindings.length > 0)
+ {
+ return beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE, interceptorBindings);
+ }
+
+ return new ArrayList<Interceptor<?>>();
+ }
+
+ private Annotation[] extractInterceptorBindings(BeanManager beanManager, Object instance, Method method)
+ {
+ ArrayList<Annotation> bindings = new ArrayList<Annotation>();
+
+ addInterceptorBindings(beanManager, bindings, instance.getClass().getDeclaredAnnotations());
+ addInterceptorBindings(beanManager, bindings, method.getDeclaredAnnotations());
+
+ return bindings.toArray(new Annotation[bindings.size()]);
+ }
+
+ private void addInterceptorBindings(BeanManager beanManager, ArrayList<Annotation> bindings,
+ Annotation[] declaredAnnotations)
+ {
+ for (Annotation annotation : declaredAnnotations)
+ {
+ if (bindings.contains(annotation))
+ {
+ continue;
+ }
+
+ Class<? extends Annotation> annotationType = annotation.annotationType();
+
+ if (annotationType.isAnnotationPresent(InterceptorBinding.class))
+ {
+ bindings.add(annotation);
+ }
+
+ if (beanManager.isStereotype(annotationType))
+ {
+ for (Annotation subAnnotation : annotationType.getDeclaredAnnotations())
+ {
+ if (bindings.contains(subAnnotation))
+ {
+ continue;
+ }
+
+ if (subAnnotation.annotationType().isAnnotationPresent(InterceptorBinding.class))
+ {
+ bindings.add(subAnnotation);
+ }
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
new file mode 100644
index 0000000..c99b4bb
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationContext.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InterceptionType;
+import javax.enterprise.inject.spi.Interceptor;
+
+import org.apache.deltaspike.core.util.interceptor.AbstractInvocationContext;
+
+/**
+ * {@link javax.interceptor.InvocationContext} implementation to support interceptor invocation
+ * before proceed with the original method or delegation.
+ */
+@Typed
+public class DeltaSpikeProxyInvocationContext<T, H> extends AbstractInvocationContext<T>
+{
+ protected List<Interceptor<H>> interceptors;
+ protected int interceptorIndex;
+ protected DeltaSpikeProxyInvocationHandler invocationHandler;
+
+ protected BeanManager beanManager;
+
+ protected boolean proceedOriginal;
+ protected Object proceedOriginalReturnValue;
+
+ public DeltaSpikeProxyInvocationContext(DeltaSpikeProxyInvocationHandler invocationHandler,
+ BeanManager beanManager, List<Interceptor<H>> interceptors,
+ T target, Method method, Object[] parameters, Object timer)
+ {
+ super(target, method, parameters, timer);
+
+ this.invocationHandler = invocationHandler;
+ this.interceptors = interceptors;
+ this.beanManager = beanManager;
+
+ this.interceptorIndex = 0;
+ }
+
+ @Override
+ public Object proceed() throws Exception
+ {
+ if (proceedOriginal)
+ {
+ return null;
+ }
+
+ if (interceptors.size() > interceptorIndex)
+ {
+ Interceptor<H> interceptor = null;
+ CreationalContext<H> creationalContext = null;
+ H interceptorInstance = null;
+
+ try
+ {
+ interceptor = interceptors.get(interceptorIndex++);
+ creationalContext = beanManager.createCreationalContext(interceptor);
+ interceptorInstance = interceptor.create(creationalContext);
+
+ return interceptor.intercept(InterceptionType.AROUND_INVOKE, interceptorInstance, this);
+ }
+ finally
+ {
+ if (creationalContext != null)
+ {
+ if (interceptorInstance != null && interceptor != null)
+ {
+ interceptor.destroy(interceptorInstance, creationalContext);
+ }
+
+ creationalContext.release();
+ }
+ }
+ }
+
+
+ // workaround for OWB 1.1, otherwise we could just return the proceedOriginalReturnValue here
+ try
+ {
+ proceedOriginal = true;
+ proceedOriginalReturnValue = invocationHandler.proceed(target, method, parameters);
+ }
+ catch (Exception e)
+ {
+ throw e;
+ }
+ catch (Throwable e)
+ {
+ // wrap the Throwable here as interceptors declared only "throws Exception"
+ throw new DeltaSpikeProxyInvocationWrapperException(e);
+ }
+
+ return null;
+ }
+
+ public boolean isProceedOriginal()
+ {
+ return proceedOriginal;
+ }
+
+ public Object getProceedOriginalReturnValue()
+ {
+ return proceedOriginalReturnValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
new file mode 100644
index 0000000..0f07cf8
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationHandler.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Interceptor;
+import javax.inject.Inject;
+import org.apache.deltaspike.core.util.ReflectionUtils;
+import org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+
+/**
+ * The {@link InvocationHandler} which will be called directly by the proxy methods.
+ * For both <code>delegateMethods</code> and <code>interceptMethods</code>
+ * (See: {@link org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator}).
+ *
+ * This {@link InvocationHandler} first executes CDI interceptors (if defined on method or class level) and
+ * after that the original method or the {@link DeltaSpikeProxy#getDelegateInvocationHandler()} will be executed,
+ * depending if the invoked method is a <code>intercept</code> or <code>delegate</code> method.
+ */
+@ApplicationScoped
+public class DeltaSpikeProxyInvocationHandler implements InvocationHandler
+{
+ @Inject
+ private BeanManager beanManager;
+
+ @Inject
+ private DeltaSpikeProxyInterceptorLookup interceptorLookup;
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable
+ {
+ // check if interceptors are defined, otherwise just call the original logik
+ List<Interceptor<?>> interceptors = interceptorLookup.lookup(proxy, method);
+ if (interceptors != null && !interceptors.isEmpty())
+ {
+ try
+ {
+ DeltaSpikeProxyInvocationContext invocationContext = new DeltaSpikeProxyInvocationContext(
+ this, beanManager, interceptors, proxy, method, parameters, null);
+
+ Object returnValue = invocationContext.proceed();
+
+ if (invocationContext.isProceedOriginal())
+ {
+ return invocationContext.getProceedOriginalReturnValue();
+ }
+
+ return returnValue;
+ }
+ catch (DeltaSpikeProxyInvocationWrapperException e)
+ {
+ throw e.getCause();
+ }
+ }
+
+ return proceed(proxy, method, parameters);
+ }
+
+ /**
+ * Calls the original method or delegates to {@link DeltaSpikeProxy#getDelegateInvocationHandler()}
+ * after invoking the interceptor chain.
+ *
+ * @param proxy The current proxy instance.
+ * @param method The current invoked method.
+ * @param parameters The method parameter.
+ * @return The original value from the original method.
+ * @throws Throwable
+ */
+ protected Object proceed(Object proxy, Method method, Object[] parameters) throws Throwable
+ {
+ DeltaSpikeProxy deltaSpikeProxy = (DeltaSpikeProxy) proxy;
+
+ if (contains(deltaSpikeProxy.getDelegateMethods(), method))
+ {
+ return deltaSpikeProxy.getDelegateInvocationHandler().invoke(proxy, method, parameters);
+ }
+ else
+ {
+ try
+ {
+ Method superAccessorMethod = DeltaSpikeProxyFactory.getSuperAccessorMethod(proxy, method);
+ return superAccessorMethod.invoke(proxy, parameters);
+ }
+ catch (InvocationTargetException e)
+ {
+ // rethrow original exception
+ throw e.getCause();
+ }
+ }
+ }
+
+ protected boolean contains(Method[] methods, Method method)
+ {
+ if (methods == null || methods.length == 0)
+ {
+ return false;
+ }
+
+ for (Method current : methods)
+ {
+ if (ReflectionUtils.hasSameSignature(method, current))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
new file mode 100644
index 0000000..be2e867
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/spi/invocation/DeltaSpikeProxyInvocationWrapperException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.spi.invocation;
+
+/**
+ * Wrapper exception to wrap and pass trough the original {@link Throwable} because
+ * the {@link javax.interceptor.InvocationContext#proceed()} method only declares "throws Exception".
+ */
+public class DeltaSpikeProxyInvocationWrapperException extends Exception
+{
+ public DeltaSpikeProxyInvocationWrapperException(Throwable e)
+ {
+ super(e);
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
index 5bae19b..e001a7d 100644
--- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
+++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/util/EnableInterceptorsProxyFactory.java
@@ -19,12 +19,14 @@
package org.apache.deltaspike.proxy.util;
import java.io.Serializable;
-import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import javax.enterprise.inject.spi.BeanManager;
+import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
public class EnableInterceptorsProxyFactory extends DeltaSpikeProxyFactory
{
@@ -51,8 +53,17 @@ public class EnableInterceptorsProxyFactory extends DeltaSpikeProxyFactory
try
{
// instantiate proxy
- Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);
- return (T) constructor.newInstance(delegate);
+ T proxy = (T) proxyClass.newInstance();
+
+ DeltaSpikeProxy deltaSpikeProxy = (DeltaSpikeProxy) proxy;
+
+ // TODO this can be optimized by caching this in a appscoped bean
+ deltaSpikeProxy.setInvocationHandler(
+ BeanProvider.getContextualReference(DeltaSpikeProxyInvocationHandler.class));
+ deltaSpikeProxy.setDelegateInvocationHandler(delegate);
+ deltaSpikeProxy.setDelegateMethods(INSTANCE.getDelegateMethods(obj.getClass()));
+
+ return proxy;
}
catch (Exception e)
{
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
new file mode 100644
index 0000000..0750ba9
--- /dev/null
+++ b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/DeltaSpikeProxyClassGeneratorHolder.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="DeltaSpikeProxyClassGeneratorHolder" immediate="true">
+ <implementation class="org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGeneratorHolder"/>
+ <reference bind="setGenerator" cardinality="1..1" interface="org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator"
+ name="Generator" policy="static" unbind="setGenerator"/>
+</scr:component>
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml b/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
deleted file mode 100644
index 3b03fe6..0000000
--- a/deltaspike/modules/proxy/api/src/main/resources/OSGI-INF/GeneratorHolder.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you under the Apache License, Version 2.0 (the
- ~ "License"); you may not use this file except in compliance
- ~ with the License. You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing,
- ~ software distributed under the License is distributed on an
- ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- ~ KIND, either express or implied. See the License for the
- ~ specific language governing permissions and limitations
- ~ under the License.
- -->
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="GeneratorHolder" immediate="true">
- <implementation class="org.apache.deltaspike.proxy.api.DeltaSpikeProxyFactory$GeneratorHolder"/>
- <reference bind="setGenerator" cardinality="1..1" interface="org.apache.deltaspike.proxy.spi.ProxyClassGenerator"
- name="Generator" policy="static" unbind="setGenerator"/>
-</scr:component>
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b4c2ed26/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
new file mode 100644
index 0000000..188ea30
--- /dev/null
+++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/AsmDeltaSpikeProxyClassGenerator.java
@@ -0,0 +1,548 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.proxy.impl;
+
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxy;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.enterprise.inject.Typed;
+
+import org.apache.deltaspike.proxy.spi.invocation.DeltaSpikeProxyInvocationHandler;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
+import org.apache.deltaspike.proxy.spi.DeltaSpikeProxyClassGenerator;
+
+@Typed
+public class AsmDeltaSpikeProxyClassGenerator implements DeltaSpikeProxyClassGenerator
+{
+ private static final String FIELDNAME_INVOCATION_HANDLER = "invocationHandler";
+ private static final String FIELDNAME_DELEGATE_INVOCATION_HANDLER = "delegateInvocationHandler";
+ private static final String FIELDNAME_DELEGATE_METHODS = "delegateMethods";
+
+ private static final Type TYPE_CLASS = Type.getType(Class.class);
+ private static final Type TYPE_OBJECT = Type.getType(Object.class);
+ private static final Type TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER =
+ Type.getType(DeltaSpikeProxyInvocationHandler.class);
+ private static final Type TYPE_METHOD_ARRAY = Type.getType(java.lang.reflect.Method[].class);
+ private static final Type TYPE_INVOCATION_HANDLER = Type.getType(InvocationHandler.class);
+
+ @Override
+ public <T> Class<T> generateProxyClass(ClassLoader classLoader,
+ Class<T> targetClass,
+ String suffix,
+ String superAccessorMethodSuffix,
+ Class<?>[] additionalInterfaces,
+ java.lang.reflect.Method[] delegateMethods,
+ java.lang.reflect.Method[] interceptMethods)
+ {
+ String proxyName = targetClass.getName() + suffix;
+ String classFileName = proxyName.replace('.', '/');
+
+ byte[] proxyBytes = generateProxyClassBytes(targetClass,
+ classFileName, superAccessorMethodSuffix, additionalInterfaces, delegateMethods, interceptMethods);
+
+ Class<T> proxyClass = (Class<T>) loadClass(classLoader, proxyName, proxyBytes,
+ targetClass.getProtectionDomain());
+
+ return proxyClass;
+ }
+
+ private static byte[] generateProxyClassBytes(Class<?> targetClass,
+ String proxyName,
+ String superAccessorMethodSuffix,
+ Class<?>[] additionalInterfaces,
+ java.lang.reflect.Method[] delegateMethods,
+ java.lang.reflect.Method[] interceptMethods)
+ {
+ Class<?> superClass = targetClass;
+ String[] interfaces = new String[] { };
+
+ if (targetClass.isInterface())
+ {
+ superClass = Object.class;
+ interfaces = new String[] { Type.getInternalName(targetClass) };
+ }
+
+ // add DeltaSpikeProxy as interface
+ interfaces = Arrays.copyOf(interfaces, interfaces.length + 1);
+ interfaces[interfaces.length - 1] = Type.getInternalName(DeltaSpikeProxy.class);
+
+ if (additionalInterfaces != null && additionalInterfaces.length > 0)
+ {
+ interfaces = Arrays.copyOf(interfaces, interfaces.length + additionalInterfaces.length);
+ for (int i = 0; i < additionalInterfaces.length; i++)
+ {
+ interfaces[(interfaces.length - 1) + i] = Type.getInternalName(additionalInterfaces[i]);
+ }
+ }
+
+ Type superType = Type.getType(superClass);
+ Type proxyType = Type.getObjectType(proxyName);
+
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyType.getInternalName(), null,
+ superType.getInternalName(), interfaces);
+
+
+ defineDefaultConstructor(cw, proxyType, superType);
+ defineDeltaSpikeProxyFields(cw);
+ defineDeltaSpikeProxyMethods(cw, proxyType);
+
+ if (delegateMethods != null)
+ {
+ for (java.lang.reflect.Method method : delegateMethods)
+ {
+ defineMethod(cw, method, proxyType);
+ }
+ }
+
+ if (interceptMethods != null)
+ {
+ for (java.lang.reflect.Method method : interceptMethods)
+ {
+ defineSuperAccessorMethod(cw, method, superType, superAccessorMethodSuffix);
+ defineMethod(cw, method, proxyType);
+ }
+ }
+
+ // copy all annotations from the source class
+ try
+ {
+ // ClassVisitor to intercept all annotation visits on the class
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM5)
+ {
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible)
+ {
+ return new CopyAnnotationVisitorAdapter(
+ super.visitAnnotation(desc, visible),
+ cw.visitAnnotation(desc, visible));
+ }
+ };
+
+ // visit class to proxy with our visitor to copy all annotations from the source class to our ClassWriter
+ String sourceClassFilename = targetClass.getName().replace('.', '/') + ".class";
+ ClassReader cr = new ClassReader(targetClass.getClassLoader().getResourceAsStream(sourceClassFilename));
+ cr.accept(cv, 0);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return cw.toByteArray();
+ }
+
+ private static void defineDefaultConstructor(ClassWriter cw, Type proxyType, Type superType)
+ {
+ GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
+ new Method("<init>", Type.VOID_TYPE, new Type[]{ }),
+ null,
+ null,
+ cw);
+
+ mg.visitCode();
+
+ // invoke super constructor
+ mg.loadThis();
+ mg.invokeConstructor(superType, Method.getMethod("void <init> ()"));
+ mg.returnValue();
+ mg.endMethod();
+
+ mg.visitEnd();
+ }
+
+ private static void defineDeltaSpikeProxyFields(ClassWriter cw)
+ {
+ // generates
+ // private DeltaSpikeProxyInvocationHandler invocationHandler;
+ cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_INVOCATION_HANDLER,
+ TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER.getDescriptor(), null, null).visitEnd();
+
+ // generates
+ // private MyInvocationHandler delegateInvocationHandler;
+ cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_DELEGATE_INVOCATION_HANDLER,
+ TYPE_INVOCATION_HANDLER.getDescriptor(), null, null).visitEnd();
+
+ // generates
+ // private Method[] delegateMethods;
+ cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_DELEGATE_METHODS,
+ TYPE_METHOD_ARRAY.getDescriptor(), null, null).visitEnd();
+ }
+
+ private static void defineDeltaSpikeProxyMethods(ClassWriter cw, Type proxyType)
+ {
+ try
+ {
+ // implement #setInvocationHandler
+ Method asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+ "setInvocationHandler", DeltaSpikeProxyInvocationHandler.class));
+ GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.loadArg(0);
+ mg.checkCast(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+ mg.putField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+
+
+ // implement #getInvocationHandler
+ asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getInvocationHandler"));
+ mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+
+
+
+
+ // implement #setDelegateInvocationHandler
+ asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+ "setDelegateInvocationHandler", InvocationHandler.class));
+ mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.loadArg(0);
+ mg.checkCast(TYPE_INVOCATION_HANDLER);
+ mg.putField(proxyType, FIELDNAME_DELEGATE_INVOCATION_HANDLER, TYPE_INVOCATION_HANDLER);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+
+
+ // implement #getDelegateInvocationHandler
+ asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getDelegateInvocationHandler"));
+ mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.getField(proxyType, FIELDNAME_DELEGATE_INVOCATION_HANDLER, TYPE_INVOCATION_HANDLER);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+
+
+
+
+ // implement #setDelegateMethods
+ asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod(
+ "setDelegateMethods", java.lang.reflect.Method[].class));
+ mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.loadArg(0);
+ mg.checkCast(TYPE_METHOD_ARRAY);
+ mg.putField(proxyType, FIELDNAME_DELEGATE_METHODS, TYPE_METHOD_ARRAY);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+
+
+ // implement #getDelegateMethods
+ asmMethod = Method.getMethod(DeltaSpikeProxy.class.getDeclaredMethod("getDelegateMethods"));
+ mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ mg.loadThis();
+ mg.getField(proxyType, FIELDNAME_DELEGATE_METHODS, TYPE_METHOD_ARRAY);
+ mg.returnValue();
+
+ mg.visitMaxs(2, 1);
+ mg.visitEnd();
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new IllegalStateException("Unable to implement " + DeltaSpikeProxy.class.getName(), e);
+ }
+ }
+
+ private static void defineSuperAccessorMethod(ClassWriter cw, java.lang.reflect.Method method, Type superType,
+ String superAccessorMethodSuffix)
+ {
+ Method originalAsmMethod = Method.getMethod(method);
+ Method newAsmMethod = new Method(method.getName() + superAccessorMethodSuffix,
+ originalAsmMethod.getReturnType(),
+ originalAsmMethod.getArgumentTypes());
+ GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, newAsmMethod, null, null, cw);
+
+ mg.visitCode();
+
+ // call super method
+ mg.loadThis();
+ mg.loadArgs();
+ mg.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ superType.getInternalName(),
+ method.getName(),
+ Type.getMethodDescriptor(method),
+ false);
+ mg.returnValue();
+
+ // finish the method
+ mg.endMethod();
+ mg.visitMaxs(10, 10);
+ mg.visitEnd();
+ }
+
+ private static void defineMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType)
+ {
+ Type methodType = Type.getType(method);
+
+ ArrayList<Type> exceptionsToCatch = new ArrayList<Type>();
+ for (Class<?> exception : method.getExceptionTypes())
+ {
+ if (!RuntimeException.class.isAssignableFrom(exception))
+ {
+ exceptionsToCatch.add(Type.getType(exception));
+ }
+ }
+
+ // push the method definition
+ int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers();
+ Method asmMethod = Method.getMethod(method);
+ GeneratorAdapter mg = new GeneratorAdapter(modifiers,
+ asmMethod,
+ null,
+ getTypes(method.getExceptionTypes()),
+ cw);
+
+ // copy annotations
+ for (Annotation annotation : method.getDeclaredAnnotations())
+ {
+ mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd();
+ }
+
+ mg.visitCode();
+
+ Label tryBlockStart = mg.mark();
+
+ mg.loadThis();
+ mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
+ mg.loadThis();
+ loadCurrentMethod(mg, method, methodType);
+ loadArguments(mg, method, methodType);
+
+ mg.invokeVirtual(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER,
+ Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])"));
+
+ // cast the result
+ mg.unbox(methodType.getReturnType());
+
+ // build try catch
+ Label tryBlockEnd = mg.mark();
+
+ // push return
+ mg.returnValue();
+
+ // catch runtime exceptions and rethrow it
+ Label rethrow = mg.mark();
+ mg.visitVarInsn(Opcodes.ASTORE, 1);
+ mg.visitVarInsn(Opcodes.ALOAD, 1);
+ mg.throwException();
+ mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, Type.getInternalName(RuntimeException.class));
+
+ // catch checked exceptions and rethrow it
+ boolean throwableCatched = false;
+ if (!exceptionsToCatch.isEmpty())
+ {
+ rethrow = mg.mark();
+ mg.visitVarInsn(Opcodes.ASTORE, 1);
+ mg.visitVarInsn(Opcodes.ALOAD, 1);
+ mg.throwException();
+
+ // catch declared exceptions and rethrow it...
+ for (Type exceptionType : exceptionsToCatch)
+ {
+ if (exceptionType.getClassName().equals(Throwable.class.getName()))
+ {
+ throwableCatched = true;
+ }
+ mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName());
+ }
+ }
+
+ // if throwable isn't alreached cachted, catch it and wrap it with an UndeclaredThrowableException and throw it
+ if (!throwableCatched)
+ {
+ Type uteType = Type.getType(UndeclaredThrowableException.class);
+ Label wrapAndRethrow = mg.mark();
+
+ mg.visitVarInsn(Opcodes.ASTORE, 1);
+ mg.newInstance(uteType);
+ mg.dup();
+ mg.visitVarInsn(Opcodes.ALOAD, 1);
+ mg.invokeConstructor(uteType,
+ Method.getMethod("void <init>(java.lang.Throwable)"));
+ mg.throwException();
+
+ mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, wrapAndRethrow, Type.getInternalName(Throwable.class));
+ }
+
+ // finish the method
+ mg.endMethod();
+ mg.visitMaxs(12, 12);
+ mg.visitEnd();
+ }
+
+ /**
+ * Generates:
+ * <pre>
+ * Method method =
+ * method.getDeclaringClass().getMethod("methodName", new Class[] { args... });
+ * </pre>
+ * @param mg
+ * @param method
+ * @param methodType
+ */
+ private static void loadCurrentMethod(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType)
+ {
+ mg.push(Type.getType(method.getDeclaringClass()));
+ mg.push(method.getName());
+
+ // create the Class[]
+ mg.push(methodType.getArgumentTypes().length);
+ mg.newArray(TYPE_CLASS);
+
+ // push parameters into array
+ for (int i = 0; i < methodType.getArgumentTypes().length; i++)
+ {
+ // keep copy of array on stack
+ mg.dup();
+
+ // push index onto stack
+ mg.push(i);
+ mg.push(methodType.getArgumentTypes()[i]);
+ mg.arrayStore(TYPE_CLASS);
+ }
+
+ // invoke getMethod() with the method name and the array of types
+ mg.invokeVirtual(TYPE_CLASS, Method.getMethod("java.lang.reflect.Method getDeclaredMethod(String, Class[])"));
+ }
+
+ /**
+ * Defines a new Object[] and push all method argmuments into the array.
+ *
+ * @param mg
+ * @param method
+ * @param methodType
+ */
+ private static void loadArguments(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType)
+ {
+ // create the Object[]
+ mg.push(methodType.getArgumentTypes().length);
+ mg.newArray(TYPE_OBJECT);
+
+ // push parameters into array
+ for (int i = 0; i < methodType.getArgumentTypes().length; i++)
+ {
+ // keep copy of array on stack
+ mg.dup();
+
+ // push index onto stack
+ mg.push(i);
+
+ mg.loadArg(i);
+ mg.valueOf(methodType.getArgumentTypes()[i]);
+ mg.arrayStore(TYPE_OBJECT);
+ }
+ }
+
+ private static Type[] getTypes(Class<?>... src)
+ {
+ Type[] result = new Type[src.length];
+ for (int i = 0; i < result.length; i++)
+ {
+ result[i] = Type.getType(src[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Adapted from http://asm.ow2.org/doc/faq.html#Q5
+ *
+ * @param b
+ *
+ * @return Class<?>
+ */
+ private static Class<?> loadClass(ClassLoader loader, String className, byte[] b,
+ ProtectionDomain protectionDomain)
+ {
+ // override classDefine (as it is protected) and define the class.
+ try
+ {
+ java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod(
+ "defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
+
+ // protected method invocation
+ boolean accessible = method.isAccessible();
+ if (!accessible)
+ {
+ method.setAccessible(true);
+ }
+ try
+ {
+ return (Class<?>) method.invoke(loader, className, b, Integer.valueOf(0), Integer.valueOf(b.length),
+ protectionDomain);
+ }
+ finally
+ {
+ if (!accessible)
+ {
+ method.setAccessible(false);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e);
+ }
+ }
+}