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>