oheger 2004/11/19 11:26:48
Modified: configuration/xdocs changes.xml
configuration/src/java/org/apache/commons/configuration
HierarchicalXMLConfiguration.java
ConfigurationKey.java
configuration/src/test/org/apache/commons/configuration
TestHierarchicalXMLConfiguration.java
Log:
Implementation of save() method for HierarchicalXMLConfiguration
Revision Changes Path
1.72 +5 -2 jakarta-commons/configuration/xdocs/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/configuration/xdocs/changes.xml,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- changes.xml 19 Nov 2004 13:19:50 -0000 1.71
+++ changes.xml 19 Nov 2004 19:26:47 -0000 1.72
@@ -8,6 +8,9 @@
<body>
<release version="1.1-dev" date="in CVS">
+ <action dev="oheger" type="add" issue="31130">
+ Added implementation of a save() method for
HierarchicalXMLConfiguration.
+ </action>
<action dev="ebourg" type="update">
Constructing a file based configuration with a File no longer throws
an exception when the file doesn't exist.
@@ -25,12 +28,12 @@
the configuration descriptor is in a JAR file (reported by Grant
Ingersoll).
</action>
<action dev="oheger" type="fix" issue="32236">
- Fixed NPE that where caused in the constructors of file based
+ Fixed NPE that were caused in the constructors of file based
configurations if an invalid file name was specified.
</action>
<action dev="oheger" type="add" issue="31797">
Added support for optional configuration sources in definition
files for
- ConfigurationFactory. A new required attribute allows to
specify whether a
+ ConfigurationFactory. A new optional attribute allows to
specify whether a
configuration source is mandatory or optional.
</action>
<action dev="ebourg" type="fix">
1.6 +124 -6
jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalXMLConfiguration.java
Index: HierarchicalXMLConfiguration.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalXMLConfiguration.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- HierarchicalXMLConfiguration.java 18 Oct 2004 15:45:10 -0000 1.5
+++ HierarchicalXMLConfiguration.java 19 Nov 2004 19:26:48 -0000 1.6
@@ -22,10 +22,22 @@
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
+import java.util.Iterator;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@@ -50,7 +62,32 @@
*/
public class HierarchicalXMLConfiguration extends HierarchicalConfiguration
implements FileConfiguration
{
+ /** Constant for the default root element name.*/
+ private static final String DEFAULT_ROOT_NAME = "configuration";
+
private FileConfiguration delegate = new FileConfigurationDelegate();
+
+ /** Stores the name of the root element.*/
+ private String rootElementName;
+
+ /**
+ * Returns the name of the root element.
+ * @return the name of the root element
+ */
+ public String getRootElementName()
+ {
+ return (rootElementName == null) ? DEFAULT_ROOT_NAME :
rootElementName;
+ }
+
+ /**
+ * Sets the name of the root element. This name is used when this
+ * configuration object is stored in an XML file.
+ * @param name the name of the root element
+ */
+ public void setRootElementName(String name)
+ {
+ rootElementName = name;
+ }
/**
* Initializes this configuration from an XML document.
@@ -121,7 +158,69 @@
}
}
}
-
+
+ /**
+ * Creates a DOM document from the internal tree of configuration nodes.
+ * @return the new document
+ * @throws ConfigurationException if an error occurs
+ */
+ protected Document createDocument() throws ConfigurationException
+ {
+ try
+ {
+ DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document document = builder.newDocument();
+ Element rootElem = document.createElement(getRootElementName());
+ document.appendChild(rootElem);
+ constructDOM(document, getRoot(), rootElem);
+ return document;
+ } /* try */
+ catch(DOMException domEx)
+ {
+ throw new ConfigurationException(domEx);
+ }
+ catch(ParserConfigurationException pex)
+ {
+ throw new ConfigurationException(pex);
+ }
+ }
+
+ /**
+ * Creates a DOM from the tree of configuration nodes.
+ * @param document the document
+ * @param node the actual node
+ * @param element the actual XML element
+ * @throws DOMException if an error occurs
+ */
+ private void constructDOM(Document document, Node node, Element element)
+ throws DOMException
+ {
+ for(Iterator it = node.getChildren().iterator(); it.hasNext();)
+ {
+ Node child = (Node) it.next();
+ if(ConfigurationKey.isAttributeKey(child.getName()))
+ {
+ if (child.getValue() != null)
+ {
+
element.setAttribute(ConfigurationKey.removeAttributeMarkers(
+ child.getName()), child.getValue().toString());
+ }
+ }
+ else
+ {
+ Element childElem = document.createElement(child.getName());
+ if(child.getValue() != null)
+ {
+ Text text =
document.createTextNode(child.getValue().toString());
+ childElem.appendChild(text);
+
+ }
+ constructDOM(document, child, childElem);
+ element.appendChild(childElem);
+ }
+ }
+ }
+
public void load() throws ConfigurationException
{
delegate.load();
@@ -195,10 +294,29 @@
delegate.save(out, encoding);
}
- public void save(Writer out) throws ConfigurationException
- {
- throw new UnsupportedOperationException("Can't save
HierarchicalXMLConfigurations");
- }
+ /**
+ * Saves the configuration to the specified writer.
+ *
+ * @param writer
+ * the writer used to save the configuration
+ * @throws ConfigurationException if an error occurs
+ */
+ public void save(Writer writer) throws ConfigurationException
+ {
+ try
+ {
+ Transformer transformer =
TransformerFactory.newInstance().newTransformer();
+ Source source = new DOMSource(createDocument());
+ Result result = new StreamResult(writer);
+
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.transform(source, result);
+ }
+ catch (TransformerException e)
+ {
+ throw new ConfigurationException(e.getMessage(), e);
+ }
+ }
public String getFileName()
{
1.6 +2 -2
jakarta-commons/configuration/src/java/org/apache/commons/configuration/ConfigurationKey.java
Index: ConfigurationKey.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/ConfigurationKey.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ConfigurationKey.java 14 Aug 2004 11:23:14 -0000 1.5
+++ ConfigurationKey.java 19 Nov 2004 19:26:48 -0000 1.6
@@ -172,7 +172,7 @@
* @param key the key
* @return the key with removed attribute markers
*/
- private static String removeAttributeMarkers(String key)
+ static String removeAttributeMarkers(String key)
{
return key.substring(ATTRIBUTE_START.length(), key.length() -
ATTRIBUTE_END.length());
}
1.3 +30 -2
jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestHierarchicalXMLConfiguration.java
Index: TestHierarchicalXMLConfiguration.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestHierarchicalXMLConfiguration.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TestHierarchicalXMLConfiguration.java 6 Sep 2004 13:12:04 -0000
1.2
+++ TestHierarchicalXMLConfiguration.java 19 Nov 2004 19:26:48 -0000
1.3
@@ -45,6 +45,15 @@
/** Test file path #2 **/
private static final String TEST_FILE2 = TEST_DIR + File.separator +
TEST_FILENAME2;
+
+ /** Test file path #3.*/
+ private static final String TEST_FILE3 = TEST_DIR + File.separator +
"test.xml";
+
+ /** File name for saving.*/
+ private static final String TEST_SAVENAME = "testhierarchicalsave.xml";
+
+ /** File path for saving.*/
+ private static final String TEST_SAVE = TEST_DIR + File.separator +
TEST_SAVENAME;
/** Instance config used for tests. */
private HierarchicalXMLConfiguration config;
@@ -144,5 +153,24 @@
}
assertEquals("Config must contain only " + KEY_COUNT + " keys.",
KEY_COUNT, count);
}
-
+
+ public void testSave() throws Exception
+ {
+ config.setFileName(TEST_FILE3);
+ config.load();
+ File saveFile = new File(TEST_SAVE);
+ config.setRootElementName("myconfig");
+ config.save(saveFile);
+
+ config = new HierarchicalXMLConfiguration();
+ config.load(saveFile.toURL());
+ assertEquals("value", config.getProperty("element"));
+ assertEquals("I'm complex!",
config.getProperty("element2.subelement.subsubelement"));
+ assertEquals(8, config.getInt("test.short"));
+ assertEquals("one", config.getString("list(0).item(0)[EMAIL
PROTECTED]"));
+ assertEquals("two", config.getString("list(0).item(1)"));
+ assertEquals("six", config.getString("list(1).sublist.item(1)"));
+
+ assertTrue(saveFile.delete());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]