You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2018/03/13 23:30:14 UTC
bval git commit: configuration refactoring
Repository: bval
Updated Branches:
refs/heads/bv2 b7b7a1032 -> 36920e87f
configuration refactoring
Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/36920e87
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/36920e87
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/36920e87
Branch: refs/heads/bv2
Commit: 36920e87f316b24231da4492c023da3feeef7ec9
Parents: b7b7a10
Author: Matt Benson <mb...@apache.org>
Authored: Tue Mar 13 18:30:07 2018 -0500
Committer: Matt Benson <mb...@apache.org>
Committed: Tue Mar 13 18:30:07 2018 -0500
----------------------------------------------------------------------
.../java/org/apache/bval/cdi/BValExtension.java | 26 +-
.../bval/jsr/BootstrapConfigurationImpl.java | 59 ++-
.../org/apache/bval/jsr/ConfigurationImpl.java | 422 +++++++++----------
.../apache/bval/jsr/xml/ValidationParser.java | 257 +++--------
.../bval/jsr/xml/ValidationParserTest.java | 6 +-
5 files changed, 295 insertions(+), 475 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/bval/blob/36920e87/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java b/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java
index 75bf195..39823a5 100644
--- a/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java
+++ b/bval-jsr/src/main/java/org/apache/bval/cdi/BValExtension.java
@@ -51,6 +51,7 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.apache.bval.jsr.ConfigurationImpl;
import org.apache.bval.util.Validate;
/**
@@ -110,7 +111,10 @@ public class BValExtension implements Extension {
if (validator != null) {
return;
}
- config.addProperty("bval.before.cdi", "true"); // ignore parts of the config relying on CDI since we didn't start yet
+ if (config instanceof ConfigurationImpl) {
+ // ignore parts of the config relying on CDI since we didn't start yet
+ ((ConfigurationImpl) config).deferBootstrapOverrides();
+ }
if (factory == null) {
factory = config.buildValidatorFactory();
}
@@ -218,17 +222,9 @@ public class BValExtension implements Extension {
if (factory != null) { // cleanup cache used to discover ValidateOnException before factory is recreated
factory.close();
}
-
- cdiIntegration(afterBeanDiscovery, beanManager);
- }
-
- private void cdiIntegration(final AfterBeanDiscovery afterBeanDiscovery, final BeanManager beanManager) {
- try {
- config.addProperty("bval.before.cdi", "false"); // now take into account all the config
- } catch (final Exception e) {
- // no-op: sadly tck does it
+ if (config instanceof ConfigurationImpl) {
+ ((ConfigurationImpl) config).releaseDeferredBootstrapOverrides();
}
-
if (!validatorFactoryFound) {
try { // recreate the factory
afterBeanDiscovery.addBean(new ValidatorFactoryBean(factory = config.buildValidatorFactory()));
@@ -272,9 +268,7 @@ public class BValExtension implements Extension {
it.postConstruct(instance);
return new Releasable<T>(context, it, instance);
- } catch (final Exception e) {
- // no-op
- } catch (final NoClassDefFoundError error) {
+ } catch (final Exception | NoClassDefFoundError error) {
// no-op
}
return null;
@@ -305,9 +299,7 @@ public class BValExtension implements Extension {
injectionTarget.preDestroy(instance);
injectionTarget.dispose(instance);
context.release();
- } catch (final Exception e) {
- // no-op
- } catch (final NoClassDefFoundError e) {
+ } catch (final Exception | NoClassDefFoundError e) {
// no-op
}
}
http://git-wip-us.apache.org/repos/asf/bval/blob/36920e87/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
index d85ab51..f7a11a3 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
@@ -18,24 +18,50 @@
*/
package org.apache.bval.jsr;
-import javax.validation.BootstrapConfiguration;
-import javax.validation.executable.ExecutableType;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
+import javax.validation.BootstrapConfiguration;
+import javax.validation.executable.ExecutableType;
+
public class BootstrapConfigurationImpl implements BootstrapConfiguration {
- private Map<String, String> properties;
- private Set<ExecutableType> defaultValidatedExecutableTypes;
- private boolean executableValidationEnabled;
- private Set<String> constraintMappingResourcePaths;
+ public static final Set<ExecutableType> DEFAULT_DEFAULT_VALIDATED_EXECUTABLE_TYPES =
+ Collections.unmodifiableSet(EnumSet.of(ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS));
+
+ public static final BootstrapConfigurationImpl DEFAULT = new BootstrapConfigurationImpl(Collections.emptySet(),
+ true, BootstrapConfigurationImpl.DEFAULT_DEFAULT_VALIDATED_EXECUTABLE_TYPES, Collections.emptyMap(),
+ Collections.emptySet());
+
+ private static Set<ExecutableType> expandExecutableValidation(Set<ExecutableType> executableTypes) {
+ if (executableTypes == DEFAULT_DEFAULT_VALIDATED_EXECUTABLE_TYPES) {
+ return executableTypes;
+ }
+ executableTypes = EnumSet.copyOf(executableTypes);
+ if (executableTypes.contains(ExecutableType.ALL)) {
+ executableTypes.clear();
+ executableTypes.add(ExecutableType.CONSTRUCTORS);
+ executableTypes.add(ExecutableType.NON_GETTER_METHODS);
+ executableTypes.add(ExecutableType.GETTER_METHODS);
+ } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL trumps NONE
+ executableTypes.clear();
+ }
+ return Collections.unmodifiableSet(executableTypes);
+ }
+
+ private final Set<String> constraintMappingResourcePaths;
+ private final boolean executableValidationEnabled;
+ private final Set<ExecutableType> defaultValidatedExecutableTypes;
+ private final Map<String, String> properties;
+ private final Set<String> valueExtractorClassNames;
+
private String parameterNameProviderClassName;
private String traversableResolverClassName;
private String messageInterpolatorClassName;
private String constraintValidatorFactoryClassName;
private String defaultProviderClassName;
private String clockProviderClassName;
- private Set<String> valueExtractorClassNames;
public BootstrapConfigurationImpl(final String defaultProviderClassName,
final String constraintValidatorFactoryClassName, final String messageInterpolatorClassName,
@@ -43,16 +69,27 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
final Set<String> constraintMappingResourcePaths, final boolean executableValidationEnabled,
final Set<ExecutableType> defaultValidatedExecutableTypes, final Map<String, String> properties,
final String clockProviderClassName, final Set<String> valueExtractorClassNames) {
- this.properties = Collections.unmodifiableMap(properties);
- this.defaultValidatedExecutableTypes = Collections.unmodifiableSet(defaultValidatedExecutableTypes);
- this.executableValidationEnabled = executableValidationEnabled;
- this.constraintMappingResourcePaths = Collections.unmodifiableSet(constraintMappingResourcePaths);
+
+ this(Collections.unmodifiableSet(constraintMappingResourcePaths), executableValidationEnabled,
+ expandExecutableValidation(defaultValidatedExecutableTypes), Collections.unmodifiableMap(properties),
+ Collections.unmodifiableSet(valueExtractorClassNames));
+
this.parameterNameProviderClassName = parameterNameProviderClassName;
this.traversableResolverClassName = traversableResolverClassName;
this.messageInterpolatorClassName = messageInterpolatorClassName;
this.constraintValidatorFactoryClassName = constraintValidatorFactoryClassName;
this.defaultProviderClassName = defaultProviderClassName;
this.clockProviderClassName = clockProviderClassName;
+ }
+
+ private BootstrapConfigurationImpl(final Set<String> constraintMappingResourcePaths,
+ final boolean executableValidationEnabled, final Set<ExecutableType> defaultValidatedExecutableTypes,
+ final Map<String, String> properties, final Set<String> valueExtractorClassNames) {
+
+ this.constraintMappingResourcePaths = constraintMappingResourcePaths;
+ this.executableValidationEnabled = executableValidationEnabled;
+ this.defaultValidatedExecutableTypes = defaultValidatedExecutableTypes;
+ this.properties = properties;
this.valueExtractorClassNames = valueExtractorClassNames;
}
http://git-wip-us.apache.org/repos/asf/bval/blob/36920e87/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
index 658273c..3e2f678 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Supplier;
import javax.validation.BootstrapConfiguration;
import javax.validation.ClockProvider;
@@ -39,7 +40,6 @@ import javax.validation.TraversableResolver;
import javax.validation.ValidationException;
import javax.validation.ValidationProviderResolver;
import javax.validation.ValidatorFactory;
-import javax.validation.executable.ExecutableType;
import javax.validation.spi.BootstrapState;
import javax.validation.spi.ConfigurationState;
import javax.validation.spi.ValidationProvider;
@@ -51,6 +51,7 @@ import org.apache.bval.jsr.resolver.DefaultTraversableResolver;
import org.apache.bval.jsr.util.IOs;
import org.apache.bval.jsr.xml.ValidationParser;
import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Lazy;
import org.apache.commons.weaver.privilizer.Privileged;
/**
@@ -60,56 +61,79 @@ import org.apache.commons.weaver.privilizer.Privileged;
* <br/>
*/
public class ConfigurationImpl implements ApacheValidatorConfiguration, ConfigurationState {
+
+ private class LazyParticipant<T> extends Lazy<T> {
+
+ private LazyParticipant(Supplier<T> init) {
+ super(init);
+ }
+
+ @Override
+ public Lazy<T> reset(Supplier<T> init) {
+ try {
+ return super.reset(init);
+ } finally {
+ ConfigurationImpl.this.prepared = false;
+ }
+ }
+
+ ConfigurationImpl override(T value) {
+ if (value != null) {
+ reset(() -> value);
+ }
+ return ConfigurationImpl.this;
+ }
+ }
+
/**
* Configured {@link ValidationProvider}
*/
//couldn't this be parameterized <ApacheValidatorConfiguration> or <? super ApacheValidatorConfiguration>?
- protected final ValidationProvider<?> provider;
+ private final ValidationProvider<ApacheValidatorConfiguration> provider;
/**
* Configured {@link ValidationProviderResolver}
*/
- protected final ValidationProviderResolver providerResolver;
+ private final ValidationProviderResolver providerResolver;
/**
* Configured {@link ValidationProvider} class
*/
- protected Class<? extends ValidationProvider<?>> providerClass;
+ private Class<? extends ValidationProvider<?>> providerClass;
- /**
- * Configured {@link MessageInterpolator}
- */
- protected MessageInterpolator defaultMessageInterpolator = new DefaultMessageInterpolator();
- protected volatile MessageInterpolator messageInterpolator = defaultMessageInterpolator;
- protected Class<? extends MessageInterpolator> messageInterpolatorClass;
+ private final MessageInterpolator defaultMessageInterpolator = new DefaultMessageInterpolator();
- /**
- * Configured {@link ConstraintValidatorFactory}
- */
- protected ConstraintValidatorFactory defaultConstraintValidatorFactory = new DefaultConstraintValidatorFactory();
- protected volatile ConstraintValidatorFactory constraintValidatorFactory = defaultConstraintValidatorFactory;
- protected Class<? extends ConstraintValidatorFactory> constraintValidatorFactoryClass;
+ private final LazyParticipant<MessageInterpolator> messageInterpolator =
+ new LazyParticipant<>(this::getDefaultMessageInterpolator);
+
+ private final ConstraintValidatorFactory defaultConstraintValidatorFactory =
+ new DefaultConstraintValidatorFactory();
+
+ private final LazyParticipant<ConstraintValidatorFactory> constraintValidatorFactory =
+ new LazyParticipant<>(this::getDefaultConstraintValidatorFactory);
+
+ private final TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();
+
+ private final LazyParticipant<TraversableResolver> traversableResolver =
+ new LazyParticipant<>(this::getDefaultTraversableResolver);
- protected TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();
- protected volatile TraversableResolver traversableResolver = defaultTraversableResolver;
- protected Class<? extends TraversableResolver> traversableResolverClass;
+ private final ParameterNameProvider defaultParameterNameProvider = new DefaultParameterNameProvider();
- protected ParameterNameProvider defaultParameterNameProvider = new DefaultParameterNameProvider();
- protected volatile ParameterNameProvider parameterNameProvider = defaultParameterNameProvider;
- protected Class<? extends ParameterNameProvider> parameterNameProviderClass;
+ private final LazyParticipant<ParameterNameProvider> parameterNameProvider =
+ new LazyParticipant<>(this::getDefaultParameterNameProvider);
- protected BootstrapConfiguration bootstrapConfiguration;
+ private final ClockProvider defaultClockProvider = Clock::systemDefaultZone;
- protected Collection<ExecutableType> executableValidation;
+ private final LazyParticipant<ClockProvider> clockProvider = new LazyParticipant<>(this::getDefaultClockProvider);
+
+ private Lazy<BootstrapConfiguration> bootstrapConfiguration = new Lazy<>(this::createBootstrapConfiguration);
private Collection<BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<>();
- protected ClockProvider defaultClockProvider = Clock::systemDefaultZone;
- protected volatile ClockProvider clockProvider = defaultClockProvider;
- protected Class<? extends ClockProvider> clockProviderClass;
- protected Set<ValueExtractor<?>> valueExtractors = new HashSet<>();
+ private Set<ValueExtractor<?>> valueExtractors = new HashSet<>();
private boolean beforeCdi = false;
+ private ClassLoader loader;
// BEGIN DEFAULTS
/**
@@ -118,22 +142,20 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
private boolean prepared = false;
// END DEFAULTS
- private Set<InputStream> mappingStreams = new HashSet<>();
- private Map<String, String> properties = new HashMap<>();
+ private final Set<InputStream> mappingStreams = new HashSet<>();
+ private final Map<String, String> properties = new HashMap<>();
private boolean ignoreXmlConfiguration = false;
- private volatile ValidationParser parser;
-
/**
* Create a new ConfigurationImpl instance.
* @param aState bootstrap state
* @param aProvider provider
*/
- public ConfigurationImpl(BootstrapState aState, ValidationProvider<?> aProvider) {
- if (aProvider != null) {
- this.provider = aProvider;
- this.providerResolver = null;
- } else if (aState != null) {
+ public ConfigurationImpl(BootstrapState aState, ValidationProvider<ApacheValidatorConfiguration> aProvider) {
+ Exceptions.raiseIf(aProvider == null && aState == null, ValidationException::new,
+ "one of provider or state is required");
+
+ if (aProvider == null) {
this.provider = null;
if (aState.getValidationProviderResolver() == null) {
providerResolver = aState.getDefaultValidationProviderResolver();
@@ -141,26 +163,14 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
providerResolver = aState.getValidationProviderResolver();
}
} else {
- throw new ValidationException("either provider or state are required");
+ this.provider = aProvider;
+ this.providerResolver = null;
}
initializePropertyDefaults();
}
/**
* {@inheritDoc}
- */
- @Override
- public ApacheValidatorConfiguration traversableResolver(TraversableResolver resolver) {
- if (resolver != null) {
- this.traversableResolverClass = null;
- this.traversableResolver = resolver;
- this.prepared = false;
- }
- return this;
- }
-
- /**
- * {@inheritDoc}
* Ignore data from the <i>META-INF/validation.xml</i> file if this
* method is called.
*
@@ -177,34 +187,33 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
*/
@Override
public ConfigurationImpl messageInterpolator(MessageInterpolator resolver) {
- if (resolver != null) {
- this.messageInterpolatorClass = null;
- this.messageInterpolator = resolver;
- this.prepared = false;
- }
- return this;
+ return messageInterpolator.override(resolver);
}
/**
* {@inheritDoc}
*/
@Override
- public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintFactory) {
- if (constraintFactory != null) {
- this.constraintValidatorFactoryClass = null;
- this.constraintValidatorFactory = constraintFactory;
- this.prepared = false;
- }
- return this;
+ public ApacheValidatorConfiguration traversableResolver(TraversableResolver resolver) {
+ return traversableResolver.override(resolver);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
+ return this.constraintValidatorFactory.override(constraintValidatorFactory);
}
@Override
public ApacheValidatorConfiguration parameterNameProvider(ParameterNameProvider parameterNameProvider) {
- if (parameterNameProvider != null) {
- this.parameterNameProviderClass = null;
- this.parameterNameProvider = parameterNameProvider;
- }
- return this;
+ return this.parameterNameProvider.override(parameterNameProvider);
+ }
+
+ @Override
+ public ApacheValidatorConfiguration clockProvider(ClockProvider clockProvider) {
+ return this.clockProvider.override(clockProvider);
}
/**
@@ -232,11 +241,7 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
*/
@Override
public ApacheValidatorConfiguration addProperty(String name, String value) {
- if ("bval.before.cdi".equals(name)) {
- beforeCdi = Boolean.parseBoolean(value);
- } else {
- properties.put(name, value);
- }
+ properties.put(name, value);
return this;
}
@@ -260,6 +265,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
return defaultParameterNameProvider;
}
+ @Override
+ public ClockProvider getDefaultClockProvider() {
+ return defaultClockProvider;
+ }
+
/**
* {@inheritDoc}
* Return a map of non type-safe custom properties.
@@ -296,22 +306,12 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
*/
@Override
public MessageInterpolator getMessageInterpolator() {
- if (beforeCdi) {
- return defaultMessageInterpolator;
- }
- if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
- synchronized (this) {
- if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
- messageInterpolator = newInstance(messageInterpolatorClass);
- }
- }
- }
- return messageInterpolator;
+ return messageInterpolator.get();
}
@Override
public BootstrapConfiguration getBootstrapConfiguration() {
- return createBootstrapConfiguration();
+ return bootstrapConfiguration.get();
}
/**
@@ -325,58 +325,13 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
return doBuildValidatorFactory();
}
- @Privileged
- private ValidatorFactory doBuildValidatorFactory() {
- prepare();
- parser.ensureValidatorFactoryCanBeBuilt();
- final ValidationProvider<?> useProvider = provider == null ? findProvider() : provider;
- return useProvider.buildValidatorFactory(this);
- }
-
- private ConfigurationImpl prepare() {
- if (prepared) {
- return this;
- }
- createBootstrapConfiguration();
- parser.applyConfigWithInstantiation(this); // instantiate the config if needed
-
- prepared = true;
- return this;
- }
-
- private BootstrapConfiguration createBootstrapConfiguration() {
- if (parser == null) {
- parser = parseValidationXml(); // already done if BootstrapConfiguration already looked up
- bootstrapConfiguration = parser.getBootstrap();
- }
- return bootstrapConfiguration;
- }
-
- /** Check whether a validation.xml file exists and parses it with JAXB */
- private ValidationParser parseValidationXml() {
- return ValidationParser.processValidationConfig(getProperties().get(Properties.VALIDATION_XML_PATH), this,
- ignoreXmlConfiguration);
- }
-
/**
* {@inheritDoc}
* @return the constraint validator factory of this configuration.
*/
@Override
public ConstraintValidatorFactory getConstraintValidatorFactory() {
- if (beforeCdi) {
- return constraintValidatorFactory;
- }
- if (constraintValidatorFactory == defaultConstraintValidatorFactory
- && constraintValidatorFactoryClass != null) {
- synchronized (this) {
- if (constraintValidatorFactory == defaultConstraintValidatorFactory
- && constraintValidatorFactoryClass != null) {
- constraintValidatorFactory = newInstance(constraintValidatorFactoryClass);
- }
- }
- }
- return constraintValidatorFactory;
+ return constraintValidatorFactory.get();
}
/**
@@ -384,73 +339,39 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
*/
@Override
public TraversableResolver getTraversableResolver() {
- if (beforeCdi) {
- return defaultTraversableResolver;
- }
- if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
- synchronized (this) {
- if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
- traversableResolver = newInstance(traversableResolverClass);
- }
- }
- }
- return traversableResolver;
+ return traversableResolver.get();
}
@Override
public ParameterNameProvider getParameterNameProvider() {
- if (beforeCdi) {
- return defaultParameterNameProvider;
- }
- if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
- synchronized (this) {
- if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
- parameterNameProvider = newInstance(parameterNameProviderClass);
- }
- }
- }
- return parameterNameProvider;
+ return parameterNameProvider.get();
}
- /**
- * Get the configured {@link ValidationProvider}.
- * @return {@link ValidationProvider}
- */
- public ValidationProvider<?> getProvider() {
- return provider;
+ @Override
+ public ClockProvider getClockProvider() {
+ return clockProvider.get();
}
- private ValidationProvider<?> findProvider() {
- if (providerClass == null) {
- return providerResolver.getValidationProviders().get(0);
- }
- final Optional<ValidationProvider<?>> knownProvider =
- providerResolver.getValidationProviders().stream().filter(providerClass::isInstance).findFirst();
- if (knownProvider.isPresent()) {
- return knownProvider.get();
- }
- try {
- return providerClass.getConstructor().newInstance();
- } catch (Exception e) {
- throw Exceptions.create(ValidationException::new, "Unable to find/create %s of type %s",
- ValidationProvider.class.getSimpleName(), providerClass);
- }
+ @Override
+ public ApacheValidatorConfiguration addValueExtractor(ValueExtractor<?> extractor) {
+ valueExtractors.add(extractor);
+ return this;
}
- /**
- * Set {@link ValidationProvider} class.
- * @param providerClass the provider type
- */
- public void setProviderClass(Class<? extends ValidationProvider<?>> providerClass) {
- this.providerClass = providerClass;
+ @Override
+ public Set<ValueExtractor<?>> getValueExtractors() {
+ return Collections.unmodifiableSet(valueExtractors);
}
- public void setExecutableValidation(final Collection<ExecutableType> executableValidation) {
- this.executableValidation = executableValidation;
+ public void deferBootstrapOverrides() {
+ beforeCdi = true;
}
- public Collection<ExecutableType> getExecutableValidation() {
- return executableValidation;
+ public void releaseDeferredBootstrapOverrides() {
+ if (beforeCdi) {
+ beforeCdi = false;
+ performBootstrapOverrides();
+ }
}
public Closeable getClosable() {
@@ -463,74 +384,107 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
}
@Privileged
- private <T> T newInstance(final Class<T> cls) {
- try {
- final BValExtension.Releasable<T> releasable = BValExtension.inject(cls);
- releasables.add(releasable);
- return releasable.getInstance();
- } catch (Exception | NoClassDefFoundError e) {
- }
- try {
- return cls.getConstructor().newInstance();
- } catch (final Exception e) {
- throw new ValidationException(e.getMessage(), e);
- }
+ private ValidatorFactory doBuildValidatorFactory() {
+ prepare();
+ return Optional.<ValidationProvider<?>> ofNullable(provider).orElseGet(this::findProvider)
+ .buildValidatorFactory(this);
}
- public void traversableResolverClass(final Class<TraversableResolver> clazz) {
- traversableResolverClass = clazz;
+ private void prepare() {
+ if (!prepared) {
+ applyBootstrapConfiguration();
+ prepared = true;
+ }
}
- public void constraintValidatorFactoryClass(final Class<ConstraintValidatorFactory> clazz) {
- constraintValidatorFactoryClass = clazz;
+ private BootstrapConfiguration createBootstrapConfiguration() {
+ if (!ignoreXmlConfiguration) {
+ loader = ValidationParser.class.getClassLoader();
+ final BootstrapConfiguration xmlBootstrap =
+ ValidationParser.processValidationConfig(getProperties().get(Properties.VALIDATION_XML_PATH), this);
+ if (xmlBootstrap != null) {
+ return xmlBootstrap;
+ }
+ }
+ loader = ApacheValidatorFactory.class.getClassLoader();
+ return BootstrapConfigurationImpl.DEFAULT;
}
- public void messageInterpolatorClass(final Class<MessageInterpolator> clazz) {
- messageInterpolatorClass = clazz;
- }
+ private void applyBootstrapConfiguration() {
+ final BootstrapConfiguration bootstrapConfig = bootstrapConfiguration.get();
- public void parameterNameProviderClass(final Class<? extends ParameterNameProvider> clazz) {
- parameterNameProviderClass = clazz;
- }
+ if (bootstrapConfig.getDefaultProviderClassName() != null) {
+ this.providerClass = loadClass(bootstrapConfig.getDefaultProviderClassName());
+ }
- @Override
- public ApacheValidatorConfiguration clockProvider(ClockProvider clockProvider) {
- this.clockProvider = clockProvider;
- return this;
+ bootstrapConfig.getProperties().forEach(this::addProperty);
+ bootstrapConfig.getConstraintMappingResourcePaths().stream().map(ValidationParser::open)
+ .forEach(this::addMapping);
+
+ if (!beforeCdi) {
+ performBootstrapOverrides();
+ }
}
- @Override
- public ApacheValidatorConfiguration addValueExtractor(ValueExtractor<?> extractor) {
- valueExtractors.add(extractor);
- return this;
+ private void performBootstrapOverrides() {
+ final BootstrapConfiguration bootstrapConfig = bootstrapConfiguration.get();
+ override(messageInterpolator, bootstrapConfig::getMessageInterpolatorClassName);
+ override(traversableResolver, bootstrapConfig::getTraversableResolverClassName);
+ override(constraintValidatorFactory, bootstrapConfig::getConstraintValidatorFactoryClassName);
+ override(parameterNameProvider, bootstrapConfig::getParameterNameProviderClassName);
+ override(clockProvider, bootstrapConfig::getClockProviderClassName);
}
- @Override
- public ClockProvider getDefaultClockProvider() {
- return defaultClockProvider;
+ @SuppressWarnings("unchecked")
+ private <T> Class<T> loadClass(final String className) {
+ try {
+ return (Class<T>) Class.forName(className, true, loader);
+ } catch (final ClassNotFoundException ex) {
+ throw new ValidationException(ex);
+ }
}
- @Override
- public Set<ValueExtractor<?>> getValueExtractors() {
- return Collections.unmodifiableSet(valueExtractors);
+ private void initializePropertyDefaults() {
+ properties.put(Properties.CONSTRAINTS_CACHE_SIZE, Integer.toString(50));
}
- @Override
- public ClockProvider getClockProvider() {
- if (beforeCdi) {
- return defaultClockProvider;
+ private ValidationProvider<?> findProvider() {
+ if (providerClass == null) {
+ return providerResolver.getValidationProviders().get(0);
}
- if (clockProvider == defaultClockProvider && clockProviderClass != null) {
- synchronized (this) {
- if (clockProvider == defaultClockProvider && clockProviderClass != null) {
- clockProvider = newInstance(clockProviderClass);
- }
- }
+ final Optional<ValidationProvider<?>> knownProvider =
+ providerResolver.getValidationProviders().stream().filter(providerClass::isInstance).findFirst();
+ if (knownProvider.isPresent()) {
+ return knownProvider.get();
+ }
+ try {
+ return providerClass.getConstructor().newInstance();
+ } catch (Exception e) {
+ throw Exceptions.create(ValidationException::new, "Unable to find/create %s of type %s",
+ ValidationProvider.class.getSimpleName(), providerClass);
}
- return clockProvider;
}
- protected void initializePropertyDefaults() {
- properties.put(Properties.CONSTRAINTS_CACHE_SIZE, Integer.toString(50));
+ private <T> void override(LazyParticipant<T> participant, Supplier<String> getClassName) {
+ final String className = getClassName.get();
+ if (className != null) {
+ final Class<T> t = loadClass(className);
+ participant.reset(() -> newInstance(t));
+ }
+ }
+
+ @Privileged
+ private <T> T newInstance(final Class<T> cls) {
+ try {
+ final BValExtension.Releasable<T> releasable = BValExtension.inject(cls);
+ releasables.add(releasable);
+ return releasable.getInstance();
+ } catch (Exception | NoClassDefFoundError e) {
+ }
+ try {
+ return cls.getConstructor().newInstance();
+ } catch (final Exception e) {
+ throw new ValidationException(e.getMessage(), e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/bval/blob/36920e87/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
index bed2e10..35d510b 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
@@ -21,27 +21,21 @@ package org.apache.bval.jsr.xml;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
-import javax.validation.ConstraintValidatorFactory;
-import javax.validation.MessageInterpolator;
-import javax.validation.ParameterNameProvider;
-import javax.validation.TraversableResolver;
+import javax.validation.BootstrapConfiguration;
import javax.validation.ValidationException;
import javax.validation.executable.ExecutableType;
-import javax.validation.spi.ValidationProvider;
import org.apache.bval.jsr.BootstrapConfigurationImpl;
import org.apache.bval.jsr.ConfigurationImpl;
@@ -72,64 +66,42 @@ public class ValidationParser {
.build();
public static String getValidationXmlFile(String file) {
- if (file == null) {
- return DEFAULT_VALIDATION_XML_FILE;
- }
- return file;
+ return file == null ? DEFAULT_VALIDATION_XML_FILE : file;
}
- public static ValidationParser processValidationConfig(final String file, final ConfigurationImpl targetConfig,
- final boolean ignoreXml) {
- final ValidationParser parser = new ValidationParser();
-
- if (!ignoreXml) {
- parser.xmlConfig = parseXmlConfig(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 (parser.xmlConfig == null) { // default config
- final CopyOnWriteArraySet<ExecutableType> executableTypes = new CopyOnWriteArraySet<>();
- executableTypes.add(ExecutableType.CONSTRUCTORS);
- executableTypes.add(ExecutableType.NON_GETTER_METHODS);
-
- parser.bootstrap = new BootstrapConfigurationImpl(null, null, null, null, null, Collections.emptySet(),
- true, executableTypes, Collections.emptyMap(), null, Collections.emptySet());
-
- targetConfig.setExecutableValidation(executableTypes);
+ if (xmlConfig.getExecutableValidation() == null) {
+ defaultValidatedExecutableTypes = BootstrapConfigurationImpl.DEFAULT_DEFAULT_VALIDATED_EXECUTABLE_TYPES;
+ executableValidationEnabled = true;
} else {
- if (parser.xmlConfig.getExecutableValidation() == null) {
- final ExecutableValidationType value = new ExecutableValidationType();
- value.setEnabled(true);
-
- final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes =
- new DefaultValidatedExecutableTypesType();
- value.setDefaultValidatedExecutableTypes(defaultValidatedExecutableTypes);
- defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.CONSTRUCTORS);
- defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.NON_GETTER_METHODS);
-
- parser.xmlConfig.setExecutableValidation(value);
- }
-
- applySimpleConfig(parser.xmlConfig, targetConfig);
+ final Optional<ExecutableValidationType> executableValidation =
+ Optional.of(xmlConfig).map(ValidationConfigType::getExecutableValidation);
+ executableValidationEnabled = executableValidation.map(ExecutableValidationType::getEnabled)
+ .filter(Predicate.isEqual(Boolean.TRUE)).isPresent();
- parser.bootstrap = new BootstrapConfigurationImpl(parser.xmlConfig.getDefaultProvider(),
- parser.xmlConfig.getConstraintValidatorFactory(), parser.xmlConfig.getMessageInterpolator(),
- parser.xmlConfig.getTraversableResolver(), parser.xmlConfig.getParameterNameProvider(),
- new HashSet<>(parser.xmlConfig.getConstraintMapping()),
- parser.xmlConfig.getExecutableValidation().getEnabled(),
- new HashSet<>(targetConfig.getExecutableValidation()), toMap(parser.xmlConfig.getProperty()),
- parser.xmlConfig.getClockProvider(), new HashSet<>(parser.xmlConfig.getValueExtractor()));
+ defaultValidatedExecutableTypes = executableValidation.filter(x -> executableValidationEnabled)
+ .map(ExecutableValidationType::getDefaultValidatedExecutableTypes)
+ .map(DefaultValidatedExecutableTypesType::getExecutableType).map(EnumSet::copyOf)
+ .orElse(EnumSet.noneOf(ExecutableType.class));
}
- return parser;
+ 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) {
- final Map<String, String> map = new HashMap<>();
- if (property != null) {
- for (final PropertyType p : property) {
- map.put(p.getName(), p.getValue());
- }
- }
- return map;
+ return property == null || property.isEmpty() ? Collections.emptyMap()
+ : property.stream().collect(Collectors.toMap(PropertyType::getName, PropertyType::getValue));
}
@Privileged
@@ -144,11 +116,27 @@ public class ValidationParser {
return SCHEMA_MANAGER.unmarshal(new InputSource(inputStream), ValidationConfigType.class);
} catch (Exception e) {
- throw new ValidationException("Unable to parse " + validationXmlFile, e);
+ throw Exceptions.create(ValidationException::new, e, "Unable to parse %s", validationXmlFile);
}
}
- protected static InputStream getInputStream(final String path) throws IOException {
+ 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,
@@ -156,158 +144,7 @@ public class ValidationParser {
return urls.isEmpty() ? null : urls.get(0).openStream();
}
- public static void applySimpleConfig(ValidationConfigType xmlConfig, ConfigurationImpl targetConfig) {
- applyExecutableValidation(xmlConfig, targetConfig);
- }
-
- private static void applyProperties(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- for (final PropertyType property : xmlConfig.getProperty()) {
- target.addProperty(property.getName(), property.getValue());
- }
- }
-
- private static void applyExecutableValidation(final ValidationConfigType xmlConfig,
- final ConfigurationImpl targetConfig) {
-
- final Set<ExecutableType> executableTypes = Optional.of(xmlConfig)
- .map(ValidationConfigType::getExecutableValidation).filter(vc -> Boolean.TRUE.equals(vc.getEnabled()))
- .map(ExecutableValidationType::getDefaultValidatedExecutableTypes)
- .map(DefaultValidatedExecutableTypesType::getExecutableType).map(EnumSet::copyOf)
- .orElseGet(() -> EnumSet.noneOf(ExecutableType.class));
-
- if (executableTypes.contains(ExecutableType.ALL)) {
- executableTypes.clear();
- executableTypes.add(ExecutableType.CONSTRUCTORS);
- executableTypes.add(ExecutableType.NON_GETTER_METHODS);
- executableTypes.add(ExecutableType.GETTER_METHODS);
- } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL trumps NONE
- executableTypes.clear();
- }
- targetConfig.setExecutableValidation(Collections.unmodifiableSet(executableTypes));
- }
-
- private static void applyMappingStreams(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- for (String rawMappingFileName : xmlConfig.getConstraintMapping()) {
- String mappingFileName = rawMappingFileName;
- if (mappingFileName.charAt(0) == '/') {
- // Classloader needs a path without a starting /
- mappingFileName = mappingFileName.substring(1);
- }
- log.log(Level.FINEST, String.format("Trying to open input stream for %s", mappingFileName));
- try {
- final InputStream in = getInputStream(mappingFileName);
- Exceptions.raiseIf(in == null, ValidationException::new,
- "Unable to open input stream for mapping file %s", mappingFileName);
- target.addMapping(in);
- } catch (IOException e) {
- Exceptions.raise(ValidationException::new, e, "Unable to open input stream for mapping file %s",
- mappingFileName);
- }
- }
- }
-
- private ValidationConfigType xmlConfig;
- private BootstrapConfigurationImpl bootstrap;
- private Collection<ValidationException> exceptions = new CopyOnWriteArrayList<ValidationException>();
-
private ValidationParser() {
// no-op
}
-
- public void applyConfigWithInstantiation(ConfigurationImpl targetConfig) {
- if (xmlConfig == null) {
- return;
- }
-
- applyProviderClass(xmlConfig, targetConfig);
- applyMessageInterpolator(xmlConfig, targetConfig);
- applyTraversableResolver(xmlConfig, targetConfig);
- applyConstraintFactory(xmlConfig, targetConfig);
- applyParameterNameProvider(xmlConfig, targetConfig);
- applyMappingStreams(xmlConfig, targetConfig);
- applyProperties(xmlConfig, targetConfig);
- }
-
- public BootstrapConfigurationImpl getBootstrap() {
- return bootstrap;
- }
-
- private void applyParameterNameProvider(final ValidationConfigType xmlConfig,
- final ConfigurationImpl targetConfig) {
- final String parameterNameProvider = xmlConfig.getParameterNameProvider();
- if (targetConfig.getParameterNameProvider() == targetConfig.getDefaultParameterNameProvider()
- && parameterNameProvider != null) {
- final Class<?> loaded = loadClass(parameterNameProvider);
- if (loaded == null) {
- log.log(Level.SEVERE, "Can't load " + parameterNameProvider);
- } else {
- final Class<? extends ParameterNameProvider> clazz = loaded.asSubclass(ParameterNameProvider.class);
- targetConfig.parameterNameProviderClass(clazz);
- log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider));
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- private void applyProviderClass(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- String providerClassName = xmlConfig.getDefaultProvider();
- if (providerClassName != null) {
- Class<? extends ValidationProvider<?>> clazz =
- (Class<? extends ValidationProvider<?>>) loadClass(providerClassName);
- target.setProviderClass(clazz);
- log.log(Level.INFO, String.format("Using %s as validation provider.", providerClassName));
- }
- }
-
- @SuppressWarnings("unchecked")
- private void applyMessageInterpolator(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- String messageInterpolatorClass = xmlConfig.getMessageInterpolator();
- if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator()
- && messageInterpolatorClass != null) {
- Class<MessageInterpolator> clazz = (Class<MessageInterpolator>) loadClass(messageInterpolatorClass);
- target.messageInterpolatorClass(clazz);
- log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass));
- }
- }
-
- @SuppressWarnings("unchecked")
- private void applyTraversableResolver(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- String traversableResolverClass = xmlConfig.getTraversableResolver();
- if (target.getTraversableResolver() == target.getDefaultTraversableResolver()
- && traversableResolverClass != null) {
- Class<TraversableResolver> clazz = (Class<TraversableResolver>) loadClass(traversableResolverClass);
- target.traversableResolverClass(clazz);
- log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass));
- }
- }
-
- @SuppressWarnings("unchecked")
- private void applyConstraintFactory(ValidationConfigType xmlConfig, ConfigurationImpl target) {
- String constraintFactoryClass = xmlConfig.getConstraintValidatorFactory();
- if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory()
- && constraintFactoryClass != null) {
- Class<ConstraintValidatorFactory> clazz =
- (Class<ConstraintValidatorFactory>) loadClass(constraintFactoryClass);
- target.constraintValidatorFactoryClass(clazz);
- log.log(Level.INFO, String.format("Using %s as constraint factory.", constraintFactoryClass));
- }
- }
-
- private Class<?> loadClass(final String className) {
- final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class);
- try {
- return Class.forName(className, true, loader);
- } catch (final ClassNotFoundException ex) {
- // TCK check BootstrapConfig is present in all cases
- // so throw next exception later
- exceptions.add(new ValidationException("Unable to load class: " + className, ex));
- return null;
- }
- }
-
- public void ensureValidatorFactoryCanBeBuilt() {
- if (!exceptions.isEmpty()) {
- throw exceptions.iterator().next();
- }
- }
}
http://git-wip-us.apache.org/repos/asf/bval/blob/36920e87/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java
index 41d4f13..a2a6faa 100644
--- a/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java
+++ b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java
@@ -82,19 +82,19 @@ public class ValidationParserTest implements ApacheValidatorConfiguration.Proper
@Test
public void testParse() {
ConfigurationImpl config = new ConfigurationImpl(null, new ApacheValidationProvider());
- ValidationParser.processValidationConfig("sample-validation.xml", config, false);
+ ValidationParser.processValidationConfig("sample-validation.xml", config);
}
@Test
public void testParseV11() {
ConfigurationImpl config = new ConfigurationImpl(null, new ApacheValidationProvider());
- ValidationParser.processValidationConfig("sample-validation11.xml", config, false);
+ ValidationParser.processValidationConfig("sample-validation11.xml", config);
}
@Test
public void testParseV20() {
ConfigurationImpl config = new ConfigurationImpl(null, new ApacheValidationProvider());
- ValidationParser.processValidationConfig("sample-validation2.xml", config, false);
+ ValidationParser.processValidationConfig("sample-validation2.xml", config);
}
@Test