Coverage Report - org.apache.commons.configuration.plist.XMLPropertyListConfiguration
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLPropertyListConfiguration
82%
88/107
90%
19/21
2,552
XMLPropertyListConfiguration$1
100%
2/2
N/A
2,552
XMLPropertyListConfiguration$ArrayNode
100%
5/5
N/A
2,552
XMLPropertyListConfiguration$PListNode
78%
28/36
67%
2/3
2,552
XMLPropertyListConfiguration$XMLPropertyListHandler
100%
52/52
100%
16/16
2,552
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.configuration.plist;
 19  
 
 20  
 import java.io.File;
 21  
 import java.io.PrintWriter;
 22  
 import java.io.Reader;
 23  
 import java.io.Writer;
 24  
 import java.math.BigDecimal;
 25  
 import java.math.BigInteger;
 26  
 import java.net.URL;
 27  
 import java.text.DateFormat;
 28  
 import java.text.ParseException;
 29  
 import java.text.SimpleDateFormat;
 30  
 import java.util.ArrayList;
 31  
 import java.util.Calendar;
 32  
 import java.util.Collection;
 33  
 import java.util.Date;
 34  
 import java.util.Iterator;
 35  
 import java.util.List;
 36  
 import java.util.Map;
 37  
 import java.util.TimeZone;
 38  
 
 39  
 import javax.xml.parsers.SAXParser;
 40  
 import javax.xml.parsers.SAXParserFactory;
 41  
 
 42  
 import org.apache.commons.codec.binary.Base64;
 43  
 import org.apache.commons.configuration.AbstractHierarchicalFileConfiguration;
 44  
 import org.apache.commons.configuration.Configuration;
 45  
 import org.apache.commons.configuration.ConfigurationException;
 46  
 import org.apache.commons.configuration.HierarchicalConfiguration;
 47  
 import org.apache.commons.configuration.MapConfiguration;
 48  
 import org.apache.commons.lang.StringEscapeUtils;
 49  
 import org.apache.commons.lang.StringUtils;
 50  
 import org.xml.sax.Attributes;
 51  
 import org.xml.sax.EntityResolver;
 52  
 import org.xml.sax.InputSource;
 53  
 import org.xml.sax.SAXException;
 54  
 import org.xml.sax.helpers.DefaultHandler;
 55  
 
 56  
 /**
 57  
  * Property list file (plist) in XML format as used by Mac OS X (http://www.apple.com/DTDs/PropertyList-1.0.dtd).
 58  
  * This configuration doesn't support the binary format used in OS X 10.4.
 59  
  *
 60  
  * <p>Example:</p>
 61  
  * <pre>
 62  
  * &lt;?xml version="1.0"?>
 63  
  * &lt;!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
 64  
  * &lt;plist version="1.0">
 65  
  *     &lt;dict>
 66  
  *         &lt;key>string&lt;/key>
 67  
  *         &lt;string>value1&lt;/string>
 68  
  *
 69  
  *         &lt;key>integer&lt;/key>
 70  
  *         &lt;integer>12345&lt;/integer>
 71  
  *
 72  
  *         &lt;key>real&lt;/key>
 73  
  *         &lt;real>-123.45E-1&lt;/real>
 74  
  *
 75  
  *         &lt;key>boolean&lt;/key>
 76  
  *         &lt;true/>
 77  
  *
 78  
  *         &lt;key>date&lt;/key>
 79  
  *         &lt;date>2005-01-01T12:00:00Z&lt;/date>
 80  
  *
 81  
  *         &lt;key>data&lt;/key>
 82  
  *         &lt;data>RHJhY28gRG9ybWllbnMgTnVucXVhbSBUaXRpbGxhbmR1cw==&lt;/data>
 83  
  *
 84  
  *         &lt;key>array&lt;/key>
 85  
  *         &lt;array>
 86  
  *             &lt;string>value1&lt;/string>
 87  
  *             &lt;string>value2&lt;/string>
 88  
  *             &lt;string>value3&lt;/string>
 89  
  *         &lt;/array>
 90  
  *
 91  
  *         &lt;key>dictionnary&lt;/key>
 92  
  *         &lt;dict>
 93  
  *             &lt;key>key1&lt;/key>
 94  
  *             &lt;string>value1&lt;/string>
 95  
  *             &lt;key>key2&lt;/key>
 96  
  *             &lt;string>value2&lt;/string>
 97  
  *             &lt;key>key3&lt;/key>
 98  
  *             &lt;string>value3&lt;/string>
 99  
  *         &lt;/dict>
 100  
  *
 101  
  *         &lt;key>nested&lt;/key>
 102  
  *         &lt;dict>
 103  
  *             &lt;key>node1&lt;/key>
 104  
  *             &lt;dict>
 105  
  *                 &lt;key>node2&lt;/key>
 106  
  *                 &lt;dict>
 107  
  *                     &lt;key>node3&lt;/key>
 108  
  *                     &lt;string>value&lt;/string>
 109  
  *                 &lt;/dict>
 110  
  *             &lt;/dict>
 111  
  *         &lt;/dict>
 112  
  *
 113  
  *     &lt;/dict>
 114  
  * &lt;/plist>
 115  
  * </pre>
 116  
  *
 117  
  * @since 1.2
 118  
  *
 119  
  * @author Emmanuel Bourg
 120  
  * @version $Revision: 727664 $, $Date: 2008-12-18 08:16:09 +0100 (Do, 18 Dez 2008) $
 121  
  */
 122  
 public class XMLPropertyListConfiguration extends AbstractHierarchicalFileConfiguration
 123  
 {
 124  
     /**
 125  
      * The serial version UID.
 126  
      */
 127  
     private static final long serialVersionUID = -3162063751042475985L;
 128  
 
 129  
     /** Size of the indentation for the generated file. */
 130  
     private static final int INDENT_SIZE = 4;
 131  
 
 132  
     /**
 133  
      * Creates an empty XMLPropertyListConfiguration object which can be
 134  
      * used to synthesize a new plist file by adding values and
 135  
      * then saving().
 136  
      */
 137  
     public XMLPropertyListConfiguration()
 138  69
     {
 139  69
     }
 140  
 
 141  
     /**
 142  
      * Creates a new instance of <code>XMLPropertyListConfiguration</code> and
 143  
      * copies the content of the specified configuration into this object.
 144  
      *
 145  
      * @param configuration the configuration to copy
 146  
      * @since 1.4
 147  
      */
 148  
     public XMLPropertyListConfiguration(HierarchicalConfiguration configuration)
 149  
     {
 150  1
         super(configuration);
 151  1
     }
 152  
 
 153  
     /**
 154  
      * Creates and loads the property list from the specified file.
 155  
      *
 156  
      * @param fileName The name of the plist file to load.
 157  
      * @throws org.apache.commons.configuration.ConfigurationException Error
 158  
      * while loading the plist file
 159  
      */
 160  
     public XMLPropertyListConfiguration(String fileName) throws ConfigurationException
 161  
     {
 162  2
         super(fileName);
 163  2
     }
 164  
 
 165  
     /**
 166  
      * Creates and loads the property list from the specified file.
 167  
      *
 168  
      * @param file The plist file to load.
 169  
      * @throws ConfigurationException Error while loading the plist file
 170  
      */
 171  
     public XMLPropertyListConfiguration(File file) throws ConfigurationException
 172  
     {
 173  11
         super(file);
 174  11
     }
 175  
 
 176  
     /**
 177  
      * Creates and loads the property list from the specified URL.
 178  
      *
 179  
      * @param url The location of the plist file to load.
 180  
      * @throws ConfigurationException Error while loading the plist file
 181  
      */
 182  
     public XMLPropertyListConfiguration(URL url) throws ConfigurationException
 183  
     {
 184  0
         super(url);
 185  0
     }
 186  
 
 187  
     public void setProperty(String key, Object value)
 188  
     {
 189  
         // special case for byte arrays, they must be stored as is in the configuration
 190  4
         if (value instanceof byte[])
 191  
         {
 192  2
             fireEvent(EVENT_SET_PROPERTY, key, value, true);
 193  2
             setDetailEvents(false);
 194  
             try
 195  
             {
 196  2
                 clearProperty(key);
 197  2
                 addPropertyDirect(key, value);
 198  
             }
 199  
             finally
 200  
             {
 201  2
                 setDetailEvents(true);
 202  2
             }
 203  2
             fireEvent(EVENT_SET_PROPERTY, key, value, false);
 204  
         }
 205  
         else
 206  
         {
 207  2
             super.setProperty(key, value);
 208  
         }
 209  4
     }
 210  
 
 211  
     public void addProperty(String key, Object value)
 212  
     {
 213  14
         if (value instanceof byte[])
 214  
         {
 215  2
             fireEvent(EVENT_ADD_PROPERTY, key, value, true);
 216  2
             addPropertyDirect(key, value);
 217  2
             fireEvent(EVENT_ADD_PROPERTY, key, value, false);
 218  
         }
 219  
         else
 220  
         {
 221  12
             super.addProperty(key, value);
 222  
         }
 223  14
     }
 224  
 
 225  
     public void load(Reader in) throws ConfigurationException
 226  
     {
 227  
         // set up the DTD validation
 228  28
         EntityResolver resolver = new EntityResolver()
 229  
         {
 230  28
             public InputSource resolveEntity(String publicId, String systemId)
 231  
             {
 232  28
                 return new InputSource(getClass().getClassLoader().getResourceAsStream("PropertyList-1.0.dtd"));
 233  
             }
 234  
         };
 235  
 
 236  
         // parse the file
 237  28
         XMLPropertyListHandler handler = new XMLPropertyListHandler(getRoot());
 238  
         try
 239  
         {
 240  28
             SAXParserFactory factory = SAXParserFactory.newInstance();
 241  28
             factory.setValidating(true);
 242  
 
 243  28
             SAXParser parser = factory.newSAXParser();
 244  28
             parser.getXMLReader().setEntityResolver(resolver);
 245  28
             parser.getXMLReader().setContentHandler(handler);
 246  28
             parser.getXMLReader().parse(new InputSource(in));
 247  
         }
 248  0
         catch (Exception e)
 249  
         {
 250  0
             throw new ConfigurationException("Unable to parse the configuration file", e);
 251  28
         }
 252  28
     }
 253  
 
 254  
     public void save(Writer out) throws ConfigurationException
 255  
     {
 256  3
         PrintWriter writer = new PrintWriter(out);
 257  
 
 258  3
         if (getEncoding() != null)
 259  
         {
 260  0
             writer.println("<?xml version=\"1.0\" encoding=\"" + getEncoding() + "\"?>");
 261  
         }
 262  
         else
 263  
         {
 264  3
             writer.println("<?xml version=\"1.0\"?>");
 265  
         }
 266  
 
 267  3
         writer.println("<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">");
 268  3
         writer.println("<plist version=\"1.0\">");
 269  
 
 270  3
         printNode(writer, 1, getRoot());
 271  
 
 272  3
         writer.println("</plist>");
 273  3
         writer.flush();
 274  3
     }
 275  
 
 276  
     /**
 277  
      * Append a node to the writer, indented according to a specific level.
 278  
      */
 279  
     private void printNode(PrintWriter out, int indentLevel, Node node)
 280  
     {
 281  28
         String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
 282  
 
 283  28
         if (node.getName() != null)
 284  
         {
 285  23
             out.println(padding + "<key>" + StringEscapeUtils.escapeXml(node.getName()) + "</key>");
 286  
         }
 287  
 
 288  28
         List children = node.getChildren();
 289  28
         if (!children.isEmpty())
 290  
         {
 291  9
             out.println(padding + "<dict>");
 292  
 
 293  9
             Iterator it = children.iterator();
 294  32
             while (it.hasNext())
 295  
             {
 296  23
                 Node child = (Node) it.next();
 297  23
                 printNode(out, indentLevel + 1, child);
 298  
 
 299  23
                 if (it.hasNext())
 300  
                 {
 301  14
                     out.println();
 302  
                 }
 303  
             }
 304  
 
 305  9
             out.println(padding + "</dict>");
 306  
         }
 307  
         else
 308  
         {
 309  19
             Object value = node.getValue();
 310  19
             printValue(out, indentLevel, value);
 311  
         }
 312  28
     }
 313  
 
 314  
     /**
 315  
      * Append a value to the writer, indented according to a specific level.
 316  
      */
 317  
     private void printValue(PrintWriter out, int indentLevel, Object value)
 318  
     {
 319  30
         String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
 320  
 
 321  30
         if (value instanceof Date)
 322  
         {
 323  2
             synchronized (PListNode.format)
 324  
             {
 325  2
                 out.println(padding + "<date>" + PListNode.format.format((Date) value) + "</date>");
 326  2
             }
 327  
         }
 328  28
         else if (value instanceof Calendar)
 329  
         {
 330  0
             printValue(out, indentLevel, ((Calendar) value).getTime());
 331  
         }
 332  28
         else if (value instanceof Number)
 333  
         {
 334  2
             if (value instanceof Double || value instanceof Float || value instanceof BigDecimal)
 335  
             {
 336  1
                 out.println(padding + "<real>" + value.toString() + "</real>");
 337  
             }
 338  
             else
 339  
             {
 340  1
                 out.println(padding + "<integer>" + value.toString() + "</integer>");
 341  
             }
 342  
         }
 343  26
         else if (value instanceof Boolean)
 344  
         {
 345  2
             if (((Boolean) value).booleanValue())
 346  
             {
 347  1
                 out.println(padding + "<true/>");
 348  
             }
 349  
             else
 350  
             {
 351  1
                 out.println(padding + "<false/>");
 352  
             }
 353  
         }
 354  24
         else if (value instanceof List)
 355  
         {
 356  5
             out.println(padding + "<array>");
 357  5
             Iterator it = ((List) value).iterator();
 358  16
             while (it.hasNext())
 359  
             {
 360  11
                 printValue(out, indentLevel + 1, it.next());
 361  
             }
 362  5
             out.println(padding + "</array>");
 363  
         }
 364  19
         else if (value instanceof HierarchicalConfiguration)
 365  
         {
 366  2
             printNode(out, indentLevel, ((HierarchicalConfiguration) value).getRoot());
 367  
         }
 368  17
         else if (value instanceof Configuration)
 369  
         {
 370  
             // display a flat Configuration as a dictionary
 371  0
             out.println(padding + "<dict>");
 372  
 
 373  0
             Configuration config = (Configuration) value;
 374  0
             Iterator it = config.getKeys();
 375  0
             while (it.hasNext())
 376  
             {
 377  
                 // create a node for each property
 378  0
                 String key = (String) it.next();
 379  0
                 Node node = new Node(key);
 380  0
                 node.setValue(config.getProperty(key));
 381  
 
 382  
                 // print the node
 383  0
                 printNode(out, indentLevel + 1, node);
 384  
 
 385  0
                 if (it.hasNext())
 386  
                 {
 387  0
                     out.println();
 388  
                 }
 389  
             }
 390  0
             out.println(padding + "</dict>");
 391  
         }
 392  17
         else if (value instanceof Map)
 393  
         {
 394  
             // display a Map as a dictionary
 395  0
             Map map = (Map) value;
 396  0
             printValue(out, indentLevel, new MapConfiguration(map));
 397  
         }
 398  17
         else if (value instanceof byte[])
 399  
         {
 400  3
             String base64 = new String(Base64.encodeBase64((byte[]) value));
 401  3
             out.println(padding + "<data>" + StringEscapeUtils.escapeXml(base64) + "</data>");
 402  
         }
 403  
         else
 404  
         {
 405  14
             out.println(padding + "<string>" + StringEscapeUtils.escapeXml(String.valueOf(value)) + "</string>");
 406  
         }
 407  30
     }
 408  
 
 409  
     /**
 410  
      * SAX Handler to build the configuration nodes while the document is being parsed.
 411  
      */
 412  
     private static class XMLPropertyListHandler extends DefaultHandler
 413  
     {
 414  
         /** The buffer containing the text node being read */
 415  28
         private StringBuffer buffer = new StringBuffer();
 416  
 
 417  
         /** The stack of configuration nodes */
 418  28
         private List stack = new ArrayList();
 419  
 
 420  
         public XMLPropertyListHandler(Node root)
 421  28
         {
 422  28
             push(root);
 423  28
         }
 424  
 
 425  
         /**
 426  
          * Return the node on the top of the stack.
 427  
          */
 428  
         private Node peek()
 429  
         {
 430  2168
             if (!stack.isEmpty())
 431  
             {
 432  2140
                 return (Node) stack.get(stack.size() - 1);
 433  
             }
 434  
             else
 435  
             {
 436  28
                 return null;
 437  
             }
 438  
         }
 439  
 
 440  
         /**
 441  
          * Remove and return the node on the top of the stack.
 442  
          */
 443  
         private Node pop()
 444  
         {
 445  786
             if (!stack.isEmpty())
 446  
             {
 447  758
                 return (Node) stack.remove(stack.size() - 1);
 448  
             }
 449  
             else
 450  
             {
 451  28
                 return null;
 452  
             }
 453  
         }
 454  
 
 455  
         /**
 456  
          * Put a node on the top of the stack.
 457  
          */
 458  
         private void push(Node node)
 459  
         {
 460  758
             stack.add(node);
 461  758
         }
 462  
 
 463  
         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
 464  
         {
 465  1438
             if ("array".equals(qName))
 466  
             {
 467  130
                 push(new ArrayNode());
 468  
             }
 469  1308
             else if ("dict".equals(qName))
 470  
             {
 471  184
                 if (peek() instanceof ArrayNode)
 472  
                 {
 473  
                     // create the configuration
 474  52
                     XMLPropertyListConfiguration config = new XMLPropertyListConfiguration();
 475  
 
 476  
                     // add it to the ArrayNode
 477  52
                     ArrayNode node = (ArrayNode) peek();
 478  52
                     node.addValue(config);
 479  
 
 480  
                     // push the root on the stack
 481  52
                     push(config.getRoot());
 482  
                 }
 483  
             }
 484  1438
         }
 485  
 
 486  
         public void endElement(String uri, String localName, String qName) throws SAXException
 487  
         {
 488  1438
             if ("key".equals(qName))
 489  
             {
 490  
                 // create a new node, link it to its parent and push it on the stack
 491  548
                 PListNode node = new PListNode();
 492  548
                 node.setName(buffer.toString());
 493  548
                 peek().addChild(node);
 494  548
                 push(node);
 495  
             }
 496  890
             else if ("dict".equals(qName))
 497  
             {
 498  
                 // remove the root of the XMLPropertyListConfiguration previously pushed on the stack
 499  184
                 pop();
 500  
             }
 501  
             else
 502  
             {
 503  706
                 if ("string".equals(qName))
 504  
                 {
 505  364
                     ((PListNode) peek()).addValue(buffer.toString());
 506  
                 }
 507  342
                 else if ("integer".equals(qName))
 508  
                 {
 509  26
                     ((PListNode) peek()).addIntegerValue(buffer.toString());
 510  
                 }
 511  316
                 else if ("real".equals(qName))
 512  
                 {
 513  26
                     ((PListNode) peek()).addRealValue(buffer.toString());
 514  
                 }
 515  290
                 else if ("true".equals(qName))
 516  
                 {
 517  26
                     ((PListNode) peek()).addTrueValue();
 518  
                 }
 519  264
                 else if ("false".equals(qName))
 520  
                 {
 521  26
                     ((PListNode) peek()).addFalseValue();
 522  
                 }
 523  238
                 else if ("data".equals(qName))
 524  
                 {
 525  28
                     ((PListNode) peek()).addDataValue(buffer.toString());
 526  
                 }
 527  210
                 else if ("date".equals(qName))
 528  
                 {
 529  52
                     ((PListNode) peek()).addDateValue(buffer.toString());
 530  
                 }
 531  158
                 else if ("array".equals(qName))
 532  
                 {
 533  130
                     ArrayNode array = (ArrayNode) pop();
 534  130
                     ((PListNode) peek()).addList(array);
 535  
                 }
 536  
 
 537  
                 // remove the plist node on the stack once the value has been parsed,
 538  
                 // array nodes remains on the stack for the next values in the list
 539  706
                 if (!(peek() instanceof ArrayNode))
 540  
                 {
 541  472
                     pop();
 542  
                 }
 543  
             }
 544  
 
 545  1438
             buffer.setLength(0);
 546  1438
         }
 547  
 
 548  
         public void characters(char[] ch, int start, int length) throws SAXException
 549  
         {
 550  1044
             buffer.append(ch, start, length);
 551  1044
         }
 552  
     }
 553  
 
 554  
     /**
 555  
      * Node extension with addXXX methods to parse the typed data passed by the SAX handler.
 556  
      * <b>Do not use this class !</b> It is used internally by XMLPropertyConfiguration
 557  
      * to parse the configuration file, it may be removed at any moment in the future.
 558  
      */
 559  682
     public static class PListNode extends Node
 560  
     {
 561  
         /**
 562  
          * The serial version UID.
 563  
          */
 564  
         private static final long serialVersionUID = -7614060264754798317L;
 565  
 
 566  
         /** The MacOS format of dates in plist files. */
 567  2
         private static DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
 568  
         static
 569  
         {
 570  2
             format.setTimeZone(TimeZone.getTimeZone("UTC"));
 571  
         }
 572  
 
 573  
         /** The GNUstep format of dates in plist files. */
 574  2
         private static DateFormat gnustepFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
 575  
 
 576  
         /**
 577  
          * Update the value of the node. If the existing value is null, it's
 578  
          * replaced with the new value. If the existing value is a list, the
 579  
          * specified value is appended to the list. If the existing value is
 580  
          * not null, a list with the two values is built.
 581  
          *
 582  
          * @param value the value to be added
 583  
          */
 584  
         public void addValue(Object value)
 585  
         {
 586  444
             if (getValue() == null)
 587  
             {
 588  444
                 setValue(value);
 589  
             }
 590  0
             else if (getValue() instanceof Collection)
 591  
             {
 592  0
                 Collection collection = (Collection) getValue();
 593  0
                 collection.add(value);
 594  
             }
 595  
             else
 596  
             {
 597  0
                 List list = new ArrayList();
 598  0
                 list.add(getValue());
 599  0
                 list.add(value);
 600  0
                 setValue(list);
 601  
             }
 602  444
         }
 603  
 
 604  
         /**
 605  
          * Parse the specified string as a date and add it to the values of the node.
 606  
          *
 607  
          * @param value the value to be added
 608  
          */
 609  
         public void addDateValue(String value)
 610  
         {
 611  
             try
 612  
             {
 613  52
                 if (value.indexOf(' ') != -1)
 614  
                 {
 615  
                     // parse the date using the GNUstep format
 616  25
                     synchronized (gnustepFormat)
 617  
                     {
 618  25
                         addValue(gnustepFormat.parse(value));
 619  25
                     }
 620  
                 }
 621  
                 else
 622  
                 {
 623  
                     // parse the date using the MacOS X format
 624  27
                     synchronized (format)
 625  
                     {
 626  27
                         addValue(format.parse(value));
 627  27
                     }
 628  
                 }
 629  
             }
 630  0
             catch (ParseException e)
 631  
             {
 632  
                 // ignore
 633  
                 ;
 634  52
             }
 635  52
         }
 636  
 
 637  
         /**
 638  
          * Parse the specified string as a byte array in base 64 format
 639  
          * and add it to the values of the node.
 640  
          *
 641  
          * @param value the value to be added
 642  
          */
 643  
         public void addDataValue(String value)
 644  
         {
 645  28
             addValue(Base64.decodeBase64(value.getBytes()));
 646  28
         }
 647  
 
 648  
         /**
 649  
          * Parse the specified string as an Interger and add it to the values of the node.
 650  
          *
 651  
          * @param value the value to be added
 652  
          */
 653  
         public void addIntegerValue(String value)
 654  
         {
 655  26
             addValue(new BigInteger(value));
 656  26
         }
 657  
 
 658  
         /**
 659  
          * Parse the specified string as a Double and add it to the values of the node.
 660  
          *
 661  
          * @param value the value to be added
 662  
          */
 663  
         public void addRealValue(String value)
 664  
         {
 665  26
             addValue(new BigDecimal(value));
 666  26
         }
 667  
 
 668  
         /**
 669  
          * Add a boolean value 'true' to the values of the node.
 670  
          */
 671  
         public void addTrueValue()
 672  
         {
 673  26
             addValue(Boolean.TRUE);
 674  26
         }
 675  
 
 676  
         /**
 677  
          * Add a boolean value 'false' to the values of the node.
 678  
          */
 679  
         public void addFalseValue()
 680  
         {
 681  26
             addValue(Boolean.FALSE);
 682  26
         }
 683  
 
 684  
         /**
 685  
          * Add a sublist to the values of the node.
 686  
          *
 687  
          * @param node the node whose value will be added to the current node value
 688  
          */
 689  
         public void addList(ArrayNode node)
 690  
         {
 691  130
             addValue(node.getValue());
 692  130
         }
 693  
     }
 694  
 
 695  
     /**
 696  
      * Container for array elements. <b>Do not use this class !</b>
 697  
      * It is used internally by XMLPropertyConfiguration to parse the
 698  
      * configuration file, it may be removed at any moment in the future.
 699  
      */
 700  130
     public static class ArrayNode extends PListNode
 701  
     {
 702  
         /**
 703  
          * The serial version UID.
 704  
          */
 705  
         private static final long serialVersionUID = 5586544306664205835L;
 706  
 
 707  
         /** The list of values in the array. */
 708  130
         private List list = new ArrayList();
 709  
 
 710  
         /**
 711  
          * Add an object to the array.
 712  
          *
 713  
          * @param value the value to be added
 714  
          */
 715  
         public void addValue(Object value)
 716  
         {
 717  286
             list.add(value);
 718  286
         }
 719  
 
 720  
         /**
 721  
          * Return the list of values in the array.
 722  
          *
 723  
          * @return the {@link List} of values
 724  
          */
 725  
         public Object getValue()
 726  
         {
 727  130
             return list;
 728  
         }
 729  
     }
 730  
 }