Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 10566 invoked from network); 22 Nov 2005 20:42:27 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 22 Nov 2005 20:42:27 -0000 Received: (qmail 58007 invoked by uid 500); 22 Nov 2005 20:42:06 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 57666 invoked by uid 500); 22 Nov 2005 20:42:04 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 57315 invoked by uid 500); 22 Nov 2005 20:42:01 -0000 Received: (qmail 57270 invoked by uid 99); 22 Nov 2005 20:42:00 -0000 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Tue, 22 Nov 2005 12:41:57 -0800 Received: (qmail 9883 invoked by uid 65534); 22 Nov 2005 20:41:37 -0000 Message-ID: <20051122204137.9880.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commons-cvs@jakarta.apache.org From: oheger@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N 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). - * - *

Example:

- *
- * <?xml version="1.0"?>
- * <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
- * <plist version="1.0">
- *     <dict>
- *         <key>string</key>
- *         <string>value1</string>
- *
- *         <key>integer</key>
- *         <integer>12345</integer>
- *
- *         <key>real</key>
- *         <real>-123.45E-1</real>
- *
- *         <key>boolean</key>
- *         <true/>
- *
- *         <key>date</key>
- *         <date>2005-01-01T12:00:00-0700</date>
- *
- *         <key>data</key>
- *         <data>RHJhY28gRG9ybWllbnMgTnVucXVhbSBUaXRpbGxhbmR1cw==</data>
- *
- *         <key>array</key>
- *         <array>
- *             <string>value1</string>
- *             <string>value2</string>
- *             <string>value3</string>
- *         </array>
- *
- *         <key>dictionnary</key>
- *         <dict>
- *             <key>key1</key>
- *             <string>value1</string>
- *             <key>key2</key>
- *             <string>value2</string>
- *             <key>key3</key>
- *             <string>value3</string>
- *         </dict>
- *
- *         <key>nested</key>
- *         <dict>
- *             <key>node1</key>
- *             <dict>
- *                 <key>node2</key>
- *                 <dict>
- *                     <key>node3</key>
- *                     <string>value</string>
- *                 </dict>
- *             </dict>
- *         </dict>
- *
- *     </dict>
- * </plist>
- * 
- * - * @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(""); - } - else - { - writer.println(""); - } - - writer.println(""); - writer.println(""); - - printNode(writer, 1, getRoot()); - - writer.println(""); - 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 + "" + StringEscapeUtils.escapeXml(node.getName()) + ""); - } - - List children = node.getChildren(); - if (!children.isEmpty()) - { - out.println(padding + ""); - - 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 + ""); - } - 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 + "" + PListNode.format.format((Date) value) + ""); - } - 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 + "" + value.toString() + ""); - } - else - { - out.println(padding + "" + value.toString() + ""); - } - } - else if (value instanceof Boolean) - { - if (((Boolean) value).booleanValue()) - { - out.println(padding + ""); - } - else - { - out.println(padding + ""); - } - } - else if (value instanceof List) - { - out.println(padding + ""); - Iterator it = ((List) value).iterator(); - while (it.hasNext()) - { - printValue(out, indentLevel + 1, it.next()); - } - out.println(padding + ""); - } - 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 + ""); - - 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 + ""); - } - 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 + "" + StringEscapeUtils.escapeXml(base64) + ""); - } - else - { - out.println(padding + "" + StringEscapeUtils.escapeXml(String.valueOf(value)) + ""); - } - } - - - /** - * Node extension with addXXX methods to parse the typed data passed by Digester. - * Do not use this class ! 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. Do not use this class ! - * 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). + * + *

Example:

+ *
+ * <?xml version="1.0"?>
+ * <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+ * <plist version="1.0">
+ *     <dict>
+ *         <key>string</key>
+ *         <string>value1</string>
+ *
+ *         <key>integer</key>
+ *         <integer>12345</integer>
+ *
+ *         <key>real</key>
+ *         <real>-123.45E-1</real>
+ *
+ *         <key>boolean</key>
+ *         <true/>
+ *
+ *         <key>date</key>
+ *         <date>2005-01-01T12:00:00-0700</date>
+ *
+ *         <key>data</key>
+ *         <data>RHJhY28gRG9ybWllbnMgTnVucXVhbSBUaXRpbGxhbmR1cw==</data>
+ *
+ *         <key>array</key>
+ *         <array>
+ *             <string>value1</string>
+ *             <string>value2</string>
+ *             <string>value3</string>
+ *         </array>
+ *
+ *         <key>dictionnary</key>
+ *         <dict>
+ *             <key>key1</key>
+ *             <string>value1</string>
+ *             <key>key2</key>
+ *             <string>value2</string>
+ *             <key>key3</key>
+ *             <string>value3</string>
+ *         </dict>
+ *
+ *         <key>nested</key>
+ *         <dict>
+ *             <key>node1</key>
+ *             <dict>
+ *                 <key>node2</key>
+ *                 <dict>
+ *                     <key>node3</key>
+ *                     <string>value</string>
+ *                 </dict>
+ *             </dict>
+ *         </dict>
+ *
+ *     </dict>
+ * </plist>
+ * 
+ * + * @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(""); + } + else + { + writer.println(""); + } + + writer.println(""); + writer.println(""); + + printNode(writer, 1, getRoot()); + + writer.println(""); + 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 + "" + StringEscapeUtils.escapeXml(node.getName()) + ""); + } + + List children = node.getChildren(); + if (!children.isEmpty()) + { + out.println(padding + ""); + + 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 + ""); + } + 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 + "" + PListNode.format.format((Date) value) + ""); + } + 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 + "" + value.toString() + ""); + } + else + { + out.println(padding + "" + value.toString() + ""); + } + } + else if (value instanceof Boolean) + { + if (((Boolean) value).booleanValue()) + { + out.println(padding + ""); + } + else + { + out.println(padding + ""); + } + } + else if (value instanceof List) + { + out.println(padding + ""); + Iterator it = ((List) value).iterator(); + while (it.hasNext()) + { + printValue(out, indentLevel + 1, it.next()); + } + out.println(padding + ""); + } + 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 + ""); + + 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 + ""); + } + 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 + "" + StringEscapeUtils.escapeXml(base64) + ""); + } + else + { + out.println(padding + "" + StringEscapeUtils.escapeXml(String.valueOf(value)) + ""); + } + } + + + /** + * Node extension with addXXX methods to parse the typed data passed by Digester. + * Do not use this class ! 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. Do not use this class ! + * 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