Class XMLConfiguration

All Implemented Interfaces:
Cloneable, Configuration, EventSource, FileBasedConfiguration, HierarchicalConfiguration<ImmutableNode>, ImmutableConfiguration, ImmutableHierarchicalConfiguration, FileBased, FileLocatorAware, InputStreamSupport, SynchronizerSupport, InMemoryNodeModelSupport, NodeKeyResolver<ImmutableNode>, NodeModelSupport<ImmutableNode>

A specialized hierarchical configuration class that is able to parse XML documents.

The parsed document will be stored keeping its structure. The class also tries to preserve as much information from the loaded XML document as possible, including comments and processing instructions. These will be contained in documents created by the save() methods, too.

Like other file based configuration classes this class maintains the name and path to the loaded configuration file. These properties can be altered using several setter methods, but they are not modified by save() and load() methods. If XML documents contain relative paths to other documents (e.g. to a DTD), these references are resolved based on the path set for this configuration.

By inheriting from AbstractConfiguration this class provides some extended functionality, e.g. interpolation of property values. Like in PropertiesConfiguration property values can contain delimiter characters (the comma ',' per default) and are then split into multiple values. This works for XML attributes and text content of elements as well. The delimiter can be escaped by a backslash. As an example consider the following XML fragment:

 <config>
   <array>10,20,30,40</array>
   <scalar>3\,1415</scalar>
   <cite text="To be or not to be\, this is the question!"/>
 </config>
 

Here the content of the array element will be split at the commas, so the array key will be assigned 4 values. In the scalar property and the text attribute of the cite element the comma is escaped, so that no splitting is performed.

The configuration API allows setting multiple values for a single attribute, e.g. something like the following is legal (assuming that the default expression engine is used):

 XMLConfiguration config = new XMLConfiguration();
 config.addProperty("test.dir[@name]", "C:\\Temp\\");
 config.addProperty("test.dir[@name]", "D:\\Data\\");
 

However, in XML such a constellation is not supported; an attribute can appear only once for a single element. Therefore, an attempt to save a configuration which violates this condition will throw an exception.

Like other Configuration implementations, XMLConfiguration uses a ListDelimiterHandler object for controlling list split operations. Per default, a list delimiter handler object is set which disables this feature. XML has a built-in support for complex structures including list properties; therefore, list splitting is not that relevant for this configuration type. Nevertheless, by setting an alternative ListDelimiterHandler implementation, this feature can be enabled. It works as for any other concrete Configuration implementation.

Whitespace in the content of XML documents is trimmed per default. In most cases this is desired. However, sometimes whitespace is indeed important and should be treated as part of the value of a property as in the following example:

   <indent>    </indent>
 

Per default the spaces in the indent element will be trimmed resulting in an empty element. To tell XMLConfiguration that spaces are relevant the xml:space attribute can be used, which is defined in the XML specification. This will look as follows:

   <indent xml:space="preserve">    </indent>
 

The value of the indent property will now contain the spaces.

XMLConfiguration implements the FileBasedConfiguration interface and thus can be used together with a file-based builder to load XML configuration files from various sources like files, URLs, or streams.

Like other Configuration implementations, this class uses a Synchronizer object to control concurrent access. By choosing a suitable implementation of the Synchronizer interface, an instance can be made thread-safe or not. Note that access to most of the properties typically set through a builder is not protected by the Synchronizer. The intended usage is that these properties are set once at construction time through the builder and after that remain constant. If you wish to change such properties during life time of an instance, you have to use the lock() and unlock() methods manually to ensure that other threads see your changes.

More information about the basic functionality supported by XMLConfiguration can be found at the user's guide at Basic features and AbstractConfiguration. There is also a separate chapter dealing with XML Configurations in special.

Since:
1.0
  • Field Details

    • DEFAULT_INDENT_SIZE

      static final int DEFAULT_INDENT_SIZE
      Constant for the default indent size.
      See Also:
    • INDENT_AMOUNT_PROPERTY

      static final String INDENT_AMOUNT_PROPERTY
      Constant for output property name used on a transformer to specify the indent amount.
      See Also:
    • DEFAULT_ROOT_NAME

      private static final String DEFAULT_ROOT_NAME
      Constant for the default root element name.
      See Also:
    • ATTR_SPACE

      private static final String ATTR_SPACE
      Constant for the name of the space attribute.
      See Also:
    • ATTR_SPACE_INTERNAL

      private static final String ATTR_SPACE_INTERNAL
      Constant for an internally used space attribute.
      See Also:
    • VALUE_PRESERVE

      private static final String VALUE_PRESERVE
      Constant for the xml:space value for preserving whitespace.
      See Also:
    • JAXP_SCHEMA_LANGUAGE

      private static final String JAXP_SCHEMA_LANGUAGE
      Schema Langauge key for the parser
      See Also:
    • W3C_XML_SCHEMA

      private static final String W3C_XML_SCHEMA
      Schema Language for the parser
      See Also:
    • rootElementName

      private String rootElementName
      Stores the name of the root element.
    • publicID

      private String publicID
      Stores the public ID from the DOCTYPE.
    • systemID

      private String systemID
      Stores the system ID from the DOCTYPE.
    • documentBuilder

      private DocumentBuilder documentBuilder
      Stores the document builder that should be used for loading.
    • validating

      private boolean validating
      Stores a flag whether DTD or Schema validation should be performed.
    • schemaValidation

      private boolean schemaValidation
      Stores a flag whether DTD or Schema validation is used
    • entityResolver

      private EntityResolver entityResolver
      The EntityResolver to use
    • locator

      private FileLocator locator
      The current file locator.
  • Constructor Details

    • XMLConfiguration

      public XMLConfiguration()
      Creates a new instance of XMLConfiguration.
    • XMLConfiguration

      public XMLConfiguration(HierarchicalConfiguration<ImmutableNode> c)
      Creates a new instance of XMLConfiguration and copies the content of the passed in configuration into this object. Note that only the data of the passed in configuration will be copied. If, for instance, the other configuration is a XMLConfiguration, too, things like comments or processing instructions will be lost.
      Parameters:
      c - the configuration to copy
      Since:
      1.4
  • Method Details

    • getRootElementNameInternal

      protected String getRootElementNameInternal()
      Gets the name of the root element. If this configuration was loaded from a XML document, the name of this document's root element is returned. Otherwise it is possible to set a name for the root element that will be used when this configuration is stored.
      Overrides:
      getRootElementNameInternal in class AbstractHierarchicalConfiguration<ImmutableNode>
      Returns:
      the name of the root element
    • setRootElementName

      public void setRootElementName(String name)
      Sets the name of the root element. This name is used when this configuration object is stored in an XML file. Note that setting the name of the root element works only if this configuration has been newly created. If the configuration was loaded from an XML file, the name cannot be changed and an UnsupportedOperationException exception is thrown. Whether this configuration has been loaded from an XML document or not can be found out using the getDocument() method.
      Parameters:
      name - the name of the root element
    • getDocumentBuilder

      public DocumentBuilder getDocumentBuilder()
      Gets the DocumentBuilder object that is used for loading documents. If no specific builder has been set, this method returns null.
      Returns:
      the DocumentBuilder for loading new documents
      Since:
      1.2
    • setDocumentBuilder

      public void setDocumentBuilder(DocumentBuilder documentBuilder)
      Sets the DocumentBuilder object to be used for loading documents. This method makes it possible to specify the exact document builder. So an application can create a builder, configure it for its special needs, and then pass it to this method.
      Parameters:
      documentBuilder - the document builder to be used; if undefined, a default builder will be used
      Since:
      1.2
    • getPublicID

      public String getPublicID()
      Gets the public ID of the DOCTYPE declaration from the loaded XML document. This is null if no document has been loaded yet or if the document does not contain a DOCTYPE declaration with a public ID.
      Returns:
      the public ID
      Since:
      1.3
    • setPublicID

      public void setPublicID(String publicID)
      Sets the public ID of the DOCTYPE declaration. When this configuration is saved, a DOCTYPE declaration will be constructed that contains this public ID.
      Parameters:
      publicID - the public ID
      Since:
      1.3
    • getSystemID

      public String getSystemID()
      Gets the system ID of the DOCTYPE declaration from the loaded XML document. This is null if no document has been loaded yet or if the document does not contain a DOCTYPE declaration with a system ID.
      Returns:
      the system ID
      Since:
      1.3
    • setSystemID

      public void setSystemID(String systemID)
      Sets the system ID of the DOCTYPE declaration. When this configuration is saved, a DOCTYPE declaration will be constructed that contains this system ID.
      Parameters:
      systemID - the system ID
      Since:
      1.3
    • isValidating

      public boolean isValidating()
      Returns the value of the validating flag.
      Returns:
      the validating flag
      Since:
      1.2
    • setValidating

      public void setValidating(boolean validating)
      Sets the value of the validating flag. This flag determines whether DTD/Schema validation should be performed when loading XML documents. This flag is evaluated only if no custom DocumentBuilder was set.
      Parameters:
      validating - the validating flag
      Since:
      1.2
    • isSchemaValidation

      public boolean isSchemaValidation()
      Returns the value of the schemaValidation flag.
      Returns:
      the schemaValidation flag
      Since:
      1.7
    • setSchemaValidation

      public void setSchemaValidation(boolean schemaValidation)
      Sets the value of the schemaValidation flag. This flag determines whether DTD or Schema validation should be used. This flag is evaluated only if no custom DocumentBuilder was set. If set to true the XML document must contain a schemaLocation definition that provides resolvable hints to the required schemas.
      Parameters:
      schemaValidation - the validating flag
      Since:
      1.7
    • setEntityResolver

      public void setEntityResolver(EntityResolver resolver)
      Sets a new EntityResolver. Setting this will cause RegisterEntityId to have no effect.
      Parameters:
      resolver - The EntityResolver to use.
      Since:
      1.7
    • getEntityResolver

      public EntityResolver getEntityResolver()
      Gets the EntityResolver.
      Returns:
      The EntityResolver.
      Since:
      1.7
    • getDocument

      public Document getDocument()
      Gets the XML document this configuration was loaded from. The return value is null if this configuration was not loaded from a XML document.
      Returns:
      the XML document this configuration was loaded from
    • getDocumentHelper

      private XMLDocumentHelper getDocumentHelper()
      Gets the helper object for managing the underlying document.
      Returns:
      the XMLDocumentHelper
    • getReferenceHandler

      private ReferenceNodeHandler getReferenceHandler()
      Gets the extended node handler with support for references.
      Returns:
      the ReferenceNodeHandler
    • initProperties

      private void initProperties(XMLDocumentHelper docHelper, boolean elemRefs)
      Initializes this configuration from an XML document.
      Parameters:
      docHelper - the helper object with the document to be parsed
      elemRefs - a flag whether references to the XML elements should be set
    • constructHierarchy

      private Map<String,String> constructHierarchy(ImmutableNode.Builder node, org.apache.commons.lang3.mutable.MutableObject<String> refValue, Element element, Map<ImmutableNode,Object> elemRefs, boolean trim, int level)
      Helper method for building the internal storage hierarchy. The XML elements are transformed into node objects.
      Parameters:
      node - a builder for the current node
      refValue - stores the text value of the element
      element - the current XML element
      elemRefs - a map for assigning references objects to nodes; can be null, then reference objects are irrelevant
      trim - a flag whether the text content of elements should be trimmed; this controls the whitespace handling
      level - the current level in the hierarchy
      Returns:
      a map with all attribute values extracted for the current node; this map also contains the value of the trim flag for this node under the key "xml:space"
    • determineValue

      private static String determineValue(String content, boolean hasChildren, boolean trimFlag)
      Determines the value of a configuration node. This method mainly checks whether the text value is to be trimmed or not. This is normally defined by the trim flag. However, if the node has children and its content is only whitespace, then it makes no sense to store any value; this would only scramble layout when the configuration is saved again.
      Parameters:
      content - the text content of this node
      hasChildren - a flag whether the node has children
      trimFlag - the trim flag
      Returns:
      the value to be stored for this node
    • processAttributes

      private static Map<String,String> processAttributes(Element element)
      Helper method for initializing the attributes of a configuration node from the given XML element.
      Parameters:
      element - the current XML element
      Returns:
      a map with all attribute values extracted for the current node
    • createChildNodeWithValue

      private ImmutableNode createChildNodeWithValue(ImmutableNode.Builder parent, ImmutableNode.Builder child, Element elem, String value, boolean trim, Map<String,String> attrmap, Map<ImmutableNode,Object> elemRefs)
      Creates a new child node, assigns its value, and adds it to its parent. This method also deals with elements whose value is a list. In this case multiple child elements must be added. The return value is the first child node which was added.
      Parameters:
      parent - the builder for the parent element
      child - the builder for the child element
      elem - the associated XML element
      value - the value of the child element
      trim - flag whether texts of elements should be trimmed
      attrmap - a map with the attributes of the current node
      elemRefs - a map for assigning references objects to nodes; can be null, then reference objects are irrelevant
      Returns:
      the first child node added to the parent
    • isSingleElementList

      private static boolean isSingleElementList(Element element)
      Checks whether an element defines a complete list. If this is the case, extended list handling can be applied.
      Parameters:
      element - the element to be checked
      Returns:
      a flag whether this is the only element defining the list
    • countChildElements

      private static int countChildElements(Node parent, String name)
      Determines the number of child elements of this given node with the specified node name.
      Parameters:
      parent - the parent node
      name - the name in question
      Returns:
      the number of child elements with this name
    • shouldTrim

      private static boolean shouldTrim(Element element, boolean currentTrim)
      Checks whether the content of the current XML element should be trimmed. This method checks whether a xml:space attribute is present and evaluates its value. See http://www.w3.org/TR/REC-xml/#sec-white-space for more details.
      Parameters:
      element - the current XML element
      currentTrim - the current trim flag
      Returns:
      a flag whether the content of this element should be trimmed
    • createDocumentBuilder

      protected DocumentBuilder createDocumentBuilder() throws ParserConfigurationException
      Creates the DocumentBuilder to be used for loading files. This implementation checks whether a specific DocumentBuilder has been set. If this is the case, this one is used. Otherwise a default builder is created. Depending on the value of the validating flag this builder will be a validating or a non validating DocumentBuilder.
      Returns:
      the DocumentBuilder for loading configuration files
      Throws:
      ParserConfigurationException - if an error occurs
      Since:
      1.2
    • createTransformer

      protected Transformer createTransformer() throws ConfigurationException
      Creates and initializes the transformer used for save operations. This base implementation initializes all of the default settings like indentation mode and the DOCTYPE. Derived classes may overload this method if they have specific needs.
      Returns:
      the transformer to use for a save operation
      Throws:
      ConfigurationException - if an error occurs
      Since:
      1.3
    • createDocument

      private Document createDocument() throws ConfigurationException
      Creates a DOM document from the internal tree of configuration nodes.
      Returns:
      the new document
      Throws:
      ConfigurationException - if an error occurs
    • initRootElementText

      private void initRootElementText(Document doc, Object value)
      Sets the text of the root element of a newly created XML Document.
      Parameters:
      doc - the document
      value - the new text to be set
    • initFileLocator

      public void initFileLocator(FileLocator loc)
      Passes the current FileLocator to this object. Note that this FileLocator object is only temporarily valid for the following invocation of read() or write(. Depending on the state of the FileHandler and which of its methods was called, the object may not be fully initialized. For instance, if the FileHandler's load(InputStream) method was called, no file information is available, and all methods of the FileLocator will return null. Stores the passed in locator for the upcoming IO operation.
      Specified by:
      initFileLocator in interface FileLocatorAware
      Parameters:
      loc - the current FileLocator
    • read

      public void read(Reader in) throws ConfigurationException, IOException
      Loads the configuration from the given reader. Note that the clear() method is not called, so the properties contained in the loaded file will be added to the current set of properties.
      Specified by:
      read in interface FileBased
      Parameters:
      in - the reader
      Throws:
      ConfigurationException - if an error occurs
      IOException - if an IO error occurs
    • read

      public void read(InputStream in) throws ConfigurationException, IOException
      Loads the configuration from the given input stream. This is analogous to read(Reader), but data is read from a stream. Note that this method will be called most time when reading an XML configuration source. By reading XML documents directly from an input stream, the file's encoding can be correctly dealt with.
      Specified by:
      read in interface InputStreamSupport
      Parameters:
      in - the input stream
      Throws:
      ConfigurationException - if an error occurs
      IOException - if an IO error occurs
    • load

      private void load(InputSource source) throws ConfigurationException
      Loads a configuration file from the specified input source.
      Parameters:
      source - the input source
      Throws:
      ConfigurationException - if an error occurs
    • write

      public void write(Writer writer) throws ConfigurationException, IOException
      Saves the configuration to the specified writer.
      Specified by:
      write in interface FileBased
      Parameters:
      writer - the writer used to save the configuration
      Throws:
      ConfigurationException - if an error occurs
      IOException - if an IO error occurs
    • write

      public void write(Writer writer, Transformer transformer) throws ConfigurationException
      Saves the configuration to the specified writer.
      Parameters:
      writer - the writer used to save the configuration.
      transformer - How to transform this configuration.
      Throws:
      ConfigurationException - if an error occurs.
      Since:
      2.7.0
    • validate

      public void validate() throws ConfigurationException
      Validate the document against the Schema.
      Throws:
      ConfigurationException - if the validation fails.