Author: radcortez Date: Fri Jan 25 15:27:43 2019 New Revision: 1852142 URL: http://svn.apache.org/viewvc?rev=1852142&view=rev Log: Update bval tomee path with latest changes from official bval repo until git hash 83f28d8.
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheMessageContext.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxy.java - copied, changed from r1852141, tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxyBuilder.java - copied, changed from r1852141, tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/LookBehindRegexHolder.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/LiskovTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/util/LookBehindRegexHolderTest.java tomee/deps/branches/bval-2/bval-tck/src/main/java/org/apache/bval/arquillian/LogTckFormatter.java tomee/deps/branches/bval-2/bval-tck/src/test/resources/logging.properties tomee/deps/branches/bval-2/src/ tomee/deps/branches/bval-2/src/site/ tomee/deps/branches/bval-2/src/site/resources/ tomee/deps/branches/bval-2/src/site/resources/images/ tomee/deps/branches/bval-2/src/site/resources/images/bval-bean-small.png tomee/deps/branches/bval-2/src/site/site.xml Removed: tomee/deps/branches/bval-2/bundle/src/main/appended-resources/META-INF/NOTICE.vm tomee/deps/branches/bval-2/bval-jsr/src/main/appended-resources/META-INF/NOTICE.vm tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java Modified: tomee/deps/branches/bval-2/CHANGES.txt tomee/deps/branches/bval-2/NOTICE tomee/deps/branches/bval-2/README.txt tomee/deps/branches/bval-2/bundle/pom.xml tomee/deps/branches/bval-2/bval-extras/pom.xml tomee/deps/branches/bval-2/bval-jsr/pom.xml tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidator.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCharSequence.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCollection.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForMap.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ParticipantFactory.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/job/ConstraintValidatorContextImpl.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataSource.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/resolver/DefaultTraversableResolver.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Exceptions.java tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/reflection/Reflection.java tomee/deps/branches/bval-2/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages.properties tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/BeanDescriptorTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/DefaultMessageInterpolatorTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/ValidationTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/example/Book.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/extensions/MethodValidatorImplTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/groups/CollectionValidationTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/groups/DefaultGroupSequenceTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/groups/GroupSequenceTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/groups/implicit/ImplicitGroupingTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/groups/inheritance/GroupInheritanceTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/util/TestUtils.java tomee/deps/branches/bval-2/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java tomee/deps/branches/bval-2/bval-jsr/src/test/resources/ValidationMessages.properties tomee/deps/branches/bval-2/bval-tck/pom.xml tomee/deps/branches/bval-2/bval-tck/src/main/java/org/apache/bval/arquillian/BValArquillianExtension.java tomee/deps/branches/bval-2/bval-tck/src/main/java/org/apache/bval/arquillian/EJBEnricher.java tomee/deps/branches/bval-2/pom.xml Modified: tomee/deps/branches/bval-2/CHANGES.txt URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/CHANGES.txt?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/CHANGES.txt (original) +++ tomee/deps/branches/bval-2/CHANGES.txt Fri Jan 25 15:27:43 2019 @@ -14,19 +14,16 @@ Content Overview ======== -This is an implementation of the Java Bean Validation (JSRs 303, 349) +This is an implementation of the Java Bean Validation (JSRs 303, 349, 380) specification for Java EE and Java SE. The technical objective is to provide a class level constraint declaration and validation facility for the Java application developer, as well as a constraint metadata repository and query API. -This implementation is based on the validation framework of Agimatec GmbH, -which was contributed to the ASF under a software grant. - Prerequisites ============= -You need a platform that supports Java SE 6 or later. +You need a platform that supports Java SE 8 or later. Documentation @@ -53,6 +50,27 @@ How do I Contribute? * Bugs and other issues can be posted on the project JIRA. +Release Notes - BVal - Version 2.0.0 +========================================== + +** Bug + * [BVAL-108] - Prefer Thread context classloader or framework-relative as appropriate to task - addresses resource loading complaints with OSGI + * [BVAL-154] - avoid storing metamodel for unconstrained types using "negative cache" + * [BVAL-157] - method named get() blows up with illegal param name + * [BVAL-158] - ExecutableValidator invokes method if it looks like a getter + +** Improvement + * [BVAL-118] - improve efficiency by associating bean metadata with the factory rather than the context + * [BVAL-159] - Drop commons dependencies + * [BVAL-160] - Implement Bean Validation 2.0 (JSR 380) + +** Task + * [BVAL-161] - Redesign bean metadata model + * [BVAL-162] - Convert remaining JUnit 3 tests to JUnit 4 + * [BVAL-163] - Remove Agimatech extensions + * [BVAL-164] - Merge core code into jsr module + + Release Notes - BVal - Version 1.1.2 ========================================== Modified: tomee/deps/branches/bval-2/NOTICE URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/NOTICE?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/NOTICE (original) +++ tomee/deps/branches/bval-2/NOTICE Fri Jan 25 15:27:43 2019 @@ -1,6 +1,6 @@ Apache BVal project -Copyright 2010-2016 The Apache Software Foundation. +Copyright 2010-2018 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/). Modified: tomee/deps/branches/bval-2/README.txt URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/README.txt?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/README.txt (original) +++ tomee/deps/branches/bval-2/README.txt Fri Jan 25 15:27:43 2019 @@ -4,7 +4,7 @@ Licensed under Apache License 2.0 - http About ===== -This is an implementation of the Java Bean Validation (JSRs 303, 349) +This is an implementation of the Java Bean Validation (JSRs 303, 349, 380) specification for Java EE and Java SE. The technical objective is to provide a class level constraint declaration and validation facility for the Java application developer, as well as a constraint @@ -28,14 +28,14 @@ Along with the developer mailing list ar System Requirements =================== -You need a platform that supports Java SE 6 or later. -Most testing has been done with Java SE 7 on Mac OS X, Windows and Linux. +You need a platform that supports Java SE 8 or later. +Most testing has been done with Java SE 8 on Mac OS X, Windows and Linux. Building ========================== To build from source code: - - Sources require Java SE 6 or higher. + - Sources require Java SE 8 or higher. - The project is built with Apache Maven (suggested is at least 3.2.1). You need to download and install Maven from: http://maven.apache.org/ - Invoke maven in the root directory or a module subdirectory: Modified: tomee/deps/branches/bval-2/bundle/pom.xml URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bundle/pom.xml?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bundle/pom.xml (original) +++ tomee/deps/branches/bval-2/bundle/pom.xml Fri Jan 25 15:27:43 2019 @@ -27,7 +27,7 @@ <parent> <groupId>org.apache.tomee.patch</groupId> <artifactId>bval-parent</artifactId> - <version>2.0.0-nonfinal-57301f3-S1-SNAPSHOT</version> + <version>2.0.1-83f28d8-SNAPSHOT</version> </parent> <!-- use fully qualified naming for OSGi bundles --> @@ -36,7 +36,7 @@ <packaging>bundle</packaging> - <description>Apache BVal - Aggregate OSGi Bundle (bval-core + bval-jsr)</description> + <description>Apache BVal - OSGi Packaging of bval-jsr</description> <dependencies> <!-- JARs to include in aggregate JAR via maven-shade-plugin --> @@ -63,7 +63,7 @@ <Implementation-Vendor>org.apache</Implementation-Vendor> <Specification-Title>Java Bean Validation</Specification-Title> <Specification-Vendor>Java Community Process</Specification-Vendor> - <Specification-Version>1.1</Specification-Version> + <Specification-Version>2.0</Specification-Version> <Bundle-DocURL>${project.url}</Bundle-DocURL> <Embed-Dependency>*;inline=true</Embed-Dependency> <Private-Package /> @@ -113,6 +113,4 @@ </build> </profile> </profiles> - </project> - Modified: tomee/deps/branches/bval-2/bval-extras/pom.xml URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-extras/pom.xml?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-extras/pom.xml (original) +++ tomee/deps/branches/bval-2/bval-extras/pom.xml Fri Jan 25 15:27:43 2019 @@ -27,14 +27,14 @@ <parent> <groupId>org.apache.tomee.patch</groupId> <artifactId>bval-parent</artifactId> - <version>2.0.0-nonfinal-57301f3-S1-SNAPSHOT</version> + <version>2.0.1-83f28d8-SNAPSHOT</version> </parent> <artifactId>bval-extras</artifactId> <name>Apache BVal :: bval-extras (optional)</name> <packaging>bundle</packaging> - <description>BVal - non-JSR303 routines and constraints</description> + <description>BVal - non-JSR380 routines and constraints</description> <dependencies> <dependency> Modified: tomee/deps/branches/bval-2/bval-jsr/pom.xml URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/pom.xml?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/pom.xml (original) +++ tomee/deps/branches/bval-2/bval-jsr/pom.xml Fri Jan 25 15:27:43 2019 @@ -24,14 +24,14 @@ <parent> <groupId>org.apache.tomee.patch</groupId> <artifactId>bval-parent</artifactId> - <version>2.0.0-nonfinal-57301f3-S1-SNAPSHOT</version> + <version>2.0.1-83f28d8-SNAPSHOT</version> </parent> <artifactId>bval-jsr</artifactId> <name>Apache BVal :: bval-jsr</name> <packaging>jar</packaging> - <description>Implementation specific classes for JSR 349 Bean Validation 1.1</description> + <description>Implementation specific classes for JSR 380 Bean Validation 2.0</description> <properties> <jaxb.version>2.2.6</jaxb.version> @@ -211,6 +211,30 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-jasper-el</artifactId> + <version>9.0.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.el</artifactId> + <version>3.0.1-b10</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.odysseus.juel</groupId> + <artifactId>juel-api</artifactId> + <version>2.2.7</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.odysseus.juel</groupId> + <artifactId>juel-impl</artifactId> + <version>2.2.7</version> + <scope>test</scope> + </dependency> </dependencies> <build> @@ -266,9 +290,6 @@ <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <mainClass>org.apache.bval.util.BValVersion</mainClass> </manifest> - <manifestEntries> - <Implementation-Build>${buildNumber}</Implementation-Build> - </manifestEntries> </archive> </configuration> </execution> Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidator.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidator.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidator.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidator.java Fri Jan 25 15:27:43 2019 @@ -20,20 +20,23 @@ package org.apache.bval.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.NotEmpty; + import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** - * Description: Check the non emptiness of an - * any object that has a public isEmpty():boolean or a valid toString() method + * {@link ConstraintValidator} implementation for {@link NotEmpty}. + * Additionally, check the non-emptiness of an + * any object that has a public isEmpty():boolean or a valid toString() method. */ public class NotEmptyValidator implements ConstraintValidator<javax.validation.constraints.NotEmpty, Object> { @Override public boolean isValid(Object value, ConstraintValidatorContext context) { if (value == null) { - return true; + return false; } if (value.getClass().isArray()) { return Array.getLength(value) > 0; Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCharSequence.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCharSequence.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCharSequence.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCharSequence.java Fri Jan 25 15:27:43 2019 @@ -29,6 +29,6 @@ public class NotEmptyValidatorForCharSeq @Override public boolean isValid(CharSequence value, ConstraintValidatorContext context) { - return value == null || value.length() > 0; + return value != null && value.length() > 0; } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCollection.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCollection.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCollection.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForCollection.java Fri Jan 25 15:27:43 2019 @@ -30,6 +30,6 @@ public class NotEmptyValidatorForCollect @Override public boolean isValid(Collection<?> value, ConstraintValidatorContext context) { - return value == null || !value.isEmpty(); + return !(value == null || value.isEmpty()); } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForMap.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForMap.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForMap.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/constraints/NotEmptyValidatorForMap.java Fri Jan 25 15:27:43 2019 @@ -29,6 +29,6 @@ public class NotEmptyValidatorForMap imp @Override public boolean isValid(Map<?, ?> value, ConstraintValidatorContext context) { - return value == null || !value.isEmpty(); + return !(value == null || value.isEmpty()); } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java Fri Jan 25 15:27:43 2019 @@ -16,6 +16,11 @@ */ package org.apache.bval.el; +import java.lang.reflect.Method; +import java.util.Formatter; +import java.util.HashMap; +import java.util.Map; + import javax.el.ArrayELResolver; import javax.el.BeanELResolver; import javax.el.CompositeELResolver; @@ -28,41 +33,48 @@ import javax.el.MapELResolver; import javax.el.ResourceBundleELResolver; import javax.el.ValueExpression; import javax.el.VariableMapper; -import java.lang.reflect.Method; -import java.util.Formatter; -import java.util.HashMap; -import java.util.Map; + +import org.apache.bval.jsr.util.LookBehindRegexHolder; // ELProcessor or JavaEE 7 would be perfect too but this impl can be used in javaee 6 public final class ELFacade implements MessageEvaluator { - private static final ExpressionFactory EXPRESSION_FACTORY; - static { - ExpressionFactory ef; - try { - ef = ExpressionFactory.newInstance(); - } catch (final Exception e) { - ef = null; + private enum EvaluationType { + IMMEDIATE("\\$"), DEFERRED("#"); + + /** + * {@link LookBehindRegexHolder} to recognize a non-escaped EL + * expression of this evaluation type, hallmarked by a trigger + * character. + */ + private final LookBehindRegexHolder regex; + + private EvaluationType(String trigger) { + this.regex = new LookBehindRegexHolder( + String.format("(?<!(?:^|[^\\\\])(?:\\\\\\\\){0,%%d}\\\\)%s\\{", trigger), n -> (n - 3) / 2); } - EXPRESSION_FACTORY = ef; } + private static final ELResolver RESOLVER = initResolver(); + private final ExpressionFactory expressionFactory = ExpressionFactory.newInstance(); + @Override public String interpolate(final String message, final Map<String, Object> annotationParameters, final Object validatedValue) { try { - if (EXPRESSION_FACTORY != null) { + if (EvaluationType.IMMEDIATE.regex.matcher(message).find()) { final BValELContext context = new BValELContext(); final VariableMapper variables = context.getVariableMapper(); annotationParameters.forEach( - (k, v) -> variables.setVariable(k, EXPRESSION_FACTORY.createValueExpression(v, Object.class))); + (k, v) -> variables.setVariable(k, expressionFactory.createValueExpression(v, Object.class))); variables.setVariable("validatedValue", - EXPRESSION_FACTORY.createValueExpression(validatedValue, Object.class)); + expressionFactory.createValueExpression(validatedValue, Object.class)); - // #{xxx} shouldn't be evaluated - return EXPRESSION_FACTORY.createValueExpression(context, message.replace("#{", "\\#{"), String.class) - .getValue(context).toString(); + // Java Bean Validation does not support EL expressions that look like JSP "deferred" expressions + return expressionFactory.createValueExpression(context, + EvaluationType.DEFERRED.regex.matcher(message).replaceAll("\\$0"), String.class).getValue(context) + .toString(); } } catch (final Exception e) { // no-op @@ -81,7 +93,7 @@ public final class ELFacade implements M return resolver; } - private static class BValELContext extends ELContext { + private class BValELContext extends ELContext { private final FunctionMapper functions = new BValFunctionMapper(); private final VariableMapper variables = new BValVariableMapper(); @@ -108,13 +120,13 @@ public final class ELFacade implements M } } - private static class BValVariableMapper extends VariableMapper { + private class BValVariableMapper extends VariableMapper { private final Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>(); @Override public ValueExpression resolveVariable(final String variable) { if ("formatter".equals(variable)) { - return EXPRESSION_FACTORY.createValueExpression(new BValFormatter(), Object.class); + return expressionFactory.createValueExpression(new BValFormatter(), Object.class); } return variables.get(variable); } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java Fri Jan 25 15:27:43 2019 @@ -181,4 +181,8 @@ public class ApacheFactoryContext implem public ConstraintCached getConstraintsCache() { return factory.getConstraintsCache(); } + + public ApacheValidatorFactory getFactory() { + return factory; + } } Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheMessageContext.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheMessageContext.java?rev=1852142&view=auto ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheMessageContext.java (added) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheMessageContext.java Fri Jan 25 15:27:43 2019 @@ -0,0 +1,36 @@ +/* + * 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.bval.jsr; + +import javax.validation.MessageInterpolator; +import javax.validation.MessageInterpolator.Context; + +/** + * Vendor-specific {@link MessageInterpolator.Context} interface extension to + * provide access to validator configuration properties. + */ +public interface ApacheMessageContext extends Context { + + /** + * Get the configuration property value specified by {@code propertyKey}, if available. + * @param propertyKey + * @return {@link String} or {@code null} + */ + String getConfigurationProperty(String propertyKey); +} Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java Fri Jan 25 15:27:43 2019 @@ -49,5 +49,15 @@ public interface ApacheValidatorConfigur * Size to use for caching of constraint-related information. Default is {@code 50}. */ String CONSTRAINTS_CACHE_SIZE = "apache.bval.constraints-cache-size"; + + /** + * Specifies whether EL evaluation is permitted in non-default message + * templates. By default this feature is disabled; if you enable it you + * should ensure that no constraint validator builds violations using + * message templates containing unchecked text (e.g. the validated + * value). To do otherwise is to expose your system to potential + * injection attacks. + */ + String CUSTOM_TEMPLATE_EXPRESSION_EVALUATION = "apache.bval.custom-template-expression-evaluation"; } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java Fri Jan 25 15:27:43 2019 @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; import javax.validation.ClockProvider; @@ -368,6 +369,9 @@ public class ApacheValidatorFactory impl getMetadataBuilders().registerCustomBuilder((Class) t, (MetadataBuilder.ForBean) b); }; participantFactory.loadServices(MetadataSource.class) - .forEach(ms -> ms.process(configuration, getConstraintsCache()::add, addBuilder)); + .forEach(ms -> { + ms.initialize(this); + ms.process(configuration, getConstraintsCache()::add, addBuilder); + }); } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java Fri Jan 25 15:27:43 2019 @@ -52,6 +52,7 @@ import org.apache.bval.jsr.xml.Validatio import org.apache.bval.util.CloseableAble; import org.apache.bval.util.Exceptions; import org.apache.bval.util.Lazy; +import org.apache.bval.util.reflection.Reflection; import org.apache.commons.weaver.privilizer.Privileged; /** @@ -156,6 +157,7 @@ public class ConfigurationImpl implement private boolean ignoreXmlConfiguration = false; private ParticipantFactory participantFactory; + private ValidationParser validationParser; /** * Create a new ConfigurationImpl instance. @@ -411,20 +413,17 @@ public class ConfigurationImpl implement private BootstrapConfiguration createBootstrapConfiguration() { try { if (!ignoreXmlConfiguration) { - loader = Thread.currentThread().getContextClassLoader(); - if (loader == null) { - loader = ValidationParser.class.getClassLoader(); - } + loader = Reflection.loaderFromThreadOrClass(ValidationParser.class); + validationParser = new ValidationParser(loader); final BootstrapConfiguration xmlBootstrap = - ValidationParser.processValidationConfig(getProperties().get(Properties.VALIDATION_XML_PATH), this); + validationParser.processValidationConfig(getProperties().get(Properties.VALIDATION_XML_PATH), this); if (xmlBootstrap != null) { return xmlBootstrap; } } - loader = Thread.currentThread().getContextClassLoader(); - if (loader == null) { - loader = ApacheValidatorFactory.class.getClassLoader(); - } + validationParser = + new ValidationParser(loader = Reflection.loaderFromThreadOrClass(ApacheValidatorFactory.class)); + return BootstrapConfigurationImpl.DEFAULT; } finally { participantFactory = new ParticipantFactory(loader); @@ -438,7 +437,7 @@ public class ConfigurationImpl implement this.providerClass = loadClass(bootstrapConfig.getDefaultProviderClassName()); } bootstrapConfig.getProperties().forEach(this::addProperty); - bootstrapConfig.getConstraintMappingResourcePaths().stream().map(ValidationParser::open) + bootstrapConfig.getConstraintMappingResourcePaths().stream().map(validationParser::open) .forEach(this::addMapping); if (!beforeCdi) { Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDefaults.java Fri Jan 25 15:27:43 2019 @@ -62,7 +62,9 @@ public class ConstraintDefaults extends final ClassLoader classloader = getClassLoader(); try (final InputStream stream = classloader.getResourceAsStream(resource)) { if (stream == null) { - log.log(Level.WARNING, String.format("Cannot find %s", resource)); + if (log.isLoggable(Level.WARNING)) { + log.log(Level.WARNING, String.format("Cannot find %s", resource)); + } } else { result.load(stream); } @@ -87,4 +89,9 @@ public class ConstraintDefaults extends e -> log.log(Level.SEVERE, "exception loading default constraint validators", e)) .collect(Collectors.toList())); } + + @Override + protected ClassLoader getClassLoader() { + return Reflection.loaderFromClassOrThread(ConstraintDefaults.class); + } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java Fri Jan 25 15:27:43 2019 @@ -16,23 +16,26 @@ */ package org.apache.bval.jsr; -import org.apache.bval.el.MessageEvaluator; -import org.apache.bval.util.reflection.Reflection; -import org.apache.commons.weaver.privilizer.Privilizing; -import org.apache.commons.weaver.privilizer.Privilizing.CallTo; - -import javax.validation.MessageInterpolator; - +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; +import java.util.Objects; +import java.util.Optional; import java.util.ResourceBundle; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; -import java.util.regex.Pattern; + +import javax.validation.MessageInterpolator; + +import org.apache.bval.el.MessageEvaluator; +import org.apache.bval.jsr.util.LookBehindRegexHolder; +import org.apache.bval.util.reflection.Reflection; +import org.apache.commons.weaver.privilizer.Privilizing; +import org.apache.commons.weaver.privilizer.Privilizing.CallTo; /** * Description: Resource bundle backed message interpolator. @@ -47,8 +50,11 @@ public class DefaultMessageInterpolator private static final String DEFAULT_VALIDATION_MESSAGES = "org.apache.bval.jsr.ValidationMessages"; private static final String USER_VALIDATION_MESSAGES = "ValidationMessages"; - /** Regular expression used to do message interpolation. */ - private static final Pattern messageParameterPattern = Pattern.compile("(\\{[\\w\\.]+\\})"); + /** + * {@link LookBehindRegexHolder} to match Bean Validation attribute patterns, considering character escaping. + */ + private static final LookBehindRegexHolder MESSAGE_PARAMETER = new LookBehindRegexHolder( + "(?<!(?:^|[^\\\\])(?:\\\\\\\\){0,%1$d}\\\\)\\{((?:[\\w\\.]|\\\\[\\{\\$\\}\\\\])+)\\}", n -> (n - 4) / 2); /** The default locale for the current user. */ private Locale defaultLocale; @@ -96,7 +102,7 @@ public class DefaultMessageInterpolator /** {@inheritDoc} */ @Override - public String interpolate(String message, Context context) { + public String interpolate(final String message, final Context context) { // probably no need for caching, but it could be done by parameters since the map // is immutable and uniquely built per Validation definition, the comparison has to be based on == and not equals though return interpolate(message, context, defaultLocale); @@ -104,28 +110,11 @@ public class DefaultMessageInterpolator /** {@inheritDoc} */ @Override - public String interpolate(String message, Context context, Locale locale) { - return interpolateMessage(message, context.getConstraintDescriptor().getAttributes(), locale, - context.getValidatedValue()); - } - - /** - * Runs the message interpolation according to algorithm specified in JSR 303. - * <br/> - * Note: - * <br/> - * Lookups in user bundles are recursive whereas lookups in default bundle are not! - * - * @param message the message to interpolate - * @param annotationParameters the parameters of the annotation for which to interpolate this message - * @param locale the <code>Locale</code> to use for the resource bundle. - * @return the interpolated message. - */ - private String interpolateMessage(String message, Map<String, Object> annotationParameters, Locale locale, - Object validatedValue) { - ResourceBundle userResourceBundle = findUserResourceBundle(locale); - ResourceBundle defaultResourceBundle = findDefaultResourceBundle(locale); + public String interpolate(final String message, final Context context, final Locale locale) { + final ResourceBundle userResourceBundle = findUserResourceBundle(locale); + final ResourceBundle defaultResourceBundle = findDefaultResourceBundle(locale); + final Map<String, Object> annotationParameters = context.getConstraintDescriptor().getAttributes(); String userBundleResolvedMessage; String resolvedMessage = message; boolean evaluatedDefaultBundleOnce = false; @@ -138,10 +127,8 @@ public class DefaultMessageInterpolator if (evaluatedDefaultBundleOnce && !hasReplacementTakenPlace(userBundleResolvedMessage, resolvedMessage)) { break; } - // search the default bundle non recursive (step2) resolvedMessage = replaceVariables(userBundleResolvedMessage, defaultResourceBundle, locale, false); - evaluatedDefaultBundleOnce = true; } while (true); @@ -149,15 +136,55 @@ public class DefaultMessageInterpolator resolvedMessage = replaceAnnotationAttributes(resolvedMessage, annotationParameters); // EL handling - if (evaluator != null) { - resolvedMessage = evaluator.interpolate(resolvedMessage, annotationParameters, validatedValue); + if (evaluateExpressionLanguage(message, context)) { + resolvedMessage = evaluator.interpolate(resolvedMessage, annotationParameters, context.getValidatedValue()); } + return resolveEscapeSequences(resolvedMessage); + } - // curly braces need to be scaped in the original msg, so unescape them now - resolvedMessage = - resolvedMessage.replace("\\{", "{").replace("\\}", "}").replace("\\\\", "\\").replace("\\$", "$"); + private boolean evaluateExpressionLanguage(String template, Context context) { + if (evaluator != null) { + if (Objects.equals(template, context.getConstraintDescriptor().getMessageTemplate())) { + return true; + } + final Optional<ApacheMessageContext> apacheMessageContext = Optional.of(context).map(ctx -> { + try { + return ctx.unwrap(ApacheMessageContext.class); + } catch (Exception e) { + return null; + } + }); + return !apacheMessageContext.isPresent() || apacheMessageContext + .map(amc -> amc.getConfigurationProperty( + ApacheValidatorConfiguration.Properties.CUSTOM_TEMPLATE_EXPRESSION_EVALUATION)) + .filter(Boolean::parseBoolean).isPresent(); + } + return false; + } + + private String resolveEscapeSequences(String s) { + int pos = s.indexOf('\\'); + if (pos < 0) { + return s; + } + StringBuilder result = new StringBuilder(s.length()); + + int prev = 0; + do { + if (pos + 1 >= s.length()) { + break; + } + if ("\\{}$".indexOf(s.charAt(pos + 1)) >= 0) { + result.append(s, prev, pos); + prev = pos + 1; + } + pos = s.indexOf('\\', pos + 2); + } while (pos > 0); - return resolvedMessage; + if (prev < s.length()) { + result.append(s, prev, s.length()); + } + return result.toString(); } private boolean hasReplacementTakenPlace(String origMessage, String newMessage) { @@ -171,16 +198,8 @@ public class DefaultMessageInterpolator * @return the resource bundle or <code>null</code> if none is found. */ private ResourceBundle getFileBasedResourceBundle(Locale locale) { - ResourceBundle rb; - final ClassLoader classLoader = Reflection.getClassLoader(DefaultMessageInterpolator.class); - if (classLoader != null) { - rb = loadBundle(classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader"); - } else { - // 2011-03-27 jw: No privileged action required. - // A class can always access the classloader of itself and of subclasses. - rb = loadBundle(getClass().getClassLoader(), locale, - USER_VALIDATION_MESSAGES + " not found by validator classloader"); - } + final ClassLoader classLoader = Reflection.loaderFromThreadOrClass(DefaultMessageInterpolator.class); + ResourceBundle rb = loadBundle(classLoader, locale, USER_VALIDATION_MESSAGES); if (LOG_FINEST) { if (rb == null) { log.log(Level.FINEST, String.format("%s not found. Delegating to %s", USER_VALIDATION_MESSAGES, @@ -197,85 +216,81 @@ public class DefaultMessageInterpolator return ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader); } catch (final MissingResourceException e) { log.fine(message); + return null; } - return null; } private String replaceVariables(String message, ResourceBundle bundle, Locale locale, boolean recurse) { - final Matcher matcher = messageParameterPattern.matcher(message); - final StringBuffer sb = new StringBuffer(64); + final Matcher matcher = MESSAGE_PARAMETER.matcher(message); + final StringBuilder sb = new StringBuilder(64); + int prev = 0; while (matcher.find()) { - final String parameter = matcher.group(1); - String resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse); - matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue)); + int start = matcher.start(); + if (start > prev) { + sb.append(message, prev, start); + } + sb.append(resolveParameter(matcher.group(1), bundle, locale, recurse).orElseGet(matcher::group)); + prev = matcher.end(); + } + if (prev < message.length()) { + sb.append(message, prev, message.length()); } - matcher.appendTail(sb); return sb.toString(); } private String replaceAnnotationAttributes(final String message, final Map<String, Object> annotationParameters) { - Matcher matcher = messageParameterPattern.matcher(message); - StringBuffer sb = new StringBuffer(64); + final Matcher matcher = MESSAGE_PARAMETER.matcher(message); + final StringBuilder sb = new StringBuilder(64); + int prev = 0; while (matcher.find()) { + int start = matcher.start(); String resolvedParameterValue; String parameter = matcher.group(1); - Object variable = annotationParameters.get(removeCurlyBrace(parameter)); - if (variable != null) { - if (variable.getClass().isArray()) { - resolvedParameterValue = Arrays.toString((Object[]) variable); - } else { - resolvedParameterValue = variable.toString(); + Object variable = annotationParameters.get(parameter); + if (variable == null) { + resolvedParameterValue = matcher.group(); + } else if (Object[].class.isInstance(variable)) { + resolvedParameterValue = Arrays.toString((Object[]) variable); + } else if (variable.getClass().isArray()) { + try { + resolvedParameterValue = (String) Reflection + .getDeclaredMethod(Arrays.class, "toString", variable.getClass()).invoke(null, variable); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new IllegalStateException("Could not expand array " + variable); } } else { - resolvedParameterValue = parameter; + resolvedParameterValue = variable.toString(); } - matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue)); + if (start > prev) { + sb.append(message, prev, start); + } + sb.append(resolvedParameterValue); + prev = matcher.end(); + } + if (prev < message.length()) { + sb.append(message, prev, message.length()); } - matcher.appendTail(sb); return sb.toString(); } - private String resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, boolean recurse) { - String parameterValue; - try { - if (bundle == null) { - parameterValue = parameterName; - } else { - parameterValue = bundle.getString(removeCurlyBrace(parameterName)); - if (recurse) { - parameterValue = replaceVariables(parameterValue, bundle, locale, recurse); - } + private Optional<String> resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, + boolean recurse) { + return Optional.ofNullable(bundle).map(b -> { + try { + return b.getString(parameterName); + } catch (final MissingResourceException e) { + return null; } - } catch (final MissingResourceException e) { - // return parameter itself - parameterValue = parameterName; - } - - return parameterValue; - } - - private String removeCurlyBrace(String parameter) { - return parameter.substring(1, parameter.length() - 1); + }).map(v -> recurse ? replaceVariables(v, bundle, locale, recurse) : v); } private ResourceBundle findDefaultResourceBundle(Locale locale) { - ResourceBundle bundle = defaultBundlesMap.get(locale); - if (bundle == null) { - bundle = ResourceBundle.getBundle(DEFAULT_VALIDATION_MESSAGES, locale); - defaultBundlesMap.put(locale, bundle); - } - return bundle; + return defaultBundlesMap.computeIfAbsent(locale, + k -> ResourceBundle.getBundle(DEFAULT_VALIDATION_MESSAGES, locale)); } private ResourceBundle findUserResourceBundle(Locale locale) { - ResourceBundle bundle = userBundlesMap.get(locale); - if (bundle == null) { - bundle = getFileBasedResourceBundle(locale); - if (bundle != null) { - userBundlesMap.put(locale, bundle); - } - } - return bundle; + return userBundlesMap.computeIfAbsent(locale, this::getFileBasedResourceBundle); } /** @@ -285,16 +300,4 @@ public class DefaultMessageInterpolator public void setLocale(Locale locale) { defaultLocale = locale; } - - /** - * Escapes the string to comply with - * {@link Matcher#appendReplacement(StringBuffer, String)} requirements. - * - * @param src - * The original string. - * @return The sanitized string. - */ - private String sanitizeForAppendReplacement(String src) { - return src.replace("\\", "\\\\").replace("$", "\\$"); - } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ParticipantFactory.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ParticipantFactory.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ParticipantFactory.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/ParticipantFactory.java Fri Jan 25 15:27:43 2019 @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; @@ -55,8 +56,8 @@ class ParticipantFactory implements Clos ParticipantFactory(ClassLoader... loaders) { super(); - this.loaders = Collections.unmodifiableList(Arrays.asList(Validate - .noNullElements(loaders, "null %s specified at index %d", ClassLoader.class.getSimpleName()).clone())); + this.loaders = Arrays.asList(loaders).stream().filter(Objects::nonNull).collect(ToUnmodifiable.list()); + Validate.validState(!this.loaders.isEmpty(), "no classloaders available"); } @Override Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java Fri Jan 25 15:27:43 2019 @@ -16,8 +16,10 @@ */ package org.apache.bval.jsr.descriptor; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -26,11 +28,13 @@ import javax.validation.metadata.Cascada import javax.validation.metadata.ContainerDescriptor; import javax.validation.metadata.ElementDescriptor; import javax.validation.metadata.ExecutableDescriptor; +import javax.validation.metadata.MethodType; import org.apache.bval.jsr.ApacheValidatorFactory; import org.apache.bval.jsr.metadata.AnnotationBehaviorMergeStrategy; import org.apache.bval.jsr.metadata.CompositeBuilder; import org.apache.bval.jsr.metadata.DualBuilder; +import org.apache.bval.jsr.metadata.EmptyBuilder; import org.apache.bval.jsr.metadata.HierarchyBuilder; import org.apache.bval.jsr.metadata.MetadataBuilder; import org.apache.bval.jsr.metadata.ReflectionBuilder; @@ -55,6 +59,8 @@ public class DescriptorManager { private final ApacheValidatorFactory validatorFactory; private final ConcurrentMap<Class<?>, BeanD<?>> beanDescriptors = new ConcurrentHashMap<>(); + // synchronization unnecessary + private final Set<Class<?>> knownUnconstrainedTypes = new HashSet<>(); private final ReflectionBuilder reflectionBuilder; public DescriptorManager(ApacheValidatorFactory validatorFactory) { @@ -70,13 +76,22 @@ public class DescriptorManager { if (beanDescriptors.containsKey(beanClass)) { return beanDescriptors.get(beanClass); } - final MetadataReader.ForBean<T> reader = - new MetadataReader(validatorFactory, beanClass).forBean(builder(beanClass)); - final BeanD<T> beanD = new BeanD<>(reader); - @SuppressWarnings("unchecked") - final BeanD<T> result = - Optional.ofNullable((BeanD<T>) beanDescriptors.putIfAbsent(beanClass, beanD)).orElse(beanD); - return result; + final boolean constrained = !knownUnconstrainedTypes.contains(beanClass); + final MetadataBuilder.ForBean<T> builder = constrained ? builder(beanClass) : EmptyBuilder.instance().forBean(); + final BeanD<T> beanD = new BeanD<>(new MetadataReader(validatorFactory, beanClass).forBean(builder)); + + if (constrained) { + // if not previously known to be unconstrained, check: + if (beanD.isBeanConstrained() || !(beanD.getConstrainedConstructors().isEmpty() + && beanD.getConstrainedMethods(MethodType.GETTER, MethodType.NON_GETTER).isEmpty())) { + @SuppressWarnings("unchecked") + final BeanD<T> result = + Optional.ofNullable((BeanD<T>) beanDescriptors.putIfAbsent(beanClass, beanD)).orElse(beanD); + return result; + } + } + knownUnconstrainedTypes.add(beanClass); + return beanD; } public void clear() { Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java Fri Jan 25 15:27:43 2019 @@ -65,10 +65,10 @@ import org.apache.bval.jsr.metadata.Empt import org.apache.bval.jsr.metadata.Meta; import org.apache.bval.jsr.metadata.MetadataBuilder; import org.apache.bval.jsr.metadata.Signature; +import org.apache.bval.jsr.util.AnnotationProxyBuilder; import org.apache.bval.jsr.util.AnnotationsManager; import org.apache.bval.jsr.util.Methods; import org.apache.bval.jsr.util.ToUnmodifiable; -import org.apache.bval.jsr.xml.AnnotationProxyBuilder; import org.apache.bval.util.Exceptions; import org.apache.bval.util.ObjectUtils; import org.apache.bval.util.Validate; @@ -123,7 +123,8 @@ class MetadataReader { } } if (mustRewrite) { - final AnnotationProxyBuilder<A> builder = new AnnotationProxyBuilder<A>(constraint); + final AnnotationProxyBuilder<A> builder = + validatorFactory.getAnnotationsManager().buildProxyFor(constraint); builder.setGroups(groups); return builder.createAnnotation(); } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/groups/Groups.java Fri Jan 25 15:27:43 2019 @@ -81,11 +81,11 @@ public class Groups { /** * Assert that the default group can be expanded to <code>defaultGroups</code>. + * Package-private method intended for unit tests. * * @param defaultGroups */ - @Deprecated - public void assertDefaultGroupSequenceIsExpandable(List<Group> defaultGroups) { + void assertDefaultGroupSequenceIsExpandable(List<Group> defaultGroups) { Consumer<List<Group>> action = (groupList) -> { final int idx = groupList.indexOf(Group.DEFAULT); if (idx >= 0) { @@ -125,4 +125,4 @@ public class Groups { components.addAll(sequences); return GroupStrategy.composite(components); } -} \ No newline at end of file +} Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/job/ConstraintValidatorContextImpl.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/job/ConstraintValidatorContextImpl.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/job/ConstraintValidatorContextImpl.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/job/ConstraintValidatorContextImpl.java Fri Jan 25 15:27:43 2019 @@ -25,11 +25,11 @@ import javax.validation.ClockProvider; import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintViolation; import javax.validation.ElementKind; -import javax.validation.MessageInterpolator; import javax.validation.ValidationException; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.CrossParameterDescriptor; +import org.apache.bval.jsr.ApacheMessageContext; import org.apache.bval.jsr.descriptor.ComposedD; import org.apache.bval.jsr.descriptor.ConstraintD; import org.apache.bval.jsr.descriptor.CrossParameterD; @@ -43,7 +43,7 @@ import org.apache.bval.util.Exceptions; import org.apache.bval.util.Lazy; import org.apache.bval.util.Validate; -public class ConstraintValidatorContextImpl<T> implements ConstraintValidatorContext, MessageInterpolator.Context { +public class ConstraintValidatorContextImpl<T> implements ConstraintValidatorContext, ApacheMessageContext { public class ConstraintViolationBuilderImpl implements ConstraintValidatorContext.ConstraintViolationBuilder { private final String template; private final PathImpl path; @@ -201,4 +201,9 @@ public class ConstraintValidatorContextI private void addError(String messageTemplate, PathImpl propertyPath) { violations.get().add(((ValidationJob) frame.getJob()).createViolation(messageTemplate, this, propertyPath)); } + + @Override + public String getConfigurationProperty(String propertyKey) { + return frame.context.getValidatorContext().getFactory().getProperties().get(propertyKey); + } } Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataSource.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataSource.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataSource.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/MetadataSource.java Fri Jan 25 15:27:43 2019 @@ -22,10 +22,18 @@ import java.util.function.Consumer; import javax.validation.ConstraintValidator; import javax.validation.spi.ConfigurationState; +import org.apache.bval.jsr.ApacheValidatorFactory; + /** * Service interface for user metadata customizations. */ public interface MetadataSource { + /** + * Initialize the {@link MetadataSource}. + * @param validatorFactory + */ + default void initialize(ApacheValidatorFactory validatorFactory) { + } /** * Add {@link ConstraintValidator} mappings and/or metadata builders. Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/XmlBuilder.java Fri Jan 25 15:27:43 2019 @@ -45,10 +45,11 @@ import javax.validation.ValidationExcept import javax.validation.groups.Default; import javax.xml.bind.JAXBElement; +import org.apache.bval.jsr.ApacheValidatorFactory; import org.apache.bval.jsr.ConstraintAnnotationAttributes; import org.apache.bval.jsr.groups.GroupConversion; +import org.apache.bval.jsr.util.AnnotationProxyBuilder; import org.apache.bval.jsr.util.ToUnmodifiable; -import org.apache.bval.jsr.xml.AnnotationProxyBuilder; import org.apache.bval.jsr.xml.AnnotationType; import org.apache.bval.jsr.xml.BeanType; import org.apache.bval.jsr.xml.ClassType; @@ -475,13 +476,14 @@ public class XmlBuilder { return lazy.get(); } + private final ApacheValidatorFactory validatorFactory; private final ConstraintMappingsType constraintMappings; private final Version version; - public XmlBuilder(ConstraintMappingsType constraintMappings) { + public XmlBuilder(ApacheValidatorFactory validatorFactory, ConstraintMappingsType constraintMappings) { super(); - this.constraintMappings = constraintMappings; - Validate.notNull(constraintMappings, "constraintMappings"); + this.validatorFactory = Validate.notNull(validatorFactory, "validatorFactory"); + this.constraintMappings = Validate.notNull(constraintMappings, "constraintMappings"); this.version = Version.of(constraintMappings); new MappingValidator(constraintMappings, this::resolveClass).validateMappings(); } @@ -519,7 +521,7 @@ public class XmlBuilder { @SuppressWarnings("unchecked") private <T> Class<T> loadClass(final String fqn) { - ClassLoader loader = Reflection.getClassLoader(XmlBuilder.class); + ClassLoader loader = Reflection.loaderFromThreadOrClass(XmlBuilder.class); if (loader == null) { loader = getClass().getClassLoader(); } @@ -544,7 +546,8 @@ public class XmlBuilder { private <A extends Annotation, T> A createConstraint(final ConstraintType constraint, ConstraintTarget target) { final Class<A> annotationClass = this.<A> loadClass(toQualifiedClassName(constraint.getAnnotation())); - final AnnotationProxyBuilder<A> annoBuilder = new AnnotationProxyBuilder<A>(annotationClass); + final AnnotationProxyBuilder<A> annoBuilder = + validatorFactory.getAnnotationsManager().buildProxyFor(annotationClass); if (constraint.getMessage() != null) { annoBuilder.setMessage(constraint.getMessage()); @@ -676,7 +679,8 @@ public class XmlBuilder { } private <A extends Annotation> Annotation createAnnotation(AnnotationType annotationType, Class<A> returnType) { - final AnnotationProxyBuilder<A> metaAnnotation = new AnnotationProxyBuilder<>(returnType); + final AnnotationProxyBuilder<A> metaAnnotation = + validatorFactory.getAnnotationsManager().buildProxyFor(returnType); for (ElementType elementType : annotationType.getElement()) { final String name = elementType.getName(); metaAnnotation.setValue(name, getElementValue(elementType, getAnnotationParameterType(returnType, name))); Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/resolver/DefaultTraversableResolver.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/resolver/DefaultTraversableResolver.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/resolver/DefaultTraversableResolver.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/resolver/DefaultTraversableResolver.java Fri Jan 25 15:27:43 2019 @@ -72,7 +72,7 @@ public class DefaultTraversableResolver /** Tries to load detect and load JPA. */ @SuppressWarnings("unchecked") private void initJpa() { - final ClassLoader classLoader = Reflection.getClassLoader(DefaultTraversableResolver.class); + final ClassLoader classLoader = Reflection.loaderFromClassOrThread(DefaultTraversableResolver.class); try { Reflection.toClass(PERSISTENCE_UTIL_CLASSNAME, classLoader); if (LOG_FINEST) { Copied: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxy.java (from r1852141, tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java) URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxy.java?p2=tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxy.java&p1=tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java&r1=1852141&r2=1852142&rev=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxy.java Fri Jan 25 15:27:43 2019 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.bval.jsr.xml; +package org.apache.bval.jsr.util; import java.io.Serializable; import java.lang.annotation.Annotation; Copied: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxyBuilder.java (from r1852141, tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java) URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxyBuilder.java?p2=tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxyBuilder.java&p1=tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java&r1=1852141&r2=1852142&rev=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationProxyBuilder.java Fri Jan 25 15:27:43 2019 @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.bval.jsr.xml; +package org.apache.bval.jsr.util; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; @@ -24,8 +24,6 @@ import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import javax.enterprise.util.AnnotationLiteral; import javax.validation.ConstraintTarget; @@ -36,7 +34,7 @@ import javax.validation.groups.ConvertGr import org.apache.bval.cdi.EmptyAnnotationLiteral; import org.apache.bval.jsr.ConstraintAnnotationAttributes; -import org.apache.bval.jsr.util.AnnotationsManager; +import org.apache.bval.util.Validate; import org.apache.bval.util.reflection.Reflection; import org.apache.commons.weaver.privilizer.Privileged; import org.apache.commons.weaver.privilizer.Privilizing; @@ -48,17 +46,6 @@ import org.apache.commons.weaver.privili */ @Privilizing(@CallTo(Reflection.class)) public final class AnnotationProxyBuilder<A extends Annotation> { - private static final ConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new ConcurrentHashMap<>(); - - public static <A> Method[] findMethods(final Class<A> annotationType) { - // cache only built-in constraints to avoid memory leaks: - // TODO use configurable cache size property? - if (annotationType.getName().startsWith("javax.validation.constraints.")) { - return METHODS_CACHE.computeIfAbsent(annotationType, Reflection::getDeclaredMethods); - } - return Reflection.getDeclaredMethods(annotationType); - } - private final Class<A> type; private final Map<String, Object> elements = new HashMap<>(); private final Method[] methods; @@ -68,21 +55,11 @@ public final class AnnotationProxyBuilde * Create a new AnnotationProxyBuilder instance. * * @param annotationType + * @param cache */ - public AnnotationProxyBuilder(final Class<A> annotationType) { - this.type = annotationType; - this.methods = findMethods(annotationType); - } - - /** - * Create a new AnnotationProxyBuilder instance. - * - * @param annotationType - * @param elements - */ - public AnnotationProxyBuilder(Class<A> annotationType, Map<String, Object> elements) { - this(annotationType); - elements.forEach(this.elements::put); + AnnotationProxyBuilder(final Class<A> annotationType, Map<Class<?>, Method[]> cache) { + this.type = Validate.notNull(annotationType, "annotationType"); + this.methods = Validate.notNull(cache, "cache").computeIfAbsent(annotationType, Reflection::getDeclaredMethods); } /** @@ -91,10 +68,11 @@ public final class AnnotationProxyBuilde * * @param annot * Annotation to be replicated. + * @param cache */ @SuppressWarnings("unchecked") - public AnnotationProxyBuilder(A annot) { - this((Class<A>) annot.annotationType()); + AnnotationProxyBuilder(A annot, Map<Class<?>, Method[]> cache) { + this((Class<A>) annot.annotationType(), cache); elements.putAll(AnnotationsManager.readAttributes(annot)); } @@ -107,17 +85,6 @@ public final class AnnotationProxyBuilde * * @param elementName * @param value - */ - @Deprecated - public Object putValue(String elementName, Object value) { - return elements.put(elementName, value); - } - - /** - * Add an element to the configuration. - * - * @param elementName - * @param value * @return whether any change occurred */ public boolean setValue(String elementName, Object value) { @@ -214,7 +181,7 @@ public final class AnnotationProxyBuilde * @return {@link Annotation} */ public A createAnnotation() { - final ClassLoader classLoader = Reflection.getClassLoader(getType()); + final ClassLoader classLoader = Reflection.loaderFromClassOrThread(getType()); @SuppressWarnings("unchecked") final Class<A> proxyClass = (Class<A>) Proxy.getProxyClass(classLoader, getType()); return doCreateAnnotation(proxyClass, new AnnotationProxy(this)); Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/AnnotationsManager.java Fri Jan 25 15:27:43 2019 @@ -56,7 +56,6 @@ import org.apache.bval.jsr.ConstraintAnn import org.apache.bval.jsr.ConstraintAnnotationAttributes.Worker; import org.apache.bval.jsr.ConstraintCached.ConstraintValidatorInfo; import org.apache.bval.jsr.metadata.Meta; -import org.apache.bval.jsr.xml.AnnotationProxyBuilder; import org.apache.bval.util.Exceptions; import org.apache.bval.util.Lazy; import org.apache.bval.util.ObjectUtils; @@ -107,8 +106,8 @@ public class AnnotationsManager { } } - private static class Composition { - static <A extends Annotation> Optional<ConstraintAnnotationAttributes.Worker<A>> validWorker( + private class Composition { + <A extends Annotation> Optional<ConstraintAnnotationAttributes.Worker<A>> validWorker( ConstraintAnnotationAttributes attr, Class<A> type) { return Optional.of(type).map(attr::analyze).filter(Worker::isValid); } @@ -179,7 +178,7 @@ public class AnnotationsManager { final int index = constraintCounts.computeIfAbsent(c.annotationType(), k -> new AtomicInteger()).getAndIncrement(); - final AnnotationProxyBuilder<Annotation> proxyBuilder = new AnnotationProxyBuilder<>(c); + final AnnotationProxyBuilder<Annotation> proxyBuilder = buildProxyFor(c); proxyBuilder.setGroups(groups); proxyBuilder.setPayload(payload); @@ -281,7 +280,6 @@ public class AnnotationsManager { } return constraints.toArray(Annotation[]::new); } - private static Optional<AnnotatedElement> substitute(AnnotatedElement e) { if (e instanceof Parameter) { @@ -310,19 +308,23 @@ public class AnnotationsManager { private final ApacheValidatorFactory validatorFactory; private final LRUCache<Class<? extends Annotation>, Composition> compositions; + private final LRUCache<Class<? extends Annotation>, Method[]> constraintAttributes; public AnnotationsManager(ApacheValidatorFactory validatorFactory) { super(); this.validatorFactory = Validate.notNull(validatorFactory); final String cacheSize = validatorFactory.getProperties().get(ConfigurationImpl.Properties.CONSTRAINTS_CACHE_SIZE); + final int sz; try { - compositions = new LRUCache<>(Integer.parseInt(cacheSize)); + sz = Integer.parseInt(cacheSize); } catch (NumberFormatException e) { throw Exceptions.create(IllegalStateException::new, e, "Cannot parse value %s for configuration property %s", cacheSize, ConfigurationImpl.Properties.CONSTRAINTS_CACHE_SIZE); } + compositions = new LRUCache<>(sz); + constraintAttributes = new LRUCache<>(sz); } public void validateConstraintDefinition(Class<? extends Annotation> type) { @@ -414,6 +416,16 @@ public class AnnotationsManager { .collect(Collectors.toCollection(() -> EnumSet.noneOf(ValidationTarget.class))); } + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <A extends Annotation> AnnotationProxyBuilder<A> buildProxyFor(Class<A> type) { + return new AnnotationProxyBuilder<>(type, (Map) constraintAttributes); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <A extends Annotation> AnnotationProxyBuilder<A> buildProxyFor(A instance) { + return new AnnotationProxyBuilder<>(instance, (Map) constraintAttributes); + } + private Composition getComposition(Class<? extends Annotation> annotationType) { return compositions.computeIfAbsent(annotationType, ct -> { final Set<ValidationTarget> composedTargets = supportedTargets(annotationType); Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/LookBehindRegexHolder.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/LookBehindRegexHolder.java?rev=1852142&view=auto ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/LookBehindRegexHolder.java (added) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/util/LookBehindRegexHolder.java Fri Jan 25 15:27:43 2019 @@ -0,0 +1,117 @@ +/* + * 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.bval.jsr.util; + +import java.util.function.IntUnaryOperator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.bval.util.Validate; + +/** + * Utility class to manage regular expressions that require simulated infinite + * lookbehind, e.g. to determine whether a sequence of escape characters is + * complete unto itself. + */ +public class LookBehindRegexHolder { + public static final int DEFAULT_INITIAL_MAXIMUM_LENGTH = 256; + public static final int DEFAULT_EXPANSION_BLOCK_SIZE = 128; + + private final String regex; + private final int expansionBlockSize; + private final IntUnaryOperator computeInjectedRepetition; + + private volatile int maximumLength; + private Pattern pattern; + + /** + * Create a new {@link LookBehindRegexHolder} instance with the default + * initial maximum length and expansion block size. + * + * @param regex + * assumed to contain a {@code %d} Java format sequence + * @param computeInjectedRepetition + * function to compute the injected number of repetitions to + * inject at {@code %d} in {@code regex} + */ + public LookBehindRegexHolder(String regex, IntUnaryOperator computeInjectedRepetition) { + this(regex, DEFAULT_INITIAL_MAXIMUM_LENGTH, DEFAULT_EXPANSION_BLOCK_SIZE, computeInjectedRepetition); + } + + /** + * Create a new {@link LookBehindRegexHolder} instance. + * + * @param regex + * assumed to contain a {@code %d} Java format sequence + * @param initialMaximumLength + * initial guess + * @param expansionBlockSize + * number of bytes by which to increase the maximum length when a + * {@link Matcher} is requested for a larger message size + * @param computeInjectedRepetition + * function to compute the injected number of repetitions to + * inject at {@code %d} in {@code regex} + */ + public LookBehindRegexHolder(String regex, int initialMaximumLength, int expansionBlockSize, + IntUnaryOperator computeInjectedRepetition) { + super(); + Validate.isTrue(regex != null && !regex.trim().isEmpty(), "empty regex"); + Validate.isTrue(initialMaximumLength > 0, "invalid initial maximum length %d", initialMaximumLength); + Validate.isTrue(expansionBlockSize > 0, "Invalid expansion block size %d", expansionBlockSize); + Validate.notNull(computeInjectedRepetition, "missing %s to compute injected repetition", + IntUnaryOperator.class.getSimpleName()); + this.regex = regex; + this.expansionBlockSize = expansionBlockSize; + this.computeInjectedRepetition = computeInjectedRepetition; + accommodate(initialMaximumLength); + } + + /** + * Get a {@link Matcher} against the specified {@link CharSequence}. + * + * @param s + * @return {@link Matcher} + */ + public Matcher matcher(CharSequence s) { + if (s.length() > maximumLength) { + accommodate(s.length()); + } + return pattern.matcher(s); + } + + int getMaximumLength() { + return this.maximumLength; + } + + String getPattern() { + return pattern.pattern(); + } + + private synchronized void accommodate(int maximumLength) { + if (this.maximumLength < maximumLength) { + if (this.maximumLength == 0) { + this.maximumLength = maximumLength; + } else { + int difference = maximumLength - this.maximumLength; + int addBlocks = difference / expansionBlockSize + 1; + this.maximumLength += addBlocks * expansionBlockSize; + } + this.pattern = + Pattern.compile(String.format(regex, computeInjectedRepetition.applyAsInt(this.maximumLength))); + } + } +} Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java Fri Jan 25 15:27:43 2019 @@ -229,7 +229,7 @@ public class SchemaManager { } static Schema loadSchema(String resource) { - final URL schemaUrl = Reflection.getClassLoader(XmlUtils.class).getResource(resource); + final URL schemaUrl = Reflection.loaderFromClassOrThread(SchemaManager.class).getResource(resource); try { return SCHEMA_FACTORY.newSchema(schemaUrl); } catch (SAXException e) { Modified: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java?rev=1852142&r1=1852141&r2=1852142&view=diff ============================================================================== --- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java (original) +++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java Fri Jan 25 15:27:43 2019 @@ -30,8 +30,10 @@ import java.util.function.Consumer; import java.util.stream.Collectors; import javax.validation.ValidationException; +import javax.validation.ValidatorFactory; import javax.validation.spi.ConfigurationState; +import org.apache.bval.jsr.ApacheValidatorFactory; import org.apache.bval.jsr.metadata.MetadataBuilder; import org.apache.bval.jsr.metadata.MetadataBuilder.ForBean; import org.apache.bval.jsr.metadata.MetadataSource; @@ -39,6 +41,7 @@ import org.apache.bval.jsr.metadata.Vali import org.apache.bval.jsr.metadata.XmlBuilder; import org.apache.bval.jsr.metadata.XmlValidationMappingProvider; import org.apache.bval.util.Exceptions; +import org.apache.bval.util.Validate; import org.apache.bval.util.reflection.Reflection; import org.apache.commons.weaver.privilizer.Privilizing; import org.apache.commons.weaver.privilizer.Privilizing.CallTo; @@ -58,9 +61,18 @@ public class ValidationMappingParser imp "META-INF/validation-mapping-2.0.xsd") .build(); + private ApacheValidatorFactory validatorFactory; + + @Override + public void initialize(ApacheValidatorFactory validatorFactory) { + this.validatorFactory = Validate.notNull(validatorFactory); + } + @Override public void process(ConfigurationState configurationState, Consumer<ValidatorMappingProvider> addValidatorMappingProvider, BiConsumer<Class<?>, ForBean<?>> addBuilder) { + Validate.validState(validatorFactory != null, "validatorFactory unknown"); + if (configurationState.isIgnoreXmlConfiguration()) { return; } @@ -70,7 +82,8 @@ public class ValidationMappingParser imp Optional.of(mapping).map(this::toMappingProvider).ifPresent(addValidatorMappingProvider); - final Map<Class<?>, MetadataBuilder.ForBean<?>> builders = new XmlBuilder(mapping).forBeans(); + final Map<Class<?>, MetadataBuilder.ForBean<?>> builders = + new XmlBuilder(validatorFactory, mapping).forBeans(); if (Collections.disjoint(beanTypes, builders.keySet())) { builders.forEach(addBuilder::accept); beanTypes.addAll(builders.keySet()); @@ -127,7 +140,12 @@ public class ValidationMappingParser imp } private Class<?> loadClass(String className, String defaultPackage) { - return loadClass(toQualifiedClassName(className, defaultPackage)); + final String fqn = toQualifiedClassName(className, defaultPackage); + try { + return Reflection.toClass(fqn, Reflection.loaderFromThreadOrClass(ValidationMappingParser.class)); + } catch (ClassNotFoundException ex) { + throw Exceptions.create(ValidationException::new, ex, "Unable to load class: %s", fqn); + } } private String toQualifiedClassName(String className, String defaultPackage) { @@ -144,16 +162,4 @@ public class ValidationMappingParser imp private boolean isQualifiedClass(String clazz) { return clazz.indexOf('.') >= 0; } - - private Class<?> loadClass(final String className) { - ClassLoader loader = Reflection.getClassLoader(ValidationMappingParser.class); - if (loader == null) { - loader = getClass().getClassLoader(); - } - try { - return Reflection.toClass(className, loader); - } catch (ClassNotFoundException ex) { - throw Exceptions.create(ValidationException::new, ex, "Unable to load class: %s", className); - } - } }