You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2013/04/01 08:43:24 UTC

[2/2] git commit: DELTASPIKE-338 first draft

DELTASPIKE-338 first draft


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/38bc0b6f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/38bc0b6f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/38bc0b6f

Branch: refs/heads/master
Commit: 38bc0b6f8efacbe2c0be9af27bbe8354274d2ba0
Parents: 9f5e1dc
Author: gpetracek <gp...@apache.org>
Authored: Mon Apr 1 07:43:26 2013 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Mon Apr 1 08:18:32 2013 +0200

----------------------------------------------------------------------
 deltaspike/modules/partial-bean/impl/pom.xml       |    1 +
 .../partialbean/impl/MethodHandlerProxy.java       |   42 ++++++++
 .../impl/PartialBeanBindingExtension.java          |   13 ---
 .../partialbean/impl/PartialBeanLifecycle.java     |   73 ++++++++++++---
 .../partialbean/impl/PartialBeanMethodHandler.java |   13 +--
 5 files changed, 107 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/38bc0b6f/deltaspike/modules/partial-bean/impl/pom.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/pom.xml b/deltaspike/modules/partial-bean/impl/pom.xml
index 5544a62..36b0591 100644
--- a/deltaspike/modules/partial-bean/impl/pom.xml
+++ b/deltaspike/modules/partial-bean/impl/pom.xml
@@ -45,6 +45,7 @@
         <dependency>
             <groupId>javassist</groupId>
             <artifactId>javassist</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/38bc0b6f/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/MethodHandlerProxy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/MethodHandlerProxy.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/MethodHandlerProxy.java
new file mode 100644
index 0000000..08c3b72
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/MethodHandlerProxy.java
@@ -0,0 +1,42 @@
+/*
+ * 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.partialbean.impl;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+//This indirection to create a proxy for javassist.util.proxy.MethodHandler is used as intermediate approach.
+//Further details see comments in PartialBeanLifecycle
+public class MethodHandlerProxy implements InvocationHandler
+{
+    private PartialBeanMethodHandler partialBeanMethodHandler;
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        //hardcoding the following parameters is ok since MethodHandlerProxy is only used for
+        //javassist.util.proxy.MethodHandler which has one method with those parameters.
+        return partialBeanMethodHandler.invoke(args[0], (Method)args[1], (Method)args[2], (Object[])args[3]);
+    }
+
+    void setPartialBeanMethodHandler(PartialBeanMethodHandler partialBeanMethodHandler)
+    {
+        this.partialBeanMethodHandler = partialBeanMethodHandler;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/38bc0b6f/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java
index fcc8abf..140a819 100644
--- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java
+++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java
@@ -20,7 +20,6 @@ package org.apache.deltaspike.partialbean.impl;
 
 import org.apache.deltaspike.core.spi.activation.Deactivatable;
 import org.apache.deltaspike.core.util.ClassDeactivationUtils;
-import org.apache.deltaspike.core.util.ClassUtils;
 import org.apache.deltaspike.core.util.bean.BeanBuilder;
 import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
 import org.apache.deltaspike.partialbean.api.PartialBeanBinding;
@@ -39,7 +38,6 @@ import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 public class PartialBeanBindingExtension implements Extension, Deactivatable
@@ -57,17 +55,6 @@ public class PartialBeanBindingExtension implements Extension, Deactivatable
     protected void init(@Observes BeforeBeanDiscovery beforeBeanDiscovery)
     {
         this.isActivated = ClassDeactivationUtils.isActivated(getClass());
-
-        if (this.isActivated)
-        {
-            this.isActivated = ClassUtils.tryToLoadClassForName("javassist.util.proxy.ProxyFactory") != null;
-
-            if (!this.isActivated && LOG.isLoggable(Level.WARNING))
-            {
-                LOG.warning("@" + PartialBeanBinding.class.getName() +
-                    " deactivated because Javassist is missing.");
-            }
-        }
     }
 
     public <X> void findInvocationHandlerBindings(@Observes ProcessAnnotatedType<X> pat, BeanManager beanManager)

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/38bc0b6f/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java
index 5babb17..dd8f51d 100644
--- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java
+++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java
@@ -18,11 +18,9 @@
  */
 package org.apache.deltaspike.partialbean.impl;
 
-import javassist.util.proxy.MethodFilter;
-import javassist.util.proxy.ProxyFactory;
-import javassist.util.proxy.ProxyObject;
 import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.core.util.ClassUtils;
 import org.apache.deltaspike.core.util.ExceptionUtils;
 import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder;
 import org.apache.deltaspike.core.util.metadata.builder.ContextualLifecycle;
@@ -34,8 +32,14 @@ import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.InjectionTarget;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.Set;
 
+//The usage of reflection and the indirection for MethodHandler is needed to avoid the hard dependency to javassist.
+//Some users don't like to have it as a required dependency,
+// but they would like to use interfaces for partial beans and don't need abstract classes as partial beans.
+
+//We use these indirections as >intermediate< approach. That way no classpath-scanner can cause issues.
 class PartialBeanLifecycle<T, H extends InvocationHandler> implements ContextualLifecycle<T>
 {
     private final Class<? extends T> partialBeanProxyClass;
@@ -43,28 +47,44 @@ class PartialBeanLifecycle<T, H extends InvocationHandler> implements Contextual
     private final InjectionTarget<T> partialBeanInjectionTarget;
     private final Class<H> handlerClass;
     private CreationalContext<?> creationalContextOfDependentHandler;
+    private final boolean isInterfaceMode;
 
     PartialBeanLifecycle(Class<T> partialBeanClass, Class<H> handlerClass, BeanManager beanManager)
     {
         this.handlerClass = handlerClass;
 
-        ProxyFactory proxyFactory = new ProxyFactory();
-
         if (partialBeanClass.isInterface())
         {
+            this.isInterfaceMode = true;
             this.partialBeanInjectionTarget = null;
-
-            proxyFactory.setInterfaces(new Class[]{partialBeanClass});
+            this.partialBeanProxyClass = partialBeanClass;
         }
         else
         {
+            this.isInterfaceMode = false;
             AnnotatedTypeBuilder<T> partialBeanTypeBuilder =
                 new AnnotatedTypeBuilder<T>().readFromType(partialBeanClass);
             this.partialBeanInjectionTarget = beanManager.createInjectionTarget(partialBeanTypeBuilder.create());
 
-            proxyFactory.setSuperclass(partialBeanClass);
+            try
+            {
+                Object proxyFactory = ClassUtils.tryToInstantiateClassForName("javassist.util.proxy.ProxyFactory");
+
+                Method setSuperclassMethod = proxyFactory.getClass().getDeclaredMethod("setSuperclass", Class.class);
+                setSuperclassMethod.invoke(proxyFactory, partialBeanClass);
+
+                Method createClassMethod = proxyFactory.getClass().getDeclaredMethod("createClass");
+
+                this.partialBeanProxyClass =
+                        ((Class<?>) createClassMethod.invoke(proxyFactory)).asSubclass(partialBeanClass);
+            }
+            catch (Exception e)
+            {
+                throw ExceptionUtils.throwAsRuntimeException(e);
+            }
         }
 
+        /*TODO re-visit the need of MethodFilter - we would need an indirection for it as with MethodHandler
         proxyFactory.setFilter(new MethodFilter()
         {
             public boolean isHandled(Method method)
@@ -72,8 +92,7 @@ class PartialBeanLifecycle<T, H extends InvocationHandler> implements Contextual
                 return !"finalize".equals(method.getName());
             }
         });
-
-        this.partialBeanProxyClass = ((Class<?>) proxyFactory.createClass()).asSubclass(partialBeanClass);
+         */
     }
 
     public T create(Bean bean, CreationalContext creationalContext)
@@ -81,8 +100,7 @@ class PartialBeanLifecycle<T, H extends InvocationHandler> implements Contextual
         try
         {
             H handlerInstance = createHandlerInstance();
-
-            T instance = this.partialBeanProxyClass.newInstance();
+            T instance = createPartialBeanProxyInstance(handlerInstance);
 
             if (this.partialBeanInjectionTarget != null)
             {
@@ -90,8 +108,6 @@ class PartialBeanLifecycle<T, H extends InvocationHandler> implements Contextual
                 this.partialBeanInjectionTarget.postConstruct(instance);
             }
 
-            PartialBeanMethodHandler<H> methodHandler = new PartialBeanMethodHandler<H>(handlerInstance);
-            ((ProxyObject) instance).setHandler(methodHandler);
             return instance;
         }
         catch (Exception e)
@@ -102,6 +118,35 @@ class PartialBeanLifecycle<T, H extends InvocationHandler> implements Contextual
         return null;
     }
 
+    private T createPartialBeanProxyInstance(H handlerInstance) throws Exception
+    {
+        T instance;
+
+        if (this.isInterfaceMode)
+        {
+            instance = (T) Proxy.newProxyInstance(
+                    ClassUtils.getClassLoader(this), new Class[]{this.partialBeanProxyClass}, handlerInstance);
+        }
+        else //partial-bean is an interface
+        {
+            instance = this.partialBeanProxyClass.newInstance();
+
+            Class methodHandlerClass = ClassUtils.tryToLoadClassForName("javassist.util.proxy.MethodHandler");
+            Method setHandlerMethod = ClassUtils.tryToLoadClassForName("javassist.util.proxy.ProxyObject")
+                    .getDeclaredMethod("setHandler", methodHandlerClass);
+
+
+            MethodHandlerProxy methodHandlerProxy = new MethodHandlerProxy();
+            methodHandlerProxy.setPartialBeanMethodHandler(new PartialBeanMethodHandler<H>(handlerInstance));
+
+            Object methodHandler = Proxy.newProxyInstance(
+                    ClassUtils.getClassLoader(this), new Class[]{methodHandlerClass}, methodHandlerProxy);
+
+            setHandlerMethod.invoke(instance, methodHandler);
+        }
+        return instance;
+    }
+
     private H createHandlerInstance()
     {
         Set<Bean<H>> handlerBeans = BeanProvider.getBeanDefinitions(this.handlerClass, false, true);

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/38bc0b6f/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanMethodHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanMethodHandler.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanMethodHandler.java
index c8a8d58..57fd99a 100644
--- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanMethodHandler.java
+++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanMethodHandler.java
@@ -18,12 +18,13 @@
  */
 package org.apache.deltaspike.partialbean.impl;
 
-import javassist.util.proxy.MethodHandler;
-
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 
-class PartialBeanMethodHandler<T extends InvocationHandler> implements MethodHandler
+/**
+ * At runtime it will be called from {@link MethodHandlerProxy} as instance of javassist.util.proxy.MethodHandler
+ */
+class PartialBeanMethodHandler<T extends InvocationHandler>
 {
     private final T handlerInstance;
 
@@ -32,6 +33,7 @@ class PartialBeanMethodHandler<T extends InvocationHandler> implements MethodHan
         this.handlerInstance = handlerInstance;
     }
 
+    //Signature given by javassist.util.proxy.MethodHandler#invoke
     public Object invoke(Object target, Method method, Method proceedMethod, Object[] arguments) throws Throwable
     {
         if (proceedMethod != null)
@@ -40,9 +42,4 @@ class PartialBeanMethodHandler<T extends InvocationHandler> implements MethodHan
         }
         return this.handlerInstance.invoke(target, method, arguments);
     }
-
-    T getHandlerInstance()
-    {
-        return this.handlerInstance;
-    }
 }