/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
 */
package org.hibernate.validator.internal.engine;

import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintExpressionLanguageFeatureLevel;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineCustomViolationExpressionLanguageFeatureLevel;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration;
import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators;
import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;

import java.lang.invoke.MethodHandles;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.validation.ClockProvider;
import jakarta.validation.ConstraintValidatorFactory;
import jakarta.validation.MessageInterpolator;
import jakarta.validation.ParameterNameProvider;
import jakarta.validation.TraversableResolver;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.spi.ConfigurationState;

import org.hibernate.validator.HibernateValidatorContext;
import org.hibernate.validator.HibernateValidatorFactory;
import org.hibernate.validator.PredefinedScopeHibernateValidatorFactory;
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager;
import org.hibernate.validator.internal.engine.constraintvalidation.PredefinedScopeConstraintValidatorManagerImpl;
import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator;
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager;
import org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.hibernate.validator.internal.metadata.provider.MetaDataProvider;
import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider;
import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider;
import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper;
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.validator.internal.util.ExecutableHelper;
import org.hibernate.validator.internal.util.ExecutableParameterNameProvider;
import org.hibernate.validator.internal.util.TypeResolutionHelper;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy;
import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory;

Factory returning initialized Validator instances.

This factory is designed to support a predefined scope of bean classes to validate and constraint validators.

/** * Factory returning initialized {@code Validator} instances. * <p> * This factory is designed to support a predefined scope of bean classes to validate and constraint validators. */
public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHibernateValidatorFactory { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
Context containing all ValidatorFactory level helpers and configuration properties.
/** * Context containing all {@link ValidatorFactory} level helpers and configuration properties. */
private final ValidatorFactoryScopedContext validatorFactoryScopedContext;
The constraint validator manager for this factory.
/** * The constraint validator manager for this factory. */
private final ConstraintValidatorManager constraintValidatorManager;
Hibernate Validator specific flags to relax constraints on parameters.
/** * Hibernate Validator specific flags to relax constraints on parameters. */
private final MethodValidationConfiguration methodValidationConfiguration; private final PredefinedScopeBeanMetaDataManager beanMetaDataManager; private final ValueExtractorManager valueExtractorManager; private final GetterPropertySelectionStrategy getterPropertySelectionStrategy; private final ValidationOrderGenerator validationOrderGenerator; public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) { Contracts.assertTrue( configurationState instanceof PredefinedScopeConfigurationImpl, "Only PredefinedScopeConfigurationImpl is supported." ); ClassLoader externalClassLoader = determineExternalClassLoader( configurationState ); PredefinedScopeConfigurationImpl hibernateSpecificConfig = (PredefinedScopeConfigurationImpl) configurationState; Map<String, String> properties = configurationState.getProperties(); this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() .allowOverridingMethodAlterParameterConstraint( determineAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) ).allowMultipleCascadedValidationOnReturnValues( determineAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) ).allowParallelMethodsDefineParameterConstraints( determineAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) ).build(); this.validatorFactoryScopedContext = new ValidatorFactoryScopedContext( configurationState.getMessageInterpolator(), configurationState.getTraversableResolver(), new ExecutableParameterNameProvider( configurationState.getParameterNameProvider() ), configurationState.getClockProvider(), determineTemporalValidationTolerance( configurationState, properties ), determineScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), determineFailFast( hibernateSpecificConfig, properties ), determineTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), determineConstraintValidatorPayload( hibernateSpecificConfig ), determineConstraintExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ), determineCustomViolationExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ) ); this.constraintValidatorManager = new PredefinedScopeConstraintValidatorManagerImpl( configurationState.getConstraintValidatorFactory(), this.validatorFactoryScopedContext.getConstraintValidatorInitializationContext() ); this.validationOrderGenerator = new ValidationOrderGenerator(); this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); ConstraintHelper constraintHelper = ConstraintHelper.forBuiltinConstraints( hibernateSpecificConfig.getBuiltinConstraints() ); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); ConstraintCreationContext constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper ); JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ), ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary XmlMetaDataProvider xmlMetaDataProvider; if ( configurationState.getMappingStreams().isEmpty() ) { xmlMetaDataProvider = null; } else { xmlMetaDataProvider = new XmlMetaDataProvider( constraintCreationContext, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader ); } Set<DefaultConstraintMapping> constraintMappings = Collections.unmodifiableSet( determineConstraintMappings( typeResolutionHelper, configurationState, javaBeanHelper, externalClassLoader ) ); registerCustomConstraintValidators( constraintMappings, constraintHelper ); this.beanMetaDataManager = new PredefinedScopeBeanMetaDataManager( constraintCreationContext, executableHelper, validatorFactoryScopedContext.getParameterNameProvider(), javaBeanHelper, validationOrderGenerator, buildMetaDataProviders( constraintCreationContext, xmlMetaDataProvider, constraintMappings ), methodValidationConfiguration, determineBeanMetaDataClassNormalizer( hibernateSpecificConfig ), hibernateSpecificConfig.getBeanClassesToInitialize() ); if ( LOG.isDebugEnabled() ) { logValidatorFactoryScopedConfiguration( validatorFactoryScopedContext ); } } @Override public Validator getValidator() { return createValidator( validatorFactoryScopedContext ); } @Override public MessageInterpolator getMessageInterpolator() { return validatorFactoryScopedContext.getMessageInterpolator(); } @Override public TraversableResolver getTraversableResolver() { return validatorFactoryScopedContext.getTraversableResolver(); } @Override public ConstraintValidatorFactory getConstraintValidatorFactory() { return constraintValidatorManager.getDefaultConstraintValidatorFactory(); } @Override public ParameterNameProvider getParameterNameProvider() { return validatorFactoryScopedContext.getParameterNameProvider().getDelegate(); } public ExecutableParameterNameProvider getExecutableParameterNameProvider() { return validatorFactoryScopedContext.getParameterNameProvider(); } @Override public ClockProvider getClockProvider() { return validatorFactoryScopedContext.getClockProvider(); } @Override public ScriptEvaluatorFactory getScriptEvaluatorFactory() { return validatorFactoryScopedContext.getScriptEvaluatorFactory(); } @Override public Duration getTemporalValidationTolerance() { return validatorFactoryScopedContext.getTemporalValidationTolerance(); } @Override public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { return getterPropertySelectionStrategy; } public boolean isFailFast() { return validatorFactoryScopedContext.isFailFast(); } public boolean isTraversableResolverResultCacheEnabled() { return validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); } @Override public <T> T unwrap(Class<T> type) { // allow unwrapping into public super types if ( type.isAssignableFrom( PredefinedScopeHibernateValidatorFactory.class ) || type.isAssignableFrom( HibernateValidatorFactory.class ) ) { return type.cast( this ); } throw LOG.getTypeNotSupportedForUnwrappingException( type ); } @Override public HibernateValidatorContext usingContext() { return new PredefinedScopeValidatorContextImpl( this ); } @Override public void close() { constraintValidatorManager.clear(); beanMetaDataManager.clear(); validatorFactoryScopedContext.getScriptEvaluatorFactory().clear(); valueExtractorManager.clear(); } public ValidatorFactoryScopedContext getValidatorFactoryScopedContext() { return this.validatorFactoryScopedContext; } Validator createValidator(ValidatorFactoryScopedContext validatorFactoryScopedContext) { return new ValidatorImpl( constraintValidatorManager.getDefaultConstraintValidatorFactory(), beanMetaDataManager, valueExtractorManager, constraintValidatorManager, validationOrderGenerator, validatorFactoryScopedContext ); } private static List<MetaDataProvider> buildMetaDataProviders( ConstraintCreationContext constraintCreationContext, XmlMetaDataProvider xmlMetaDataProvider, Set<DefaultConstraintMapping> constraintMappings) { List<MetaDataProvider> metaDataProviders = newArrayList(); if ( xmlMetaDataProvider != null ) { metaDataProviders.add( xmlMetaDataProvider ); } if ( !constraintMappings.isEmpty() ) { metaDataProviders.add( new ProgrammaticMetaDataProvider( constraintCreationContext, constraintMappings ) ); } return metaDataProviders; } }