Author: oheger Date: Sun Dec 2 21:21:16 2012 New Revision: 1416265 URL: http://svn.apache.org/viewvc?rev=1416265&view=rev Log: Initial (yet incomplete) implementation of CombinedConfigurationBuilder (which is intended to replace DefaultConfigurationBuilder).
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java - copied, changed from r1406255, commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationDeclaration.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/FileExtensionConfigurationBuilderProvider.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiWrapDynaBean.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiWrapDynaClass.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/ParametersBeanTestImpl.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/ParametersBeanTestImplBeanInfo.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/TestBuilderParametersBeanInfo.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/ commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestBaseConfigurationBuilderProvider.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedBuilderParameters.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestConfigurationDeclaration.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestFileExtensionConfigurationBuilderProvider.java (with props) commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestMultiWrapDynaBean.java (with props) Modified: commons/proper/configuration/trunk/src/test/resources/testDigesterConfiguration.xml Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java?rev=1416265&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java (added) +++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java Sun Dec 2 21:21:16 2012 @@ -0,0 +1,383 @@ +/* + * 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.commons.configuration.builder.combined; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.ConfigurationUtils; +import org.apache.commons.configuration.beanutils.BeanHelper; +import org.apache.commons.configuration.builder.BasicBuilderParameters; +import org.apache.commons.configuration.builder.BasicConfigurationBuilder; +import org.apache.commons.configuration.builder.BuilderParameters; +import org.apache.commons.configuration.builder.ConfigurationBuilder; + +/** + * <p> + * A fully-functional, reflection-based implementation of the + * {@code ConfigurationBuilderProvider} interface which can deal with the + * default tags defining configuration sources. + * </p> + * <p> + * An instance of this class is initialized with the names of the + * {@code ConfigurationBuilder} class used by this provider and the concrete + * {@code Configuration} class. The {@code ConfigurationBuilder} class must be + * derived from {@link BasicConfigurationBuilder}. When asked for the builder + * object, an instance of the builder class is created and initialized from the + * bean declaration associated with the current configuration source. + * </p> + * <p> + * {@code ConfigurationBuilder} objects are configured using parameter objects. + * When declaring configuration sources in XML it should not be necessary to + * define the single parameter objects. Rather, simple and complex properties + * are set in the typical way of a bean declaration (i.e. as attributes of the + * current XML element or as child elements). This class creates all supported + * parameter objects (whose names also must be provided at construction time) + * and takes care that their properties are initialized according to the current + * bean declaration. + * </p> + * <p> + * The use of reflection to create builder instances allows a generic + * implementation supporting many concrete builder classes. Another reason for + * this approach is that builder classes are only loaded if actually needed. + * Some specialized {@code Configuration} implementations require specific + * external dependencies which should not be mandatory for the use of + * {@code CombinedConfigurationBuilder}. Because such classes are lazily loaded, + * an application only has to include the dependencies it actually uses. + * </p> + * + * @version $Id$ + * @since 2.0 + */ +public class BaseConfigurationBuilderProvider implements + ConfigurationBuilderProvider +{ + /** The types of the constructor parameters for a basic builder. */ + private static final Class<?>[] CTOR_PARAM_TYPES = { + Class.class, Map.class, Boolean.TYPE + }; + + /** The name of the builder class. */ + private final String builderClass; + + /** The name of a builder class with reloading support. */ + private final String reloadingBuilderClass; + + /** Stores the name of the configuration class to be created. */ + private final String configurationClass; + + /** A collection with the names of parameter classes. */ + private final Collection<String> parameterClasses; + + /** + * Creates a new instance of {@code BaseConfigurationBuilderProvider} and + * initializes all its properties. + * + * @param bldrCls the name of the builder class (must not be <b>null</b>) + * @param reloadBldrCls the name of a builder class to be used if reloading + * support is required (<b>null</b> if reloading is not supported) + * @param configCls the name of the configuration class (must not be + * <b>null</b>) + * @param paramCls a collection with the names of parameters classes; an + * instance of {@link BasicBuilderParameters} is created + * automatically and does not need to be contained in this list; the + * collection can be <b>null</b> if no additional parameter objects + * are needed + * @throws IllegalArgumentException if a required parameter is missing + */ + public BaseConfigurationBuilderProvider(String bldrCls, + String reloadBldrCls, String configCls, Collection<String> paramCls) + { + if (bldrCls == null) + { + throw new IllegalArgumentException( + "Builder class must not be null!"); + } + if (configCls == null) + { + throw new IllegalArgumentException( + "Configuration class must not be null!"); + } + + builderClass = bldrCls; + reloadingBuilderClass = reloadBldrCls; + configurationClass = configCls; + parameterClasses = initParameterClasses(paramCls); + } + + /** + * Returns the name of the class of the builder created by this provider. + * + * @return the builder class + */ + public String getBuilderClass() + { + return builderClass; + } + + /** + * Returns the name of the class of the builder created by this provider if + * the reload flag is set. If this method returns <b>null</b>, reloading + * builders are not supported by this provider. + * + * @return the reloading builder class + */ + public String getReloadingBuilderClass() + { + return reloadingBuilderClass; + } + + /** + * Returns the name of the configuration class created by the builder + * produced by this provider. + * + * @return the configuration class + */ + public String getConfigurationClass() + { + return configurationClass; + } + + /** + * Returns an unmodifiable collection with the names of parameter classes + * supported by this provider. + * + * @return the parameter classes + */ + public Collection<String> getParameterClasses() + { + return parameterClasses; + } + + /** + * {@inheritDoc} This implementation delegates to some protected methods to + * create a new builder instance using reflection and to configure it with + * parameter values defined by the passed in {@code BeanDeclaration}. + */ + public ConfigurationBuilder<? extends Configuration> getConfiguration( + ConfigurationDeclaration decl) throws ConfigurationException + { + try + { + Collection<BuilderParameters> params = createParameterObjects(); + initializeParameterObjects(decl, params); + BasicConfigurationBuilder<? extends Configuration> builder = + createBuilder(decl, params); + configureBuilder(builder, decl, params); + return builder; + } + catch (ConfigurationException cex) + { + throw cex; + } + catch (Exception ex) + { + throw new ConfigurationException(ex); + } + } + + /** + * Determines the <em>allowFailOnInit</em> flag for the newly created + * builder based on the given {@code ConfigurationDeclaration}. Some + * combinations of flags in the declaration say that a configuration source + * is optional, but an empty instance should be created if its creation + * fail. + * + * @param decl the current {@code ConfigurationDeclaration} + * @return the value of the <em>allowFailOnInit</em> flag + */ + protected boolean isAllowFailOnInit(ConfigurationDeclaration decl) + { + return decl.isOptional() && decl.isForceCreate(); + } + + /** + * Creates a collection of parameter objects to be used for configuring the + * builder. This method creates instances of the parameter classes passed to + * the constructor. An instance of {@link BasicBuilderParameters} is added + * automatically. + * + * @return a collection with parameter objects for the builder + * @throws Exception if an error occurs while creating parameter objects via + * reflection + */ + protected Collection<BuilderParameters> createParameterObjects() + throws Exception + { + Collection<BuilderParameters> params = + new ArrayList<BuilderParameters>( + getParameterClasses().size() + 1); + params.add(new BasicBuilderParameters()); + for (String paramcls : getParameterClasses()) + { + params.add(createParameterObject(paramcls)); + } + return params; + } + + /** + * Initializes the parameter objects with data stored in the current bean + * declaration. This method is called before the newly created builder + * instance is configured with the parameter objects. It maps attributes of + * the bean declaration to properties of parameter objects. + * + * @param decl the current {@code ConfigurationDeclaration} + * @param params the collection with (uninitialized) parameter objects + * @throws Exception if an error occurs + */ + protected void initializeParameterObjects(ConfigurationDeclaration decl, + Collection<BuilderParameters> params) throws Exception + { + MultiWrapDynaBean wrapBean = new MultiWrapDynaBean(params); + BeanHelper.initBean(wrapBean, decl); + } + + /** + * Creates a new, uninitialized instance of the builder class managed by + * this provider. This implementation determines the builder class to be + * used by delegating to {@code determineBuilderClass()}. It then calls the + * constructor expecting the configuration class, the map with properties, + * and the<em>allowFailOnInit</em> flag. + * + * @param decl the current {@code ConfigurationDeclaration} + * @param params initialization parameters for the new builder object + * @return the newly created builder instance + * @throws Exception if an error occurs + */ + protected BasicConfigurationBuilder<? extends Configuration> createBuilder( + ConfigurationDeclaration decl, Collection<BuilderParameters> params) + throws Exception + { + Class<?> bldCls = + ConfigurationUtils.loadClass(determineBuilderClass(decl)); + Class<?> configCls = + ConfigurationUtils.loadClass(determineConfigurationClass(decl, + params)); + Constructor<?> ctor = bldCls.getConstructor(CTOR_PARAM_TYPES); + // ? extends Configuration is the minimum constraint + @SuppressWarnings("unchecked") + BasicConfigurationBuilder<? extends Configuration> builder = + (BasicConfigurationBuilder<? extends Configuration>) ctor + .newInstance(configCls, null, isAllowFailOnInit(decl)); + return builder; + } + + /** + * Configures a newly created builder instance with its initialization + * parameters. This method is called after a new instance was created using + * reflection. This implementation passes the parameter objects to the + * builder's {@code configure()} method. + * + * @param builder the builder to be initialized + * @param decl the current {@code ConfigurationDeclaration} + * @param params the collection with initialization parameter objects + * @throws Exception if an error occurs + */ + protected void configureBuilder( + BasicConfigurationBuilder<? extends Configuration> builder, + ConfigurationDeclaration decl, Collection<BuilderParameters> params) + throws Exception + { + builder.configure(params.toArray(new BuilderParameters[params.size()])); + } + + /** + * Determines the name of the class to be used for a new builder instance. + * This implementation selects between the normal and the reloading builder + * class, based on the passed in {@code ConfigurationDeclaration}. If a + * reloading builder is desired, but this provider has no reloading support, + * an exception is thrown. + * + * @param decl the current {@code ConfigurationDeclaration} + * @return the name of the builder class + * @throws ConfigurationException if the builder class cannot be determined + */ + protected String determineBuilderClass(ConfigurationDeclaration decl) + throws ConfigurationException + { + if (decl.isReload()) + { + if (getReloadingBuilderClass() == null) + { + throw new ConfigurationException( + "No support for reloading for builder class " + + getBuilderClass()); + } + return getReloadingBuilderClass(); + } + return getBuilderClass(); + } + + /** + * Determines the name of the configuration class produced by the builder. + * This method is called when obtaining the arguments for invoking the + * constructor of the builder class. This implementation just returns the + * pre-configured configuration class name. Derived classes may determine + * this class name dynamically based on the passed in parameters. + * + * @param decl the current {@code ConfigurationDeclaration} + * @param params the collection with parameter objects + * @return the name of the builder's result configuration class + * @throws ConfigurationException if an error occurs + */ + protected String determineConfigurationClass(ConfigurationDeclaration decl, + Collection<BuilderParameters> params) throws ConfigurationException + { + return getConfigurationClass(); + } + + /** + * Creates an instance of a parameter class using reflection. + * + * @param paramcls the parameter class + * @return the newly created instance + * @throws Exception if an error occurs + */ + private static BuilderParameters createParameterObject(String paramcls) + throws Exception + { + Class<?> cls = ConfigurationUtils.loadClass(paramcls); + BuilderParameters p = (BuilderParameters) cls.newInstance(); + return p; + } + + /** + * Creates a new, unmodifiable collection for the parameter classes. + * + * @param paramCls the collection with parameter classes passed to the + * constructor + * @return the collection to be stored + */ + private static Collection<String> initParameterClasses( + Collection<String> paramCls) + { + if (paramCls == null) + { + return Collections.emptySet(); + } + else + { + return Collections.unmodifiableCollection(new ArrayList<String>( + paramCls)); + } + } +} Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/BaseConfigurationBuilderProvider.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java?rev=1416265&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java (added) +++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java Sun Dec 2 21:21:16 2012 @@ -0,0 +1,130 @@ +/* + * 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.commons.configuration.builder.combined; + +import java.util.Collections; +import java.util.Map; + +import org.apache.commons.configuration.HierarchicalConfiguration; +import org.apache.commons.configuration.builder.BasicConfigurationBuilder; +import org.apache.commons.configuration.builder.BuilderParameters; +import org.apache.commons.configuration.builder.ConfigurationBuilder; + +/** + * <p> + * A specialized parameters object for a {@link CombinedConfigurationBuilder}. + * </p> + * <p> + * This class defines methods for setting properties for customizing a builder + * for combined configurations. Note that some of these properties can also be + * set in the configuration definition file. If this is the case, the settings + * in the definition file override the content of this object. + * </p> + * <p> + * This class is not thread-safe. It is intended that an instance is constructed + * and initialized by a single thread during configuration of a + * {@code ConfigurationBuilder}. + * </p> + * + * @version $Id$ + * @since 2.0 + */ +public class CombinedBuilderParameters implements BuilderParameters +{ + /** Constant for the key in the parameters map used by this class. */ + private static final String PARAM_KEY = + BasicConfigurationBuilder.RESERVED_PARAMETER + + CombinedBuilderParameters.class.getName(); + + /** The definition configuration builder. */ + private ConfigurationBuilder<? extends HierarchicalConfiguration> definitionBuilder; + + /** + * Looks up an instance of this class in the specified parameters map. This + * is equivalent to {@code fromParameters(params, false};} + * + * @param params the map with parameters (must not be <b>null</b> + * @return the instance obtained from the map or <b>null</b> + * @throws NullPointerException if the map is <b>null</b> + */ + public static CombinedBuilderParameters fromParameters( + Map<String, Object> params) + { + return fromParameters(params, false); + } + + /** + * Looks up an instance of this class in the specified parameters map and + * optionally creates a new one if none is found. This method can be used to + * obtain an instance of this class which has been stored in a parameters + * map. It is compatible with the {@code getParameters()} method. + * + * @param params the map with parameters (must not be <b>null</b> + * @param createIfMissing determines the behavior if no instance is found in + * the map; if <b>true</b>, a new instance with default settings is + * created; if <b>false</b>, <b>null</b> is returned + * @return the instance obtained from the map or <b>null</b> + * @throws NullPointerException if the map is <b>null</b> + */ + public static CombinedBuilderParameters fromParameters( + Map<String, Object> params, boolean createIfMissing) + { + CombinedBuilderParameters result = + (CombinedBuilderParameters) params.get(PARAM_KEY); + if (result == null && createIfMissing) + { + result = new CombinedBuilderParameters(); + } + return result; + } + + /** + * Returns the {@code ConfigurationBuilder} object for obtaining the + * definition configuration. + * + * @return the definition {@code ConfigurationBuilder} + */ + public ConfigurationBuilder<? extends HierarchicalConfiguration> getDefinitionBuilder() + { + return definitionBuilder; + } + + /** + * Sets the {@code ConfigurationBuilder} for the definition configuration. + * This is the configuration which contains the configuration sources that + * form the combined configuration. + * + * @param builder the definition {@code ConfigurationBuilder} + * @return a reference to this object for method chaining + */ + public CombinedBuilderParameters setDefinitionBuilder( + ConfigurationBuilder<? extends HierarchicalConfiguration> builder) + { + definitionBuilder = builder; + return this; + } + + /** + * {@inheritDoc} This implementation returns a map which contains this + * object itself under a specific key. The static {@code fromParameters()} + * method can be used to extract an instance from a parameters map. + */ + public Map<String, Object> getParameters() + { + return Collections.singletonMap(PARAM_KEY, (Object) this); + } +} Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedBuilderParameters.java ------------------------------------------------------------------------------ svn:mime-type = text/plain