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>