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 2014/06/30 15:00:26 UTC

[1/2] git commit: DELTASPIKE-650 optional proxies for converters and validators with properties

Repository: deltaspike
Updated Branches:
  refs/heads/master fe8f62401 -> 0584be0cf


DELTASPIKE-650 optional proxies for converters and validators with properties


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

Branch: refs/heads/master
Commit: a411ec7161fff842dc261969692fd10abc99ad57
Parents: fe8f624
Author: gpetracek <gp...@apache.org>
Authored: Mon Jun 30 14:48:43 2014 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Mon Jun 30 14:48:43 2014 +0200

----------------------------------------------------------------------
 .../InjectionAwareApplicationWrapper.java       |  12 ++
 .../proxy/ConverterAndValidatorLifecycle.java   | 132 +++++++++++++++
 .../ConverterAndValidatorProxyExtension.java    | 169 +++++++++++++++++++
 .../proxy/ConverterInvocationHandler.java       |  43 +++++
 .../proxy/DefaultPartialStateHolder.java        |  71 ++++++++
 .../proxy/DelegatingMethodHandler.java          |  45 +++++
 .../injection/proxy/MethodHandlerProxy.java     |  42 +++++
 .../jsf/impl/injection/proxy/ProxyMarker.java   |  23 +++
 .../proxy/ValidatorInvocationHandler.java       |  43 +++++
 .../javax.enterprise.inject.spi.Extension       |   3 +-
 10 files changed, 582 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/InjectionAwareApplicationWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/InjectionAwareApplicationWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/InjectionAwareApplicationWrapper.java
index b18b36a..a229f3d 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/InjectionAwareApplicationWrapper.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/InjectionAwareApplicationWrapper.java
@@ -18,7 +18,9 @@
  */
 package org.apache.deltaspike.jsf.impl.injection;
 
+import org.apache.deltaspike.core.util.ProxyUtils;
 import org.apache.deltaspike.jsf.api.config.JsfModuleConfig;
+import org.apache.deltaspike.jsf.impl.injection.proxy.ProxyMarker;
 import org.apache.deltaspike.jsf.impl.security.SecurityAwareViewHandler;
 
 import javax.faces.FacesException;
@@ -77,6 +79,11 @@ public class InjectionAwareApplicationWrapper extends ApplicationWrapper
         {
             return defaultResult;
         }
+
+        if (result instanceof ProxyMarker || ProxyUtils.isProxiedClass(result.getClass()))
+        {
+            return result;
+        }
         else
         {
             return new ConverterWrapper(result, this.fullStateSavingFallbackEnabled);
@@ -106,6 +113,11 @@ public class InjectionAwareApplicationWrapper extends ApplicationWrapper
         {
             return defaultResult;
         }
+
+        if (result instanceof ProxyMarker || ProxyUtils.isProxiedClass(result.getClass()))
+        {
+            return result;
+        }
         else
         {
             return new ValidatorWrapper(result, this.fullStateSavingFallbackEnabled);

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorLifecycle.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorLifecycle.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorLifecycle.java
new file mode 100644
index 0000000..90a3e6e
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorLifecycle.java
@@ -0,0 +1,132 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+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;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.faces.component.PartialStateHolder;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+class ConverterAndValidatorLifecycle<T, H extends InvocationHandler> implements ContextualLifecycle<T>
+{
+    private final Class<? extends T> generatedProxyClass;
+
+    private final InjectionTarget<T> injectionTargetForGeneratedProxy;
+    private final Class<H> handlerClass;
+
+    ConverterAndValidatorLifecycle(Class<T> originalClass, Class<H> handlerClass, BeanManager beanManager)
+    {
+        this.handlerClass = handlerClass;
+
+        AnnotatedTypeBuilder<T> typeBuilder = new AnnotatedTypeBuilder<T>().readFromType(originalClass);
+        this.injectionTargetForGeneratedProxy = beanManager.createInjectionTarget(typeBuilder.create());
+
+        try
+        {
+            Object proxyFactory = ClassUtils.tryToInstantiateClassForName("javassist.util.proxy.ProxyFactory");
+
+            Method setSuperclassMethod = proxyFactory.getClass().getDeclaredMethod("setSuperclass", Class.class);
+            setSuperclassMethod.invoke(proxyFactory, originalClass);
+
+            List<Class> interfaces = new ArrayList<Class>();
+            Collections.addAll(interfaces, originalClass.getInterfaces());
+            interfaces.add(ProxyMarker.class);
+
+            if (!interfaces.contains(PartialStateHolder.class))
+            {
+                interfaces.add(PartialStateHolder.class);
+            }
+
+            Method method = proxyFactory.getClass().getMethod("setInterfaces", new Class[]{new Class[]{}.getClass()});
+            method.invoke(proxyFactory, new Object[] {interfaces.toArray(new Class[interfaces.size()])});
+
+            Method createClassMethod = proxyFactory.getClass().getDeclaredMethod("createClass");
+
+            this.generatedProxyClass = ((Class<?>) createClassMethod.invoke(proxyFactory)).asSubclass(originalClass);
+        }
+        catch (Exception e)
+        {
+            throw ExceptionUtils.throwAsRuntimeException(e);
+        }
+    }
+
+    public T create(Bean bean, CreationalContext creationalContext)
+    {
+        try
+        {
+            H handlerInstance = ClassUtils.tryToInstantiateClass(this.handlerClass);
+            T instance = createProxyInstance(handlerInstance);
+
+            if (this.injectionTargetForGeneratedProxy != null)
+            {
+                this.injectionTargetForGeneratedProxy.inject(instance, creationalContext);
+                this.injectionTargetForGeneratedProxy.postConstruct(instance);
+            }
+
+            return instance;
+        }
+        catch (Exception e)
+        {
+            ExceptionUtils.throwAsRuntimeException(e);
+        }
+        //can't happen
+        return null;
+    }
+
+    private T createProxyInstance(H handlerInstance) throws Exception
+    {
+        T instance = this.generatedProxyClass.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.setDelegatingMethodHandler(new DelegatingMethodHandler<H>(handlerInstance));
+
+        Object methodHandler = Proxy.newProxyInstance(
+                ClassUtils.getClassLoader(this), new Class[]{methodHandlerClass}, methodHandlerProxy);
+
+        setHandlerMethod.invoke(instance, methodHandler);
+        return instance;
+    }
+
+    public void destroy(Bean<T> bean, T instance, CreationalContext<T> creationalContext)
+    {
+        if (this.injectionTargetForGeneratedProxy != null)
+        {
+            this.injectionTargetForGeneratedProxy.preDestroy(instance);
+        }
+
+        creationalContext.release();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
new file mode 100644
index 0000000..dff508f
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
@@ -0,0 +1,169 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+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 javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.faces.convert.Converter;
+import javax.faces.validator.Validator;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+public class ConverterAndValidatorProxyExtension implements Extension, Deactivatable
+{
+    private static final Logger LOG = Logger.getLogger(ConverterAndValidatorProxyExtension.class.getName());
+
+    private Boolean isActivated = true;
+    private Set<Class<?>> classesToProxy = new HashSet<Class<?>>();
+
+    protected void init(@Observes BeforeBeanDiscovery beforeBeanDiscovery)
+    {
+        this.isActivated = ClassDeactivationUtils.isActivated(getClass());
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    public <X> void findConverterAndValidatorsWhichNeedProxiesForDependencyInjectionSupport(
+        @Observes ProcessAnnotatedType<X> pat)
+    {
+        if (!this.isActivated)
+        {
+            return;
+        }
+
+        Class<X> beanClass = pat.getAnnotatedType().getJavaClass();
+
+        if (!(Converter.class.isAssignableFrom(beanClass) || (Validator.class.isAssignableFrom(beanClass))))
+        {
+            return;
+        }
+
+        //converters/validators without properties for tags, will be handled by the corresponding manual wrapper
+        if (!hasPublicProperty(beanClass))
+        {
+            return;
+        }
+
+        Object proxyFactory = ClassUtils.tryToInstantiateClassForName("javassist.util.proxy.ProxyFactory");
+
+        if (proxyFactory == null)
+        {
+            LOG.warning("To use dependency-injection in converters/validators with properties, " +
+                "you have to add javassist to the application.");
+            return;
+        }
+
+        if (!(Modifier.isFinal(beanClass.getModifiers())))
+        {
+            this.classesToProxy.add(beanClass);
+            pat.veto();
+        }
+        else
+        {
+            LOG.warning("To use dependency-injection in converters/validators with properties, " +
+                "you they aren't allowed to be 'final'.");
+        }
+    }
+
+    protected <X> boolean hasPublicProperty(Class<X> beanClass)
+    {
+        for (Method currentMethod : beanClass.getMethods())
+        {
+            if (currentMethod.getName().startsWith("set") && currentMethod.getName().length() > 3
+                && currentMethod.getParameterTypes().length == 1 &&
+                hasGetterMethod(beanClass, currentMethod.getName().substring(3)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean hasGetterMethod(Class beanClass, String name)
+    {
+        try
+        {
+            if (beanClass.getMethod("get" + name) != null || beanClass.getMethod("is") + name != null)
+            {
+                return true;
+            }
+        }
+        catch (Exception e)
+        {
+            return false;
+        }
+        return false;
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    public <X> void createBeans(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager)
+    {
+        if (!this.isActivated)
+        {
+            return;
+        }
+
+        for (Class<?> originalClass : this.classesToProxy)
+        {
+            Bean bean = createBean(originalClass, beanManager);
+
+            if (bean != null)
+            {
+                afterBeanDiscovery.addBean(bean);
+            }
+        }
+
+        this.classesToProxy.clear();
+    }
+
+    protected <T> Bean<T> createBean(Class<T> beanClass, BeanManager beanManager)
+    {
+        Class<? extends InvocationHandler> invocationHandlerClass =
+            Converter.class.isAssignableFrom(beanClass) ?
+                ConverterInvocationHandler.class : ValidatorInvocationHandler.class;
+
+        AnnotatedType<T> annotatedType = new AnnotatedTypeBuilder<T>().readFromType(beanClass).create();
+
+        ConverterAndValidatorLifecycle beanLifecycle =
+            new ConverterAndValidatorLifecycle(beanClass, invocationHandlerClass, beanManager);
+
+        BeanBuilder<T> beanBuilder = new BeanBuilder<T>(beanManager)
+            .readFromType(annotatedType)
+            .passivationCapable(true)
+            .beanLifecycle(beanLifecycle)
+            .addType(ProxyMarker.class);
+
+        return beanBuilder.create();
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterInvocationHandler.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterInvocationHandler.java
new file mode 100644
index 0000000..6bf457c
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterInvocationHandler.java
@@ -0,0 +1,43 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+import javax.faces.component.PartialStateHolder;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class ConverterInvocationHandler implements InvocationHandler
+{
+    private DefaultPartialStateHolder defaultPartialStateHolder = new DefaultPartialStateHolder();
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        // if the original class implements PartialStateHolder already, we won't get in here
+        if (PartialStateHolder.class.equals(method.getDeclaringClass()))
+        {
+            return method.invoke(defaultPartialStateHolder, args);
+        }
+        else
+        {
+            //shouldn't happen, because DelegatingMethodHandler delegates all methods to the real implementations
+            return method.invoke(proxy, args);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DefaultPartialStateHolder.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DefaultPartialStateHolder.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DefaultPartialStateHolder.java
new file mode 100644
index 0000000..70b2e95
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DefaultPartialStateHolder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+import javax.faces.component.PartialStateHolder;
+import javax.faces.context.FacesContext;
+
+//the converter-/validator proxy needs to implement PartialStateHolder to force a special path of the jsf state handling
+//which forces a call to InjectionAwareApplicationWrapper on the postback.
+//this class provides the default behaviour for the reflection calls,
+//if the original converter-/validator doesn't implement the interface
+public class DefaultPartialStateHolder implements PartialStateHolder
+{
+    private boolean transientValue;
+    private boolean initialStateMarked;
+
+    @Override
+    public Object saveState(FacesContext context)
+    {
+        return null; //not needed
+    }
+
+    @Override
+    public void restoreState(FacesContext context, Object state)
+    {
+        //not needed
+    }
+
+    @Override
+    public boolean isTransient()
+    {
+        return this.transientValue;
+    }
+
+    @Override
+    public void setTransient(boolean newTransientValue)
+    {
+        this.transientValue = newTransientValue;
+    }
+
+    public void clearInitialState()
+    {
+        this.initialStateMarked = false;
+    }
+
+    public boolean initialStateMarked()
+    {
+        return this.initialStateMarked;
+    }
+
+    public void markInitialState()
+    {
+        this.initialStateMarked = true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DelegatingMethodHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DelegatingMethodHandler.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DelegatingMethodHandler.java
new file mode 100644
index 0000000..4da76ff
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/DelegatingMethodHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Handler delegates to implemented methods, if they exist
+ */
+class DelegatingMethodHandler<T extends InvocationHandler>
+{
+    private final T handlerInstance;
+
+    DelegatingMethodHandler(T handlerInstance)
+    {
+        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)
+        {
+            return proceedMethod.invoke(target, arguments);
+        }
+        return this.handlerInstance.invoke(target, method, arguments);
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/MethodHandlerProxy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/MethodHandlerProxy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/MethodHandlerProxy.java
new file mode 100644
index 0000000..0c02a3a
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/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.jsf.impl.injection.proxy;
+
+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 DelegatingMethodHandler delegatingMethodHandler;
+
+    @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 delegatingMethodHandler.invoke(args[0], (Method)args[1], (Method)args[2], (Object[])args[3]);
+    }
+
+    void setDelegatingMethodHandler(DelegatingMethodHandler delegatingMethodHandler)
+    {
+        this.delegatingMethodHandler = delegatingMethodHandler;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ProxyMarker.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ProxyMarker.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ProxyMarker.java
new file mode 100644
index 0000000..2e1d9d3
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ProxyMarker.java
@@ -0,0 +1,23 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+public interface ProxyMarker
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ValidatorInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ValidatorInvocationHandler.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ValidatorInvocationHandler.java
new file mode 100644
index 0000000..3a2db36
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ValidatorInvocationHandler.java
@@ -0,0 +1,43 @@
+/*
+ * 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.jsf.impl.injection.proxy;
+
+import javax.faces.component.PartialStateHolder;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class ValidatorInvocationHandler implements InvocationHandler
+{
+    private DefaultPartialStateHolder defaultPartialStateHolder = new DefaultPartialStateHolder();
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        // if the original class implements PartialStateHolder already, we won't get in here
+        if (PartialStateHolder.class.equals(method.getDeclaringClass()))
+        {
+            return method.invoke(defaultPartialStateHolder, args);
+        }
+        else
+        {
+            //shouldn't happen, because DelegatingMethodHandler delegates all methods to the real implementations
+            return method.invoke(proxy, args);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/a411ec71/deltaspike/modules/jsf/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index a634c99..8aa9295 100644
--- a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -20,4 +20,5 @@
 org.apache.deltaspike.jsf.impl.scope.view.ViewScopedExtension
 
 org.apache.deltaspike.jsf.impl.scope.mapped.MappedJsf2ScopeExtension
-org.apache.deltaspike.jsf.impl.config.view.ViewConfigExtension
\ No newline at end of file
+org.apache.deltaspike.jsf.impl.config.view.ViewConfigExtension
+org.apache.deltaspike.jsf.impl.injection.proxy.ConverterAndValidatorProxyExtension
\ No newline at end of file


[2/2] git commit: DELTASPIKE-654 veto converters and validators without injection-points or normal-scope

Posted by gp...@apache.org.
DELTASPIKE-654 veto converters and validators without injection-points or normal-scope


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

Branch: refs/heads/master
Commit: 0584be0cf1d55fafcf09163e28d0923aab095b1b
Parents: a411ec7
Author: gpetracek <gp...@apache.org>
Authored: Mon Jun 30 14:51:30 2014 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Mon Jun 30 14:54:25 2014 +0200

----------------------------------------------------------------------
 .../ConverterAndValidatorProxyExtension.java    | 22 +++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/0584be0c/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
index dff508f..7c6f58a 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/injection/proxy/ConverterAndValidatorProxyExtension.java
@@ -34,6 +34,7 @@ import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
 import javax.faces.convert.Converter;
 import javax.faces.validator.Validator;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -55,7 +56,7 @@ public class ConverterAndValidatorProxyExtension implements Extension, Deactivat
 
     @SuppressWarnings("UnusedDeclaration")
     public <X> void findConverterAndValidatorsWhichNeedProxiesForDependencyInjectionSupport(
-        @Observes ProcessAnnotatedType<X> pat)
+        @Observes ProcessAnnotatedType<X> pat, BeanManager beanManager)
     {
         if (!this.isActivated)
         {
@@ -69,6 +70,14 @@ public class ConverterAndValidatorProxyExtension implements Extension, Deactivat
             return;
         }
 
+        Bean<X> bean = new BeanBuilder<X>(beanManager).readFromType(pat.getAnnotatedType()).create();
+        //veto normal converters/validators -> they will get excluded from the special handling later on
+        if (!hasInjectionPoints(bean) && !hasNormalScopeAnnotation(bean, beanManager))
+        {
+            pat.veto();
+            return;
+        }
+
         //converters/validators without properties for tags, will be handled by the corresponding manual wrapper
         if (!hasPublicProperty(beanClass))
         {
@@ -96,6 +105,17 @@ public class ConverterAndValidatorProxyExtension implements Extension, Deactivat
         }
     }
 
+    protected <X> boolean hasInjectionPoints(Bean<X> bean)
+    {
+        return !bean.getInjectionPoints().isEmpty();
+    }
+
+    protected <X> boolean hasNormalScopeAnnotation(Bean<X> bean, BeanManager beanManager)
+    {
+        Class<? extends Annotation> scopeAnnotationClass = bean.getScope();
+        return  scopeAnnotationClass != null && beanManager.isNormalScope(scopeAnnotationClass);
+    }
+
     protected <X> boolean hasPublicProperty(Class<X> beanClass)
     {
         for (Method currentMethod : beanClass.getMethods())