Repository: struts
Updated Branches:
  refs/heads/master 779b2bd24 -> b6afefeea


WW-4505 Add plugin to support bean validation

Add first implementation of the new bean validation plugin.

This plugin is based on the plugin from Umesh Awasthi:
https://github.com/struts-community-plugins/jsr303-validator-plugin


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

Branch: refs/heads/master
Commit: 95da4e341f74a97d360e521139950bd7be0dac62
Parents: 73ef38d
Author: Johannes Geppert <joh...@gmail.com>
Authored: Tue May 26 20:39:30 2015 +0200
Committer: Johannes Geppert <joh...@gmail.com>
Committed: Tue May 26 20:39:30 2015 +0200

----------------------------------------------------------------------
 plugins/bean-validation/pom.xml                 |  57 +++++
 .../beanvalidation/constraints/FieldMatch.java  |  87 ++++++++
 .../constraints/impl/FieldMatchValidator.java   |  53 +++++
 .../validation/constant/ValidatorConstants.java |  41 ++++
 .../interceptor/BeanValidationInterceptor.java  | 219 +++++++++++++++++++
 .../interceptor/BeanValidationManager.java      |  34 +++
 .../DefaultBeanValidationManager.java           | 118 ++++++++++
 .../src/main/resources/LICENSE.txt              | 174 +++++++++++++++
 .../src/main/resources/NOTICE.txt               |   8 +
 .../src/main/resources/struts-plugin.xml        |  75 +++++++
 plugins/pom.xml                                 |   1 +
 11 files changed, 867 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml
new file mode 100644
index 0000000..a7a02f0
--- /dev/null
+++ b/plugins/bean-validation/pom.xml
@@ -0,0 +1,57 @@
+<?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.
+ */
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <parent>
+        <groupId>org.apache.struts</groupId>
+        <artifactId>struts2-plugins</artifactId>
+        <version>2.5-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>struts2-bean-validation</artifactId>
+    <name>Struts 2 Bean Validation Plugin</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+            <version>1.1.0.Final</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.2</version>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/FieldMatch.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/FieldMatch.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/FieldMatch.java
new file mode 100644
index 0000000..69bf7c8
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/FieldMatch.java
@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.constraints;
+
+import org.apache.struts.beanvalidation.constraints.impl.FieldMatchValidator;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+
+/**
+ * Validation annotation to validate that two fields are equals.
+ * An array of fields and their matching confirmation fields can be supplied.
+ * <p/>
+ * Example, compare 1 pair of fields:
+ * <pre>
+ *
+ * @FieldMatch(first = "password", second = "confirmPassword", message = "The 
password fields must match")
+ * </pre>
+ * <p/>
+ * Example, compare more than 1 pair of fields:
+ * <pre>
+ * @FieldMatch.List({
+ *      @FieldMatch(first = "password", second = "confirmPassword", message = 
"The password fields must match"),
+ *      @FieldMatch(first = "email", second = "confirmEmail", message = "The 
email fields must match")
+ * })
+ * </pre>
+ */
+
+@Constraint(validatedBy = FieldMatchValidator.class)
+@Documented
+@Target({TYPE, ANNOTATION_TYPE})
+@Retention(RUNTIME)
+public @interface FieldMatch {
+    String message() default "Fields are not matching";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+    /**
+     * @return The first field
+     */
+    String first();
+
+    /**
+     * @return The second field
+     */
+    String second();
+
+    /**
+     * Defines several <code>@FieldMatch</code> annotations on the same element
+     *
+     * @see FieldMatch
+     */
+    @Target({TYPE, ANNOTATION_TYPE})
+    @Retention(RUNTIME)
+    @Documented
+    @interface List {
+        FieldMatch[] value();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidator.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidator.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidator.java
new file mode 100644
index 0000000..9ad2d19
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidator.java
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.constraints.impl;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts.beanvalidation.constraints.FieldMatch;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+public class FieldMatchValidator implements ConstraintValidator<FieldMatch, 
Object> {
+
+    private static final Logger LOG = 
LogManager.getLogger(FieldMatchValidator.class);
+    private String firstFieldName;
+    private String secondFieldName;
+
+    public void initialize(final FieldMatch constraintAnnotation) {
+        this.firstFieldName = constraintAnnotation.first();
+        this.secondFieldName = constraintAnnotation.second();
+    }
+
+    public boolean isValid(final Object value, final 
ConstraintValidatorContext context) {
+        try {
+            final Object firstObj = PropertyUtils.getProperty(value, 
this.firstFieldName);
+            final Object secondObj = PropertyUtils.getProperty(value, 
this.secondFieldName);
+            return firstObj == null && secondObj == null || firstObj != null 
&& firstObj.equals(secondObj);
+        } catch (final Exception ex) {
+            LOG.info("Error while getting values from object", ex);
+            return false;
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/constant/ValidatorConstants.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/constant/ValidatorConstants.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/constant/ValidatorConstants.java
new file mode 100644
index 0000000..a0e61f7
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/constant/ValidatorConstants.java
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.validation.constant;
+
+/**
+ * <p>Class consisting various constant values being used within
+ * bean validation plugin </p>
+ * <p/>
+ * <p>
+ * These values can be overridden using struts.xml file by providing custom 
values.
+ * </p>
+ */
+public final class ValidatorConstants {
+
+    public static final String PROVIDER_CLASS = 
"struts.beanValidation.providerClass";
+    public static final String IGNORE_XMLCONFIGURAITION = 
"struts.beanValidation.ignoreXMLConfiguration";
+    public static final String CONVERT_MESSAGE_TO_UTF8 = 
"struts.beanValidation.convertMessageToUtf";
+    public static final String CONVERT_MESSAGE_FROM = 
"struts.beanValidation.convertMessageFromEncoding";
+    public static final String FIELD_SEPERATOR = ".";
+    public static final String MODELDRIVEN_PREFIX = "model";
+    public static final String EMPTY_SPACE = "";
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationInterceptor.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationInterceptor.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationInterceptor.java
new file mode 100644
index 0000000..162e8e6
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationInterceptor.java
@@ -0,0 +1,219 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.validation.interceptor;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.ModelDriven;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
+import com.opensymphony.xwork2.util.AnnotationUtils;
+import com.opensymphony.xwork2.validator.DelegatingValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts.beanvalidation.validation.constant.ValidatorConstants;
+import org.apache.struts2.interceptor.validation.SkipValidation;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * <p>
+ * Bean Validation interceptor. This Interceptor do not itself provide any 
Bean validation functionality but
+ * works as a bridge between Bean validation implementation's like Apache Bval 
or Hibernate Validator and Struts2 validation mechanism.
+ * </p>
+ * <p>
+ * Interceptor will create a Validation Factory based on the provider class 
and will validate requested method or Action
+ * class. Hibernate bean validator will be used as a default validator in case 
of no provider class will be supplied to
+ * the interceptor.
+ * </p>
+ */
+public class BeanValidationInterceptor extends MethodFilterInterceptor {
+
+    private static final Logger LOG = 
LogManager.getLogger(BeanValidationInterceptor.class);
+    protected BeanValidationManager beanValidationManager;
+    protected boolean convertToUtf8 = false;
+    protected String convertFromEncoding = "ISO-8859-1";
+
+    @Inject()
+    public void setBeanValidationManager(BeanValidationManager 
beanValidationManager) {
+        this.beanValidationManager = beanValidationManager;
+    }
+
+    @Inject(value = ValidatorConstants.CONVERT_MESSAGE_TO_UTF8, required = 
false)
+    public void setConvertToUtf8(String convertToUtf8) {
+        this.convertToUtf8 = BooleanUtils.toBoolean(convertToUtf8);
+    }
+
+    @Inject(value = ValidatorConstants.CONVERT_MESSAGE_FROM, required = false)
+    public void setConvertFromEncoding(String convertFromEncoding) {
+        this.convertFromEncoding = convertFromEncoding;
+    }
+
+    @Override
+    protected String doIntercept(ActionInvocation invocation) throws Exception 
{
+        Validator validator = this.beanValidationManager.getValidator();
+        if (validator == null) {
+            LOG.debug("There is no Bean Validator configured in class path. 
Skipping Bean validation..");
+            return invocation.invoke();
+        }
+        LOG.debug("Starting bean validation using validator: {}", 
validator.getClass());
+
+        Object action = invocation.getAction();
+        ActionProxy actionProxy = invocation.getProxy();
+        String methodName = actionProxy.getMethod();
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Validating [{}/{}] with method [{}]", 
invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), 
methodName);
+        }
+
+        Collection<Method> annotatedMethods = 
AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class);
+
+        if (!annotatedMethods.contains(getActionMethod(action.getClass(), 
methodName))) {
+            // performing bean validation on action
+            performBeanValidation(action, validator);
+        }
+
+        return invocation.invoke();
+    }
+
+    protected void performBeanValidation(Object action, Validator validator) {
+
+        LOG.trace("Initiating bean validation..");
+
+        Set<ConstraintViolation<Object>> constraintViolations;
+
+        if (action instanceof ModelDriven) {
+            LOG.trace("Performing validation on model..");
+            constraintViolations = validator.validate(((ModelDriven) 
action).getModel());
+        } else {
+            LOG.trace("Performing validation on action..");
+            constraintViolations = validator.validate(action);
+        }
+
+        addBeanValidationErrors(constraintViolations, action);
+    }
+
+    @SuppressWarnings("nls")
+    private void addBeanValidationErrors(Set<ConstraintViolation<Object>> 
constraintViolations, Object action) {
+        if (constraintViolations != null) {
+            ValidatorContext validatorContext = new 
DelegatingValidatorContext(action);
+            for (ConstraintViolation<Object> constraintViolation : 
constraintViolations) {
+                String key = constraintViolation.getMessage();
+                String message = key;
+                try {
+                    message = validatorContext.getText(key);
+                    if (convertToUtf8 && StringUtils.isNotBlank(message)) {
+                        message = new 
String(message.getBytes(convertFromEncoding), "UTF-8");
+                    }
+                } catch (Exception e) {
+                    LOG.error("Error while trying to fetch message: {}", key, 
e);
+                }
+
+                if (isActionError(constraintViolation)) {
+                    LOG.debug("Adding action error [{}]", message);
+                    validatorContext.addActionError(message);
+                } else {
+                    ValidationError validationError = 
buildBeanValidationError(constraintViolation, message);
+                    String fieldName = validationError.getFieldName();
+                    if (action instanceof ModelDriven && 
fieldName.startsWith(ValidatorConstants.MODELDRIVEN_PREFIX)) {
+                        fieldName = fieldName.replace("model.", 
ValidatorConstants.EMPTY_SPACE);
+                    }
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Adding field error [{}] with message [{}]", 
fieldName, validationError.getMessage());
+                    }
+                    validatorContext.addFieldError(fieldName, 
validationError.getMessage());
+                }
+            }
+        }
+    }
+
+    protected ValidationError 
buildBeanValidationError(ConstraintViolation<Object> violation, String message) 
{
+
+        if (violation.getPropertyPath().iterator().next().getName() != null) {
+            String fieldName = violation.getPropertyPath().toString();
+            String finalMessage = StringUtils.removeStart(message, fieldName + 
ValidatorConstants.FIELD_SEPERATOR);
+            return new ValidationError(fieldName, finalMessage);
+        }
+
+        return null;
+    }
+
+    /**
+     * Decide if a violation should be added to the fieldErrors or actionErrors
+     */
+    protected boolean isActionError(ConstraintViolation<Object> violation) {
+        return violation.getLeafBean() == violation.getInvalidValue();
+    }
+
+    /**
+     * This is copied from DefaultActionInvocation
+     */
+    protected Method getActionMethod(Class actionClass, String methodName) 
throws NoSuchMethodException {
+        Method method;
+
+        try {
+            method = actionClass.getMethod(methodName, new Class[0]);
+        } catch (NoSuchMethodException e) {
+            // hmm -- OK, try doXxx instead
+            try {
+                String altMethodName = "do" + methodName.substring(0, 
1).toUpperCase() +
+                        methodName.substring(1);
+                method = actionClass.getMethod(altMethodName, new Class[0]);
+            } catch (NoSuchMethodException e1) {
+                // throw the original one
+                throw e;
+            }
+        }
+
+        return method;
+    }
+
+    /**
+     * Inner class for validation error
+     * Nice concept taken from  Oval plugin.
+     */
+
+    class ValidationError {
+        private final String fieldName;
+        private final String message;
+
+        ValidationError(String fieldName, String message) {
+            this.fieldName = fieldName;
+            this.message = message;
+        }
+
+        public String getFieldName() {
+            return this.fieldName;
+        }
+
+        public String getMessage() {
+            return this.message;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationManager.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationManager.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationManager.java
new file mode 100644
index 0000000..bb52754
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/BeanValidationManager.java
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.validation.interceptor;
+
+import javax.validation.Validator;
+
+/**
+ * <p>
+ * Validation manager which is responsible for providing instance of {@link 
Validator} based on the underlying validation provider.
+ * For any JSR303 complaint implementation,{@link Validator} should be 
implemented in thread safe way.
+ * </p>
+ */
+public interface BeanValidationManager {
+
+    Validator getValidator();
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/DefaultBeanValidationManager.java
----------------------------------------------------------------------
diff --git 
a/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/DefaultBeanValidationManager.java
 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/DefaultBeanValidationManager.java
new file mode 100644
index 0000000..f03e19e
--- /dev/null
+++ 
b/plugins/bean-validation/src/main/java/org/apache/struts/beanvalidation/validation/interceptor/DefaultBeanValidationManager.java
@@ -0,0 +1,118 @@
+/*
+ * $Id$
+ *
+ * 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.struts.beanvalidation.validation.interceptor;
+
+import com.opensymphony.xwork2.inject.Inject;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts.beanvalidation.validation.constant.ValidatorConstants;
+
+import javax.validation.Configuration;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * <p>
+ * This is the central class for javax.validation (JSR-303) setup in a Struts2 
: It bootstraps a
+ * javax.validation.ValidationFactory and exposes it through the 
javax.validation.Validator interface and the. When
+ * talking to an instance of this bean we will be talking to the default 
Validator of the underlying ValidatorFactory.
+ * </p>
+ * <p>
+ * This is very convenient in that you don't have to perform yet another call 
on the factory, assuming that you will
+ * almost always use the default Validator anyway.You need to pass provider 
class in order for this plugin to hook
+ * itself to underlying validation Factory. Any of following Validation 
provider can be provided using
+ * <code>struts.beanValidation.providerClass</code>
+ * <ul>
+ * <li>Hibernate Validator - 
<code>org.hibernate.validator.HibernateValidator</code></li>
+ * <li>Apache Bval - 
<code>org.apache.bval.jsr303.ApacheValidationProvider</code></li>
+ * </ul>
+ * </p>
+ */
+public class DefaultBeanValidationManager
+        implements BeanValidationManager {
+
+    private static final Logger LOG = 
LogManager.getLogger(DefaultBeanValidationManager.class);
+
+    protected Class<? extends ValidationProvider> providerClass;
+
+    private ValidatorFactory validationFactory;
+
+    @Inject
+    public DefaultBeanValidationManager(
+                @Inject(value = ValidatorConstants.PROVIDER_CLASS, required = 
false) String providerClassName,
+                @Inject(value = ValidatorConstants.IGNORE_XMLCONFIGURAITION, 
required = false)String ignoreXMLConfiguration) {
+        super();
+        LOG.info("Initializing bean validation11 factory to get a validator");
+
+        if (StringUtils.isNotBlank(providerClassName)) {
+            try {
+                this.providerClass = (Class<? extends ValidationProvider>) 
Class.forName(providerClassName);
+                LOG.info(this.providerClass.getName() + " validator found");
+            } catch (ClassNotFoundException e) {
+                LOG.error("Unable to find any bean validator implementation 
for " + providerClassName);
+                LOG.error("Unable to load bean validation provider class", e);
+            }
+
+        }
+        if (this.providerClass == null) {
+            LOG.info("********** No bean validator class defined - Falling 
back to default provider **********");
+        }
+
+        Configuration configuration =
+                (this.providerClass != null ? 
Validation.byProvider(this.providerClass).configure()
+                        : Validation.byDefaultProvider().configure());
+        if (BooleanUtils.toBoolean(ignoreXMLConfiguration)) {
+            configuration.ignoreXmlConfiguration();
+            LOG.info("XML configurations will be ignore by Validator, to 
enable XML based validation, set struts.beanValidation.ignoreXMLConfiguration 
to false.");
+        }
+        if (configuration != null) {
+            this.validationFactory = configuration.buildValidatorFactory();
+        }
+
+    }
+
+    /**
+     * <p>
+     * Method to return Validator instance.This will take in to account the 
provider class will try to create a
+     * validation factory from given Validator. Validator will be returned 
based on the user preference.Validator will
+     * be created based on the following cases.
+     * </p>
+     * <p>
+     * In case user has specify explicitly and in a type safe fashion the 
expected provider, it will be used to create
+     * validation factory and an instance of javax.validation.Validator will 
be returned.
+     * </p>
+     * <p>
+     * In this case, the default validation provider resolver will be used to 
locate available providers. The chosen
+     * provider is defined as followed:
+     * <li>if the XML configuration defines a provider, this provider is 
used</li>
+     * <li>if the XML configuration does not define a provider or if no XML 
configuration is present the first provider
+     * returned by the ValidationProviderResolver instance is used.</li>
+     * </p>
+     */
+    public Validator getValidator() {
+        return this.validationFactory.getValidator();
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/resources/LICENSE.txt
----------------------------------------------------------------------
diff --git a/plugins/bean-validation/src/main/resources/LICENSE.txt 
b/plugins/bean-validation/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..dd5b3a5
--- /dev/null
+++ b/plugins/bean-validation/src/main/resources/LICENSE.txt
@@ -0,0 +1,174 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/resources/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plugins/bean-validation/src/main/resources/NOTICE.txt 
b/plugins/bean-validation/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..93770c6
--- /dev/null
+++ b/plugins/bean-validation/src/main/resources/NOTICE.txt
@@ -0,0 +1,8 @@
+Apache Struts
+Copyright 2000-2015 The Apache Software Foundation
+
+This plugin is based on the work of Umesh Awasthi implementation
+https://github.com/umeshawasthi/jsr303-validator-plugin
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/bean-validation/src/main/resources/struts-plugin.xml
----------------------------------------------------------------------
diff --git a/plugins/bean-validation/src/main/resources/struts-plugin.xml 
b/plugins/bean-validation/src/main/resources/struts-plugin.xml
new file mode 100644
index 0000000..b45c6cb
--- /dev/null
+++ b/plugins/bean-validation/src/main/resources/struts-plugin.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+/*
+ * $Id$
+ *
+ * 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.
+ */
+-->
+
+<!DOCTYPE struts PUBLIC
+        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
+        "http://struts.apache.org/dtds/struts-2.3.dtd";>
+
+<struts>
+    <constant name="struts.beanValidation.providerClass" value=""/>
+    <constant name="struts.beanValidation.ignoreXMLConfiguration" 
value="false"/>
+    <constant name="struts.beanValidation.convertMessageToUtf" value="false"/>
+    <constant name="struts.beanValidation.convertMessageFromEncoding" 
value="ISO-8859-1"/>
+
+    <bean 
type="org.apache.struts.beanvalidation.validation.interceptor.BeanValidationManager"
+          
class="org.apache.struts.beanvalidation.validation.interceptor.DefaultBeanValidationManager"
+          scope="singleton"/>
+
+    <package name="struts-bean-validation" extends="struts-default">
+        <interceptors>
+            <interceptor name="beanValidation" 
class="org.apache.struts.beanvalidation.validation.interceptor.BeanValidationInterceptor"/>
+
+            <interceptor-stack name="beanValidationDefaultStack">
+                <interceptor-ref name="exception"/>
+                <interceptor-ref name="alias"/>
+                <interceptor-ref name="servletConfig"/>
+                <interceptor-ref name="i18n"/>
+                <interceptor-ref name="prepare"/>
+                <interceptor-ref name="chain"/>
+                <interceptor-ref name="scopedModelDriven"/>
+                <interceptor-ref name="modelDriven"/>
+                <interceptor-ref name="fileUpload"/>
+                <interceptor-ref name="checkbox"/>
+                <interceptor-ref name="datetime"/>
+                <interceptor-ref name="multiselect"/>
+                <interceptor-ref name="staticParams"/>
+                <interceptor-ref name="actionMappingParams"/>
+                <interceptor-ref name="params"/>
+                <interceptor-ref name="conversionError"/>
+                <interceptor-ref name="beanValidation">
+                    <param 
name="excludeMethods">input,back,cancel,browse</param>
+                </interceptor-ref>
+                <interceptor-ref name="workflow">
+                    <param 
name="excludeMethods">input,back,cancel,browse</param>
+                </interceptor-ref>
+                <interceptor-ref name="debugging"/>
+                <interceptor-ref name="deprecation"/>
+            </interceptor-stack>
+
+        </interceptors>
+
+        <default-interceptor-ref name="beanValidationDefaultStack"/>
+
+    </package>
+</struts>

http://git-wip-us.apache.org/repos/asf/struts/blob/95da4e34/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 6c9b7b4..2f1fe76 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -34,6 +34,7 @@
     <name>Struts Plugins</name>
 
     <modules>
+        <module>bean-validation</module>
         <module>cdi</module>
         <module>config-browser</module>
         <module>convention</module>

Reply via email to