This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/master by this push: new c094052 Uses Java Reflections instead BeanUtils to read property c094052 is described below commit c0940529690697611aaab38ea9ea1186d909267b Author: Lukasz Lenart <lukaszlen...@apache.org> AuthorDate: Fri Mar 4 12:52:33 2022 +0100 Uses Java Reflections instead BeanUtils to read property --- .../validation/BeanValidationExampleAction.java | 30 ++++---- .../conversion/annotations/TypeConversion.java | 3 +- plugins/bean-validation/pom.xml | 18 +++-- .../constraints/impl/FieldMatchValidator.java | 19 ++++- .../constraints/impl/FieldMatchValidatorTest.java | 84 ++++++++++++++++++++++ pom.xml | 2 +- 6 files changed, 129 insertions(+), 27 deletions(-) diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java index 67190e0..4c07f51 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java @@ -27,22 +27,24 @@ import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.interceptor.validation.SkipValidation; -import org.hibernate.validator.constraints.Email; -import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; -import javax.validation.constraints.*; +import javax.validation.constraints.Email; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.util.Date; -/** - * <!-- START SNIPPET: beanValidatationExample --> - */ +// <!-- START SNIPPET: beanValidationExample --> @Namespace("/bean-validation") @ParentPackage("bean-validation") @Action(results = { - @Result(name = "input", location = "bean-validation.jsp"), - @Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp") + @Result(name = "input", location = "bean-validation.jsp"), + @Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp") }) @FieldMatch(first = "fieldExpressionValidatorField", second = "requiredValidatorField", message = "requiredValidatorField and fieldExpressionValidatorField are not matching") @ScriptAssert(lang = "javascript", script = "_this.dateValidatorField != null && _this.dateValidatorField.before(new java.util.Date())", message = "Date need to before now") @@ -82,10 +84,10 @@ public class BeanValidationExampleAction extends ActionSupport { private String fieldExpressionValidatorField = null; @Action(value = "bean-validation", results = { - @Result(name = "success", location = "bean-validation.jsp") + @Result(name = "success", location = "bean-validation.jsp") }) @SkipValidation - public String beanValidation(){ + public String beanValidation() { return SUCCESS; } @@ -150,7 +152,7 @@ public class BeanValidationExampleAction extends ActionSupport { } public void setFieldExpressionValidatorField( - String fieldExpressionValidatorField) { + String fieldExpressionValidatorField) { this.fieldExpressionValidatorField = fieldExpressionValidatorField; } @@ -163,8 +165,4 @@ public class BeanValidationExampleAction extends ActionSupport { } } -/** - * <!-- END SNIPPET: beanValidatationExample --> - */ - - +// <!-- END SNIPPET: beanValidationExample --> diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java index 6c86d4a..eda8a58 100644 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java +++ b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java @@ -38,7 +38,8 @@ import java.lang.annotation.Target; * * <p> * Application wide conversion:<br> - * The conversion rules will be assembled within the <code>xwork-conversion.properties</code> file within the classpath root. + * The conversion rules will be assembled within the <code>struts-conversion.properties</code> or + * <code>xwork-conversion.properties</code> (deprecated) file within the classpath root. * Set type to: <code>type = ConversionType.APPLICATION</code> * </p> * <!-- END SNIPPET: description --> diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml index b593675..aed8f05 100644 --- a/plugins/bean-validation/pom.xml +++ b/plugins/bean-validation/pom.xml @@ -45,11 +45,6 @@ </dependency> <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - </dependency> - - <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.2.Final</version> @@ -60,6 +55,17 @@ <artifactId>javax.el</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <!-- this library is excluded in the parent pom as it clashes with Easymock dependencies --> + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + <version>3.2</version> + </dependency> <!-- The Java EE API modules listed below are all marked @Deprecated(forRemoval=true), because they are scheduled @@ -94,4 +100,4 @@ </dependencies> -</project> \ No newline at end of file +</project> 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 index 9ad2d19..40837cb 100644 --- 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 @@ -20,17 +20,20 @@ */ 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; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> { private static final Logger LOG = LogManager.getLogger(FieldMatchValidator.class); + private String firstFieldName; private String secondFieldName; @@ -41,13 +44,23 @@ public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Obje 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); + final Object firstObj = readPropertyValue(value, this.firstFieldName); + final Object secondObj = readPropertyValue(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; } + } + private Object readPropertyValue(Object bean, String propertyName) throws Exception { + BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); + for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) { + if (propertyName.equals(descriptor.getName())) { + return descriptor.getReadMethod().invoke(bean); + } + } + return null; } + } diff --git a/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidatorTest.java b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidatorTest.java new file mode 100644 index 0000000..5b5608c --- /dev/null +++ b/plugins/bean-validation/src/test/java/org/apache/struts/beanvalidation/constraints/impl/FieldMatchValidatorTest.java @@ -0,0 +1,84 @@ +/* + * 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.struts.beanvalidation.constraints.FieldMatch; +import org.junit.Test; +import org.mockito.Mockito; + +import javax.validation.ConstraintValidatorContext; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FieldMatchValidatorTest { + + @Test + public void matchingFields() { + // given + FieldMatchValidator validator = new FieldMatchValidator(); + validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class)); + + ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class); + + // when + FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "12345678"); + + boolean valid = validator.isValid(bean, context); + + // then + assertTrue(valid); + } + + @Test + public void notMatchingFields() { + // given + FieldMatchValidator validator = new FieldMatchValidator(); + validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class)); + + ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class); + + // when + FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "87654321"); + + boolean valid = validator.isValid(bean, context); + + // then + assertFalse(valid); + } + + @FieldMatch(first = "password", second = "repeatPassword") + public static class FieldMatchTestBean { + String password; + String repeatPassword; + + public FieldMatchTestBean(String password, String repeatPassword) { + this.password = password; + this.repeatPassword = repeatPassword; + } + + public String getPassword() { + return password; + } + + public String getRepeatPassword() { + return repeatPassword; + } + } +} diff --git a/pom.xml b/pom.xml index cc586d6..a238c0c 100644 --- a/pom.xml +++ b/pom.xml @@ -1075,7 +1075,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>3.3.3</version> + <version>4.3.1</version> <exclusions> <!-- The mockito-core artifact and easymock artifact use different versions of objenesis (2.6 vs 3.1). Excluding the older version here to pass enforcer. When next upgrading mockito-core, confirm whether this exclusion is still required. -->