Author: rmannibucau
Date: Wed Jul 17 08:37:00 2013
New Revision: 1504049

URL: http://svn.apache.org/r1504049
Log:
handling of ValidOnExecution configuration for cdi method validation

Modified:
    
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValExtension.java
    
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValInterceptor.java
    bval/branches/bval-11/bval-tck11/work-tests-suite.xml

Modified: 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValExtension.java
URL: 
http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValExtension.java?rev=1504049&r1=1504048&r2=1504049&view=diff
==============================================================================
--- 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValExtension.java
 (original)
+++ 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValExtension.java
 Wed Jul 17 08:37:00 2013
@@ -42,9 +42,11 @@ import javax.validation.executable.Execu
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -69,7 +71,7 @@ public class BValExtension implements Ex
         config = Validation.byDefaultProvider().configure();
         try {
             final BootstrapConfiguration bootstrap = 
config.getBootstrapConfiguration();
-            globalExecutableTypes = 
bootstrap.getDefaultValidatedExecutableTypes();
+            globalExecutableTypes = 
convertToRuntimeTypes(bootstrap.getDefaultValidatedExecutableTypes());
             isExecutableValidationEnabled = 
bootstrap.isExecutableValidationEnabled();
         } catch (final Exception e) { // custom providers can throw an 
exception
             LOGGER.log(Level.SEVERE, e.getMessage(), e);
@@ -79,16 +81,46 @@ public class BValExtension implements Ex
         }
     }
 
+    private static Set<ExecutableType> convertToRuntimeTypes(final 
Set<ExecutableType> defaultValidatedExecutableTypes) {
+        final Set<ExecutableType> types = new 
CopyOnWriteArraySet<ExecutableType>();
+        for (final ExecutableType type : defaultValidatedExecutableTypes) {
+            if (ExecutableType.IMPLICIT.equals(type)) {
+                types.add(ExecutableType.CONSTRUCTORS);
+                types.add(ExecutableType.NON_GETTER_METHODS);
+            } else if (ExecutableType.ALL.equals(type)) {
+                types.add(ExecutableType.CONSTRUCTORS);
+                types.add(ExecutableType.NON_GETTER_METHODS);
+                types.add(ExecutableType.GETTER_METHODS);
+                break;
+            } else if (!ExecutableType.NONE.equals(type)) {
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public Set<ExecutableType> getGlobalExecutableTypes() {
+        return globalExecutableTypes;
+    }
+
     public static BValExtension getInstance() {
         return bmpSingleton;
     }
 
     public void addBvalBinding(final @Observes BeforeBeanDiscovery 
beforeBeanDiscovery, final BeanManager beanManager) {
+        if (!isExecutableValidationEnabled) {
+            return;
+        }
+
         beforeBeanDiscovery.addInterceptorBinding(BValBinding.class);
         
beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(BValInterceptor.class));
     }
 
     public <A> void processAnnotatedType(final @Observes 
ProcessAnnotatedType<A> pat) {
+        if (!isExecutableValidationEnabled) {
+            return;
+        }
+
         final Class<A> javaClass = pat.getAnnotatedType().getJavaClass();
         final int modifiers = javaClass.getModifiers();
         if (!javaClass.getName().startsWith("javax.") && 
!javaClass.getName().startsWith("org.apache.bval")

Modified: 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValInterceptor.java
URL: 
http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValInterceptor.java?rev=1504049&r1=1504048&r2=1504049&view=diff
==============================================================================
--- 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValInterceptor.java
 (original)
+++ 
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/cdi/BValInterceptor.java
 Wed Jul 17 08:37:00 2013
@@ -27,22 +27,39 @@ import javax.interceptor.InvocationConte
 import javax.validation.ConstraintViolation;
 import javax.validation.ConstraintViolationException;
 import javax.validation.Validator;
+import javax.validation.executable.ExecutableType;
 import javax.validation.executable.ExecutableValidator;
+import javax.validation.executable.ValidateOnExecution;
 import javax.validation.metadata.MethodDescriptor;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 @Interceptor
 @BValBinding
 public class BValInterceptor {
+    private Collection<ExecutableType> classConfiguration = null;
+    private final Map<Method, Boolean> methodConfiguration = new 
ConcurrentHashMap<Method, Boolean>();
+
     @Inject
     private Validator validator;
 
+    @Inject
+    private BValExtension globalConfiguration;
+
     @AroundInvoke
     public Object around(final InvocationContext context) throws Throwable {
+        final Method method = context.getMethod();
+        if 
(!isMethodValidated(Proxies.classFor(context.getTarget().getClass()), method)) {
+            return context.proceed();
+        }
+
         final ExecutableValidator ev = validator.forExecutables();
 
-        final Method method = context.getMethod();
         final MethodDescriptor constraintsForMethod = 
validator.getConstraintsForClass(Proxies.classFor(method.getDeclaringClass())).getConstraintsForMethod(method.getName(),
 method.getParameterTypes());
         if (constraintsForMethod == null) {
             return context.proceed();
@@ -66,4 +83,78 @@ public class BValInterceptor {
 
         return result;
     }
+
+    private boolean isMethodValidated(final Class<?> targetClass, final Method 
method) throws NoSuchMethodException {
+        Boolean methodConfig;// config
+        if (classConfiguration == null) {
+            synchronized (this) {
+                if (classConfiguration == null) {
+                    classConfiguration = new 
CopyOnWriteArraySet<ExecutableType>();
+
+                    final ValidateOnExecution annotation = 
targetClass.getAnnotation(ValidateOnExecution.class);
+                    if (annotation == null) {
+                        
classConfiguration.addAll(globalConfiguration.getGlobalExecutableTypes());
+                    } else {
+                        for (final ExecutableType type : annotation.type()) {
+                            if (ExecutableType.IMPLICIT.equals(type)) {
+                                
classConfiguration.add(ExecutableType.CONSTRUCTORS);
+                                
classConfiguration.add(ExecutableType.NON_GETTER_METHODS);
+                            } else if (ExecutableType.ALL.equals(type)) {
+                                
classConfiguration.add(ExecutableType.CONSTRUCTORS);
+                                
classConfiguration.add(ExecutableType.NON_GETTER_METHODS);
+                                
classConfiguration.add(ExecutableType.GETTER_METHODS);
+                                break;
+                            } else if (!ExecutableType.NONE.equals(type)) {
+                                classConfiguration.add(type);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        methodConfig = methodConfiguration.get(method);
+        if (methodConfig == null) {
+            synchronized (this) {
+                methodConfig = methodConfiguration.get(method);
+                if (methodConfig == null) {
+                    // reuse Proxies to avoid issue with some subclassing libs 
removing annotations
+                    final ValidateOnExecution annotation = 
targetClass.getMethod(method.getName(), 
method.getParameterTypes()).getAnnotation(ValidateOnExecution.class);
+                    if (annotation == null) {
+                        methodConfig = doValidMethod(method, 
classConfiguration);
+                    } else {
+                        final Collection<ExecutableType> config = new 
HashSet<ExecutableType>();
+                        for (final ExecutableType type : annotation.type()) {
+                            if (ExecutableType.IMPLICIT.equals(type)) { // on 
method it just means validate, even on getters
+                                config.add(ExecutableType.CONSTRUCTORS);
+                                config.add(ExecutableType.NON_GETTER_METHODS);
+                                config.add(ExecutableType.GETTER_METHODS);
+                            } else if (ExecutableType.ALL.equals(type)) {
+                                config.add(ExecutableType.CONSTRUCTORS);
+                                config.add(ExecutableType.NON_GETTER_METHODS);
+                                config.add(ExecutableType.GETTER_METHODS);
+                                break;
+                            } else if (!ExecutableType.NONE.equals(type)) {
+                                config.add(type);
+                            }
+                        }
+                        methodConfig = doValidMethod(method, config);
+                    }
+                }
+                methodConfiguration.put(method, methodConfig);
+            }
+        }
+
+        return methodConfig;
+    }
+
+    private boolean doValidMethod(final Method method, final 
Collection<ExecutableType> config) {
+        final boolean getter = isGetter(method);
+        return (!getter && config.contains(ExecutableType.NON_GETTER_METHODS)) 
|| (getter && config.contains(ExecutableType.GETTER_METHODS));
+    }
+
+    private static boolean isGetter(final Method method) {
+        final String name = method.getName();
+        return (name.startsWith("get") || name.startsWith("is")) && 
method.getReturnType() != Void.TYPE && method.getParameterTypes().length == 0;
+    }
 }

Modified: bval/branches/bval-11/bval-tck11/work-tests-suite.xml
URL: 
http://svn.apache.org/viewvc/bval/branches/bval-11/bval-tck11/work-tests-suite.xml?rev=1504049&r1=1504048&r2=1504049&view=diff
==============================================================================
--- bval/branches/bval-11/bval-tck11/work-tests-suite.xml (original)
+++ bval/branches/bval-11/bval-tck11/work-tests-suite.xml Wed Jul 17 08:37:00 
2013
@@ -19,14 +19,14 @@ JUST HERE TO BE ABLE TO RUN TCK ONE BY O
 think to add 
-Dvalidation.provider=org.apache.bval.jsr303.ApacheValidationProvider to your 
runner config
 -->
 <suite name="tmp" verbose="1">
-    <test name="tmp">
-        <classes>
-            <!--<class 
name="org.hibernate.beanvalidation.tck.tests.integration.cdi.executable.ExecutableValidationTest">-->
-            <class 
name="org.hibernate.beanvalidation.tck.tests.integration.ee.cdi.ConstraintValidatorInjectionTest">
-                <methods>
+  <test name="tmp">
+    <classes>
+      <class
+        
name="org.hibernate.beanvalidation.tck.tests.integration.cdi.executable.global.ExecutableValidationBasedOnGlobalConfigurationTest">
+        <methods>
 
-                </methods>
-            </class>
-        </classes>
-    </test>
+        </methods>
+      </class>
+    </classes>
+  </test>
 </suite>


Reply via email to