You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by ra...@apache.org on 2018/10/12 15:00:51 UTC
svn commit: r1843674 [14/22] - in /tomee/deps/branches/bval-2: ./ bundle/
bundle/src/ bundle/src/main/ bundle/src/main/appended-resources/
bundle/src/main/appended-resources/META-INF/ bval-extras/ bval-extras/src/
bval-extras/src/main/ bval-extras/src/...
Added: 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/xml/AnnotationProxy.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxy.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,169 @@
+/*
+ * 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.xml;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import javax.validation.Valid;
+
+import org.apache.bval.jsr.metadata.Signature;
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.ObjectUtils;
+import org.apache.bval.util.StringUtils;
+import org.apache.bval.util.reflection.Reflection;
+
+/**
+ * Description: <br/>
+ * InvocationHandler implementation of <code>Annotation</code> that pretends it is a "real" source code annotation.
+ * <p/>
+ */
+class AnnotationProxy implements Annotation, InvocationHandler, Serializable {
+
+ /** Serialization version */
+ private static final long serialVersionUID = 1L;
+
+ private Signature EQUALS = new Signature("equals", Object.class);
+
+ private final Class<? extends Annotation> annotationType;
+ private final SortedMap<String, Object> values;
+
+ /**
+ * Create a new AnnotationProxy instance.
+ *
+ * @param <A>
+ * @param descriptor
+ */
+ <A extends Annotation> AnnotationProxy(AnnotationProxyBuilder<A> descriptor) {
+ this.annotationType = descriptor.getType();
+ values = new TreeMap<>();
+ int processedValuesFromDescriptor = 0;
+ for (final Method m : descriptor.getMethods()) {
+ if (descriptor.contains(m.getName())) {
+ values.put(m.getName(), descriptor.getValue(m.getName()));
+ processedValuesFromDescriptor++;
+ } else {
+ if (m.getDefaultValue() == null) {
+ Exceptions.raise(IllegalArgumentException::new, "No value provided for %s", m.getName());
+ }
+ values.put(m.getName(), m.getDefaultValue());
+ }
+ }
+ Exceptions.raiseUnless(processedValuesFromDescriptor == descriptor.size() || Valid.class.equals(annotationType),
+ IllegalArgumentException::new, "Trying to instantiate %s with unknown parameters.",
+ f -> f.args(annotationType.getName()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (values.containsKey(method.getName())) {
+ return values.get(method.getName());
+ }
+ if (EQUALS.equals(Signature.of(method))) {
+ return equalTo(args[0]);
+ }
+ return method.invoke(this, args);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return annotationType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return values.entrySet().stream()
+ .map(e -> String.format("%s=%s", e.getKey(), StringUtils.valueOf(e.getValue())))
+ .collect(Collectors.joining(", ", String.format("@%s(", annotationType().getName()), ")"));
+ }
+
+ @Override
+ public int hashCode() {
+ return values.entrySet().stream().mapToInt(e -> {
+ return (127 * e.getKey().hashCode()) ^ ObjectUtils.hashCode(e.getValue());
+ }).sum();
+ }
+
+ private boolean equalTo(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Annotation) {
+ final Annotation other = (Annotation) obj;
+ return other.annotationType().equals(annotationType)
+ && values.entrySet().stream().allMatch(e -> memberEquals(other, e.getKey(), e.getValue()));
+ }
+ return false;
+ }
+
+ private boolean memberEquals(Annotation other, String name, Object value) {
+ final Method member = Reflection.getDeclaredMethod(annotationType, name);
+ final Object otherValue;
+ try {
+ otherValue = member.invoke(other);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ throw new IllegalStateException(e);
+ }
+ Exceptions.raiseIf(otherValue == null || !otherValue.getClass().equals(value.getClass()),
+ IllegalStateException::new, "Unexpected value %s for member %s of %s", otherValue, name, other);
+
+ if (value instanceof Object[]) {
+ return Arrays.equals((Object[]) value, (Object[]) otherValue);
+ }
+ if (value instanceof byte[]) {
+ return Arrays.equals((byte[]) value, (byte[]) otherValue);
+ }
+ if (value instanceof short[]) {
+ return Arrays.equals((short[]) value, (short[]) otherValue);
+ }
+ if (value instanceof int[]) {
+ return Arrays.equals((int[]) value, (int[]) otherValue);
+ }
+ if (value instanceof char[]) {
+ return Arrays.equals((char[]) value, (char[]) otherValue);
+ }
+ if (value instanceof long[]) {
+ return Arrays.equals((long[]) value, (long[]) otherValue);
+ }
+ if (value instanceof float[]) {
+ return Arrays.equals((float[]) value, (float[]) otherValue);
+ }
+ if (value instanceof double[]) {
+ return Arrays.equals((double[]) value, (double[]) otherValue);
+ }
+ if (value instanceof boolean[]) {
+ return Arrays.equals((boolean[]) value, (boolean[]) otherValue);
+ }
+ return value.equals(otherValue);
+ }
+}
Added: 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/xml/AnnotationProxyBuilder.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/AnnotationProxyBuilder.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,268 @@
+/*
+ * 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.xml;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+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;
+import javax.validation.Payload;
+import javax.validation.Valid;
+import javax.validation.ValidationException;
+import javax.validation.groups.ConvertGroup;
+
+import org.apache.bval.cdi.EmptyAnnotationLiteral;
+import org.apache.bval.jsr.ConstraintAnnotationAttributes;
+import org.apache.bval.jsr.util.AnnotationsManager;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privileged;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
+/**
+ * Description: Holds the information and creates an annotation proxy during xml
+ * parsing of validation mapping constraints. <br/>
+ */
+@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;
+ private boolean changed;
+
+ /**
+ * Create a new AnnotationProxyBuilder instance.
+ *
+ * @param annotationType
+ */
+ 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);
+ }
+
+ /**
+ * Create a builder initially configured to create an annotation equivalent
+ * to {@code annot}.
+ *
+ * @param annot
+ * Annotation to be replicated.
+ */
+ @SuppressWarnings("unchecked")
+ public AnnotationProxyBuilder(A annot) {
+ this((Class<A>) annot.annotationType());
+ elements.putAll(AnnotationsManager.readAttributes(annot));
+ }
+
+ public Method[] getMethods() {
+ return methods;
+ }
+
+ /**
+ * Add an element to the configuration.
+ *
+ * @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) {
+ final boolean result = !Objects.equals(elements.put(elementName, value), value);
+ changed |= result;
+ return result;
+ }
+
+ /**
+ * Get the specified element value from the current configuration.
+ *
+ * @param elementName
+ * @return Object value
+ */
+ public Object getValue(String elementName) {
+ return elements.get(elementName);
+ }
+
+ /**
+ * Learn whether a given element has been configured.
+ *
+ * @param elementName
+ * @return <code>true</code> if an <code>elementName</code> element is found
+ * on this annotation
+ */
+ public boolean contains(String elementName) {
+ return elements.containsKey(elementName);
+ }
+
+ /**
+ * Get the number of configured elements.
+ *
+ * @return int
+ */
+ public int size() {
+ return elements.size();
+ }
+
+ /**
+ * Get the configured Annotation type.
+ *
+ * @return Class<A>
+ */
+ public Class<A> getType() {
+ return type;
+ }
+
+ /**
+ * Configure the well-known JSR303 "message" element.
+ *
+ * @param message
+ * @return
+ */
+ public boolean setMessage(String message) {
+ return setValue(ConstraintAnnotationAttributes.MESSAGE.getAttributeName(), message);
+ }
+
+ /**
+ * Configure the well-known JSR303 "groups" element.
+ *
+ * @param groups
+ * @return
+ */
+ public boolean setGroups(Class<?>[] groups) {
+ return setValue(ConstraintAnnotationAttributes.GROUPS.getAttributeName(), groups);
+ }
+
+ /**
+ * Configure the well-known JSR303 "payload" element.
+ *
+ * @param payload
+ * @return
+ */
+ public boolean setPayload(Class<? extends Payload>[] payload) {
+ return setValue(ConstraintAnnotationAttributes.PAYLOAD.getAttributeName(), payload);
+ }
+
+ /**
+ * Configure the well-known "validationAppliesTo" element.
+ *
+ * @param constraintTarget
+ */
+ public boolean setValidationAppliesTo(ConstraintTarget constraintTarget) {
+ return setValue(ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO.getAttributeName(), constraintTarget);
+ }
+
+ public boolean isChanged() {
+ return changed;
+ }
+
+ /**
+ * Create the annotation represented by this builder.
+ *
+ * @return {@link Annotation}
+ */
+ public A createAnnotation() {
+ final ClassLoader classLoader = Reflection.getClassLoader(getType());
+ @SuppressWarnings("unchecked")
+ final Class<A> proxyClass = (Class<A>) Proxy.getProxyClass(classLoader, getType());
+ return doCreateAnnotation(proxyClass, new AnnotationProxy(this));
+ }
+
+ @Privileged
+ private A doCreateAnnotation(final Class<A> proxyClass, final InvocationHandler handler) {
+ try {
+ final Constructor<A> constructor = proxyClass.getConstructor(InvocationHandler.class);
+ final boolean mustUnset = Reflection.setAccessible(constructor, true); // java
+ // 8
+ try {
+ return constructor.newInstance(handler);
+ } finally {
+ if (mustUnset) {
+ Reflection.setAccessible(constructor, false);
+ }
+ }
+ } catch (Exception e) {
+ throw new ValidationException("Unable to create annotation for configured constraint", e);
+ }
+ }
+
+ public static final class ValidAnnotation extends EmptyAnnotationLiteral<Valid> implements Valid {
+ private static final long serialVersionUID = 1L;
+
+ public static final ValidAnnotation INSTANCE = new ValidAnnotation();
+ }
+
+ public static final class ConvertGroupAnnotation extends AnnotationLiteral<ConvertGroup> implements ConvertGroup {
+ private static final long serialVersionUID = 1L;
+
+ private final Class<?> from;
+ private final Class<?> to;
+
+ public ConvertGroupAnnotation(final Class<?> from, final Class<?> to) {
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public Class<?> from() {
+ return from;
+ }
+
+ @Override
+ public Class<?> to() {
+ return to;
+ }
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/MappingValidator.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/MappingValidator.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/MappingValidator.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/MappingValidator.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,245 @@
+/*
+ * 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.xml;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.validation.ValidationException;
+
+import org.apache.bval.jsr.ConstraintAnnotationAttributes;
+import org.apache.bval.jsr.metadata.ContainerElementKey;
+import org.apache.bval.jsr.metadata.Meta;
+import org.apache.bval.jsr.metadata.Meta.ForConstructor;
+import org.apache.bval.jsr.metadata.Signature;
+import org.apache.bval.jsr.util.Methods;
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Validate;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.bval.util.reflection.TypeUtils;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
+@Privilizing(@CallTo(Reflection.class))
+public class MappingValidator {
+ private static final Set<ConstraintAnnotationAttributes> RESERVED_CONSTRAINT_ELEMENT_NAMES = Collections
+ .unmodifiableSet(EnumSet.of(ConstraintAnnotationAttributes.GROUPS, ConstraintAnnotationAttributes.MESSAGE,
+ ConstraintAnnotationAttributes.PAYLOAD, ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO));
+
+ private static <T> BinaryOperator<T> enforceUniqueness(String message, Function<? super T, ?> describe) {
+ return (t, u) -> {
+ throw Exceptions.create(ValidationException::new, message, describe.apply(t));
+ };
+ }
+
+ private final ConstraintMappingsType constraintMappings;
+ private final Function<String, Class<?>> resolveClass;
+
+ public MappingValidator(ConstraintMappingsType constraintMappings, Function<String, Class<?>> resolveClass) {
+ super();
+ this.constraintMappings = Validate.notNull(constraintMappings, "constraintMappings");
+ this.resolveClass = Validate.notNull(resolveClass, "resolveClass");
+ }
+
+ public void validateMappings() {
+ constraintMappings.getBean().stream().map(this::applyChecks).collect(Collectors.toMap(Function.identity(),
+ Function.identity(), enforceUniqueness("Duplicate XML constrained bean %s", Class::getName)));
+ }
+
+ private Class<?> applyChecks(BeanType bean) {
+ final Class<?> t = resolveClass.apply(bean.getClazz());
+
+ final ClassType classType = bean.getClassType();
+ if (classType != null) {
+ constraints(new Meta.ForClass<>(t), classType.getConstraint());
+ }
+ final Set<String> fieldProperties = fieldProperties(t, bean.getField());
+ final Set<String> getterProperties = getterProperties(t, bean.getGetter());
+ final Set<Signature> methods = methods(t, bean.getMethod());
+ @SuppressWarnings("unused")
+ final Set<Signature> constructors = constructors(t, bean.getConstructor());
+
+ final Set<String> propertyOverlap = new HashSet<>(fieldProperties);
+ propertyOverlap.retainAll(getterProperties);
+
+ if (!propertyOverlap.isEmpty()) {
+ Exceptions.raise(ValidationException::new,
+ "The following %s properties were specified via XML field and getter: %s", bean.getClazz(),
+ propertyOverlap);
+ }
+ final Set<String> getterMethodOverlap = methods.stream().filter(s -> s.getParameterTypes().length == 0)
+ .map(Signature::getName).filter(Methods::isGetter).map(Methods::propertyName)
+ .filter(getterProperties::contains).collect(Collectors.toSet());
+
+ if (!getterMethodOverlap.isEmpty()) {
+ Exceptions.raise(ValidationException::new,
+ "The following %s getters were specified via XML getter and method: %s", bean.getClazz(),
+ getterMethodOverlap);
+ }
+ return t;
+ }
+
+ private Set<String> fieldProperties(Class<?> t, List<FieldType> fields) {
+ return fields.stream().peek(f -> {
+ final Field fld = Reflection.find(t, c -> Reflection.getDeclaredField(c, f.getName()));
+ if (fld == null) {
+ Exceptions.raise(ValidationException::new, "Unknown XML constrained field %s of %s", f.getName(), t);
+ }
+ final Meta.ForField metaField = new Meta.ForField(fld);
+ constraints(metaField, f.getConstraint());
+ containerElements(metaField, f.getContainerElementType());
+ }).collect(Collectors.toMap(FieldType::getName, Function.identity(),
+ enforceUniqueness("Duplicate XML constrained field %s of " + t, FieldType::getName))).keySet();
+ }
+
+ private Set<String> getterProperties(Class<?> t, List<GetterType> getters) {
+ return getters.stream().peek(g -> {
+ final Method getter = Methods.getter(t, g.getName());
+ if (getter == null) {
+ Exceptions.raise(ValidationException::new, "Unknown XML constrained getter for property %s of %s",
+ g.getName(), t);
+ }
+ final Meta.ForMethod metaGetter = new Meta.ForMethod(getter);
+ constraints(metaGetter, g.getConstraint());
+ containerElements(metaGetter, g.getContainerElementType());
+ }).collect(Collectors.toMap(GetterType::getName, Function.identity(),
+ enforceUniqueness("Duplicate XML constrained getter %s of " + t, GetterType::getName))).keySet();
+ }
+
+ private Set<Signature> methods(Class<?> t, List<MethodType> methods) {
+ return methods.stream().map(mt -> {
+ final Class<?>[] parameterTypes = getParameterTypes(mt.getParameter());
+ final Signature result = new Signature(mt.getName(), parameterTypes);
+ final Method m = Reflection.find(t, c -> Reflection.getDeclaredMethod(c, mt.getName(), parameterTypes));
+ Exceptions.raiseIf(m == null, ValidationException::new, "Unknown method %s of %s", result, t);
+
+ Optional.of(mt).map(MethodType::getReturnValue).ifPresent(rv -> {
+ final Meta.ForMethod metaMethod = new Meta.ForMethod(m);
+ constraints(metaMethod, rv.getConstraint());
+ containerElements(metaMethod, rv.getContainerElementType());
+ });
+ final Parameter[] params = m.getParameters();
+
+ IntStream.range(0, parameterTypes.length).forEach(n -> {
+ final Meta.ForParameter metaParam = new Meta.ForParameter(params[n], params[n].getName());
+ final ParameterType parameterType = mt.getParameter().get(n);
+ constraints(metaParam, parameterType.getConstraint());
+ containerElements(metaParam, parameterType.getContainerElementType());
+ });
+
+ return result;
+ }).collect(Collectors.toSet());
+ }
+
+ private Set<Signature> constructors(Class<?> t, List<ConstructorType> ctors) {
+ return ctors.stream().map(ctor -> {
+ final Class<?>[] parameterTypes = getParameterTypes(ctor.getParameter());
+ final Signature result = new Signature(t.getSimpleName(), parameterTypes);
+ final Constructor<?> dc = Reflection.getDeclaredConstructor(t, parameterTypes);
+ Exceptions.raiseIf(dc == null, ValidationException::new, "Unknown %s constructor %s", t, result);
+
+ Optional.of(ctor).map(ConstructorType::getReturnValue).ifPresent(rv -> {
+ final ForConstructor<?> metaCtor = new Meta.ForConstructor<>(dc);
+ constraints(metaCtor, rv.getConstraint());
+ containerElements(metaCtor, rv.getContainerElementType());
+ });
+ final Parameter[] params = dc.getParameters();
+
+ IntStream.range(0, parameterTypes.length).forEach(n -> {
+ final Meta.ForParameter metaParam = new Meta.ForParameter(params[n], params[n].getName());
+ final ParameterType parameterType = ctor.getParameter().get(n);
+ constraints(metaParam, parameterType.getConstraint());
+ containerElements(metaParam, parameterType.getContainerElementType());
+ });
+ return result;
+ }).collect(Collectors.toSet());
+ }
+
+ private Class<?>[] getParameterTypes(List<ParameterType> paramElements) {
+ return paramElements.stream().map(ParameterType::getType).map(resolveClass).toArray(Class[]::new);
+ }
+
+ private Set<ContainerElementKey> containerElements(Meta<?> meta,
+ List<ContainerElementTypeType> containerElementTypes) {
+ if (containerElementTypes.isEmpty()) {
+ return Collections.emptySet();
+ }
+ final Class<?> containerType = TypeUtils.getRawType(meta.getType(), null);
+ final int typeParameterCount = containerType.getTypeParameters().length;
+ if (typeParameterCount == 0) {
+ Exceptions.raise(ValidationException::new, "Cannot specify container element types for %s",
+ meta.describeHost());
+ }
+ return containerElementTypes.stream().map(e -> {
+ Integer typeArgumentIndex = e.getTypeArgumentIndex();
+ if (typeArgumentIndex == null) {
+ if (typeParameterCount > 1) {
+ Exceptions.raise(ValidationException::new,
+ "Unable to resolve unspecified type argument index for %s", meta.describeHost());
+ }
+ typeArgumentIndex = Integer.valueOf(0);
+ }
+ final ContainerElementKey result = new ContainerElementKey(containerType, typeArgumentIndex);
+
+ final Meta.ForContainerElement elementMeta = new Meta.ForContainerElement(meta, result);
+
+ constraints(elementMeta, e.getConstraint());
+ containerElements(elementMeta, e.getContainerElementType());
+
+ return result;
+ }).collect(Collectors.toMap(Function.identity(), ContainerElementKey::getTypeArgumentIndex, enforceUniqueness(
+ "Duplicate XML constrained container element %d of " + meta.describeHost(), Function.identity()))).keySet();
+ }
+
+ private void constraints(Meta<?> meta, List<ConstraintType> constraints) {
+ constraints.forEach(constraint -> {
+ final Class<?> annotation = resolveClass.apply(constraint.getAnnotation());
+ Exceptions.raiseUnless(annotation.isAnnotation(), ValidationException::new, "%s is not an annotation",
+ annotation);
+
+ final Set<String> missingElements = Stream.of(Reflection.getDeclaredMethods(annotation))
+ .filter(m -> m.getParameterCount() == 0 && m.getDefaultValue() == null).map(Method::getName)
+ .collect(Collectors.toSet());
+
+ for (final ElementType elementType : constraint.getElement()) {
+ final String name = elementType.getName();
+ if (RESERVED_CONSTRAINT_ELEMENT_NAMES.stream().map(ConstraintAnnotationAttributes::getAttributeName)
+ .anyMatch(Predicate.isEqual(name))) {
+ Exceptions.raise(ValidationException::new, "Constraint of %s declares reserved parameter name %s.",
+ meta.describeHost(), name);
+ }
+ missingElements.remove(name);
+ }
+ Exceptions.raiseUnless(missingElements.isEmpty(), ValidationException::new,
+ "Missing required elements of %s: %s", annotation, missingElements);
+ });
+ }
+}
Added: 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=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/SchemaManager.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,294 @@
+/*
+ * 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.xml;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.validation.ValidationException;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.UnmarshallerHandler;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.ValidatorHandler;
+
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Lazy;
+import org.apache.bval.util.StringUtils;
+import org.apache.bval.util.Validate;
+import org.apache.bval.util.reflection.Reflection;
+import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * Unmarshals XML converging on latest schema version. Presumes backward compatiblity between schemae.
+ */
+public class SchemaManager {
+ public static class Builder {
+ private final SortedMap<Key, Lazy<Schema>> data = new TreeMap<>();
+
+ public Builder add(String version, String ns, String resource) {
+ data.put(new Key(version, ns), new Lazy<>(() -> SchemaManager.loadSchema(resource)));
+ return this;
+ }
+
+ public SchemaManager build() {
+ return new SchemaManager(new TreeMap<>(data));
+ }
+ }
+
+ private static class Key implements Comparable<Key> {
+ private static final Comparator<Key> CMP = Comparator.comparing(Key::getVersion).thenComparing(Key::getNs);
+
+ final String version;
+ final String ns;
+
+ Key(String version, String ns) {
+ super();
+ Validate.isTrue(StringUtils.isNotBlank(version), "version cannot be null/empty/blank");
+ this.version = version;
+ Validate.isTrue(StringUtils.isNotBlank(ns), "ns cannot be null/empty/blank");
+ this.ns = ns;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getNs() {
+ return ns;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ return Optional.ofNullable(obj).filter(SchemaManager.Key.class::isInstance)
+ .map(SchemaManager.Key.class::cast)
+ .filter(k -> Objects.equals(this.version, k.version) && Objects.equals(this.ns, k.ns)).isPresent();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(version, ns);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s:%s", version, ns);
+ }
+
+ @Override
+ public int compareTo(Key o) {
+ return CMP.compare(this, o);
+ }
+ }
+
+ private class DynamicValidatorHandler extends XMLFilterImpl {
+ ContentHandler ch;
+ SAXParseException e;
+
+ @Override
+ public void setContentHandler(ContentHandler handler) {
+ super.setContentHandler(handler);
+ this.ch = handler;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ if (getContentHandler() == ch) {
+ final String version = Objects.toString(atts.getValue("version"), data.firstKey().getVersion());
+ final Key schemaKey = new Key(version, uri);
+ Exceptions.raiseUnless(data.containsKey(schemaKey), ValidationException::new,
+ "Unknown validation schema %s", schemaKey);
+
+ final Schema schema = data.get(schemaKey).get();
+ final ValidatorHandler vh = schema.newValidatorHandler();
+ vh.startDocument();
+ vh.setContentHandler(ch);
+ super.setContentHandler(vh);
+ }
+ try {
+ super.startElement(uri, localName, qName, atts);
+ } catch (SAXParseException e) {
+ this.e = e;
+ }
+ }
+
+ @Override
+ public void error(SAXParseException e) throws SAXException {
+ this.e = e;
+ super.error(e);
+ }
+
+ @Override
+ public void fatalError(SAXParseException e) throws SAXException {
+ this.e = e;
+ super.fatalError(e);
+ }
+
+ void validate() throws SAXParseException {
+ if (e != null) {
+ throw e;
+ }
+ }
+ }
+
+ //@formatter:off
+ private enum XmlAttributeType {
+ CDATA, ID, IDREF, IDREFS, NMTOKEN, NMTOKENS, ENTITY, ENTITIES, NOTATION;
+ //@formatter:on
+ }
+
+ private class SchemaRewriter extends XMLFilterImpl {
+ private boolean root = true;
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ final Key schemaKey =
+ new Key(Objects.toString(atts.getValue("version"), data.firstKey().getVersion()), uri);
+
+ if (!target.equals(schemaKey) && data.containsKey(schemaKey)) {
+ uri = target.ns;
+ if (root) {
+ atts = rewrite(atts);
+ root = false;
+ }
+ }
+ super.startElement(uri, localName, qName, atts);
+ }
+
+ private Attributes rewrite(Attributes atts) {
+ final AttributesImpl result;
+ if (atts instanceof AttributesImpl) {
+ result = (AttributesImpl) atts;
+ } else {
+ result = new AttributesImpl(atts);
+ }
+ set(result, "", VERSION_ATTRIBUTE, "", XmlAttributeType.CDATA, target.version);
+ return result;
+ }
+
+ private void set(AttributesImpl attrs, String uri, String localName, String qName, XmlAttributeType type,
+ String value) {
+ for (int i = 0, sz = attrs.getLength(); i < sz; i++) {
+ if (Objects.equals(qName, attrs.getQName(i))
+ || Objects.equals(uri, attrs.getURI(i)) && Objects.equals(localName, attrs.getLocalName(i))) {
+ attrs.setAttribute(i, uri, localName, qName, type.name(), value);
+ return;
+ }
+ }
+ attrs.addAttribute(uri, localName, qName, type.name(), value);
+ }
+ }
+
+ public static final String VERSION_ATTRIBUTE = "version";
+
+ private static final Logger log = Logger.getLogger(SchemaManager.class.getName());
+ private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ private static final SAXParserFactory SAX_PARSER_FACTORY;
+
+ static {
+ SAX_PARSER_FACTORY = SAXParserFactory.newInstance();
+ SAX_PARSER_FACTORY.setNamespaceAware(true);
+ }
+
+ static Schema loadSchema(String resource) {
+ final URL schemaUrl = Reflection.getClassLoader(XmlUtils.class).getResource(resource);
+ try {
+ return SCHEMA_FACTORY.newSchema(schemaUrl);
+ } catch (SAXException e) {
+ log.log(Level.WARNING, String.format("Unable to parse schema: %s", resource), e);
+ return null;
+ }
+ }
+
+ private static Class<?> getObjectFactory(Class<?> type) throws ClassNotFoundException {
+ final String className = String.format("%s.%s", type.getPackage().getName(), "ObjectFactory");
+ return Reflection.toClass(className, type.getClassLoader());
+ }
+
+ private final Key target;
+ private final SortedMap<Key, Lazy<Schema>> data;
+ private final String description;
+
+ private SchemaManager(SortedMap<Key, Lazy<Schema>> data) {
+ super();
+ this.data = Collections.unmodifiableSortedMap(data);
+ this.target = data.lastKey();
+ this.description = target.ns.substring(target.ns.lastIndexOf('/') + 1);
+ }
+
+ public Optional<Schema> getSchema(String ns, String version) {
+ return Optional.of(new Key(version, ns)).map(data::get).map(Lazy::get);
+ }
+
+ public Optional<Schema> getSchema(Document document) {
+ return Optional.ofNullable(document).map(Document::getDocumentElement)
+ .map(e -> getSchema(e.getAttribute(XMLConstants.XMLNS_ATTRIBUTE), e.getAttribute(VERSION_ATTRIBUTE))).get();
+ }
+
+ public <E extends Exception> Schema requireSchema(Document document, Function<String, E> exc) throws E {
+ return getSchema(document).orElseThrow(() -> Objects.requireNonNull(exc, "exc")
+ .apply(String.format("Unknown %s schema", Objects.toString(description, ""))));
+ }
+
+ public <T> T unmarshal(InputSource input, Class<T> type) throws Exception {
+ final XMLReader xmlReader = SAX_PARSER_FACTORY.newSAXParser().getXMLReader();
+
+ // validate specified schema:
+ final DynamicValidatorHandler schemaValidator = new DynamicValidatorHandler();
+ xmlReader.setContentHandler(schemaValidator);
+
+ // rewrite to latest schema, if required:
+ final SchemaRewriter schemaRewriter = new SchemaRewriter();
+ schemaValidator.setContentHandler(schemaRewriter);
+
+ JAXBContext jc = JAXBContext.newInstance(getObjectFactory(type));
+ // unmarshal:
+ final UnmarshallerHandler unmarshallerHandler = jc.createUnmarshaller().getUnmarshallerHandler();
+ schemaRewriter.setContentHandler(unmarshallerHandler);
+
+ xmlReader.parse(input);
+ schemaValidator.validate();
+
+ @SuppressWarnings("unchecked")
+ final JAXBElement<T> result = (JAXBElement<T>) unmarshallerHandler.getResult();
+ return result.getValue();
+ }
+}
Added: 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=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,159 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import javax.validation.ValidationException;
+import javax.validation.spi.ConfigurationState;
+
+import org.apache.bval.jsr.metadata.MetadataBuilder;
+import org.apache.bval.jsr.metadata.MetadataBuilder.ForBean;
+import org.apache.bval.jsr.metadata.MetadataSource;
+import org.apache.bval.jsr.metadata.ValidatorMappingProvider;
+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.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+import org.xml.sax.InputSource;
+
+/**
+ * Uses JAXB to parse constraints.xml based on the validation-mapping XML schema.
+ */
+@Privilizing(@CallTo(Reflection.class))
+public class ValidationMappingParser implements MetadataSource {
+ private static final SchemaManager SCHEMA_MANAGER = new SchemaManager.Builder()
+ .add(XmlBuilder.Version.v10.getId(), "http://jboss.org/xml/ns/javax/validation/mapping",
+ "META-INF/validation-mapping-1.0.xsd")
+ .add(XmlBuilder.Version.v11.getId(), "http://jboss.org/xml/ns/javax/validation/mapping",
+ "META-INF/validation-mapping-1.1.xsd")
+ .add(XmlBuilder.Version.v20.getId(), "http://xmlns.jcp.org/xml/ns/validation/mapping",
+ "META-INF/validation-mapping-2.0.xsd")
+ .build();
+
+ @Override
+ public void process(ConfigurationState configurationState,
+ Consumer<ValidatorMappingProvider> addValidatorMappingProvider, BiConsumer<Class<?>, ForBean<?>> addBuilder) {
+ if (configurationState.isIgnoreXmlConfiguration()) {
+ return;
+ }
+ final Set<Class<?>> beanTypes = new HashSet<>();
+ for (final InputStream xmlStream : configurationState.getMappingStreams()) {
+ final ConstraintMappingsType mapping = parseXmlMappings(xmlStream);
+
+ Optional.of(mapping).map(this::toMappingProvider).ifPresent(addValidatorMappingProvider);
+
+ final Map<Class<?>, MetadataBuilder.ForBean<?>> builders = new XmlBuilder(mapping).forBeans();
+ if (Collections.disjoint(beanTypes, builders.keySet())) {
+ builders.forEach(addBuilder::accept);
+ beanTypes.addAll(builders.keySet());
+ } else {
+ Exceptions.raise(ValidationException::new,
+ builders.keySet().stream().filter(beanTypes::contains).map(Class::getName).collect(Collectors
+ .joining("bean classes specified multiple times for XML validation mapping: [", "; ", "]")));
+ }
+ }
+ }
+
+ /**
+ * @param in
+ * XML stream to parse using the validation-mapping-1.0.xsd
+ */
+ private ConstraintMappingsType parseXmlMappings(final InputStream in) {
+ try {
+ return SCHEMA_MANAGER.unmarshal(new InputSource(in), ConstraintMappingsType.class);
+ } catch (Exception e) {
+ throw new ValidationException("Failed to parse XML deployment descriptor file.", e);
+ } finally {
+ try {
+ in.reset(); // can be read several times + we ensured it was
+ // re-readable in addMapping()
+ } catch (final IOException e) {
+ // no-op
+ }
+ }
+ }
+
+ private ValidatorMappingProvider toMappingProvider(ConstraintMappingsType mapping) {
+ if (mapping.getConstraintDefinition().isEmpty()) {
+ return null;
+ }
+ final Map<Class<? extends Annotation>, ValidatedByType> validatorMappings = new HashMap<>();
+
+ for (ConstraintDefinitionType constraintDefinition : mapping.getConstraintDefinition()) {
+ final String annotationClassName = constraintDefinition.getAnnotation();
+
+ final Class<?> clazz = loadClass(annotationClassName, mapping.getDefaultPackage());
+
+ Exceptions.raiseUnless(clazz.isAnnotation(), ValidationException::new, "%s is not an annotation",
+ annotationClassName);
+
+ final Class<? extends Annotation> annotationClass = clazz.asSubclass(Annotation.class);
+
+ Exceptions.raiseIf(validatorMappings.containsKey(annotationClass), ValidationException::new,
+ "XML constraint validator(s) for %s already configured.", annotationClass);
+
+ validatorMappings.put(annotationClass, constraintDefinition.getValidatedBy());
+ }
+ return new XmlValidationMappingProvider(validatorMappings,
+ cn -> toQualifiedClassName(cn, mapping.getDefaultPackage()));
+ }
+
+ private Class<?> loadClass(String className, String defaultPackage) {
+ return loadClass(toQualifiedClassName(className, defaultPackage));
+ }
+
+ private String toQualifiedClassName(String className, String defaultPackage) {
+ if (!isQualifiedClass(className)) {
+ if (className.startsWith("[L") && className.endsWith(";")) {
+ className = "[L" + defaultPackage + '.' + className.substring(2);
+ } else {
+ className = defaultPackage + '.' + className;
+ }
+ }
+ return className;
+ }
+
+ 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);
+ }
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,149 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import javax.validation.BootstrapConfiguration;
+import javax.validation.ValidationException;
+import javax.validation.executable.ExecutableType;
+
+import org.apache.bval.jsr.BootstrapConfigurationImpl;
+import org.apache.bval.jsr.ConfigurationImpl;
+import org.apache.bval.jsr.metadata.XmlBuilder;
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privileged;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+import org.xml.sax.InputSource;
+
+/**
+ * Description: uses jaxb to parse validation.xml<br/>
+ */
+@Privilizing(@CallTo(Reflection.class))
+public class ValidationParser {
+
+ private static final String DEFAULT_VALIDATION_XML_FILE = "META-INF/validation.xml";
+ private static final Logger log = Logger.getLogger(ValidationParser.class.getName());
+
+ private static final SchemaManager SCHEMA_MANAGER = new SchemaManager.Builder()
+ .add(XmlBuilder.Version.v10.getId(), "http://jboss.org/xml/ns/javax/validation/configuration",
+ "META-INF/validation-configuration-1.0.xsd")
+ .add(XmlBuilder.Version.v11.getId(), "http://jboss.org/xml/ns/javax/validation/configuration",
+ "META-INF/validation-configuration-1.1.xsd")
+ .add(XmlBuilder.Version.v20.getId(), "http://xmlns.jcp.org/xml/ns/validation/configuration",
+ "META-INF/validation-configuration-2.0.xsd")
+ .build();
+
+ public static String getValidationXmlFile(String file) {
+ return file == null ? DEFAULT_VALIDATION_XML_FILE : file;
+ }
+
+ public static BootstrapConfiguration processValidationConfig(final String file,
+ final ConfigurationImpl targetConfig) {
+ final ValidationConfigType xmlConfig = parseXmlConfig(file);
+ if (xmlConfig == null) {
+ return null;
+ }
+ final boolean executableValidationEnabled;
+ final Set<ExecutableType> defaultValidatedExecutableTypes;
+
+ if (xmlConfig.getExecutableValidation() == null) {
+ defaultValidatedExecutableTypes = EnumSet.of(ExecutableType.IMPLICIT);
+ executableValidationEnabled = true;
+ } else {
+ final Optional<ExecutableValidationType> executableValidation =
+ Optional.of(xmlConfig).map(ValidationConfigType::getExecutableValidation);
+ executableValidationEnabled = executableValidation.map(ExecutableValidationType::getEnabled)
+ .filter(Predicate.isEqual(Boolean.TRUE)).isPresent();
+
+ defaultValidatedExecutableTypes = executableValidation.filter(x -> executableValidationEnabled)
+ .map(ExecutableValidationType::getDefaultValidatedExecutableTypes)
+ .map(DefaultValidatedExecutableTypesType::getExecutableType).map(EnumSet::copyOf)
+ .orElse(EnumSet.noneOf(ExecutableType.class));
+ }
+ return new BootstrapConfigurationImpl(xmlConfig.getDefaultProvider(), xmlConfig.getConstraintValidatorFactory(),
+ xmlConfig.getMessageInterpolator(), xmlConfig.getTraversableResolver(),
+ xmlConfig.getParameterNameProvider(), new HashSet<>(xmlConfig.getConstraintMapping()),
+ executableValidationEnabled, defaultValidatedExecutableTypes, toMap(xmlConfig.getProperty()),
+ xmlConfig.getClockProvider(), new HashSet<>(xmlConfig.getValueExtractor()));
+ }
+
+ private static Map<String, String> toMap(final List<PropertyType> property) {
+ return property == null || property.isEmpty() ? Collections.emptyMap()
+ : property.stream().collect(Collectors.toMap(PropertyType::getName, PropertyType::getValue));
+ }
+
+ @Privileged
+ private static ValidationConfigType parseXmlConfig(final String validationXmlFile) {
+ try (InputStream inputStream = getInputStream(getValidationXmlFile(validationXmlFile))) {
+ if (inputStream == null) {
+ log.log(Level.FINEST,
+ String.format("No %s found. Using annotation based configuration only.", validationXmlFile));
+ return null;
+ }
+ log.log(Level.FINEST, String.format("%s found.", validationXmlFile));
+
+ return SCHEMA_MANAGER.unmarshal(new InputSource(inputStream), ValidationConfigType.class);
+ } catch (Exception e) {
+ throw Exceptions.create(ValidationException::new, e, "Unable to parse %s", validationXmlFile);
+ }
+ }
+
+ public static InputStream open(String mappingFileName) {
+ if (mappingFileName.charAt(0) == '/') {
+ // Classloader needs a path without a starting /
+ mappingFileName = mappingFileName.substring(1);
+ }
+ try {
+ final InputStream in = getInputStream(mappingFileName);
+ Exceptions.raiseIf(in == null, ValidationException::new,
+ "Unable to open input stream for mapping file %s", mappingFileName);
+ return(in);
+ } catch (IOException e) {
+ throw Exceptions.create(ValidationException::new, e, "Unable to open input stream for mapping file %s",
+ mappingFileName);
+ }
+ }
+
+ static InputStream getInputStream(final String path) throws IOException {
+ final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class);
+ final List<URL> urls = Collections.list(loader.getResources(path));
+ Exceptions.raiseIf(urls.stream().distinct().count() > 1, ValidationException::new,
+ "More than one %s is found in the classpath", path);
+ return urls.isEmpty() ? null : urls.get(0).openStream();
+ }
+
+ private ValidationParser() {
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,67 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.helpers.DefaultValidationEventHandler;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.apache.bval.util.reflection.Reflection;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+class XmlUtils {
+ private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
+ private static final Logger log = Logger.getLogger(XmlUtils.class.getName());
+ private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+ static Schema loadSchema(String resource) {
+ final URL schemaUrl = Reflection.getClassLoader(XmlUtils.class).getResource(resource);
+ try {
+ return SCHEMA_FACTORY.newSchema(schemaUrl);
+ } catch (SAXException e) {
+ log.log(Level.WARNING, String.format("Unable to parse schema: %s", resource), e);
+ return null;
+ }
+ }
+
+ static Document parse(InputStream in) throws SAXException, IOException, ParserConfigurationException {
+ return DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(in);
+ }
+
+ static <T> T unmarshal(Document document, Schema schema, Class<T> type) throws JAXBException {
+ final JAXBContext jc = JAXBContext.newInstance(type);
+ final Unmarshaller unmarshaller = jc.createUnmarshaller();
+ unmarshaller.setSchema(schema);
+ unmarshaller.setEventHandler(new DefaultValidationEventHandler());
+ final JAXBElement<T> root = unmarshaller.unmarshal(document, type);
+ return root.getValue();
+ }
+}
\ No newline at end of file
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/routines/EMailValidationUtils.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,75 @@
+/*
+ * 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.routines;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Description: holds the regexp to validate an email address<br>
+ * User: roman.stumm<br>
+ * Date: 17.06.2010<br>
+ * Time: 10:40:59<br>
+ */
+public class EMailValidationUtils {
+ private static String ATOM = "[^\\x00-\\x1F\\(\\)\\<\\>\\@\\,\\;\\:\\\\\\\"\\.\\[\\]\\s]";
+ private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*";
+ private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
+ public static final Pattern DEFAULT_EMAIL_PATTERN;
+
+ static {
+ DEFAULT_EMAIL_PATTERN = Pattern.compile("^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$",
+ Pattern.CASE_INSENSITIVE);
+ }
+
+ /**
+ * Learn whether a given object is a valid email address.
+ *
+ * @param value
+ * to check
+ * @return <code>true</code> if the validation passes
+ */
+ public static boolean isValid(Object value) {
+ return isValid(value, DEFAULT_EMAIL_PATTERN);
+ }
+
+ /**
+ * Learn whether a particular value matches a given pattern per
+ * {@link Matcher#matches()}.
+ *
+ * @param value
+ * @param aPattern
+ * @return <code>true</code> if <code>value</code> was a <code>String</code>
+ * matching <code>aPattern</code>
+ */
+ // TODO it would seem to make sense to move or reduce the visibility of this
+ // method as it is more general than email.
+ public static boolean isValid(Object value, Pattern aPattern) {
+ if (value == null) {
+ return true;
+ }
+ if (!(value instanceof CharSequence)) {
+ return false;
+ }
+ CharSequence seq = (CharSequence) value;
+ if (seq.length() == 0) {
+ return true;
+ }
+ return aPattern.matcher(seq).matches();
+ }
+
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/BValVersion.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,195 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+
+/**
+ * This class contains version information for BVal.
+ * It uses Ant's filter tokens to convert the template into a java
+ * file with current information.
+ */
+@Privilizing(@CallTo(Reflection.class))
+public class BValVersion {
+
+ /** Project name */
+ public static final String PROJECT_NAME = "Apache BVal";
+ /** Unique id of the current project/version/revision */
+ public static final String PROJECT_ID;
+ /** Version number */
+ public static final String VERSION_NUMBER;
+ /** Major release number */
+ public static final int MAJOR_RELEASE;
+ /** Minor release number */
+ public static final int MINOR_RELEASE;
+ /** Patch/point release number */
+ public static final int PATCH_RELEASE;
+ /** Release status */
+ public static final String RELEASE_STATUS;
+ /** Version control revision number */
+ public static final String REVISION_NUMBER;
+
+ static {
+ Properties revisionProps = new Properties();
+ try (InputStream in = BValVersion.class.getResourceAsStream("/META-INF/org.apache.bval.revision.properties")) {
+ if (in != null) {
+ revisionProps.load(in);
+ }
+ } catch (IOException ioe) {
+ }
+
+ String vers = revisionProps.getProperty("project.version");
+ if (StringUtils.isBlank(vers)) {
+ vers = "0.0.0";
+ }
+ VERSION_NUMBER = vers;
+
+ StringTokenizer tok = new StringTokenizer(VERSION_NUMBER, ".-");
+ int major, minor, patch;
+ try {
+ major = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+ } catch (Exception e) {
+ major = 0;
+ }
+
+ try {
+ minor = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+ } catch (Exception e) {
+ minor = 0;
+ }
+
+ try {
+ patch = tok.hasMoreTokens() ? Integer.parseInt(tok.nextToken()) : 0;
+ } catch (Exception e) {
+ patch = 0;
+ }
+
+ String revision = revisionProps.getProperty("svn.revision");
+ if (StringUtils.isBlank(revision)) {
+ revision = "unknown";
+ } else {
+ tok = new StringTokenizer(revision, ":");
+ String strTok = null;
+ while (tok.hasMoreTokens()) {
+ try {
+ strTok = tok.nextToken();
+ } catch (Exception e) {
+ }
+ }
+ if (strTok != null) {
+ revision = strTok;
+ }
+ }
+
+ MAJOR_RELEASE = major;
+ MINOR_RELEASE = minor;
+ PATCH_RELEASE = patch;
+ RELEASE_STATUS = tok.hasMoreTokens() ? tok.nextToken("!") : "";
+ REVISION_NUMBER = revision;
+ PROJECT_ID = PROJECT_NAME + " " + VERSION_NUMBER + "-r" + REVISION_NUMBER;
+ }
+
+ /**
+ * Get the project version number.
+ * @return String
+ */
+ public static String getVersion() {
+ return VERSION_NUMBER;
+ }
+
+ /**
+ * Get the version control revision number.
+ * @return String
+ */
+ public static String getRevision() {
+ return REVISION_NUMBER;
+ }
+
+ /**
+ * Get the project name.
+ * @return String
+ */
+ public static String getName() {
+ return PROJECT_NAME;
+ }
+
+ /**
+ * Get the fully-qualified project id.
+ * @return String
+ */
+ public static String getID() {
+ return PROJECT_ID;
+ }
+
+ /**
+ * Main method of this class that prints the {@link #toString()} to <code>System.out</code>.
+ * @param args ignored
+ */
+ public static void main(String[] args) {
+ System.out.println(new BValVersion().toString());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder(80 * 40);
+ appendBanner(buf);
+ buf.append("\n");
+
+ appendProperty("os.name", buf).append("\n");
+ appendProperty("os.version", buf).append("\n");
+ appendProperty("os.arch", buf).append("\n\n");
+
+ appendProperty("java.version", buf).append("\n");
+ appendProperty("java.vendor", buf).append("\n\n");
+
+ buf.append("java.class.path:\n");
+ final StringTokenizer tok = new StringTokenizer(Reflection.getProperty("java.class.path"));
+ while (tok.hasMoreTokens()) {
+ buf.append("\t").append(tok.nextToken());
+ buf.append("\n");
+ }
+ buf.append("\n");
+
+ appendProperty("user.dir", buf).append("\n");
+ return buf.toString();
+ }
+
+ private void appendBanner(StringBuilder buf) {
+ buf.append("Project").append(": ").append(getName());
+ buf.append("\n");
+ buf.append("Version").append(": ").append(getVersion());
+ buf.append("\n");
+ buf.append("Revision").append(": ").append(getRevision());
+ buf.append("\n");
+ }
+
+ private StringBuilder appendProperty(String prop, StringBuilder buf) {
+ return buf.append(prop).append(": ").append(Reflection.getProperty(prop));
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/CloseableAble.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/CloseableAble.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/CloseableAble.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/CloseableAble.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,27 @@
+/*
+ * 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.util;
+
+import java.io.Closeable;
+
+@FunctionalInterface
+public interface CloseableAble {
+
+ Closeable getCloseable();
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Comparators.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Comparators.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Comparators.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Comparators.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,54 @@
+/*
+ * 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.util;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+/**
+ * {@link Comparator} related utilities.
+ */
+public class Comparators {
+
+ /**
+ * Get a {@link Comparator} capable of comparing {@link Iterable}s.
+ *
+ * @param each
+ * @return {@link Comparator}
+ */
+ public static <T, I extends Iterable<T>> Comparator<I> comparingIterables(Comparator<? super T> each) {
+ return (quid, quo) -> {
+ final Iterator<T> quids = quid.iterator();
+ final Iterator<T> quos = quo.iterator();
+
+ while (quids.hasNext()) {
+ if (quos.hasNext()) {
+ final int rz = each.compare(quids.next(), quos.next());
+ if (rz != 0) {
+ return rz;
+ }
+ continue;
+ }
+ return 1;
+ }
+ return quos.hasNext() ? -1 : 0;
+ };
+ }
+
+ private Comparators() {
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/EmulatedAnnotatedType.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/EmulatedAnnotatedType.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/EmulatedAnnotatedType.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/EmulatedAnnotatedType.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,125 @@
+/*
+ * 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.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AnnotatedTypeVariable;
+import java.lang.reflect.AnnotatedWildcardType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+public class EmulatedAnnotatedType<T extends Type> implements AnnotatedType {
+ private static class Parameterized extends EmulatedAnnotatedType<ParameterizedType>
+ implements AnnotatedParameterizedType {
+
+ Parameterized(ParameterizedType wrapped) {
+ super(wrapped);
+ }
+
+ @Override
+ public AnnotatedType[] getAnnotatedActualTypeArguments() {
+ return wrapArray(wrapped.getActualTypeArguments());
+ }
+ }
+
+ private static class Variable extends EmulatedAnnotatedType<TypeVariable<?>> implements AnnotatedTypeVariable {
+
+ Variable(TypeVariable<?> wrapped) {
+ super(wrapped);
+ }
+
+ @Override
+ public AnnotatedType[] getAnnotatedBounds() {
+ return wrapped.getAnnotatedBounds();
+ }
+ }
+
+ private static class Wildcard extends EmulatedAnnotatedType<WildcardType> implements AnnotatedWildcardType {
+
+ Wildcard(WildcardType wrapped) {
+ super(wrapped);
+ }
+
+ @Override
+ public AnnotatedType[] getAnnotatedLowerBounds() {
+ return wrapArray(wrapped.getLowerBounds());
+ }
+
+ @Override
+ public AnnotatedType[] getAnnotatedUpperBounds() {
+ return wrapArray(wrapped.getUpperBounds());
+ }
+ }
+
+ public static EmulatedAnnotatedType<?> wrap(Type type) {
+ if (type instanceof ParameterizedType) {
+ return new EmulatedAnnotatedType.Parameterized((ParameterizedType) type);
+ }
+ if (type instanceof TypeVariable<?>) {
+ return new EmulatedAnnotatedType.Variable((TypeVariable<?>) type);
+ }
+ if (type instanceof WildcardType) {
+ return new EmulatedAnnotatedType.Wildcard((WildcardType) type);
+ }
+ return new EmulatedAnnotatedType<>(type);
+ }
+
+ private static EmulatedAnnotatedType<?>[] wrapArray(Type[] types) {
+ return Stream.of(types).map(EmulatedAnnotatedType::wrap).toArray(EmulatedAnnotatedType[]::new);
+ }
+
+ private static final Annotation[] EMPTY_ANNOTATION_ARRAY = {};
+
+ protected final T wrapped;
+ private final Optional<AnnotatedElement> annotated;
+
+ private EmulatedAnnotatedType(T wrapped) {
+ super();
+ this.wrapped = Validate.notNull(wrapped);
+ this.annotated =
+ Optional.of(wrapped).filter(AnnotatedElement.class::isInstance).map(AnnotatedElement.class::cast);
+ }
+
+ @Override
+ public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
+ return annotated.map(e -> e.getAnnotation(annotationClass)).orElse(null);
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return annotated.map(AnnotatedElement::getAnnotations).orElse(EMPTY_ANNOTATION_ARRAY);
+ }
+
+ @Override
+ public Annotation[] getDeclaredAnnotations() {
+ return annotated.map(AnnotatedElement::getDeclaredAnnotations).orElse(EMPTY_ANNOTATION_ARRAY);
+ }
+
+ @Override
+ public Type getType() {
+ return wrapped;
+ }
+}
Added: tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Escapes.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Escapes.java?rev=1843674&view=auto
==============================================================================
--- tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Escapes.java (added)
+++ tomee/deps/branches/bval-2/bval-jsr/src/main/java/org/apache/bval/util/Escapes.java Fri Oct 12 15:00:48 2018
@@ -0,0 +1,203 @@
+/**
+ * Copyright (C) 2006-2018 Talend Inc. - www.talend.com
+ * <p>
+ * Licensed 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+// taken from commons-lang3
+public final class Escapes {
+ private static final CharSequenceTranslator UNESCAPE_JAVA =
+ new AggregateTranslator(
+ new OctalUnescaper(), // .between('\1', '\377'),
+ new UnicodeUnescaper(),
+ new LookupTranslator(new String[][] {
+ {"\\b", "\b"},
+ {"\\n", "\n"},
+ {"\\t", "\t"},
+ {"\\f", "\f"},
+ {"\\r", "\r"}
+ }),
+ new LookupTranslator(
+ new String[][] {
+ {"\\\\", "\\"},
+ {"\\\"", "\""},
+ {"\\'", "'"},
+ {"\\", ""}
+ })
+ );
+
+ private Escapes() {
+ // no-op
+ }
+
+ public static int unescapeJava(final CharSequence from, final int offset, final Writer output) {
+ // return StringEscapeUtils.UNESCAPE_JAVA.translate(path, pos.getIndex(), target);
+ return UNESCAPE_JAVA.translate(from, offset, output);
+ }
+
+ protected interface CharSequenceTranslator {
+ int translate(CharSequence input, int index, Writer out);
+ }
+
+ private static class AggregateTranslator implements CharSequenceTranslator {
+ private final CharSequenceTranslator[] translators;
+
+ private AggregateTranslator(final CharSequenceTranslator... translators) {
+ this.translators = translators;
+ }
+
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) {
+ for (final CharSequenceTranslator translator : translators) {
+ final int consumed = translator.translate(input, index, out);
+ if(consumed != 0) {
+ return consumed;
+ }
+ }
+ return 0;
+ }
+ }
+
+ private static class OctalUnescaper implements CharSequenceTranslator {
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) {
+ final int remaining = input.length() - index - 1;
+ final StringBuilder builder = new StringBuilder();
+ if (input.charAt(index) == '\\' && remaining > 0 && isOctalDigit(input.charAt(index + 1))) {
+ final int next = index + 1;
+ final int next2 = index + 2;
+ final int next3 = index + 3;
+
+ builder.append(input.charAt(next));
+
+ if (remaining > 1 && isOctalDigit(input.charAt(next2))) {
+ builder.append(input.charAt(next2));
+ if (remaining > 2 && isZeroToThree(input.charAt(next)) && isOctalDigit(input.charAt(next3))) {
+ builder.append(input.charAt(next3));
+ }
+ }
+
+ try {
+ out.write(Integer.parseInt(builder.toString(), 8));
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return 1 + builder.length();
+ }
+ return 0;
+ }
+
+ private boolean isOctalDigit(final char ch) {
+ return ch >= '0' && ch <= '7';
+ }
+
+ private boolean isZeroToThree(final char ch) {
+ return ch >= '0' && ch <= '3';
+ }
+ }
+
+ public static class UnicodeUnescaper implements CharSequenceTranslator {
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) {
+ if (input.charAt(index) == '\\' && index + 1 < input.length() && input.charAt(index + 1) == 'u') {
+ int i = 2;
+ while (index + i < input.length() && input.charAt(index + i) == 'u') {
+ i++;
+ }
+
+ if (index + i < input.length() && input.charAt(index + i) == '+') {
+ i++;
+ }
+
+ if (index + i + 4 <= input.length()) {
+ // Get 4 hex digits
+ final CharSequence unicode = input.subSequence(index + i, index + i + 4);
+
+ try {
+ final int value = Integer.parseInt(unicode.toString(), 16);
+ out.write((char) value);
+ } catch (final NumberFormatException nfe) {
+ throw new IllegalArgumentException("Unable to parse unicode value: " + unicode, nfe);
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return i + 4;
+ }
+ throw new IllegalArgumentException("Less than 4 hex digits in unicode value: '" + input.subSequence(index, input.length())
+ + "' due to end of CharSequence");
+ }
+ return 0;
+ }
+ }
+
+ public static class LookupTranslator implements CharSequenceTranslator {
+ private final Map<String, String> lookupMap;
+ private final Set<Character> prefixSet;
+ private final int shortest;
+ private final int longest;
+
+ private LookupTranslator(final String[][] lookup) {
+ lookupMap = new HashMap<>();
+ prefixSet = new HashSet<>();
+ int _shortest = Integer.MAX_VALUE;
+ int _longest = 0;
+ if (lookup != null) {
+ for (final CharSequence[] seq : lookup) {
+ this.lookupMap.put(seq[0].toString(), seq[1].toString());
+ this.prefixSet.add(seq[0].charAt(0));
+ final int sz = seq[0].length();
+ if (sz < _shortest) {
+ _shortest = sz;
+ }
+ if (sz > _longest) {
+ _longest = sz;
+ }
+ }
+ }
+ shortest = _shortest;
+ longest = _longest;
+ }
+
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) {
+ if (prefixSet.contains(input.charAt(index))) {
+ int max = longest;
+ if (index + longest > input.length()) {
+ max = input.length() - index;
+ }
+ for (int i = max; i >= shortest; i--) {
+ final CharSequence subSeq = input.subSequence(index, index + i);
+ final String result = lookupMap.get(subSeq.toString());
+
+ if (result != null) {
+ try {
+ out.write(result);
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return i;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+}