You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2012/12/02 22:21:20 UTC

svn commit: r1416265 [1/3] - in /commons/proper/configuration/trunk/src: main/java/org/apache/commons/configuration/builder/combined/ test/java/org/apache/commons/configuration/builder/ test/java/org/apache/commons/configuration/builder/combined/ test/...

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