Class CombinedConfiguration
- All Implemented Interfaces:
Cloneable,Configuration,EventListener<ConfigurationEvent>,EventSource,HierarchicalConfiguration<ImmutableNode>,ImmutableConfiguration,ImmutableHierarchicalConfiguration,SynchronizerSupport,InMemoryNodeModelSupport,NodeKeyResolver<ImmutableNode>,NodeModelSupport<ImmutableNode>
- Direct Known Subclasses:
DynamicCombinedConfiguration
A hierarchical composite configuration class.
This class maintains a list of configuration objects, which can be added using the diverse addConfiguration()
methods. After that the configurations can be accessed either by name (if one was provided when the configuration was
added) or by index. For the whole set of managed configurations a logical node structure is constructed. For this
purpose a NodeCombiner object can be set. This makes it
possible to specify different algorithms for the combination process.
The big advantage of this class is that it creates a truly hierarchical structure of all the properties stored in the contained configurations - even if some of them are no hierarchical configurations per se. So all enhanced features provided by a hierarchical configuration (for example choosing an expression engine) are applicable.
The class works by registering itself as an event listener at all added configurations. So it gets notified whenever
one of these configurations is changed and can invalidate its internal node structure. The next time a property is
accessed the node structure will be re-constructed using the current state of the managed configurations. Note that,
depending on the used NodeCombiner, this may be a complex operation.
Because of the way a CombinedConfiguration is working it has more or less view character: it provides a logic
view on the configurations it contains. In this constellation not all methods defined for hierarchical configurations
- especially methods that update the stored properties - can be implemented in a consistent manner. Using such
methods (like addProperty(), or clearProperty() on a CombinedConfiguration is not strictly
forbidden, however, depending on the current NodeCombiner and the involved properties, the results may be
different than expected. Some examples may illustrate this:
- Imagine a
CombinedConfigurationcc containing two child configurations with the following content:- user.properties
-
gui.background = blue gui.position = (10, 10, 400, 200)
- default.properties
-
gui.background = black gui.foreground = white home.dir = /data
NodeCombineraOverrideCombineris used. This combiner will ensure that defined user settings take precedence over the default values. If the resultingCombinedConfigurationis queried for the background color,bluewill be returned because this value is defined inuser.properties. Now consider what happens if the keygui.backgroundis removed from theCombinedConfiguration:cc.clearProperty("gui.background");Will acc.containsKey("gui.background")now return false? No, it won't! TheclearProperty()operation is executed on the node set of the combined configuration, which was constructed from the nodes of the two child configurations. It causes the value of the background node to be cleared, which is also part of the first child configuration. This modification of one of its child configurations causes theCombinedConfigurationto be re-constructed. This time theOverrideCombinercannot find agui.backgroundproperty in the first child configuration, but it finds one in the second, and adds it to the resulting combined configuration. So the property is still present (with a different value now). addProperty()can also be problematic: Most node combiners use special view nodes for linking parts of the original configurations' data together. If new properties are added to such a special node, they do not belong to any of the managed configurations and thus hang in the air. Using the same configurations as in the last example, the statementaddProperty("database.user", "scott");would cause such a hanging property. If now one of the child configurations is changed and theCombinedConfigurationis re-constructed, this property will disappear! (Add operations are not problematic if they result in a child configuration being updated. For instance anaddProperty("home.url", "localhost");will alter the second child configuration - because the prefix home is here already present; when theCombinedConfigurationis re-constructed, this change is taken into account.)
Because of such problems it is recommended to perform updates only on the managed child configurations.
Whenever the node structure of a CombinedConfiguration becomes invalid (either because one of the contained
configurations was modified or because the invalidate() method was directly called) an event is generated. So
this can be detected by interested event listeners. This also makes it possible to add a combined configuration into
another one.
Notes about thread-safety: This configuration implementation uses a Synchronizer object to protect instances
against concurrent access. The concrete Synchronizer implementation used determines whether an instance of
this class is thread-safe or not. In contrast to other implementations derived from
BaseHierarchicalConfiguration, thread-safety is an issue here because the nodes structure used by this
configuration has to be constructed dynamically when a child configuration is changed. Therefore, when multiple
threads are involved which also manipulate one of the child configurations, a proper Synchronizer object
should be set. Note that the Synchronizer objects used by the child configurations do not really matter.
Because immutable in-memory nodes structures are used for them there is no danger that updates on child
configurations could interfere with read operations on the combined configuration.
- Since:
- 1.3
-
Nested Class Summary
Nested classes/interfaces inherited from class org.apache.commons.configuration2.BaseHierarchicalConfiguration
BaseHierarchicalConfiguration.BuilderVisitor -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final EventType<ConfigurationEvent> Constant for the event type fired when the internal node structure of a combined configuration becomes invalid. -
Constructor Summary
ConstructorsConstructorDescriptionCreates a new instance ofCombinedConfigurationthat uses a union combiner.Creates a new instance ofCombinedConfigurationand initializes the combiner to be used. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddConfiguration(Configuration config) Adds a new configuration to this combined configuration.voidaddConfiguration(Configuration config, String name) Adds a new configuration to this combined configuration with an optional name.voidaddConfiguration(Configuration config, String name, String at) Adds a new configuration to this combined configuration.protected voidbeginRead(boolean optimize) Notifies this configuration'sSynchronizerthat a read operation is about to start.protected voidbeginWrite(boolean optimize) Notifies this configuration'sSynchronizerthat an update operation is about to start.protected voidClears this configuration.clone()Returns a copy of this object.getConfiguration(int index) Gets the configuration at the specified index.getConfiguration(String name) Gets the configuration with the given name.Gets a List of the names of all the configurations that have been added in the order they were added.Gets a set with the names of all configurations contained in this combined configuration.Gets a List of all the configurations that have been added.Gets theExpressionEnginefor converting flat child configurations to hierarchical ones.Gets the node combiner that is used for creating the combined node structure.intGets the number of configurations that are contained in this combined configuration.Gets the configuration source, in which the specified key is defined.getSources(String key) Gets a set with the configuration sources, in which the specified key is defined.voidInvalidates this combined configuration.voidonEvent(ConfigurationEvent event) Event listener call back for configuration update events.removeConfiguration(String name) Removes the configuration with the specified name.booleanremoveConfiguration(Configuration config) Removes the specified configuration from this combined configuration.removeConfigurationAt(int index) Removes the configuration at the specified index.voidsetConversionExpressionEngine(ExpressionEngine conversionExpressionEngine) Sets theExpressionEnginefor converting flat child configurations to hierarchical ones.voidsetNodeCombiner(NodeCombiner nodeCombiner) Sets the node combiner.Methods inherited from class org.apache.commons.configuration2.BaseHierarchicalConfiguration
childConfigurationsAt, childConfigurationsAt, cloneNodeModel, configurationAt, configurationAt, configurationsAt, configurationsAt, createSubConfigurationForTrackedNode, getNodeModel, getSubConfigurationNodeSelector, getSubConfigurationParentModel, immutableChildConfigurationsAt, immutableConfigurationAt, immutableConfigurationAt, immutableConfigurationsAt, initSubConfigurationForThisParent, interpolatedConfiguration, subnodeConfigurationChanged, subsetMethods inherited from class org.apache.commons.configuration2.AbstractHierarchicalConfiguration
addNodes, addNodesInternal, addPropertyDirect, addPropertyInternal, clearPropertyDirect, clearTree, clearTreeInternal, containsKeyInternal, containsValueInternal, fetchNodeList, getExpressionEngine, getKeysInternal, getKeysInternal, getKeysInternal, getMaxIndex, getMaxIndexInternal, getModel, getPropertyInternal, getRootElementName, getRootElementNameInternal, isEmptyInternal, nodeDefined, nodeKey, resolveAddKey, resolveKey, resolveNodeKey, resolveUpdateKey, setExpressionEngine, setPropertyInternal, sizeInternal, toStringMethods inherited from class org.apache.commons.configuration2.AbstractConfiguration
addErrorLogListener, addProperty, append, clear, clearProperty, cloneInterpolator, contains, containsKey, containsValue, copy, endRead, endWrite, get, get, getArray, getArray, getBigDecimal, getBigDecimal, getBigInteger, getBigInteger, getBoolean, getBoolean, getBoolean, getByte, getByte, getByte, getCollection, getCollection, getConfigurationDecoder, getConversionHandler, getDouble, getDouble, getDouble, getDuration, getDuration, getEncodedString, getEncodedString, getFloat, getFloat, getFloat, getInt, getInt, getInteger, getInterpolator, getKeys, getKeys, getKeys, getList, getList, getList, getList, getListDelimiterHandler, getLogger, getLong, getLong, getLong, getProperties, getProperties, getProperty, getShort, getShort, getShort, getString, getString, getStringArray, getSynchronizer, immutableSubset, initLogger, installInterpolator, interpolate, interpolate, isEmpty, isScalarValue, isThrowExceptionOnMissing, lock, setConfigurationDecoder, setConversionHandler, setDefaultLookups, setInterpolator, setListDelimiterHandler, setLogger, setParentInterpolator, setPrefixLookups, setProperty, setSynchronizer, setThrowExceptionOnMissing, size, unlockMethods inherited from class org.apache.commons.configuration2.event.BaseEventSource
addEventListener, clearErrorListeners, clearEventListeners, copyEventListeners, createErrorEvent, createEvent, fireError, fireEvent, getEventListenerRegistrations, getEventListeners, isDetailEvents, removeEventListener, setDetailEventsMethods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface org.apache.commons.configuration2.Configuration
addProperty, clear, clearProperty, getInterpolator, installInterpolator, setInterpolator, setPropertyMethods inherited from interface org.apache.commons.configuration2.ImmutableConfiguration
containsKey, containsValue, get, get, getArray, getArray, getBigDecimal, getBigDecimal, getBigInteger, getBigInteger, getBoolean, getBoolean, getBoolean, getByte, getByte, getByte, getCollection, getCollection, getDouble, getDouble, getDouble, getDuration, getDuration, getEncodedString, getEncodedString, getEnum, getEnum, getFloat, getFloat, getFloat, getInt, getInt, getInteger, getKeys, getKeys, getKeys, getList, getList, getList, getList, getLong, getLong, getLong, getProperties, getProperty, getShort, getShort, getShort, getString, getString, getStringArray, immutableSubset, isEmpty, sizeMethods inherited from interface org.apache.commons.configuration2.sync.SynchronizerSupport
getSynchronizer, lock, setSynchronizer, unlock
-
Field Details
-
COMBINED_INVALIDATE
Constant for the event type fired when the internal node structure of a combined configuration becomes invalid.- Since:
- 2.0
-
-
Constructor Details
-
CombinedConfiguration
public CombinedConfiguration()Creates a new instance ofCombinedConfigurationthat uses a union combiner.- See Also:
-
CombinedConfiguration
Creates a new instance ofCombinedConfigurationand initializes the combiner to be used.- Parameters:
comb- the node combiner (can be null, then a union combiner is used as default)
-
-
Method Details
-
addConfiguration
Adds a new configuration to this combined configuration. The new configuration is not given a name. Its properties will be added under the root of the combined node structure.- Parameters:
config- the configuration to add (must not be null)
-
addConfiguration
Adds a new configuration to this combined configuration with an optional name. The new configuration's properties will be added under the root of the combined node structure.- Parameters:
config- the configuration to add (must not be null)name- the name of this configuration (can be null)
-
addConfiguration
Adds a new configuration to this combined configuration. It is possible (but not mandatory) to give the new configuration a name. This name must be unique, otherwise aConfigurationRuntimeExceptionwill be thrown. With the optionalatargument you can specify where in the resulting node structure the content of the added configuration should appear. This is a string that uses dots as property delimiters (independent on the current expression engine). For instance if you pass in the string"database.tables", all properties of the added configuration will occur in this branch.- Parameters:
config- the configuration to add (must not be null)name- the name of this configuration (can be null)at- the position of this configuration in the combined tree (can be null)
-
beginRead
Notifies this configuration'sSynchronizerthat a read operation is about to start. This method is called by all methods which access this configuration in a read-only mode. Subclasses may override it to perform additional actions before this read operation. The boolean optimize argument can be evaluated by overridden methods in derived classes. Some operations which require a lock do not need a fully initialized configuration object. By setting this flag to true, such operations can give a corresponding hint. An overridden implementation ofbeginRead()can then decide to skip some initialization steps. All basic operations in this class (and most of the basicConfigurationimplementations) call this method with a parameter value of false. In any case the inherited method must be called! Otherwise, proper synchronization is not guaranteed. This implementation checks whether a combined root node is available. If not, it is constructed by requesting a write lock.- Overrides:
beginReadin classAbstractConfiguration- Parameters:
optimize- a flag whether optimization can be performed
-
beginWrite
Notifies this configuration'sSynchronizerthat an update operation is about to start. This method is called by all methods which modify this configuration. Subclasses may override it to perform additional operations before an update. For a description of the boolean optimize argument refer to the documentation ofbeginRead(). In any case the inherited method must be called! Otherwise, proper synchronization is not guaranteed. This implementation checks whether a combined root node is available. If not, it is constructed now.- Overrides:
beginWritein classAbstractConfiguration- Parameters:
optimize- a flag whether optimization can be performed- See Also:
-
clearInternal
Clears this configuration. All contained configurations will be removed.- Overrides:
clearInternalin classAbstractHierarchicalConfiguration<ImmutableNode>
-
clone
Returns a copy of this object. This implementation performs a deep clone, i.e. all contained configurations will be cloned, too. For this to work, all contained configurations must be cloneable. Registered event listeners won't be cloned. The clone will use the same node combiner than the original.- Overrides:
clonein classAbstractHierarchicalConfiguration<ImmutableNode>- Returns:
- the copied object
-
getConfiguration
Gets the configuration at the specified index. The contained configurations are numbered in the order they were added to this combined configuration. The index of the first configuration is 0.- Parameters:
index- the index- Returns:
- the configuration at this index
-
getConfiguration
Gets the configuration with the given name. This can be null if no such configuration exists.- Parameters:
name- the name of the configuration- Returns:
- the configuration with this name
-
getConfigurationNameList
Gets a List of the names of all the configurations that have been added in the order they were added. A NULL value will be present in the list for each configuration that was added without a name.- Returns:
- A List of all the configuration names.
- Since:
- 1.7
-
getConfigurationNames
Gets a set with the names of all configurations contained in this combined configuration. Of course here are only these configurations listed, for which a name was specified when they were added.- Returns:
- a set with the names of the contained configurations (never null)
-
getConfigurations
Gets a List of all the configurations that have been added.- Returns:
- A List of all the configurations.
- Since:
- 1.7
-
getConversionExpressionEngine
Gets theExpressionEnginefor converting flat child configurations to hierarchical ones.- Returns:
- the conversion expression engine
- Since:
- 1.6
-
getNodeCombiner
Gets the node combiner that is used for creating the combined node structure.- Returns:
- the node combiner
-
getNumberOfConfigurations
Gets the number of configurations that are contained in this combined configuration.- Returns:
- the number of contained configurations
-
getSource
Gets the configuration source, in which the specified key is defined. This method will determine the configuration node that is identified by the given key. The following constellations are possible:- If no node object is found for this key, null is returned.
- If the key maps to multiple nodes belonging to different configuration sources, a
IllegalArgumentExceptionis thrown (in this case no unique source can be determined). - If exactly one node is found for the key, the (child) configuration object, to which the node belongs is determined and returned.
- For keys that have been added directly to this combined configuration and that do not belong to the namespaces defined by existing child configurations this configuration will be returned.
- Parameters:
key- the key of a configuration property- Returns:
- the configuration, to which this property belongs or null if the key cannot be resolved
- Throws:
IllegalArgumentException- if the key maps to multiple properties and the source cannot be determined, or if the key is null- Since:
- 1.5
-
getSources
Gets a set with the configuration sources, in which the specified key is defined. This method determines the configuration nodes that are identified by the given key. It then determines the configuration sources to which these nodes belong and adds them to the result set. Note the following points:- If no node object is found for this key, an empty set is returned.
- For keys that have been added directly to this combined configuration and that do not belong to the namespaces defined by existing child configurations this combined configuration is contained in the result set.
- Parameters:
key- the key of a configuration property- Returns:
- a set with the configuration sources, which contain this property
- Since:
- 2.0
-
invalidate
Invalidates this combined configuration. This means that the next time a property is accessed the combined node structure must be re-constructed. Invalidation of a combined configuration also means that an event of typeEVENT_COMBINED_INVALIDATEis fired. Note that while other events most times appear twice (once before and once after an update), this event is only fired once (after update). -
onEvent
Event listener call back for configuration update events. This method is called whenever one of the contained configurations was modified. It invalidates this combined configuration.- Specified by:
onEventin interfaceEventListener<ConfigurationEvent>- Parameters:
event- the update event
-
removeConfiguration
Removes the specified configuration from this combined configuration.- Parameters:
config- the configuration to be removed- Returns:
- a flag whether this configuration was found and could be removed
-
removeConfiguration
Removes the configuration with the specified name.- Parameters:
name- the name of the configuration to be removed- Returns:
- the removed configuration (null if this configuration was not found)
-
removeConfigurationAt
Removes the configuration at the specified index.- Parameters:
index- the index- Returns:
- the removed configuration
-
setConversionExpressionEngine
Sets theExpressionEnginefor converting flat child configurations to hierarchical ones. When constructing the root node for this combined configuration the properties of all child configurations must be combined to a single hierarchical node structure. In this process, non hierarchical configurations are converted to hierarchical ones first. This can be problematic if a child configuration contains keys that are no compatible with the default expression engine used by hierarchical configurations. Therefore it is possible to specify a specific expression engine to be used for this purpose.- Parameters:
conversionExpressionEngine- the conversion expression engine- Since:
- 1.6
- See Also:
-
setNodeCombiner
Sets the node combiner. This object will be used when the combined node structure is to be constructed. It must not be null, otherwise anIllegalArgumentExceptionexception is thrown. Changing the node combiner causes an invalidation of this combined configuration, so that the new combiner immediately takes effect.- Parameters:
nodeCombiner- the node combiner
-