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 [2/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/...
Copied: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java (from r1406255, commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java?p2=commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java&p1=commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java&r1=1406255&r2=1416265&rev=1416265&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java Sun Dec 2 21:21:16 2012
@@ -14,36 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.configuration;
+package org.apache.commons.configuration.builder.combined;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.apache.commons.configuration.AbstractConfiguration;
+import org.apache.commons.configuration.CombinedConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.SubnodeConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.beanutils.BeanDeclaration;
-import org.apache.commons.configuration.beanutils.BeanFactory;
-import org.apache.commons.configuration.beanutils.BeanHelper;
-import org.apache.commons.configuration.beanutils.DefaultBeanFactory;
import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
-import org.apache.commons.configuration.event.ConfigurationErrorListener;
-import org.apache.commons.configuration.event.ConfigurationListener;
-import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
-import org.apache.commons.configuration.resolver.CatalogResolver;
-import org.apache.commons.configuration.resolver.EntityRegistry;
-import org.apache.commons.configuration.resolver.EntityResolverSupport;
-import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.builder.BasicConfigurationBuilder;
+import org.apache.commons.configuration.builder.BuilderListener;
+import org.apache.commons.configuration.builder.ConfigurationBuilder;
+import org.apache.commons.configuration.builder.FileBasedBuilderParameters;
+import org.apache.commons.configuration.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration.tree.DefaultExpressionEngine;
import org.apache.commons.configuration.tree.OverrideCombiner;
import org.apache.commons.configuration.tree.UnionCombiner;
-import org.apache.commons.lang.text.StrLookup;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.xml.sax.EntityResolver;
/**
* <p>
@@ -64,7 +63,7 @@ import org.xml.sax.EntityResolver;
* </p>
* <p>
* It is also possible to add custom tags to the configuration definition file.
- * For this purpose register your own {@code ConfigurationProvider}
+ * For this purpose register your own {@code BaseConfigurationBuilderProvider}
* implementation for your tag using the {@code addConfigurationProvider()}
* method. This provider will then be called when the corresponding custom tag
* is detected. For the default configuration classes providers are already
@@ -109,7 +108,7 @@ import org.xml.sax.EntityResolver;
* </p>
* <p>
* Each configuration declaration consists of a tag whose name is associated
- * with a {@code ConfigurationProvider}. This can be one of the
+ * with a {@code BaseConfigurationBuilderProvider}. This can be one of the
* predefined tags like {@code properties}, or {@code xml}, or
* a custom tag, for which a configuration provider was registered. Attributes
* and sub elements with specific initialization parameters can be added. There
@@ -216,8 +215,7 @@ import org.xml.sax.EntityResolver;
* Configuration team</a>
* @version $Id$
*/
-public class DefaultConfigurationBuilder extends XMLConfiguration implements
- ConfigurationBuilder
+public class CombinedConfigurationBuilder extends BasicConfigurationBuilder<CombinedConfiguration>
{
/**
* Constant for the name of the additional configuration. If the
@@ -225,7 +223,7 @@ public class DefaultConfigurationBuilder
* section, a special union configuration is created and added under this
* name to the resulting combined configuration.
*/
- public static final String ADDITIONAL_NAME = DefaultConfigurationBuilder.class
+ public static final String ADDITIONAL_NAME = CombinedConfigurationBuilder.class
.getName()
+ "/ADDITIONAL_CONFIG";
@@ -236,7 +234,7 @@ public class DefaultConfigurationBuilder
public static final int EVENT_ERR_LOAD_OPTIONAL = 51;
/** Constant for the name of the configuration bean factory. */
- static final String CONFIG_BEAN_FACTORY_NAME = DefaultConfigurationBuilder.class
+ static final String CONFIG_BEAN_FACTORY_NAME = CombinedConfigurationBuilder.class
.getName()
+ ".CONFIG_BEAN_FACTORY_NAME";
@@ -282,6 +280,12 @@ public class DefaultConfigurationBuilder
+ "forceCreate"
+ DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
+ /** Constant for the reload attribute. */
+ static final String ATTR_RELOAD = DefaultExpressionEngine.DEFAULT_ATTRIBUTE_START
+ + XMLBeanDeclaration.RESERVED_PREFIX
+ + "reload"
+ + DefaultExpressionEngine.DEFAULT_ATTRIBUTE_END;
+
/**
* Constant for the tag attribute for providers.
*/
@@ -346,7 +350,7 @@ public class DefaultConfigurationBuilder
static final String KEY_LOOKUP_KEY = XMLBeanDeclaration.ATTR_PREFIX + "prefix]";
/**
- * Constance for the FileSystem.
+ * Constant for the FileSystem.
*/
static final String FILE_SYSTEM = SEC_HEADER + ".fileSystem";
@@ -361,142 +365,156 @@ public class DefaultConfigurationBuilder
static final String KEY_COMBINER = KEY_RESULT + ".nodeCombiner";
/** Constant for the XML file extension. */
- static final String EXT_XML = ".xml";
+ static final String EXT_XML = "xml";
+
+ /** Constant for the file-based configuration builder class. */
+ private static final String FILE_BUILDER =
+ "org.apache.commons.configuration.builder.FileBasedConfigurationBuilder";
+
+ /** Constant for the reloading file-based configuration builder class. */
+ private static final String RELOADING_BUILDER =
+ "org.apache.commons.configuration.builder.ReloadingFileBasedConfigurationBuilder";
+
+ /** Constant for the name of the file-based builder parameters class. */
+ private static final String FILE_PARAMS =
+ "org.apache.commons.configuration.builder.FileBasedBuilderParameters";
/** Constant for the provider for properties files. */
- private static final ConfigurationProvider PROPERTIES_PROVIDER = new FileExtensionConfigurationProvider(
- XMLPropertiesConfiguration.class, PropertiesConfiguration.class,
- EXT_XML);
+ private static final ConfigurationBuilderProvider PROPERTIES_PROVIDER =
+ new FileExtensionConfigurationBuilderProvider(
+ FILE_BUILDER,
+ RELOADING_BUILDER,
+ "org.apache.commons.configuration.XMLPropertiesConfiguration",
+ "org.apache.commons.configuration.PropertiesConfiguration",
+ EXT_XML, Arrays.asList(FILE_PARAMS));
/** Constant for the provider for XML files. */
- private static final ConfigurationProvider XML_PROVIDER = new XMLConfigurationProvider();
+ private static final ConfigurationBuilderProvider XML_PROVIDER =
+ new BaseConfigurationBuilderProvider(FILE_BUILDER, RELOADING_BUILDER,
+ "org.apache.commons.configuration.XMLConfiguration",
+ Arrays.asList(FILE_PARAMS));
/** Constant for the provider for JNDI sources. */
- private static final ConfigurationProvider JNDI_PROVIDER = new ConfigurationProvider(
- JNDIConfiguration.class);
+ private static final BaseConfigurationBuilderProvider JNDI_PROVIDER = null;/*new BaseConfigurationBuilderProvider(
+ JNDIConfiguration.class);*/
/** Constant for the provider for system properties. */
- private static final ConfigurationProvider SYSTEM_PROVIDER = new ConfigurationProvider(
- SystemConfiguration.class);
+ private static final BaseConfigurationBuilderProvider SYSTEM_PROVIDER = null;/*new BaseConfigurationBuilderProvider(
+ SystemConfiguration.class);*/
/** Constant for the provider for ini files. */
- private static final ConfigurationProvider INI_PROVIDER =
- new FileConfigurationProvider(HierarchicalINIConfiguration.class);
+ private static final BaseConfigurationBuilderProvider INI_PROVIDER =
+ new BaseConfigurationBuilderProvider(FILE_BUILDER, RELOADING_BUILDER,
+ "org.apache.commons.configuration.HierarchicalINIConfiguration",
+ Arrays.asList(FILE_PARAMS));
/** Constant for the provider for environment properties. */
- private static final ConfigurationProvider ENV_PROVIDER =
- new ConfigurationProvider(EnvironmentConfiguration.class);
+ private static final BaseConfigurationBuilderProvider ENV_PROVIDER = null;/*
+ new BaseConfigurationBuilderProvider(EnvironmentConfiguration.class);*/
/** Constant for the provider for plist files. */
- private static final ConfigurationProvider PLIST_PROVIDER = new FileExtensionConfigurationProvider(
- "org.apache.commons.configuration.plist.XMLPropertyListConfiguration",
- "org.apache.commons.configuration.plist.PropertyListConfiguration",
- EXT_XML);
+ private static final BaseConfigurationBuilderProvider PLIST_PROVIDER =
+ new FileExtensionConfigurationBuilderProvider(
+ FILE_BUILDER,
+ RELOADING_BUILDER,
+ "org.apache.commons.configuration.plist.XMLPropertyListConfiguration",
+ "org.apache.commons.configuration.plist.PropertyListConfiguration",
+ EXT_XML, Arrays.asList(FILE_PARAMS));
/** Constant for the provider for configuration definition files.*/
- private static final ConfigurationProvider BUILDER_PROVIDER = new ConfigurationBuilderProvider();
+ private static final BaseConfigurationBuilderProvider BUILDER_PROVIDER = null;
/** An array with the names of the default tags. */
private static final String[] DEFAULT_TAGS = {
- "properties", "xml", "hierarchicalXml", "jndi", "system", "plist",
- "configuration", "ini", "env"
+ "properties", "xml", "hierarchicalXml", "plist",
+ "ini"/*, "configuration", "env", "jndi", "system"*/
};
/** An array with the providers for the default tags. */
- private static final ConfigurationProvider[] DEFAULT_PROVIDERS = {
- PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, JNDI_PROVIDER,
- SYSTEM_PROVIDER, PLIST_PROVIDER, BUILDER_PROVIDER, INI_PROVIDER,
- ENV_PROVIDER
+ private static final ConfigurationBuilderProvider[] DEFAULT_PROVIDERS = {
+ PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, PLIST_PROVIDER, INI_PROVIDER/*, JNDI_PROVIDER,
+ SYSTEM_PROVIDER, BUILDER_PROVIDER,
+ ENV_PROVIDER*/
};
/**
- * The serial version UID.
- */
- private static final long serialVersionUID = -3113777854714492123L;
-
- /**
* A specialized {@code StrLookup} object which operates on the combined
* configuration constructed by this builder. This object is used as
* default lookup for {@code ConfigurationInterpolator} objects assigned to
* newly created configuration objects.
*/
- private final StrLookup combinedConfigLookup = new StrLookup()
- {
- @Override
- public String lookup(String key)
- {
- if (constructedConfiguration != null)
- {
- Object value =
- constructedConfiguration.resolveContainerStore(key);
- return (value != null) ? value.toString() : null;
- }
- return null;
- }
- };
+// private final StrLookup combinedConfigLookup = new StrLookup()
+// {
+// @Override
+// public String lookup(String key)
+// {
+// if (constructedConfiguration != null)
+// {
+// Object value =
+// constructedConfiguration.resolveContainerStore(key);
+// return (value != null) ? value.toString() : null;
+// }
+// return null;
+// }
+// };
+//
+ /** Stores a map with the registered configuration builder providers. */
+ private final Map<String, ConfigurationBuilderProvider> providers =
+ new HashMap<String, ConfigurationBuilderProvider>();
- /** Stores the configuration that is currently constructed.*/
- private CombinedConfiguration constructedConfiguration;
+ /** The builder for the definition configuration. */
+ private ConfigurationBuilder<? extends HierarchicalConfiguration> definitionBuilder;
- /** Stores a map with the registered configuration providers. */
- private final Map<String, ConfigurationProvider> providers;
+ /** Stores temporarily the configuration with the builder definitions. */
+ private HierarchicalConfiguration definitionConfiguration;
+
+ /** The object with data about configuration sources. */
+ private ConfigurationSourceData sourceData;
/** Stores the base path to the configuration sources to load. */
private String configurationBasePath;
/**
- * Creates a new instance of {@code DefaultConfigurationBuilder}. A
- * configuration definition file is not yet loaded. Use the diverse setter
- * methods provided by file based configurations to specify the
- * configuration definition file.
+ * Creates a new instance of {@code CombinedConfigurationBuilder}. No parameters
+ * are set.
*/
- public DefaultConfigurationBuilder()
+ public CombinedConfigurationBuilder()
{
- super();
- providers = new HashMap<String, ConfigurationProvider>();
- registerDefaultProviders();
- registerBeanFactory();
- setLogger(LogFactory.getLog(getClass()));
- addErrorLogListener(); // log errors per default
+ super(CombinedConfiguration.class);
+ initialize();
}
/**
- * Creates a new instance of {@code DefaultConfigurationBuilder} and
- * sets the specified configuration definition file.
*
- * @param file the configuration definition file
+ * Creates a new instance of {@code CombinedConfigurationBuilder} and sets
+ * the specified initialization parameters.
+ * @param params a map with initialization parameters
*/
- public DefaultConfigurationBuilder(File file)
+ public CombinedConfigurationBuilder(Map<String, Object> params)
{
- this();
- setFile(file);
+ super(CombinedConfiguration.class, params);
+ initialize();
}
/**
- * Creates a new instance of {@code DefaultConfigurationBuilder} and
- * sets the specified configuration definition file.
*
- * @param fileName the name of the configuration definition file
- * @throws ConfigurationException if an error occurs when the file is loaded
+ * Creates a new instance of {@code CombinedConfigurationBuilder} and sets
+ * the specified initialization parameters and the <em>allowFailOnInit</em> flag.
+ * @param params a map with initialization parameters
+ * @param allowFailOnInit the <em>allowFailOnInit</em> flag
*/
- public DefaultConfigurationBuilder(String fileName)
- throws ConfigurationException
+ public CombinedConfigurationBuilder(Map<String, Object> params, boolean allowFailOnInit)
{
- this();
- setFileName(fileName);
+ super(CombinedConfiguration.class, params, allowFailOnInit);
+ initialize();
}
/**
- * Creates a new instance of {@code DefaultConfigurationBuilder} and
- * sets the specified configuration definition file.
- *
- * @param url the URL to the configuration definition file
- * @throws ConfigurationException if an error occurs when the file is loaded
+ * Initializes this instance.
*/
- public DefaultConfigurationBuilder(URL url) throws ConfigurationException
+ private void initialize()
{
- this();
- setURL(url);
+ registerDefaultProviders();
}
/**
@@ -507,8 +525,7 @@ public class DefaultConfigurationBuilder
*/
public String getConfigurationBasePath()
{
- return (configurationBasePath != null) ? configurationBasePath
- : getBasePath();
+ return configurationBasePath;
}
/**
@@ -528,15 +545,17 @@ public class DefaultConfigurationBuilder
}
/**
- * Adds a configuration provider for the specified tag. Whenever this tag is
- * encountered in the configuration definition file this provider will be
- * called to create the configuration object.
+ * Adds a {@code ConfigurationBuilderProvider} for the specified tag.
+ * Whenever this tag is encountered in the configuration definition file
+ * this provider will be called to create the configuration builder object.
*
* @param tagName the name of the tag in the configuration definition file
- * @param provider the provider for this tag
+ * (must not be <b>null</b>
+ * @param provider the provider for this tag (must not be <b>null</b>
+ * @throws IllegalArgumentException if a required parameter is missing
*/
public void addConfigurationProvider(String tagName,
- ConfigurationProvider provider)
+ ConfigurationBuilderProvider provider)
{
if (tagName == null)
{
@@ -551,43 +570,30 @@ public class DefaultConfigurationBuilder
}
/**
- * Removes the configuration provider for the specified tag name.
+ * Removes the {@code ConfigurationBuilderProvider} for the specified tag name.
*
* @param tagName the tag name
* @return the removed configuration provider or <b>null</b> if none was
* registered for that tag
*/
- public ConfigurationProvider removeConfigurationProvider(String tagName)
+ public ConfigurationBuilderProvider removeConfigurationProvider(String tagName)
{
return providers.remove(tagName);
}
/**
- * Returns the configuration provider for the given tag.
+ * Returns the {@code ConfigurationBuilderProvider} for the given tag.
*
* @param tagName the name of the tag
* @return the provider that was registered for this tag or <b>null</b> if
* there is none
*/
- public ConfigurationProvider providerForTag(String tagName)
+ public ConfigurationBuilderProvider providerForTag(String tagName)
{
return providers.get(tagName);
}
/**
- * Returns the configuration provided by this builder. Loads and parses the
- * configuration definition file and creates instances for the declared
- * configurations.
- *
- * @return the configuration
- * @throws ConfigurationException if an error occurs
- */
- public Configuration getConfiguration() throws ConfigurationException
- {
- return getConfiguration(true);
- }
-
- /**
* Returns the configuration provided by this builder. If the boolean
* parameter is <b>true</b>, the configuration definition file will be
* loaded. It will then be parsed, and instances for the declared
@@ -603,61 +609,192 @@ public class DefaultConfigurationBuilder
public CombinedConfiguration getConfiguration(boolean load)
throws ConfigurationException
{
- if (load)
- {
- load();
- }
-
initFileSystem();
initSystemProperties();
configureEntityResolver();
registerConfiguredProviders();
registerConfiguredLookups();
- CombinedConfiguration result = createResultConfiguration();
- constructedConfiguration = result;
+// CombinedConfiguration result = createResultConfiguration();
+// constructedConfiguration = result;
- List<SubnodeConfiguration> overrides = fetchTopLevelOverrideConfigs();
- overrides.addAll(fetchChildConfigs(KEY_OVERRIDE));
- initCombinedConfiguration(result, overrides, KEY_OVERRIDE_LIST);
+ return null;
+ }
- List<SubnodeConfiguration> additionals = fetchChildConfigs(KEY_UNION);
- if (!additionals.isEmpty())
+ /**
+ * Returns the {@code ConfigurationBuilder} which creates the definition
+ * configuration.
+ *
+ * @return the builder for the definition configuration
+ * @throws ConfigurationException if an error occurs
+ */
+ public synchronized ConfigurationBuilder<? extends HierarchicalConfiguration> getDefinitionBuilder()
+ throws ConfigurationException
+ {
+ if (definitionBuilder == null)
{
- CombinedConfiguration addConfig = createAdditionalsConfiguration(result);
- result.addConfiguration(addConfig, ADDITIONAL_NAME);
- initCombinedConfiguration(addConfig, additionals,
- KEY_ADDITIONAL_LIST);
+ definitionBuilder = setupDefinitionBuilder(getParameters());
+ addDefinitionBuilderChangeListener(definitionBuilder);
}
+ return definitionBuilder;
+ }
- return result;
+ /**
+ * Returns the configuration builder with the given name. With this method
+ * a builder of a child configuration which was given a name in the
+ * configuration definition file can be accessed directly.
+ * @param name the name of the builder in question
+ * @return the child configuration builder with this name
+ * @throws ConfigurationException if an error occurs setting up the definition configuration or no builder with this name exists
+ */
+ public synchronized ConfigurationBuilder<? extends Configuration> getNamedBuilder(String name) throws ConfigurationException
+ {
+ ConfigurationBuilder<? extends Configuration> builder = getSourceData().getNamedBuilder(name);
+ if(builder == null)
+ {
+ throw new ConfigurationException("Builder cannot be resolved: " + name);
+ }
+ return builder;
}
/**
- * Creates the resulting combined configuration. This method is called by
- * {@code getConfiguration()}. It checks whether the
- * {@code header} section of the configuration definition file
- * contains a {@code result} element. If this is the case, it will be
- * used to initialize the properties of the newly created configuration
- * object.
+ * Returns a set with the names of all child configuration builders. A tag
+ * defining a configuration source in the configuration definition file can
+ * have the {@code config-name} attribute. If this attribute is present,
+ * the corresponding builder is assigned this name and can be directly
+ * accessed through the {@link #getNamedBuilder(String)} method. This
+ * method returns a collection with all available builder names.
+ * @return a collection with the names of all builders
+ * @throws ConfigurationException if an error occurs setting up the definition configuration
+ */
+ public synchronized Set<String> builderNames() throws ConfigurationException
+ {
+ return Collections.unmodifiableSet(getSourceData().builderNames());
+ }
+
+ /**
+ * {@inheritDoc} This implementation resets some specific internal state of
+ * this builder.
+ */
+ @Override
+ public synchronized void resetParameters()
+ {
+ super.resetParameters();
+ definitionBuilder = null;
+ definitionConfiguration = null;
+
+ if (sourceData != null)
+ {
+ sourceData.cleanUp();
+ sourceData = null;
+ }
+ }
+
+ /**
+ * Obtains the {@code ConfigurationBuilder} object which provides access to
+ * the configuration containing the definition of the combined configuration
+ * to create. If a definition builder is defined in the parameters, it is
+ * used. Otherwise, a file specification must be available. Then a builder
+ * which opens this file is created. Note: This method is called from a
+ * synchronized block.
+ *
+ * @param params the current parameters for this builder
+ * @return the builder for the definition configuration
+ * @throws ConfigurationException if an error occurs
+ */
+ protected ConfigurationBuilder<? extends HierarchicalConfiguration> setupDefinitionBuilder(
+ Map<String, Object> params) throws ConfigurationException
+ {
+ CombinedBuilderParameters cbParams =
+ CombinedBuilderParameters.fromParameters(params);
+ if (cbParams != null)
+ {
+ ConfigurationBuilder<? extends HierarchicalConfiguration> defBuilder =
+ cbParams.getDefinitionBuilder();
+ if (defBuilder != null)
+ {
+ return defBuilder;
+ }
+ }
+
+ FileBasedBuilderParameters fileParams =
+ FileBasedBuilderParameters.fromParameters(params);
+ if (fileParams != null)
+ {
+ return new FileBasedConfigurationBuilder<XMLConfiguration>(
+ XMLConfiguration.class).configure(fileParams);
+ }
+
+ throw new ConfigurationException(
+ "No builder for configuration definition specified!");
+ }
+
+ /**
+ * Returns the configuration containing the definition of the combined
+ * configuration to be created. This method only returns a defined result
+ * during construction of the result configuration. The definition
+ * configuration is obtained from the definition builder at first access and
+ * then stored temporarily to ensure that during result construction always
+ * the same configuration instance is used. (Otherwise, it would be possible
+ * that the definition builder returns a different instance when queried
+ * multiple times.)
*
- * @return the resulting configuration object
+ * @return the definition configuration
* @throws ConfigurationException if an error occurs
*/
- protected CombinedConfiguration createResultConfiguration()
+ protected HierarchicalConfiguration getDefinitionConfiguration()
throws ConfigurationException
{
- XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_RESULT, true);
- CombinedConfiguration result = (CombinedConfiguration) BeanHelper
- .createBean(decl, CombinedConfiguration.class);
+ if (definitionConfiguration == null)
+ {
+ definitionConfiguration = getDefinitionBuilder().getConfiguration();
+ }
+ return definitionConfiguration;
+ }
- if (getMaxIndex(KEY_COMBINER) < 0)
+ /**
+ * {@inheritDoc} This implementation creates a bean declaration from the
+ * {@code result} property of the definition configuration. This might be
+ * undefined. In this case, an empty declaration with only the result class
+ * name is returned.
+ */
+ @Override
+ protected BeanDeclaration createResultDeclaration(Map<String, Object> params)
+ throws ConfigurationException
+ {
+ return new XMLBeanDeclaration(getDefinitionConfiguration(), KEY_RESULT,
+ true, CombinedConfiguration.class.getName());
+ }
+
+ /**
+ * {@inheritDoc} This implementation processes the definition configuration
+ * in order to
+ * <ul>
+ * <li>initialize the resulting {@code CombinedConfiguration}</li>
+ * <li>determine the builders for all configuration sources</li>
+ * <li>populate the resulting {@code CombinedConfiguration}</li>
+ * </ul>
+ */
+ @Override
+ protected void initResultInstance(CombinedConfiguration result)
+ throws ConfigurationException
+ {
+ HierarchicalConfiguration config = getDefinitionConfiguration();
+ if (config.getMaxIndex(KEY_COMBINER) < 0)
{
// No combiner defined => set default
result.setNodeCombiner(new OverrideCombiner());
}
- return result;
+ ConfigurationSourceData data = getSourceData();
+ createAndAddConfigurations(result, data.getOverrideBuilders(), data);
+
+ if (!data.getUnionBuilders().isEmpty())
+ {
+ CombinedConfiguration addConfig = createAdditionalsConfiguration(result);
+ result.addConfiguration(addConfig, ADDITIONAL_NAME);
+ createAndAddConfigurations(addConfig, data.getUnionBuilders(), data);
+ }
}
/**
@@ -687,45 +824,6 @@ public class DefaultConfigurationBuilder
}
/**
- * Initializes a combined configuration for the configurations of a specific
- * section. This method is called for the override and for the additional
- * section (if it exists).
- *
- * @param config the configuration to be initialized
- * @param containedConfigs the list with the declarations of the contained
- * configurations
- * @param keyListNodes a list with the declaration of list nodes
- * @throws ConfigurationException if an error occurs
- */
- protected void initCombinedConfiguration(CombinedConfiguration config,
- List<? extends BaseHierarchicalConfiguration> containedConfigs,
- String keyListNodes) throws ConfigurationException
- {
- List<Object> listNodes = getList(keyListNodes);
- for (Object listNode : listNodes)
- {
- config.getNodeCombiner().addListNode((String) listNode);
- }
-
- for (HierarchicalConfiguration conf : containedConfigs)
- {
- ConfigurationDeclaration decl = new ConfigurationDeclaration(this,
- conf);
- if (getLogger().isDebugEnabled())
- {
- getLogger().debug("Creating configuration " + decl.getBeanClassName() + " with name "
- + decl.getConfiguration().getString(ATTR_NAME));
- }
- AbstractConfiguration newConf = createConfigurationAt(decl);
- if (newConf != null)
- {
- config.addConfiguration(newConf, decl.getConfiguration()
- .getString(ATTR_NAME), decl.getAt());
- }
- }
- }
-
- /**
* Registers the default configuration providers supported by this class.
* This method will be called during initialization. It registers
* configuration providers for the tags that are supported by default.
@@ -745,14 +843,14 @@ public class DefaultConfigurationBuilder
*/
protected void registerConfiguredProviders() throws ConfigurationException
{
- List<SubnodeConfiguration> nodes = configurationsAt(KEY_CONFIGURATION_PROVIDERS);
- for (SubnodeConfiguration config : nodes)
- {
- XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
- String key = config.getString(KEY_PROVIDER_KEY);
- addConfigurationProvider(key, (ConfigurationProvider) BeanHelper
- .createBean(decl));
- }
+// List<SubnodeConfiguration> nodes = configurationsAt(KEY_CONFIGURATION_PROVIDERS);
+// for (SubnodeConfiguration config : nodes)
+// {
+// XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
+// String key = config.getString(KEY_PROVIDER_KEY);
+// addConfigurationProvider(key, (BaseConfigurationBuilderProvider) BeanHelper
+// .createBean(decl));
+// }
}
/**
@@ -762,26 +860,26 @@ public class DefaultConfigurationBuilder
*/
protected void registerConfiguredLookups() throws ConfigurationException
{
- List<SubnodeConfiguration> nodes = configurationsAt(KEY_CONFIGURATION_LOOKUPS);
- for (SubnodeConfiguration config : nodes)
- {
- XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
- String key = config.getString(KEY_LOOKUP_KEY);
- StrLookup lookup = (StrLookup) BeanHelper.createBean(decl);
- BeanHelper.setProperty(lookup, "configuration", this);
- ConfigurationInterpolator.registerGlobalLookup(key, lookup);
- this.getInterpolator().registerLookup(key, lookup);
- }
+// List<SubnodeConfiguration> nodes = configurationsAt(KEY_CONFIGURATION_LOOKUPS);
+// for (SubnodeConfiguration config : nodes)
+// {
+// XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
+// String key = config.getString(KEY_LOOKUP_KEY);
+// StrLookup lookup = (StrLookup) BeanHelper.createBean(decl);
+// BeanHelper.setProperty(lookup, "configuration", this);
+// ConfigurationInterpolator.registerGlobalLookup(key, lookup);
+// this.getInterpolator().registerLookup(key, lookup);
+// }
}
protected void initFileSystem() throws ConfigurationException
{
- if (getMaxIndex(FILE_SYSTEM) == 0)
- {
- HierarchicalConfiguration config = configurationAt(FILE_SYSTEM);
- XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
- setFileSystem((FileSystem) BeanHelper.createBean(decl));
- }
+// if (getMaxIndex(FILE_SYSTEM) == 0)
+// {
+// HierarchicalConfiguration config = configurationAt(FILE_SYSTEM);
+// XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
+// setFileSystem((FileSystem) BeanHelper.createBean(decl));
+// }
}
/**
@@ -790,32 +888,32 @@ public class DefaultConfigurationBuilder
*/
protected void initSystemProperties() throws ConfigurationException
{
- String fileName = getString(KEY_SYSTEM_PROPS);
- if (fileName != null)
- {
- try
- {
- SystemConfiguration.setSystemProperties(getConfigurationBasePath(), fileName);
- }
- catch (Exception ex)
- {
- throw new ConfigurationException("Error setting system properties from " + fileName, ex);
- }
-
- }
+// String fileName = getString(KEY_SYSTEM_PROPS);
+// if (fileName != null)
+// {
+// try
+// {
+// SystemConfiguration.setSystemProperties(getConfigurationBasePath(), fileName);
+// }
+// catch (Exception ex)
+// {
+// throw new ConfigurationException("Error setting system properties from " + fileName, ex);
+// }
+//
+// }
}
protected void configureEntityResolver() throws ConfigurationException
{
- if (getMaxIndex(KEY_ENTITY_RESOLVER) == 0)
- {
- XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_ENTITY_RESOLVER, true);
- EntityResolver resolver = (EntityResolver) BeanHelper.createBean(decl, CatalogResolver.class);
- BeanHelper.setProperty(resolver, "fileSystem", getFileSystem());
- BeanHelper.setProperty(resolver, "baseDir", getBasePath());
- BeanHelper.setProperty(resolver, "substitutor", getSubstitutor());
- setEntityResolver(resolver);
- }
+// if (getMaxIndex(KEY_ENTITY_RESOLVER) == 0)
+// {
+// XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_ENTITY_RESOLVER, true);
+// EntityResolver resolver = (EntityResolver) BeanHelper.createBean(decl, CatalogResolver.class);
+// BeanHelper.setProperty(resolver, "fileSystem", getFileSystem());
+// BeanHelper.setProperty(resolver, "baseDir", getBasePath());
+// BeanHelper.setProperty(resolver, "substitutor", getSubstitutor());
+// setEntityResolver(resolver);
+// }
}
/**
@@ -828,970 +926,336 @@ public class DefaultConfigurationBuilder
* @param value the value to be interpolated
* @return the interpolated value
*/
- @Override
- protected Object interpolate(Object value)
- {
- Object result = super.interpolate(value);
- if (constructedConfiguration != null)
- {
- result = constructedConfiguration.interpolate(result);
- }
- return result;
- }
-
- /**
- * Creates a configuration object from the specified configuration
- * declaration.
+// @Override
+// protected Object interpolate(Object value)
+// {
+// Object result = super.interpolate(value);
+// if (constructedConfiguration != null)
+// {
+// result = constructedConfiguration.interpolate(result);
+// }
+// return result;
+// }
+
+ /**
+ * Obtains the data object for the configuration sources and the
+ * corresponding builders. This object is created on first access and reset
+ * when the definition builder sends a change event. This method is called
+ * in a synchronized block.
*
- * @param decl the configuration declaration
- * @return the new configuration object
+ * @return the object with information about configuration sources
* @throws ConfigurationException if an error occurs
*/
- private AbstractConfiguration createConfigurationAt(
- ConfigurationDeclaration decl) throws ConfigurationException
+ private ConfigurationSourceData getSourceData()
+ throws ConfigurationException
{
- try
- {
- return (AbstractConfiguration) BeanHelper.createBean(decl);
- }
- catch (Exception ex)
+ if (sourceData == null)
{
- // redirect to configuration exceptions
- throw new ConfigurationException(ex);
+ sourceData = createSourceData();
}
+ return sourceData;
}
/**
- * Returns a list with {@code SubnodeConfiguration} objects for the
- * child nodes of the specified configuration node.
+ * Creates the data object for configuration sources and the corresponding
+ * builders.
*
- * @param node the start node
- * @return a list with subnode configurations for the node's children
+ * @return the newly created data object
+ * @throws ConfigurationException if an error occurs
*/
- private List<SubnodeConfiguration> fetchChildConfigs(ConfigurationNode node)
+ private ConfigurationSourceData createSourceData()
+ throws ConfigurationException
{
- List<ConfigurationNode> children = node.getChildren();
- List<SubnodeConfiguration> result = new ArrayList<SubnodeConfiguration>(children.size());
- for (ConfigurationNode child : children)
- {
- result.add(createSubnodeConfiguration(child));
- }
+ ConfigurationSourceData result = new ConfigurationSourceData();
+ result.initFromDefinitionConfiguration(getDefinitionConfiguration());
return result;
}
/**
- * Returns a list with {@code SubnodeConfiguration} objects for the
- * child nodes of the node specified by the given key.
- *
- * @param key the key (must define exactly one node)
- * @return a list with subnode configurations for the node's children
- */
- private List<SubnodeConfiguration> fetchChildConfigs(String key)
- {
- List<ConfigurationNode> nodes = fetchNodeList(key);
- if (nodes.size() > 0)
- {
- return fetchChildConfigs(nodes.get(0));
- }
- else
- {
- return Collections.emptyList();
- }
- }
-
- /**
- * Finds the override configurations that are defined as top level elements
- * in the configuration definition file. This method will fetch the child
- * elements of the root node and remove the nodes that represent other
- * configuration sections. The remaining nodes are treated as definitions
- * for override configurations.
+ * Adds a listener at the given definition builder which resets this builder
+ * when a reset of the definition builder happens. This way it is ensured
+ * that this builder produces a new combined configuration when its
+ * definition configuration changes.
*
- * @return a list with subnode configurations for the top level override
- * configurations
+ * @param defBuilder the definition builder
*/
- private List<SubnodeConfiguration> fetchTopLevelOverrideConfigs()
+ private void addDefinitionBuilderChangeListener(
+ final ConfigurationBuilder<? extends HierarchicalConfiguration> defBuilder)
{
- List<SubnodeConfiguration> configs = fetchChildConfigs(getRootNode());
- for (Iterator<SubnodeConfiguration> it = configs.iterator(); it.hasNext();)
+ defBuilder.addBuilderListener(new BuilderListener()
{
- String nodeName = it.next().getRootNode().getName();
- for (int i = 0; i < CONFIG_SECTIONS.length; i++)
+ public void builderReset(
+ ConfigurationBuilder<? extends Configuration> builder)
{
- if (CONFIG_SECTIONS[i].equals(nodeName))
+ synchronized (CombinedConfigurationBuilder.this)
{
- it.remove();
- break;
+ reset();
+ definitionBuilder = defBuilder;
}
}
- }
- return configs;
+ });
}
/**
- * Registers the bean factory used by this class if necessary. This method
- * is called by the constructor to ensure that the required bean factory is
- * available.
+ * Queries the current {@code Configuration} objects from the given builders
+ * and adds them to the specified combined configuration.
+ *
+ * @param cc the resulting combined configuration
+ * @param builders the collection with configuration builders
+ * @param srcData the data object for configuration sources
+ * @throws ConfigurationException if an error occurs
*/
- private void registerBeanFactory()
+ private static void createAndAddConfigurations(CombinedConfiguration cc,
+ Collection<ConfigurationBuilder<? extends Configuration>> builders,
+ ConfigurationSourceData srcData) throws ConfigurationException
{
- synchronized (DefaultConfigurationBuilder.class)
+ for (ConfigurationBuilder<? extends Configuration> builder : builders)
{
- if (!BeanHelper.registeredFactoryNames().contains(
- CONFIG_BEAN_FACTORY_NAME))
+ ConfigurationDeclaration decl = srcData.getDeclaration(builder);
+ assert decl != null : "Cannot resolve builder!";
+ try
{
- BeanHelper.registerBeanFactory(CONFIG_BEAN_FACTORY_NAME,
- new ConfigurationBeanFactory());
+ cc.addConfiguration(
+ (AbstractConfiguration) builder.getConfiguration(),
+ decl.getName(), decl.getAt());
+ }
+ catch (ConfigurationException cex)
+ {
+ // ignore exceptions for optional configurations
+ if (!decl.isOptional())
+ {
+ throw cex;
+ }
}
}
}
/**
- * <p>
- * A base class for creating and initializing configuration sources.
- * </p>
- * <p>
- * Concrete sub classes of this base class are responsible for creating
- * specific {@code Configuration} objects for the tags in the
- * configuration definition file. The configuration factory will parse the
- * definition file and try to find a matching
- * {@code ConfigurationProvider} for each encountered tag. This
- * provider is then asked to create a corresponding
- * {@code Configuration} object. It is up to a concrete
- * implementation how this object is created and initialized.
- * </p>
- * <p>
- * Note that at the moment only configuration classes derived from
- * {@link AbstractConfiguration} are supported.
- * </p>
+ * A data class for storing information about all configuration sources
+ * defined for a combined builder.
*/
- public static class ConfigurationProvider extends DefaultBeanFactory
+ private class ConfigurationSourceData
{
- /** Stores the class of the configuration to be created. */
- private Class<?> configurationClass;
+ /** A list with all builders for override configurations. */
+ private final Collection<ConfigurationBuilder<? extends Configuration>> overrideBuilders;
- /** Stores the name of the configuration class to be created.*/
- private String configurationClassName;
+ /** A list with all builders for union configurations. */
+ private final Collection<ConfigurationBuilder<? extends Configuration>> unionBuilders;
- /**
- * Creates a new uninitialized instance of {@code ConfigurationProvider}.
- */
- public ConfigurationProvider()
- {
- this((Class<?>) null);
- }
+ /** A list with all sub builders (override plus union). */
+ private final Collection<ConfigurationBuilder<? extends Configuration>> allBuilders;
- /**
- * Creates a new instance of {@code ConfigurationProvider} and
- * sets the class of the configuration created by this provider.
- *
- * @param configClass the configuration class
- */
- public ConfigurationProvider(Class<?> configClass)
- {
- setConfigurationClass(configClass);
- }
+ /** A map for direct access to a builder by its name. */
+ private final Map<String, ConfigurationBuilder<? extends Configuration>> namedBuilders;
/**
- * Creates a new instance of {@code ConfigurationProvider} and
- * sets the name of the class of the configuration created by this
- * provider.
- *
- * @param configClassName the name of the configuration class
- * @since 1.4
+ * A map for retrieving the bean declarations associated with
+ * configuration builders.
*/
- public ConfigurationProvider(String configClassName)
- {
- setConfigurationClassName(configClassName);
- }
+ private final Map<ConfigurationBuilder<? extends Configuration>, ConfigurationDeclaration> declarations;
- /**
- * Returns the class of the configuration returned by this provider.
- *
- * @return the class of the provided configuration
- */
- public Class<?> getConfigurationClass()
- {
- return configurationClass;
- }
+ /** A listener for reacting on changes of sub builders. */
+ private BuilderListener changeListener;
/**
- * Sets the class of the configuration returned by this provider.
- *
- * @param configurationClass the configuration class
+ * Creates a new instance of {@code ConfigurationSourceData}.
*/
- public void setConfigurationClass(Class<?> configurationClass)
+ public ConfigurationSourceData()
{
- this.configurationClass = configurationClass;
+ overrideBuilders =
+ new LinkedList<ConfigurationBuilder<? extends Configuration>>();
+ unionBuilders =
+ new LinkedList<ConfigurationBuilder<? extends Configuration>>();
+ allBuilders =
+ new LinkedList<ConfigurationBuilder<? extends Configuration>>();
+ namedBuilders =
+ new HashMap<String, ConfigurationBuilder<? extends Configuration>>();
+ declarations =
+ new HashMap<ConfigurationBuilder<? extends Configuration>, ConfigurationDeclaration>();
}
/**
- * Returns the name of the configuration class returned by this
- * provider.
+ * Initializes this object from the specified definition configuration.
*
- * @return the configuration class name
- * @since 1.4
+ * @param config the definition configuration
+ * @throws ConfigurationException if an error occurs
*/
- public String getConfigurationClassName()
+ public void initFromDefinitionConfiguration(
+ HierarchicalConfiguration config) throws ConfigurationException
{
- return configurationClassName;
- }
+ createBuilders(overrideBuilders,
+ fetchTopLevelOverrideConfigs(config));
+ createBuilders(overrideBuilders,
+ config.childConfigurationsAt(KEY_OVERRIDE));
+ createBuilders(unionBuilders,
+ config.childConfigurationsAt(KEY_UNION));
- /**
- * Sets the name of the configuration class returned by this provider.
- *
- * @param configurationClassName the name of the configuration class
- * @since 1.4
- */
- public void setConfigurationClassName(String configurationClassName)
- {
- this.configurationClassName = configurationClassName;
+ allBuilders.addAll(overrideBuilders);
+ allBuilders.addAll(unionBuilders);
+ registerChangeListener();
}
/**
- * Returns the configuration. This method is called to fetch the
- * configuration from the provider. This implementation will call the
- * inherited {@link
- * org.apache.commons.configuration.beanutils.DefaultBeanFactory#createBean(Class, BeanDeclaration, Object)
- * createBean()} method to create a new instance of the
- * configuration class.
- *
- * @param decl the bean declaration with initialization parameters for
- * the configuration
- * @return the new configuration object
- * @throws Exception if an error occurs
+ * Frees resources used by this object and performs clean up. This
+ * method is called when the owning builder is reset.
*/
- public AbstractConfiguration getConfiguration(
- ConfigurationDeclaration decl) throws Exception
+ public void cleanUp()
{
- return (AbstractConfiguration) createBean(fetchConfigurationClass(),
- decl, null);
- }
-
- /**
- * Returns an uninitialized configuration of the represented type. This
- * method will be called for optional configurations when the
- * {@code getConfiguration()} method caused an error and the
- * {@code forceCreate} attribute is set. A concrete sub class can
- * here try to create an uninitialized, empty configuration, which may
- * be possible if the error was created during initialization. This base
- * implementation just returns <b>null</b>.
- *
- * @param decl the bean declaration with initialization parameters for
- * the configuration
- * @return the new configuration object
- * @throws Exception if an error occurs
- * @since 1.4
- */
- public AbstractConfiguration getEmptyConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- return null;
- }
-
- /**
- * Returns the configuration class supported by this provider. If a
- * class object was set, it is returned. Otherwise the method tries to
- * resolve the class name.
- *
- * @return the class of the configuration to be created
- * @since 1.4
- */
- protected synchronized Class<?> fetchConfigurationClass() throws Exception
- {
- if (getConfigurationClass() == null)
+ for (ConfigurationBuilder<?> b : allBuilders)
{
- setConfigurationClass(loadClass(getConfigurationClassName()));
+ b.removeBuilderListener(changeListener);
}
- return getConfigurationClass();
}
/**
- * Loads the class with the specified name dynamically. If the class's
- * name is <b>null</b>, <b>null</b> will also be returned.
+ * Returns a collection with all configuration builders defined in the
+ * override section.
*
- * @param className the name of the class to be loaded
- * @return the class object
- * @throws ClassNotFoundException if class loading fails
- * @since 1.4
+ * @return the override configuration builders
*/
- protected Class<?> loadClass(String className)
- throws ClassNotFoundException
+ public Collection<ConfigurationBuilder<? extends Configuration>> getOverrideBuilders()
{
- return (className != null) ? Class.forName(className, true,
- getClass().getClassLoader()) : null;
+ return overrideBuilders;
}
- }
-
- /**
- * <p>
- * A specialized {@code BeanDeclaration} implementation that
- * represents the declaration of a configuration source.
- * </p>
- * <p>
- * Instances of this class are able to extract all information about a
- * configuration source from the configuration definition file. The
- * declaration of a configuration source is very similar to a bean
- * declaration processed by {@code XMLBeanDeclaration}. There are
- * very few differences, e.g. some reserved attributes like
- * {@code optional} and {@code at} and the fact that a bean
- * factory is never needed.
- * </p>
- */
- public static class ConfigurationDeclaration extends XMLBeanDeclaration
- {
- /** Stores a reference to the associated configuration builder. */
- private DefaultConfigurationBuilder configurationBuilder;
/**
- * Creates a new instance of {@code ConfigurationDeclaration} and
- * initializes it.
+ * Returns a collection with all configuration builders defined in the
+ * union section.
*
- * @param builder the associated configuration builder
- * @param config the configuration this declaration is based onto
+ * @return the union configuration builders
*/
- public ConfigurationDeclaration(DefaultConfigurationBuilder builder,
- HierarchicalConfiguration config)
+ public Collection<ConfigurationBuilder<? extends Configuration>> getUnionBuilders()
{
- super(config);
- configurationBuilder = builder;
+ return unionBuilders;
}
/**
- * Returns the associated configuration builder.
- *
- * @return the configuration builder
- */
- public DefaultConfigurationBuilder getConfigurationBuilder()
- {
- return configurationBuilder;
- }
-
- /**
- * Returns the value of the {@code at} attribute.
- *
- * @return the value of the {@code at} attribute (can be <b>null</b>)
- */
- public String getAt()
- {
- String result = this.getConfiguration().getString(ATTR_AT_RES);
- return (result == null) ? this.getConfiguration().getString(ATTR_AT)
- : result;
- }
-
- /**
- * Returns a flag whether this is an optional configuration.
+ * Returns the {@code ConfigurationBuilder} with the given name. If no
+ * such builder is defined in the definition configuration, result is
+ * <b>null</b>.
*
- * @return a flag if this declaration points to an optional
- * configuration
+ * @param name the name of the builder in question
+ * @return the builder with this name or <b>null</b>
*/
- public boolean isOptional()
+ public ConfigurationBuilder<? extends Configuration> getNamedBuilder(
+ String name)
{
- Boolean value = this.getConfiguration().getBoolean(ATTR_OPTIONAL_RES,
- null);
- if (value == null)
- {
- value = this.getConfiguration().getBoolean(ATTR_OPTIONAL,
- Boolean.FALSE);
- }
- return value.booleanValue();
+ return namedBuilders.get(name);
}
/**
- * Returns a flag whether this configuration should always be created
- * and added to the resulting combined configuration. This flag is
- * evaluated only for optional configurations whose normal creation has
- * caused an error. If for such a configuration the
- * {@code forceCreate} attribute is set and the corresponding
- * configuration provider supports this mode, an empty configuration
- * will be created and added to the resulting combined configuration.
+ * Returns a set with the names of all known named builders.
*
- * @return the value of the {@code forceCreate} attribute
- * @since 1.4
+ * @return the names of the available sub builders
*/
- public boolean isForceCreate()
+ public Set<String> builderNames()
{
- return this.getConfiguration().getBoolean(ATTR_FORCECREATE, false);
+ return namedBuilders.keySet();
}
/**
- * Returns the name of the bean factory. For configuration source
- * declarations always a reserved factory is used. This factory's name
- * is returned by this implementation.
+ * Returns the {@code ConfigurationDeclaration} associated with the
+ * specified builder. If the builder is unknown, result is <b>null</b>.
*
- * @return the name of the bean factory
+ * @param builder the builder in question
+ * @return the {@code ConfigurationDeclaration} for this builder or
+ * <b>null</b>
*/
- @Override
- public String getBeanFactoryName()
+ public ConfigurationDeclaration getDeclaration(
+ ConfigurationBuilder<?> builder)
{
- return CONFIG_BEAN_FACTORY_NAME;
+ return declarations.get(builder);
}
/**
- * Returns the bean's class name. This implementation will always return
- * <b>null</b>.
- *
- * @return the name of the bean's class
+ * Registers a change listener at all sub builders. Whenever one of the
+ * sub builders is reset, the combined configuration managed by this
+ * builder has to be reset, too.
*/
- @Override
- public String getBeanClassName()
+ private void registerChangeListener()
{
- return null;
- }
+ changeListener = new BuilderListener()
+ {
+ public void builderReset(
+ ConfigurationBuilder<? extends Configuration> builder)
+ {
+ resetResult();
+ }
+ };
- /**
- * Checks whether the given node is reserved. This method will take
- * further reserved attributes into account
- *
- * @param nd the node
- * @return a flag whether this node is reserved
- */
- @Override
- protected boolean isReservedNode(ConfigurationNode nd)
- {
- if (super.isReservedNode(nd))
+ for (ConfigurationBuilder<?> b : allBuilders)
{
- return true;
+ b.addBuilderListener(changeListener);
}
-
- return nd.isAttribute()
- && ((ATTR_ATNAME.equals(nd.getName()) && nd.getParentNode()
- .getAttributeCount(RESERVED_PREFIX + ATTR_ATNAME) == 0) || (ATTR_OPTIONALNAME
- .equals(nd.getName()) && nd.getParentNode()
- .getAttributeCount(RESERVED_PREFIX + ATTR_OPTIONALNAME) == 0));
}
/**
- * Performs interpolation. This implementation will delegate
- * interpolation to the configuration builder, which takes care that the
- * currently constructed configuration is taken into account, too.
+ * Finds the override configurations that are defined as top level
+ * elements in the configuration definition file. This method fetches
+ * the child elements of the root node and removes the nodes that
+ * represent other configuration sections. The remaining nodes are
+ * treated as definitions for override configurations.
*
- * @param value the value to be interpolated
- * @return the interpolated value
+ * @param config the definition configuration
+ * @return a list with sub configurations for the top level override
+ * configurations
*/
- @Override
- protected Object interpolate(Object value)
- {
- return getConfigurationBuilder().interpolate(value);
- }
- }
-
- /**
- * A specialized {@code BeanFactory} implementation that handles
- * configuration declarations. This class will retrieve the correct
- * configuration provider and delegate the task of creating the
- * configuration to this object.
- */
- static class ConfigurationBeanFactory implements BeanFactory
- {
- /** The logger. */
- private Log logger = LogFactory.getLog(DefaultConfigurationBuilder.class);
-
- /**
- * Creates an instance of a bean class. This implementation expects that
- * the passed in bean declaration is a declaration for a configuration.
- * It will determine the responsible configuration provider and delegate
- * the call to this instance. If creation of the configuration fails
- * and the {@code optional} attribute is set, the exception will
- * be ignored. If the {@code forceCreate} attribute is set, too,
- * the provider is asked to create an empty configuration. A return
- * value of <b>null</b> means that no configuration could be created.
- *
- * @param beanClass the bean class (will be ignored)
- * @param data the declaration
- * @param param an additional parameter (will be ignored)
- * @return the newly created configuration
- * @throws Exception if an error occurs
- */
- public Object createBean(Class<?> beanClass, BeanDeclaration data,
- Object param) throws Exception
+ private List<SubnodeConfiguration> fetchTopLevelOverrideConfigs(
+ HierarchicalConfiguration config)
{
- ConfigurationDeclaration decl = (ConfigurationDeclaration) data;
- String tagName = decl.getNode().getName();
- ConfigurationProvider provider = decl.getConfigurationBuilder()
- .providerForTag(tagName);
- if (provider == null)
+ List<SubnodeConfiguration> configs =
+ config.childConfigurationsAt(null);
+ for (Iterator<SubnodeConfiguration> it = configs.iterator(); it
+ .hasNext();)
{
- throw new ConfigurationRuntimeException(
- "No ConfigurationProvider registered for tag "
- + tagName);
- }
-
- try
- {
- AbstractConfiguration config = provider.getConfiguration(decl);
- installInterpolator(decl, config);
- return config;
- }
- catch (Exception ex)
- {
- // If this is an optional configuration, ignore the exception
- if (!decl.isOptional())
- {
- throw ex;
- }
- else
+ String nodeName = it.next().getRootElementName();
+ for (int i = 0; i < CONFIG_SECTIONS.length; i++)
{
- if (logger.isDebugEnabled())
- {
- logger.debug("Load failed for optional configuration " + tagName + ": "
- + ex.getMessage());
- }
- // Notify registered error listeners
- decl.getConfigurationBuilder().fireError(
- EVENT_ERR_LOAD_OPTIONAL,
- decl.getConfiguration().getString(ATTR_NAME), null,
- ex);
-
- if (decl.isForceCreate())
+ if (CONFIG_SECTIONS[i].equals(nodeName))
{
- try
- {
- return provider.getEmptyConfiguration(decl);
- }
- catch (Exception ex2)
- {
- // Ignore exception, return null in this case
- logger.warn("Could not create instance of optional configuration "
- + tagName, ex2);
- }
+ it.remove();
+ break;
}
- return null;
}
}
+ return configs;
}
/**
- * Returns the default class for this bean factory.
- *
- * @return the default class
- */
- public Class<?> getDefaultBeanClass()
- {
- // Here some valid class must be returned, otherwise BeanHelper
- // will complain that the bean's class cannot be determined
- return Configuration.class;
- }
-
- /**
- * Installs a specialized {@code ConfigurationInterpolator} on a newly
- * created configuration which also takes the combined configuration
- * created by the builder into account. With this
- * {@code ConfigurationInterpolator} the interpolation facilities of
- * this child configuration are extended to include all other
- * configurations created by this builder.
- *
- * @param decl the {@code ConfigurationDeclaration}
- * @param config the newly created configuration instance
- */
- private void installInterpolator(ConfigurationDeclaration decl,
- AbstractConfiguration config)
- {
- ConfigurationInterpolator parent = new ConfigurationInterpolator();
- parent.setDefaultLookup(decl.getConfigurationBuilder().combinedConfigLookup);
- config.getInterpolator().setParentInterpolator(parent);
- }
- }
-
- /**
- * A specialized provider implementation that deals with file based
- * configurations. Ensures that the base path is correctly set and that the
- * load() method gets called.
- */
- public static class FileConfigurationProvider extends ConfigurationProvider
- {
- /**
- * Creates a new instance of {@code FileConfigurationProvider}.
- */
- public FileConfigurationProvider()
- {
- super();
- }
-
- /**
- * Creates a new instance of {@code FileConfigurationProvider}
- * and sets the configuration class.
+ * Creates configuration builder objects from the given configurations
+ * for configuration sources.
*
- * @param configClass the class for the configurations to be created
+ * @param builders the collection with builders to be filled
+ * @param sources the definitions for the single configuration sources
+ * @throws ConfigurationException if an error occurs
*/
- public FileConfigurationProvider(Class<?> configClass)
+ private void createBuilders(
+ Collection<ConfigurationBuilder<? extends Configuration>> builders,
+ Collection<? extends HierarchicalConfiguration> sources)
+ throws ConfigurationException
{
- super(configClass);
- }
-
- /**
- * Creates a new instance of {@code FileConfigurationProvider}
- * and sets the configuration class name.
- *
- * @param configClassName the name of the configuration to be created
- * @since 1.4
- */
- public FileConfigurationProvider(String configClassName)
- {
- super(configClassName);
- }
-
- /**
- * Creates the configuration. After that {@code load()} will be
- * called. If this configuration is marked as optional, exceptions will
- * be ignored.
- *
- * @param decl the declaration
- * @return the new configuration
- * @throws Exception if an error occurs
- */
- @Override
- public AbstractConfiguration getConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- AbstractConfiguration result = getEmptyConfiguration(decl);
- if (result instanceof FileSystemBased)
+ for (HierarchicalConfiguration src : sources)
{
- DefaultConfigurationBuilder builder = decl.getConfigurationBuilder();
- if (builder.getFileSystem() != null)
+ ConfigurationBuilderProvider provider =
+ providerForTag(src.getRootElementName());
+ if (provider == null)
{
- ((FileSystemBased) result).setFileSystem(builder.getFileSystem());
+ throw new ConfigurationException(
+ "Unsupported configuration source: "
+ + src.getRootElementName());
}
- }
- ((FileConfiguration) result).load();
- return result;
- }
-
- /**
- * Returns an uninitialized file configuration. This method will be
- * called for optional configurations when the
- * {@code getConfiguration()} method caused an error and the
- * {@code forceCreate} attribute is set. It will create the
- * configuration of the represented type, but the {@code load()}
- * method won't be called. This way non-existing configuration files can
- * be handled gracefully: If loading a the file fails, an empty
- * configuration will be created that is already configured with the
- * correct file name.
- *
- * @param decl the bean declaration with initialization parameters for
- * the configuration
- * @return the new configuration object
- * @throws Exception if an error occurs
- * @since 1.4
- */
- @Override
- public AbstractConfiguration getEmptyConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- AbstractConfiguration config = super.getConfiguration(decl);
-
- /**
- * Some wrapper classes may need to pass the EntityResolver to XMLConfigurations
- * they construct buy may not be an XMLConfiguration.
- */
- if (config instanceof EntityResolverSupport)
- {
- DefaultConfigurationBuilder builder = decl.getConfigurationBuilder();
- EntityResolver resolver = builder.getEntityResolver();
- ((EntityResolverSupport) config).setEntityResolver(resolver);
- }
-
- return config;
- }
-
- /**
- * Initializes the bean instance. Ensures that the file configuration's
- * base path will be initialized with the base path of the factory so
- * that relative path names can be correctly resolved.
- *
- * @param bean the bean to be initialized
- * @param data the declaration
- * @throws Exception if an error occurs
- */
- @Override
- protected void initBeanInstance(Object bean, BeanDeclaration data)
- throws Exception
- {
- FileConfiguration config = (FileConfiguration) bean;
- config.setBasePath(((ConfigurationDeclaration) data)
- .getConfigurationBuilder().getConfigurationBasePath());
- super.initBeanInstance(bean, data);
- }
- }
-
- /**
- * A specialized configuration provider for XML configurations. This
- * implementation acts like a {@code FileConfigurationProvider}, but
- * it will copy all entity IDs that have been registered for the
- * configuration builder to the new XML configuration before it is loaded.
- *
- * @since 1.6
- */
- public static class XMLConfigurationProvider extends FileConfigurationProvider
- {
- /**
- * Creates a new instance of {@code XMLConfigurationProvider}.
- */
- public XMLConfigurationProvider()
- {
- super(XMLConfiguration.class);
- }
-
- /**
- * Returns a new empty configuration instance. This implementation
- * performs some additional initialization specific to XML
- * configurations.
- *
- * @param decl the configuration declaration
- * @return the new configuration
- * @throws Exception if an error occurs
- */
- @Override
- public AbstractConfiguration getEmptyConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- XMLConfiguration config = (XMLConfiguration) super
- .getEmptyConfiguration(decl);
-
- DefaultConfigurationBuilder builder = decl
- .getConfigurationBuilder();
- EntityResolver resolver = builder.getEntityResolver();
- if (resolver instanceof EntityRegistry)
- {
- // copy the registered entities
- config.getRegisteredEntities().putAll(
- builder.getRegisteredEntities());
- }
- else
- {
- config.setEntityResolver(resolver);
- }
- return config;
- }
- }
-
- /**
- * A specialized configuration provider for file based configurations that
- * can handle configuration sources whose concrete type depends on the
- * extension of the file to be loaded. One example is the
- * {@code properties} tag: if the file ends with ".xml" a
- * XMLPropertiesConfiguration object must be created, otherwise a
- * PropertiesConfiguration object.
- */
- static class FileExtensionConfigurationProvider extends
- FileConfigurationProvider
- {
- /**
- * Stores the class to be created when the file extension matches.
- */
- private Class<?> matchingClass;
-
- /**
- * Stores the name of the class to be created when the file extension
- * matches.
- */
- private String matchingClassName;
-
- /**
- * Stores the class to be created when the file extension does not
- * match.
- */
- private Class<?> defaultClass;
-
- /**
- * Stores the name of the class to be created when the file extension
- * does not match.
- */
- private String defaultClassName;
-
- /** Stores the file extension to be checked against. */
- private String fileExtension;
-
- /**
- * Creates a new instance of
- * {@code FileExtensionConfigurationProvider} and initializes it.
- *
- * @param matchingClass the class to be created when the file extension
- * matches
- * @param defaultClass the class to be created when the file extension
- * does not match
- * @param extension the file extension to be checked against
- */
- public FileExtensionConfigurationProvider(Class<?> matchingClass,
- Class<?> defaultClass, String extension)
- {
- this.matchingClass = matchingClass;
- this.defaultClass = defaultClass;
- fileExtension = extension;
- }
-
- /**
- * Creates a new instance of
- * {@code FileExtensionConfigurationProvider} and initializes it
- * with the names of the classes to be created.
- *
- * @param matchingClassName the name of the class to be created when the
- * file extension matches
- * @param defaultClassName the name of the class to be created when the
- * file extension does not match
- * @param extension the file extension to be checked against
- * @since 1.4
- */
- public FileExtensionConfigurationProvider(String matchingClassName,
- String defaultClassName, String extension)
- {
- this.matchingClassName = matchingClassName;
- this.defaultClassName = defaultClassName;
- fileExtension = extension;
- }
-
- /**
- * Returns the matching class object, no matter whether it was defined
- * as a class or as a class name.
- *
- * @return the matching class object
- * @throws Exception if an error occurs
- * @since 1.4
- */
- protected synchronized Class<?> fetchMatchingClass() throws Exception
- {
- if (matchingClass == null)
- {
- matchingClass = loadClass(matchingClassName);
- }
- return matchingClass;
- }
-
- /**
- * Returns the default class object, no matter whether it was defined as
- * a class or as a class name.
- *
- * @return the default class object
- * @throws Exception if an error occurs
- * @since 1.4
- */
- protected synchronized Class<?> fetchDefaultClass() throws Exception
- {
- if (defaultClass == null)
- {
- defaultClass = loadClass(defaultClassName);
- }
- return defaultClass;
- }
-
- /**
- * Creates the configuration object. The class is determined by the file
- * name's extension.
- *
- * @param beanClass the class
- * @param data the bean declaration
- * @return the new bean
- * @throws Exception if an error occurs
- */
- @Override
- protected Object createBeanInstance(Class<?> beanClass,
- BeanDeclaration data) throws Exception
- {
- String fileName = ((ConfigurationDeclaration) data)
- .getConfiguration().getString(ATTR_FILENAME);
- if (fileName != null
- && fileName.toLowerCase().trim().endsWith(fileExtension))
- {
- return super.createBeanInstance(fetchMatchingClass(), data);
- }
- else
- {
- return super.createBeanInstance(fetchDefaultClass(), data);
- }
- }
- }
- /**
- * A specialized configuration provider class that allows to include other
- * configuration definition files.
- */
- static class ConfigurationBuilderProvider extends ConfigurationProvider
- {
- /**
- * Creates a new instance of {@code ConfigurationBuilderProvider}.
- */
- public ConfigurationBuilderProvider()
- {
- super(DefaultConfigurationBuilder.class);
- }
-
- /**
- * Creates the configuration. First creates a configuration builder
- * object. Then returns the configuration created by this builder.
- *
- * @param decl the configuration declaration
- * @return the configuration
- * @exception Exception if an error occurs
- */
- @Override
- public AbstractConfiguration getConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- DefaultConfigurationBuilder builder = (DefaultConfigurationBuilder) super
- .getConfiguration(decl);
- return builder.getConfiguration(true);
- }
-
- /**
- * Returns an empty configuration in case of an optional configuration
- * could not be created. This implementation returns an empty combined
- * configuration.
- *
- * @param decl the configuration declaration
- * @return the configuration
- * @exception Exception if an error occurs
- * @since 1.4
- */
- @Override
- public AbstractConfiguration getEmptyConfiguration(
- ConfigurationDeclaration decl) throws Exception
- {
- return new CombinedConfiguration();
- }
-
- /**
- * {@inheritDoc} This implementation ensures that the configuration
- * builder created by this provider inherits the properties from the
- * current configuration builder.
- */
- @Override
- protected void initBeanInstance(Object bean, BeanDeclaration data)
- throws Exception
- {
- ConfigurationDeclaration decl = (ConfigurationDeclaration) data;
- initChildBuilder(decl.getConfigurationBuilder(),
- (DefaultConfigurationBuilder) bean);
- super.initBeanInstance(bean, data);
- }
-
- /**
- * Initializes the given child configuration builder from its parent
- * builder. This method copies the values of some properties from the
- * parent builder to the child builder so that the child inherits
- * properties from its parent.
- *
- * @param parent the parent builder
- * @param child the child builder
- */
- private static void initChildBuilder(
- DefaultConfigurationBuilder parent,
- DefaultConfigurationBuilder child)
- {
- child.setBasePath(parent.getBasePath());
- child.setDelimiterParsingDisabled(parent
- .isDelimiterParsingDisabled());
- child.setListDelimiter(parent.getListDelimiter());
- child.setThrowExceptionOnMissing(parent.isThrowExceptionOnMissing());
- child.setLogger(parent.getLogger());
-
- child.clearConfigurationListeners();
- for (ConfigurationListener l : parent.getConfigurationListeners())
- {
- child.addConfigurationListener(l);
- }
- child.clearErrorListeners();
- for (ConfigurationErrorListener l : parent.getErrorListeners())
- {
- child.addErrorListener(l);
+ ConfigurationDeclaration decl =
+ new ConfigurationDeclaration(
+ CombinedConfigurationBuilder.this, src);
+ ConfigurationBuilder<? extends Configuration> builder =
+ provider.getConfiguration(decl);
+ builders.add(builder);
+ declarations.put(builder, decl);
+ if (decl.getName() != null)
+ {
+ namedBuilders.put(decl.getName(), builder);
+ }
}
}
}
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java?rev=1416265&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java (added)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java Sun Dec 2 21:21:16 2012
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.builder.ConfigurationBuilder;
+
+/**
+ * <p>
+ * An interface for creating builders for configuration sources of a
+ * {@link CombinedConfigurationBuilder}.
+ * </p>
+ * <p>
+ * When processing its definition file {@code CombinedConfigurationBuilder}
+ * scans for tags declaring configuration sources and maps them to
+ * implementations of this interface. The instances are then used to obtain
+ * builder objects to create the corresponding configuration sources. Parameters
+ * of the builders are provided as {@link ConfigurationDeclaration} objects.
+ * </p>
+ *
+ * @version $Id$
+ * @since 2.0
+ */
+public interface ConfigurationBuilderProvider
+{
+ /**
+ * Returns the builder for the configuration source managed by this
+ * provider. This method is called during processing of the combined
+ * configuration definition file.
+ *
+ * @param decl the bean declaration with initialization parameters for the
+ * configuration builder
+ * @return the {@code ConfigurationBuilder} object created by this provider
+ * @throws ConfigurationException if an error occurs
+ */
+ ConfigurationBuilder<? extends Configuration> getConfiguration(
+ ConfigurationDeclaration decl)
+ throws ConfigurationException;
+}
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/ConfigurationBuilderProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain