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

javax.validation.Validation Maven / Gradle / Ivy

There is a newer version: 2.0.1.Final
Show newest version
// $Id: Validation.java 16369 2009-04-21 09:55:35Z epbernard $
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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
* 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 javax.validation;

import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.ArrayList;
import java.util.Enumeration;
import java.net.URL;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import javax.validation.bootstrap.GenericBootstrap;
import javax.validation.bootstrap.ProviderSpecificBootstrap;
import javax.validation.spi.BootstrapState;
import javax.validation.spi.ValidationProvider;

/**
 * This class is the entry point for the Bean Validation framework. There are three ways
 * to bootstrap the framework:
 * 
    *
  • * The easiest approach is to build the default ValidatorFactory. *
     * ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
     * 
    * In this case, the default validation provider resolver * will be used to locate available providers. * * The chosen provider is defined as followed: *
      *
    • if the XML configuration defines a provider, this provider is used
    • *
    • if the XML configuration does not define a provider or if no XML configuration * is present the first provider returned by the ValidationProviderResolver * isntance is used.
    • *
    *
  • *
  • * The second bootstrap approach allows to choose a custom * ValidationProviderResolver. The chosen * ValidationProvider is then determined in the same way * as in the default bootstrapping case (see above). *
     * Configuration<?> configuration = Validation
     *    .byDefaultProvider()
     *    .providerResolver( new MyResolverStrategy() )
     *    .configure();
     * ValidatorFactory factory = configuration.buildValidatorFactory();
     * 
    *
  • * *

    *

  • * The third approach allows you to specify explicitly and in * a type safe fashion the expected provider by * using its specific Configuration sub-interface. * * Optionally you can choose a custom ValidationProviderResolver. *
     * ACMEConfiguration configuration = Validation
     *    .byProvider(ACMEConfiguration.class)
     *    .providerResolver( new MyResolverStrategy() )  // optionally set the provider resolver
     *    .configure();
     * ValidatorFactory factory = configuration.buildValidatorFactory();
     * 
    *
  • *
* Note:
*
    *
  • * The ValidatorFactory object built by the bootstrap process should be cached * and shared amongst Validator consumers. *
  • *
  • * This class is thread-safe. *
  • *
* * @author Emmanuel Bernard * @author Hardy Feretnschik */ public class Validation { /** * Build and return a ValidatorFactory instance based on the * default Bean Validation provider and following the * XML configuration. *

* The provider list is resolved using the default validation provider resolver * logic. *

The code is semantically equivalent to * Validation.byDefaultProvider().configure().buildValidatorFactory() * * @return ValidatorFactory instance. * @throws ValidationException if the ValidatorFactory cannot be built */ public static ValidatorFactory buildDefaultValidatorFactory() { return byDefaultProvider().configure().buildValidatorFactory(); } /** * Build a Configuration. The provider list is resolved * using the strategy provided to the bootstrap state. *

	 * Configuration<?> configuration = Validation
	 *    .byDefaultProvider()
	 *    .providerResolver( new MyResolverStrategy() )
	 *    .configure();
	 * ValidatorFactory factory = configuration.buildValidatorFactory();
	 * 
* The provider can be specified in the XML configuration. If the XML * configuration does not exsist or if no provider is specified, * the first available provider will be returned. * * @return instance building a generic Configuration * compliant with the bootstrap state provided. */ public static GenericBootstrap byDefaultProvider() { return new GenericBootstrapImpl(); } /** * Build a Configuration for a particular provider implementation. * Optionally overrides the provider resolution strategy used to determine the provider. *

* Used by applications targeting a specific provider programmatically. *

*

	 * ACMEConfiguration configuration =
	 *     Validation.byProvider(ACMEConfiguration.class)
	 *             .providerResolver( new MyResolverStrategy() )
	 *             .configure();
	 * 
, * where ACMEConfiguration is the * Configuration sub interface uniquely identifying the * ACME Bean Validation provider. * * @param configurationType the Configuration sub interface * uniquely defining the targeted provider. * * @return instance building a provider specific Configuration * sub interface implementation. */ public static > ProviderSpecificBootstrap byProvider(Class configurationType) { return new ProviderSpecificBootstrapImpl( configurationType ); } //private class, not exposed private static class ProviderSpecificBootstrapImpl> implements ProviderSpecificBootstrap { private Class configurationType; private ValidationProviderResolver resolver; public ProviderSpecificBootstrapImpl(Class configurationType) { this.configurationType = configurationType; } /** * Optionally define the provider resolver implementation used. * If not defined, use the default ValidationProviderResolver * * @param resolver ValidationProviderResolver implementation used * * @return self */ public ProviderSpecificBootstrap providerResolver(ValidationProviderResolver resolver) { this.resolver = resolver; return this; } /** * Determine the provider implementation suitable for byProvider(Class) * and delegate the creation of this specific Configuration subclass to the provider. * * @return a Configuration sub interface implementation */ public T configure() { if ( configurationType == null ) { throw new ValidationException( "builder is mandatory. Use Validation.byDefaultProvider() to use the generic provider discovery mechanism" ); } GenericBootstrapImpl state = new GenericBootstrapImpl(); if ( resolver == null ) { resolver = state.getDefaultValidationProviderResolver(); } else { //stay null if no resolver is defined state.providerResolver( resolver ); } for ( ValidationProvider provider : resolver.getValidationProviders() ) { if ( provider.isSuitable( configurationType ) ) { return provider.createSpecializedConfiguration( state, configurationType ); } } throw new ValidationException( "Unable to find provider: " + configurationType ); } } //private class, not exposed private static class GenericBootstrapImpl implements GenericBootstrap, BootstrapState { private ValidationProviderResolver resolver; private ValidationProviderResolver defaultResolver; public GenericBootstrap providerResolver(ValidationProviderResolver resolver) { this.resolver = resolver; return this; } public ValidationProviderResolver getValidationProviderResolver() { return resolver; } public ValidationProviderResolver getDefaultValidationProviderResolver() { if (defaultResolver == null) { defaultResolver = new DefaultValidationProviderResolver(); } return defaultResolver; } public Configuration configure() { ValidationProviderResolver resolver = this.resolver == null ? getDefaultValidationProviderResolver() : this.resolver; if ( resolver.getValidationProviders().size() == 0 ) { //FIXME looks like an assertion error almost throw new ValidationException( "Unable to find a default provider" ); } return resolver.getValidationProviders().get( 0 ).createGenericConfiguration( this ); } } /** * Find ValidationProvider according to the default ValidationProviderResolver defined in the * Bean Validation specification. This implementation uses the current classloader or the classloader which has loaded * the current class if the current class loader is unavailable. The classloader is used to retrieve the Service Provider files. *

* This class implements the Service Provider pattern described here. * Since we cannot rely on Java 6 we have to reimplement the Service functionality. *

* * @author Emmanuel Bernard * @author Hardy Ferentschik */ private static class DefaultValidationProviderResolver implements ValidationProviderResolver { //cache per classloader for an appropriate discovery //keep them in a weak hashmap to avoid memory leaks and allow proper hot redeployment //TODO use a WeakConcurrentHashMap private static final Map> providersPerClassloader = new WeakHashMap>(); private static final String SERVICES_FILE = "META-INF/services/" + ValidationProvider.class.getName(); public List getValidationProviders() { ClassLoader classloader = Thread.currentThread().getContextClassLoader(); if ( classloader == null ) { classloader = DefaultValidationProviderResolver.class.getClassLoader(); } List providers; synchronized ( providersPerClassloader ) { providers = providersPerClassloader.get( classloader ); } if ( providers == null ) { providers = new ArrayList(); String name = null; try { Enumeration providerDefinitions = classloader.getResources( SERVICES_FILE ); while ( providerDefinitions.hasMoreElements() ) { URL url = providerDefinitions.nextElement(); InputStream stream = url.openStream(); try { BufferedReader reader = new BufferedReader( new InputStreamReader( stream ), 100 ); name = reader.readLine(); while ( name != null ) { name = name.trim(); if ( !name.startsWith( "#" ) ) { final Class providerClass = loadClass( name, DefaultValidationProviderResolver.class ); providers.add( ( ValidationProvider ) providerClass.newInstance() ); } name = reader.readLine(); } } finally { stream.close(); } } } catch ( IOException e ) { throw new ValidationException( "Unable to read " + SERVICES_FILE, e ); } catch ( ClassNotFoundException e ) { //TODO is it better to not fail the whole loading because of a black sheep? throw new ValidationException( "Unable to load Bean Validation provider " + name, e ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to instanciate Bean Validation provider" + name, e ); } catch ( InstantiationException e ) { throw new ValidationException( "Unable to instanciate Bean Validation provider" + name, e ); } synchronized ( providersPerClassloader ) { providersPerClassloader.put( classloader, providers ); } } return providers; } private static Class loadClass(String name, Class caller) throws ClassNotFoundException { try { //try context classloader, if fails try caller classloader ClassLoader loader = Thread.currentThread().getContextClassLoader(); if ( loader != null ) { return loader.loadClass( name ); } } catch ( ClassNotFoundException e ) { //trying caller classloader if ( caller == null ) { throw e; } } return Class.forName( name, true, caller.getClassLoader() ); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy