commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ohe...@apache.org
Subject svn commit: r348244 [3/3] - in /jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration: ./ plist/
Date Tue, 22 Nov 2005 20:41:33 GMT
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java?rev=348244&r1=348243&r2=348244&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java
(original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java
Tue Nov 22 12:40:57 2005
@@ -1,521 +1,521 @@
-/*
- * Copyright 2005 The Apache Software Foundation.
- *
- * Licensed 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.plist;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.configuration.AbstractHierarchicalFileConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.HierarchicalConfiguration;
-import org.apache.commons.configuration.MapConfiguration;
-import org.apache.commons.digester.AbstractObjectCreationFactory;
-import org.apache.commons.digester.Digester;
-import org.apache.commons.digester.ObjectCreateRule;
-import org.apache.commons.digester.SetNextRule;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.commons.lang.StringUtils;
-import org.xml.sax.Attributes;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-
-/**
- * Mac OS X configuration file (http://www.apple.com/DTDs/PropertyList-1.0.dtd).
- *
- * <p>Example:</p>
- * <pre>
- * &lt;?xml version="1.0"?>
- * &lt;!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
- * &lt;plist version="1.0">
- *     &lt;dict>
- *         &lt;key>string&lt;/key>
- *         &lt;string>value1&lt;/string>
- *
- *         &lt;key>integer&lt;/key>
- *         &lt;integer>12345&lt;/integer>
- *
- *         &lt;key>real&lt;/key>
- *         &lt;real>-123.45E-1&lt;/real>
- *
- *         &lt;key>boolean&lt;/key>
- *         &lt;true/>
- *
- *         &lt;key>date&lt;/key>
- *         &lt;date>2005-01-01T12:00:00-0700&lt;/date>
- *
- *         &lt;key>data&lt;/key>
- *         &lt;data>RHJhY28gRG9ybWllbnMgTnVucXVhbSBUaXRpbGxhbmR1cw==&lt;/data>
- *
- *         &lt;key>array&lt;/key>
- *         &lt;array>
- *             &lt;string>value1&lt;/string>
- *             &lt;string>value2&lt;/string>
- *             &lt;string>value3&lt;/string>
- *         &lt;/array>
- *
- *         &lt;key>dictionnary&lt;/key>
- *         &lt;dict>
- *             &lt;key>key1&lt;/key>
- *             &lt;string>value1&lt;/string>
- *             &lt;key>key2&lt;/key>
- *             &lt;string>value2&lt;/string>
- *             &lt;key>key3&lt;/key>
- *             &lt;string>value3&lt;/string>
- *         &lt;/dict>
- *
- *         &lt;key>nested&lt;/key>
- *         &lt;dict>
- *             &lt;key>node1&lt;/key>
- *             &lt;dict>
- *                 &lt;key>node2&lt;/key>
- *                 &lt;dict>
- *                     &lt;key>node3&lt;/key>
- *                     &lt;string>value&lt;/string>
- *                 &lt;/dict>
- *             &lt;/dict>
- *         &lt;/dict>
- *
- *     &lt;/dict>
- * &lt;/plist>
- * </pre>
- *
- * @since 1.2
- *
- * @author Emmanuel Bourg
- * @version $Revision$, $Date$
- */
-public class XMLPropertyListConfiguration extends AbstractHierarchicalFileConfiguration
-{
-    private static final int INDENT_SIZE = 4;
-
-    /**
-     * Creates an empty XMLPropertyListConfiguration object which can be
-     * used to synthesize a new plist file by adding values and
-     * then saving().
-     */
-    public XMLPropertyListConfiguration() { }
-
-    /**
-     * Creates and loads the property list from the specified file.
-     *
-     * @param fileName The name of the plist file to load.
-     * @throws org.apache.commons.configuration.ConfigurationException Error while loading
the plist file
-     */
-    public XMLPropertyListConfiguration(String fileName) throws ConfigurationException
-    {
-        super(fileName);
-    }
-
-    /**
-     * Creates and loads the property list from the specified file.
-     *
-     * @param file The plist file to load.
-     * @throws ConfigurationException Error while loading the plist file
-     */
-    public XMLPropertyListConfiguration(File file) throws ConfigurationException
-    {
-        super(file);
-    }
-
-    /**
-     * Creates and loads the property list from the specified URL.
-     *
-     * @param url The location of the plist file to load.
-     * @throws ConfigurationException Error while loading the plist file
-     */
-    public XMLPropertyListConfiguration(URL url) throws ConfigurationException
-    {
-        super(url);
-    }
-
-    public void load(Reader in) throws ConfigurationException
-    {
-        // set up the digester
-        Digester digester = new Digester();
-
-        // set up the DTD validation
-        digester.setEntityResolver(new EntityResolver()
-        {
-            public InputSource resolveEntity(String publicId, String systemId)
-            {
-                return new InputSource(getClass().getClassLoader().getResourceAsStream("PropertyList-1.0.dtd"));
-            }
-        });
-        digester.setValidating(true);
-
-        // dictionary rules
-        digester.addRule("*/key", new ObjectCreateRule(PListNode.class)
-        {
-            public void end() throws Exception
-            {
-                // leave the node on the stack to set the value
-            }
-        });
-
-        digester.addCallMethod("*/key", "setName", 0);
-
-        digester.addRule("*/dict/string", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/data", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/integer", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/real", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/true", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/false", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/date", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/dict", new SetNextAndPopRule("addChild"));
-
-        digester.addCallMethod("*/dict/string", "addValue", 0);
-        digester.addCallMethod("*/dict/data", "addDataValue", 0);
-        digester.addCallMethod("*/dict/integer", "addIntegerValue", 0);
-        digester.addCallMethod("*/dict/real", "addRealValue", 0);
-        digester.addCallMethod("*/dict/true", "addTrueValue");
-        digester.addCallMethod("*/dict/false", "addFalseValue");
-        digester.addCallMethod("*/dict/date", "addDateValue", 0);
-
-        // rules for arrays
-        digester.addRule("*/dict/array", new SetNextAndPopRule("addChild"));
-        digester.addRule("*/dict/array", new ObjectCreateRule(ArrayNode.class));
-        digester.addSetNext("*/dict/array", "addList");
-
-        digester.addRule("*/array/array", new ObjectCreateRule(ArrayNode.class));
-        digester.addSetNext("*/array/array", "addList");
-
-        digester.addCallMethod("*/array/string", "addValue", 0);
-        digester.addCallMethod("*/array/data", "addDataValue", 0);
-        digester.addCallMethod("*/array/integer", "addIntegerValue", 0);
-        digester.addCallMethod("*/array/real", "addRealValue", 0);
-        digester.addCallMethod("*/array/true", "addTrueValue");
-        digester.addCallMethod("*/array/false", "addFalseValue");
-        digester.addCallMethod("*/array/date", "addDateValue", 0);
-
-        // rule for a dictionary in an array
-        digester.addFactoryCreate("*/array/dict", new AbstractObjectCreationFactory()
-        {
-            public Object createObject(Attributes attributes) throws Exception
-            {
-                // create the configuration
-                XMLPropertyListConfiguration config = new XMLPropertyListConfiguration();
-
-                // add it to the ArrayNode
-                ArrayNode node = (ArrayNode) getDigester().peek();
-                node.addValue(config);
-
-                // push the root on the stack
-                return config.getRoot();
-            }
-        });
-
-        // parse the file
-        digester.push(getRoot());
-        try
-        {
-            digester.parse(in);
-        }
-        catch (Exception e)
-        {
-            throw new ConfigurationException("Unable to parse the configuration file", e);
-        }
-    }
-
-    /**
-     * Digester rule that sets the object on the stack to the n-1 object
-     * and remove both of them from the stack. This rule is used to remove
-     * the configuration node from the stack once its value has been parsed.
-     */
-    private class SetNextAndPopRule extends SetNextRule
-    {
-        public SetNextAndPopRule(String methodName)
-        {
-            super(methodName);
-        }
-
-        public void end(String namespace, String name) throws Exception
-        {
-            super.end(namespace, name);
-            digester.pop();
-        }
-    }
-
-    public void save(Writer out) throws ConfigurationException
-    {
-        PrintWriter writer = new PrintWriter(out);
-
-        if (getEncoding() != null)
-        {
-            writer.println("<?xml version=\"1.0\" encoding=\"" + getEncoding() + "\"?>");
-        }
-        else
-        {
-            writer.println("<?xml version=\"1.0\"?>");
-        }
-
-        writer.println("<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">");
-        writer.println("<plist version=\"1.0\">");
-
-        printNode(writer, 1, getRoot());
-
-        writer.println("</plist>");
-        writer.flush();
-    }
-
-    /**
-     * Append a node to the writer, indented according to a specific level.
-     */
-    private void printNode(PrintWriter out, int indentLevel, Node node)
-    {
-        String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
-
-        if (node.getName() != null)
-        {
-            out.println(padding + "<key>" + StringEscapeUtils.escapeXml(node.getName())
+ "</key>");
-        }
-
-        List children = node.getChildren();
-        if (!children.isEmpty())
-        {
-            out.println(padding + "<dict>");
-
-            Iterator it = children.iterator();
-            while (it.hasNext())
-            {
-                Node child = (Node) it.next();
-                printNode(out, indentLevel + 1, child);
-
-                if (it.hasNext())
-                {
-                    out.println();
-                }
-            }
-
-            out.println(padding + "</dict>");
-        }
-        else
-        {
-            Object value = node.getValue();
-            printValue(out, indentLevel, value);
-        }
-    }
-
-    /**
-     * Append a value to the writer, indented according to a specific level.
-     */
-    private void printValue(PrintWriter out, int indentLevel, Object value)
-    {
-        String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
-
-        if (value instanceof Date)
-        {
-            out.println(padding + "<date>" + PListNode.format.format((Date) value)
+ "</date>");
-        }
-        else if (value instanceof Calendar)
-        {
-            printValue(out, indentLevel, ((Calendar) value).getTime());
-        }
-        else if (value instanceof Number)
-        {
-            if (value instanceof Double || value instanceof Float || value instanceof BigDecimal)
-            {
-                out.println(padding + "<real>" + value.toString() + "</real>");
-            }
-            else
-            {
-                out.println(padding + "<integer>" + value.toString() + "</integer>");
-            }
-        }
-        else if (value instanceof Boolean)
-        {
-            if (((Boolean) value).booleanValue())
-            {
-                out.println(padding + "<true/>");
-            }
-            else
-            {
-                out.println(padding + "<false/>");
-            }
-        }
-        else if (value instanceof List)
-        {
-            out.println(padding + "<array>");
-            Iterator it = ((List) value).iterator();
-            while (it.hasNext())
-            {
-                printValue(out, indentLevel + 1, it.next());
-            }
-            out.println(padding + "</array>");
-        }
-        else if (value instanceof HierarchicalConfiguration)
-        {
-            printNode(out, indentLevel, ((HierarchicalConfiguration) value).getRoot());
-        }
-        else if (value instanceof Configuration)
-        {
-            // display a flat Configuration as a dictionary
-            out.println(padding + "<dict>");
-
-            Configuration config = (Configuration) value;
-            Iterator it = config.getKeys();
-            while (it.hasNext())
-            {
-                // create a node for each property
-                String key = (String) it.next();
-                Node node = new Node(key);
-                node.setValue(config.getProperty(key));
-
-                // print the node
-                printNode(out, indentLevel + 1, node);
-
-                if (it.hasNext())
-                {
-                    out.println();
-                }
-            }
-            out.println(padding + "</dict>");
-        }
-        else if (value instanceof Map)
-        {
-            // display a Map as a dictionary
-            Map map = (Map) value;
-            printValue(out, indentLevel, new MapConfiguration(map));
-        }
-        else if (value instanceof byte[])
-        {
-            String base64 = new String(Base64.encodeBase64((byte[]) value));
-            out.println(padding + "<data>" + StringEscapeUtils.escapeXml(base64) +
"</data>");
-        }
-        else
-        {
-            out.println(padding + "<string>" + StringEscapeUtils.escapeXml(String.valueOf(value))
+ "</string>");
-        }
-    }
-
-
-    /**
-     * Node extension with addXXX methods to parse the typed data passed by Digester.
-     * <b>Do not use this class !</b> It is used internally by XMLPropertyConfiguration
-     * to parse the configuration file, it may be removed at any moment in the future.
-     */
-    public static class PListNode extends Node
-    {
-        private static DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
-
-        public void addChild(Node child)
-        {
-            super.addChild(child);
-        }
-
-        public void setName(String string)
-        {
-            super.setName(string);
-        }
-
-        public void addValue(Object value)
-        {
-            if (getValue() == null)
-            {
-                setValue(value);
-            }
-            else if (getValue() instanceof List)
-            {
-                List list = (List) getValue();
-                list.add(value);
-            }
-            else
-            {
-                List list = new ArrayList();
-                list.add(getValue());
-                list.add(value);
-                setValue(list);
-            }
-        }
-
-        public void addDateValue(String value)
-        {
-            try
-            {
-                addValue(format.parse(value));
-            }
-            catch (ParseException e)
-            {
-                e.printStackTrace();
-            }
-        }
-
-        public void addDataValue(String value)
-        {
-            addValue(Base64.decodeBase64(value.getBytes()));
-        }
-
-        public void addIntegerValue(String value)
-        {
-            addValue(new Integer(value));
-        }
-
-        public void addRealValue(String value)
-        {
-            addValue(new Double(value));
-        }
-
-        public void addTrueValue()
-        {
-            addValue(Boolean.TRUE);
-        }
-
-        public void addFalseValue()
-        {
-            addValue(Boolean.FALSE);
-        }
-
-        public void addList(ArrayNode node)
-        {
-            addValue(node.getValue());
-        }
-    }
-
-    /**
-     * Container for array elements. <b>Do not use this class !</b>
-     * It is used internally by XMLPropertyConfiguration to parse the
-     * configuration file, it may be removed at any moment in the future.
-     */
-    public static class ArrayNode extends PListNode
-    {
-        private List list = new ArrayList();
-
-        public void addValue(Object value)
-        {
-            list.add(value);
-        }
-
-        public Object getValue()
-        {
-            return list;
-        }
-    }
-}
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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.plist;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.configuration.AbstractHierarchicalFileConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.digester.AbstractObjectCreationFactory;
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.ObjectCreateRule;
+import org.apache.commons.digester.SetNextRule;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+/**
+ * Mac OS X configuration file (http://www.apple.com/DTDs/PropertyList-1.0.dtd).
+ *
+ * <p>Example:</p>
+ * <pre>
+ * &lt;?xml version="1.0"?>
+ * &lt;!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+ * &lt;plist version="1.0">
+ *     &lt;dict>
+ *         &lt;key>string&lt;/key>
+ *         &lt;string>value1&lt;/string>
+ *
+ *         &lt;key>integer&lt;/key>
+ *         &lt;integer>12345&lt;/integer>
+ *
+ *         &lt;key>real&lt;/key>
+ *         &lt;real>-123.45E-1&lt;/real>
+ *
+ *         &lt;key>boolean&lt;/key>
+ *         &lt;true/>
+ *
+ *         &lt;key>date&lt;/key>
+ *         &lt;date>2005-01-01T12:00:00-0700&lt;/date>
+ *
+ *         &lt;key>data&lt;/key>
+ *         &lt;data>RHJhY28gRG9ybWllbnMgTnVucXVhbSBUaXRpbGxhbmR1cw==&lt;/data>
+ *
+ *         &lt;key>array&lt;/key>
+ *         &lt;array>
+ *             &lt;string>value1&lt;/string>
+ *             &lt;string>value2&lt;/string>
+ *             &lt;string>value3&lt;/string>
+ *         &lt;/array>
+ *
+ *         &lt;key>dictionnary&lt;/key>
+ *         &lt;dict>
+ *             &lt;key>key1&lt;/key>
+ *             &lt;string>value1&lt;/string>
+ *             &lt;key>key2&lt;/key>
+ *             &lt;string>value2&lt;/string>
+ *             &lt;key>key3&lt;/key>
+ *             &lt;string>value3&lt;/string>
+ *         &lt;/dict>
+ *
+ *         &lt;key>nested&lt;/key>
+ *         &lt;dict>
+ *             &lt;key>node1&lt;/key>
+ *             &lt;dict>
+ *                 &lt;key>node2&lt;/key>
+ *                 &lt;dict>
+ *                     &lt;key>node3&lt;/key>
+ *                     &lt;string>value&lt;/string>
+ *                 &lt;/dict>
+ *             &lt;/dict>
+ *         &lt;/dict>
+ *
+ *     &lt;/dict>
+ * &lt;/plist>
+ * </pre>
+ *
+ * @since 1.2
+ *
+ * @author Emmanuel Bourg
+ * @version $Revision$, $Date$
+ */
+public class XMLPropertyListConfiguration extends AbstractHierarchicalFileConfiguration
+{
+    private static final int INDENT_SIZE = 4;
+
+    /**
+     * Creates an empty XMLPropertyListConfiguration object which can be
+     * used to synthesize a new plist file by adding values and
+     * then saving().
+     */
+    public XMLPropertyListConfiguration() { }
+
+    /**
+     * Creates and loads the property list from the specified file.
+     *
+     * @param fileName The name of the plist file to load.
+     * @throws org.apache.commons.configuration.ConfigurationException Error while loading
the plist file
+     */
+    public XMLPropertyListConfiguration(String fileName) throws ConfigurationException
+    {
+        super(fileName);
+    }
+
+    /**
+     * Creates and loads the property list from the specified file.
+     *
+     * @param file The plist file to load.
+     * @throws ConfigurationException Error while loading the plist file
+     */
+    public XMLPropertyListConfiguration(File file) throws ConfigurationException
+    {
+        super(file);
+    }
+
+    /**
+     * Creates and loads the property list from the specified URL.
+     *
+     * @param url The location of the plist file to load.
+     * @throws ConfigurationException Error while loading the plist file
+     */
+    public XMLPropertyListConfiguration(URL url) throws ConfigurationException
+    {
+        super(url);
+    }
+
+    public void load(Reader in) throws ConfigurationException
+    {
+        // set up the digester
+        Digester digester = new Digester();
+
+        // set up the DTD validation
+        digester.setEntityResolver(new EntityResolver()
+        {
+            public InputSource resolveEntity(String publicId, String systemId)
+            {
+                return new InputSource(getClass().getClassLoader().getResourceAsStream("PropertyList-1.0.dtd"));
+            }
+        });
+        digester.setValidating(true);
+
+        // dictionary rules
+        digester.addRule("*/key", new ObjectCreateRule(PListNode.class)
+        {
+            public void end() throws Exception
+            {
+                // leave the node on the stack to set the value
+            }
+        });
+
+        digester.addCallMethod("*/key", "setName", 0);
+
+        digester.addRule("*/dict/string", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/data", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/integer", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/real", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/true", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/false", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/date", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/dict", new SetNextAndPopRule("addChild"));
+
+        digester.addCallMethod("*/dict/string", "addValue", 0);
+        digester.addCallMethod("*/dict/data", "addDataValue", 0);
+        digester.addCallMethod("*/dict/integer", "addIntegerValue", 0);
+        digester.addCallMethod("*/dict/real", "addRealValue", 0);
+        digester.addCallMethod("*/dict/true", "addTrueValue");
+        digester.addCallMethod("*/dict/false", "addFalseValue");
+        digester.addCallMethod("*/dict/date", "addDateValue", 0);
+
+        // rules for arrays
+        digester.addRule("*/dict/array", new SetNextAndPopRule("addChild"));
+        digester.addRule("*/dict/array", new ObjectCreateRule(ArrayNode.class));
+        digester.addSetNext("*/dict/array", "addList");
+
+        digester.addRule("*/array/array", new ObjectCreateRule(ArrayNode.class));
+        digester.addSetNext("*/array/array", "addList");
+
+        digester.addCallMethod("*/array/string", "addValue", 0);
+        digester.addCallMethod("*/array/data", "addDataValue", 0);
+        digester.addCallMethod("*/array/integer", "addIntegerValue", 0);
+        digester.addCallMethod("*/array/real", "addRealValue", 0);
+        digester.addCallMethod("*/array/true", "addTrueValue");
+        digester.addCallMethod("*/array/false", "addFalseValue");
+        digester.addCallMethod("*/array/date", "addDateValue", 0);
+
+        // rule for a dictionary in an array
+        digester.addFactoryCreate("*/array/dict", new AbstractObjectCreationFactory()
+        {
+            public Object createObject(Attributes attributes) throws Exception
+            {
+                // create the configuration
+                XMLPropertyListConfiguration config = new XMLPropertyListConfiguration();
+
+                // add it to the ArrayNode
+                ArrayNode node = (ArrayNode) getDigester().peek();
+                node.addValue(config);
+
+                // push the root on the stack
+                return config.getRoot();
+            }
+        });
+
+        // parse the file
+        digester.push(getRoot());
+        try
+        {
+            digester.parse(in);
+        }
+        catch (Exception e)
+        {
+            throw new ConfigurationException("Unable to parse the configuration file", e);
+        }
+    }
+
+    /**
+     * Digester rule that sets the object on the stack to the n-1 object
+     * and remove both of them from the stack. This rule is used to remove
+     * the configuration node from the stack once its value has been parsed.
+     */
+    private class SetNextAndPopRule extends SetNextRule
+    {
+        public SetNextAndPopRule(String methodName)
+        {
+            super(methodName);
+        }
+
+        public void end(String namespace, String name) throws Exception
+        {
+            super.end(namespace, name);
+            digester.pop();
+        }
+    }
+
+    public void save(Writer out) throws ConfigurationException
+    {
+        PrintWriter writer = new PrintWriter(out);
+
+        if (getEncoding() != null)
+        {
+            writer.println("<?xml version=\"1.0\" encoding=\"" + getEncoding() + "\"?>");
+        }
+        else
+        {
+            writer.println("<?xml version=\"1.0\"?>");
+        }
+
+        writer.println("<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">");
+        writer.println("<plist version=\"1.0\">");
+
+        printNode(writer, 1, getRoot());
+
+        writer.println("</plist>");
+        writer.flush();
+    }
+
+    /**
+     * Append a node to the writer, indented according to a specific level.
+     */
+    private void printNode(PrintWriter out, int indentLevel, Node node)
+    {
+        String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
+
+        if (node.getName() != null)
+        {
+            out.println(padding + "<key>" + StringEscapeUtils.escapeXml(node.getName())
+ "</key>");
+        }
+
+        List children = node.getChildren();
+        if (!children.isEmpty())
+        {
+            out.println(padding + "<dict>");
+
+            Iterator it = children.iterator();
+            while (it.hasNext())
+            {
+                Node child = (Node) it.next();
+                printNode(out, indentLevel + 1, child);
+
+                if (it.hasNext())
+                {
+                    out.println();
+                }
+            }
+
+            out.println(padding + "</dict>");
+        }
+        else
+        {
+            Object value = node.getValue();
+            printValue(out, indentLevel, value);
+        }
+    }
+
+    /**
+     * Append a value to the writer, indented according to a specific level.
+     */
+    private void printValue(PrintWriter out, int indentLevel, Object value)
+    {
+        String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
+
+        if (value instanceof Date)
+        {
+            out.println(padding + "<date>" + PListNode.format.format((Date) value)
+ "</date>");
+        }
+        else if (value instanceof Calendar)
+        {
+            printValue(out, indentLevel, ((Calendar) value).getTime());
+        }
+        else if (value instanceof Number)
+        {
+            if (value instanceof Double || value instanceof Float || value instanceof BigDecimal)
+            {
+                out.println(padding + "<real>" + value.toString() + "</real>");
+            }
+            else
+            {
+                out.println(padding + "<integer>" + value.toString() + "</integer>");
+            }
+        }
+        else if (value instanceof Boolean)
+        {
+            if (((Boolean) value).booleanValue())
+            {
+                out.println(padding + "<true/>");
+            }
+            else
+            {
+                out.println(padding + "<false/>");
+            }
+        }
+        else if (value instanceof List)
+        {
+            out.println(padding + "<array>");
+            Iterator it = ((List) value).iterator();
+            while (it.hasNext())
+            {
+                printValue(out, indentLevel + 1, it.next());
+            }
+            out.println(padding + "</array>");
+        }
+        else if (value instanceof HierarchicalConfiguration)
+        {
+            printNode(out, indentLevel, ((HierarchicalConfiguration) value).getRoot());
+        }
+        else if (value instanceof Configuration)
+        {
+            // display a flat Configuration as a dictionary
+            out.println(padding + "<dict>");
+
+            Configuration config = (Configuration) value;
+            Iterator it = config.getKeys();
+            while (it.hasNext())
+            {
+                // create a node for each property
+                String key = (String) it.next();
+                Node node = new Node(key);
+                node.setValue(config.getProperty(key));
+
+                // print the node
+                printNode(out, indentLevel + 1, node);
+
+                if (it.hasNext())
+                {
+                    out.println();
+                }
+            }
+            out.println(padding + "</dict>");
+        }
+        else if (value instanceof Map)
+        {
+            // display a Map as a dictionary
+            Map map = (Map) value;
+            printValue(out, indentLevel, new MapConfiguration(map));
+        }
+        else if (value instanceof byte[])
+        {
+            String base64 = new String(Base64.encodeBase64((byte[]) value));
+            out.println(padding + "<data>" + StringEscapeUtils.escapeXml(base64) +
"</data>");
+        }
+        else
+        {
+            out.println(padding + "<string>" + StringEscapeUtils.escapeXml(String.valueOf(value))
+ "</string>");
+        }
+    }
+
+
+    /**
+     * Node extension with addXXX methods to parse the typed data passed by Digester.
+     * <b>Do not use this class !</b> It is used internally by XMLPropertyConfiguration
+     * to parse the configuration file, it may be removed at any moment in the future.
+     */
+    public static class PListNode extends Node
+    {
+        private static DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
+
+        public void addChild(Node child)
+        {
+            super.addChild(child);
+        }
+
+        public void setName(String string)
+        {
+            super.setName(string);
+        }
+
+        public void addValue(Object value)
+        {
+            if (getValue() == null)
+            {
+                setValue(value);
+            }
+            else if (getValue() instanceof List)
+            {
+                List list = (List) getValue();
+                list.add(value);
+            }
+            else
+            {
+                List list = new ArrayList();
+                list.add(getValue());
+                list.add(value);
+                setValue(list);
+            }
+        }
+
+        public void addDateValue(String value)
+        {
+            try
+            {
+                addValue(format.parse(value));
+            }
+            catch (ParseException e)
+            {
+                e.printStackTrace();
+            }
+        }
+
+        public void addDataValue(String value)
+        {
+            addValue(Base64.decodeBase64(value.getBytes()));
+        }
+
+        public void addIntegerValue(String value)
+        {
+            addValue(new Integer(value));
+        }
+
+        public void addRealValue(String value)
+        {
+            addValue(new Double(value));
+        }
+
+        public void addTrueValue()
+        {
+            addValue(Boolean.TRUE);
+        }
+
+        public void addFalseValue()
+        {
+            addValue(Boolean.FALSE);
+        }
+
+        public void addList(ArrayNode node)
+        {
+            addValue(node.getValue());
+        }
+    }
+
+    /**
+     * Container for array elements. <b>Do not use this class !</b>
+     * It is used internally by XMLPropertyConfiguration to parse the
+     * configuration file, it may be removed at any moment in the future.
+     */
+    public static class ArrayNode extends PListNode
+    {
+        private List list = new ArrayList();
+
+        public void addValue(Object value)
+        {
+            list.add(value);
+        }
+
+        public Object getValue()
+        {
+            return list;
+        }
+    }
+}

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/plist/XMLPropertyListConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message