All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.bval.jsr.ApacheValidatorFactory Maven / Gradle / Ivy

/*
 * 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 java.io.Closeable;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;

import jakarta.validation.ClockProvider;
import jakarta.validation.ConstraintValidatorFactory;
import jakarta.validation.MessageInterpolator;
import jakarta.validation.ParameterNameProvider;
import jakarta.validation.TraversableResolver;
import jakarta.validation.Validation;
import jakarta.validation.ValidationException;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.spi.ConfigurationState;
import jakarta.validation.valueextraction.ValueExtractor;

import org.apache.bval.jsr.descriptor.DescriptorManager;
import org.apache.bval.jsr.groups.GroupsComputer;
import org.apache.bval.jsr.metadata.MetadataBuilder;
import org.apache.bval.jsr.metadata.MetadataBuilder.ForBean;
import org.apache.bval.jsr.metadata.MetadataBuilders;
import org.apache.bval.jsr.metadata.MetadataSource;
import org.apache.bval.jsr.util.AnnotationsManager;
import org.apache.bval.jsr.valueextraction.ValueExtractors;
import org.apache.bval.jsr.valueextraction.ValueExtractors.OnDuplicateContainerElementKey;
import org.apache.bval.util.CloseableAble;
import org.apache.bval.util.reflection.Reflection;
import org.apache.commons.weaver.privilizer.Privilizing;
import org.apache.commons.weaver.privilizer.Privilizing.CallTo;

/**
 * Description: a factory is a complete configurated object that can create
 * validators.
* This instance is not thread-safe.
*/ @Privilizing(@CallTo(Reflection.class)) public class ApacheValidatorFactory implements ValidatorFactory, Cloneable { private static volatile ApacheValidatorFactory DEFAULT_FACTORY; /** * Convenience method to retrieve a default global ApacheValidatorFactory * * @return {@link ApacheValidatorFactory} */ public static ApacheValidatorFactory getDefault() { if (DEFAULT_FACTORY == null) { synchronized (ApacheValidatorFactory.class) { if (DEFAULT_FACTORY == null) { DEFAULT_FACTORY = Validation.byProvider(ApacheValidationProvider.class).configure() .buildValidatorFactory().unwrap(ApacheValidatorFactory.class); } } } return DEFAULT_FACTORY; } /** * Set a particular {@link ApacheValidatorFactory} instance as the default. * * @param aDefaultFactory */ public static void setDefault(ApacheValidatorFactory aDefaultFactory) { DEFAULT_FACTORY = aDefaultFactory; } private static ValueExtractors createBaseValueExtractors(ParticipantFactory participantFactory) { final ValueExtractors result = new ValueExtractors(OnDuplicateContainerElementKey.OVERWRITE); participantFactory.loadServices(ValueExtractor.class).forEach(result::add); return result; } private final Map properties; private final AnnotationsManager annotationsManager; private final DescriptorManager descriptorManager = new DescriptorManager(this); private final MetadataBuilders metadataBuilders = new MetadataBuilders(); private final ConstraintCached constraintsCache = new ConstraintCached(); private final Map, Class> unwrappedClassCache = new ConcurrentHashMap<>(); private final Collection toClose = new ArrayList<>(); private final GroupsComputer groupsComputer = new GroupsComputer(); private final ParticipantFactory participantFactory; private final ValueExtractors valueExtractors; private MessageInterpolator messageResolver; private TraversableResolver traversableResolver; private ConstraintValidatorFactory constraintValidatorFactory; private ParameterNameProvider parameterNameProvider; private ClockProvider clockProvider; /** * Create a new ApacheValidatorFactory instance. */ public ApacheValidatorFactory(ConfigurationState configuration) { properties = new HashMap<>(configuration.getProperties()); parameterNameProvider = configuration.getParameterNameProvider(); messageResolver = configuration.getMessageInterpolator(); traversableResolver = configuration.getTraversableResolver(); constraintValidatorFactory = configuration.getConstraintValidatorFactory(); clockProvider = configuration.getClockProvider(); if (configuration instanceof CloseableAble) { toClose.add(((CloseableAble) configuration).getCloseable()); } participantFactory = new ParticipantFactory(Thread.currentThread().getContextClassLoader(), ApacheValidatorFactory.class.getClassLoader()); toClose.add(participantFactory); valueExtractors = createBaseValueExtractors(participantFactory).createChild(); configuration.getValueExtractors().forEach(valueExtractors::add); annotationsManager = new AnnotationsManager(this); loadAndVerifyUserCustomizations(configuration); } public Map, Class> getUnwrappedClassCache() { return unwrappedClassCache; } /** * Get the property map of this {@link ApacheValidatorFactory}. * * @return Map */ public Map getProperties() { return properties; } /** * Shortcut method to create a new Validator instance with factory's settings * * @return the new validator instance */ @Override public Validator getValidator() { return usingContext().getValidator(); } /** * {@inheritDoc} * * @return the validator factory's context */ @Override public ApacheFactoryContext usingContext() { return new ApacheFactoryContext(this); } /** * {@inheritDoc} */ @Override public synchronized ApacheValidatorFactory clone() { try { return (ApacheValidatorFactory) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); // VM bug. } } /** * Set the {@link MessageInterpolator} used. * * @param messageResolver */ public final void setMessageInterpolator(MessageInterpolator messageResolver) { if (messageResolver != null) { this.messageResolver = messageResolver; } } /** * {@inheritDoc} */ @Override public MessageInterpolator getMessageInterpolator() { return messageResolver; } /** * Set the {@link TraversableResolver} used. * * @param traversableResolver */ public final void setTraversableResolver(TraversableResolver traversableResolver) { if (traversableResolver != null) { this.traversableResolver = traversableResolver; } } public void setParameterNameProvider(final ParameterNameProvider parameterNameProvider) { if (parameterNameProvider != null) { this.parameterNameProvider = parameterNameProvider; } } public void setClockProvider(final ClockProvider clockProvider) { if (clockProvider != null) { this.clockProvider = clockProvider; } } /** * {@inheritDoc} */ @Override public TraversableResolver getTraversableResolver() { return traversableResolver; } /** * Set the {@link ConstraintValidatorFactory} used. * * @param constraintValidatorFactory */ public final void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) { if (constraintValidatorFactory != null) { this.constraintValidatorFactory = constraintValidatorFactory; if (DefaultConstraintValidatorFactory.class.isInstance(constraintValidatorFactory)) { toClose.add(Closeable.class.cast(constraintValidatorFactory)); } } } /** * {@inheritDoc} */ @Override public ConstraintValidatorFactory getConstraintValidatorFactory() { return constraintValidatorFactory; } @Override public ParameterNameProvider getParameterNameProvider() { return parameterNameProvider; } @Override public ClockProvider getClockProvider() { return clockProvider; } @Override public void close() { try { for (final Closeable c : toClose) { c.close(); } toClose.clear(); } catch (final Exception e) { // no-op } } /** * Return an object of the specified type to allow access to the provider-specific API. If the Bean Validation * provider implementation does not support the specified class, the ValidationException is thrown. * * @param type * the class of the object to be returned. * @return an instance of the specified class * @throws ValidationException * if the provider does not support the call. */ @Override public T unwrap(final Class type) { if (type.isInstance(this)) { @SuppressWarnings("unchecked") final T result = (T) this; return result; } // FIXME 2011-03-27 jw: // This code is unsecure. // It should allow only a fixed set of classes. // Can't fix this because don't know which classes this method should support. if (!(type.isInterface() || Modifier.isAbstract(type.getModifiers()))) { return newInstance(type); } try { final Class cls = Reflection.toClass(type.getName() + "Impl"); if (type.isAssignableFrom(cls)) { @SuppressWarnings("unchecked") T result = (T) newInstance(cls); return result; } } catch (ClassNotFoundException e) { // do nothing } throw new ValidationException("Type " + type + " not supported"); } private T newInstance(final Class cls) { try { return Reflection.newInstance(cls); } catch (final RuntimeException e) { throw new ValidationException(e.getCause()); } } /** * Get the constraint cache used. * * @return {@link ConstraintCached} */ public ConstraintCached getConstraintsCache() { return constraintsCache; } /** * Get the {@link AnnotationsManager}. * * @return {@link AnnotationsManager} */ public AnnotationsManager getAnnotationsManager() { return annotationsManager; } /** * Get the {@link DescriptorManager}. * * @return {@link DescriptorManager} */ public DescriptorManager getDescriptorManager() { return descriptorManager; } /** * Get the {@link ValueExtractors}. * * @return {@link ValueExtractors} */ public ValueExtractors getValueExtractors() { return valueExtractors; } public MetadataBuilders getMetadataBuilders() { return metadataBuilders; } public GroupsComputer getGroupsComputer() { return groupsComputer; } private void loadAndVerifyUserCustomizations(ConfigurationState configuration) { @SuppressWarnings({ "unchecked", "rawtypes" }) final BiConsumer, ForBean> addBuilder = (t, b) -> { getMetadataBuilders().registerCustomBuilder((Class) t, (MetadataBuilder.ForBean) b); }; participantFactory.loadServices(MetadataSource.class) .forEach(ms -> { ms.initialize(this); ms.process(configuration, getConstraintsCache()::add, addBuilder); }); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy