Coverage report

  %line %branch
org.apache.commons.configuration.plist.PropertyListConfiguration
82% 
99% 

 1  
 /*
 2  
  * Copyright 2005 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License")
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.configuration.plist;
 18  
 
 19  
 import java.io.File;
 20  
 import java.io.PrintWriter;
 21  
 import java.io.Reader;
 22  
 import java.io.Writer;
 23  
 import java.net.URL;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 
 29  
 import org.apache.commons.codec.binary.Hex;
 30  
 import org.apache.commons.configuration.AbstractHierarchicalFileConfiguration;
 31  
 import org.apache.commons.configuration.Configuration;
 32  
 import org.apache.commons.configuration.ConfigurationException;
 33  
 import org.apache.commons.configuration.HierarchicalConfiguration;
 34  
 import org.apache.commons.configuration.MapConfiguration;
 35  
 import org.apache.commons.lang.StringUtils;
 36  
 
 37  
 /**
 38  
  * NeXT / OpenStep style configuration.
 39  
  * (http://developer.apple.com/documentation/Cocoa/Conceptual/PropertyLists/Concepts/OldStylePListsConcept.html)
 40  
  *
 41  
  * <p>Example:</p>
 42  
  * <pre>
 43  
  * {
 44  
  *     foo = "bar";
 45  
  *
 46  
  *     array = ( value1, value2, value3 );
 47  
  *
 48  
  *     data = &lt;4f3e0145ab>;
 49  
  *
 50  
  *     nested =
 51  
  *     {
 52  
  *         key1 = value1;
 53  
  *         key2 = value;
 54  
  *         nested =
 55  
  *         {
 56  
  *             foo = bar
 57  
  *         }
 58  
  *     }
 59  
  * }
 60  
  * </pre>
 61  
  *
 62  
  * @since 1.2
 63  
  *
 64  
  * @author Emmanuel Bourg
 65  
  * @version $Revision$, $Date: 2005-12-06 04:10:27 +0100 (Tue, 06 Dec 2005) $
 66  
  */
 67  
 public class PropertyListConfiguration extends AbstractHierarchicalFileConfiguration
 68  
 {
 69  
     /** Size of the indentation for the generated file. */
 70  
     private static final int INDENT_SIZE = 4;
 71  
 
 72  
     /**
 73  
      * Creates an empty PropertyListConfiguration object which can be
 74  
      * used to synthesize a new plist file by adding values and
 75  
      * then saving().
 76  126
      */
 77  
     public PropertyListConfiguration()
 78  252
     {
 79  252
     }
 80  
 
 81  
     /**
 82  
      * Creates and loads the property list from the specified file.
 83  
      *
 84  
      * @param fileName The name of the plist file to load.
 85  
      * @throws ConfigurationException Error while loading the plist file
 86  
      */
 87  
     public PropertyListConfiguration(String fileName) throws ConfigurationException
 88  
     {
 89  0
         super(fileName);
 90  0
     }
 91  
 
 92  
     /**
 93  
      * Creates and loads the property list from the specified file.
 94  
      *
 95  
      * @param file The plist file to load.
 96  
      * @throws ConfigurationException Error while loading the plist file
 97  1
      */
 98  1
     public PropertyListConfiguration(File file) throws ConfigurationException
 99  
     {
 100  2
         super(file);
 101  2
     }
 102  
 
 103  
     /**
 104  
      * Creates and loads the property list from the specified URL.
 105  
      *
 106  
      * @param url The location of the plist file to load.
 107  
      * @throws ConfigurationException Error while loading the plist file
 108  
      */
 109  
     public PropertyListConfiguration(URL url) throws ConfigurationException
 110  
     {
 111  0
         super(url);
 112  0
     }
 113  15
 
 114  
     public void load(Reader in) throws ConfigurationException
 115  
     {
 116  30
         PropertyListParser parser = new PropertyListParser(in);
 117  15
         try
 118  14
         {
 119  14
 
 120  30
             HierarchicalConfiguration config = parser.parse();
 121  28
             setRoot(config.getRoot());
 122  29
         }
 123  
         catch (ParseException e)
 124  14
         {
 125  2
             throw new ConfigurationException(e);
 126  
         }
 127  28
     }
 128  1
 
 129  1
     public void save(Writer out) throws ConfigurationException
 130  1
     {
 131  3
         PrintWriter writer = new PrintWriter(out);
 132  2
         printNode(writer, 0, getRoot());
 133  2
         writer.flush();
 134  2
     }
 135  
 
 136  
     /**
 137  
      * Append a node to the writer, indented according to a specific level.
 138  22
      */
 139  
     private void printNode(PrintWriter out, int indentLevel, Node node)
 140  22
     {
 141  44
         String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
 142  19
 
 143  44
         if (node.getName() != null)
 144  
         {
 145  38
             out.print(padding + quoteString(node.getName()) + " = ");
 146  22
         }
 147  22
 
 148  64
         // get all non trivial nodes
 149  44
         List children = new ArrayList(node.getChildren());
 150  64
         Iterator it = children.iterator();
 151  148
         while (it.hasNext())
 152  
         {
 153  41
             Node child = (Node) it.next();
 154  40
             if (child.getValue() == null && (child.getChildren() == class="keyword">null || child.getChildren().isEmpty()))
 155  
             {
 156  2
                 it.remove();
 157  22
             }
 158  
         }
 159  
 
 160  51
         if (!children.isEmpty())
 161  
         {
 162  6
             // skip a line, except for the root dictionary
 163  14
             if (indentLevel > 0)
 164  
             {
 165  19
                 out.println();
 166  
             }
 167  
 
 168  21
             out.println(padding + "{");
 169  33
 
 170  
             // display the children
 171  33
             it = children.iterator();
 172  66
             while (it.hasNext())
 173  19
             {
 174  38
                 Node child = (Node) it.next();
 175  
 
 176  57
                 printNode(out, indentLevel + 1, child);
 177  19
 
 178  
                 // add a semi colon for elements that are not dictionaries
 179  53
                 Object value = child.getValue();
 180  38
                 if (value != null && !(value instanceof Map) && !(value instanceof Configuration))
 181  
                 {
 182  30
                     out.println(";");
 183  19
                 }
 184  
 
 185  6
                 // skip a line after arrays and dictionaries
 186  38
                 if (it.hasNext() && (value == null || value instanceof List))
 187  
                 {
 188  12
                     out.println();
 189  7
                 }
 190  
             }
 191  
 
 192  21
             out.print(padding + "}");
 193  
 
 194  4
             // line feed if the dictionary is not in an array
 195  14
             if (node.getParent() != null)
 196  
             {
 197  8
                 out.println();
 198  
             }
 199  
         }
 200  15
         else
 201  15
         {
 202  
             // display the leaf value
 203  52
             Object value = node.getValue();
 204  30
             printValue(out, indentLevel, value);
 205  
         }
 206  44
     }
 207  
 
 208  
     /**
 209  
      * Append a value to the writer, indented according to a specific level.
 210  26
      */
 211  
     private void printValue(PrintWriter out, int indentLevel, Object value)
 212  26
     {
 213  52
         String padding = StringUtils.repeat(" ", indentLevel * INDENT_SIZE);
 214  6
 
 215  58
         if (value instanceof List)
 216  23
         {
 217  12
             out.print("( ");
 218  23
             Iterator it = ((List) value).iterator();
 219  57
             while (it.hasNext())
 220  
             {
 221  28
                 printValue(out, indentLevel + 1, it.next());
 222  22
                 if (it.hasNext())
 223  
                 {
 224  18
                     out.print(", ");
 225  
                 }
 226  20
             }
 227  12
             out.print(" )");
 228  2
         }
 229  40
         else if (value instanceof HierarchicalConfiguration)
 230  18
         {
 231  4
             printNode(out, indentLevel, ((HierarchicalConfiguration) value).getRoot());
 232  
         }
 233  36
         else if (value instanceof Configuration)
 234  
         {
 235  
             // display a flat Configuration as a dictionary
 236  0
             out.println();
 237  0
             out.println(padding + "{");
 238  
 
 239  0
             Configuration config = (Configuration) value;
 240  0
             Iterator it = config.getKeys();
 241  0
             while (it.hasNext())
 242  
             {
 243  0
                 String key = (String) it.next();
 244  0
                 Node node = new Node(key);
 245  0
                 node.setValue(config.getProperty(key));
 246  
 
 247  0
                 printNode(out, indentLevel + 1, node);
 248  0
                 out.println(";");
 249  18
             }
 250  0
             out.println(padding + "}");
 251  
         }
 252  36
         else if (value instanceof Map)
 253  
         {
 254  
             // display a Map as a dictionary
 255  18
             Map map = (Map) value;
 256  0
             printValue(out, indentLevel, new MapConfiguration(map));
 257  2
         }
 258  36
         else if (value instanceof byte[])
 259  16
         {
 260  4
             out.print("<" + new String(Hex.encodeHex((byte[]) value)) + ">");
 261  16
         }
 262  32
         else if (value != null)
 263  26
         {
 264  32
             out.print(quoteString(String.valueOf(value)));
 265  
         }
 266  52
     }
 267  
 
 268  
     /**
 269  
      * Quote the specified string if necessary, that's if the string contains:
 270  
      * <ul>
 271  
      *   <li>a space character (' ', '\t', '\r', '\n')</li>
 272  
      *   <li>a quote '"'</li>
 273  
      *   <li>special characters in plist files ('(', ')', '{', '}', '=', ';', ',')</li>
 274  
      * </ul>
 275  
      * Quotes within the string are escaped.
 276  
      *
 277  
      * <p>Examples:</p>
 278  
      * <ul>
 279  
      *   <li>abcd -> abcd</li>
 280  
      *   <li>ab cd -> "ab cd"</li>
 281  
      *   <li>foo"bar -> "foo\"bar"</li>
 282  
      *   <li>foo;bar -> "foo;bar"</li>
 283  
      * </ul>
 284  40
      */
 285  
     String quoteString(String s)
 286  1
     {
 287  80
         if (s == null)
 288  
         {
 289  41
             return null;
 290  
         }
 291  
 
 292  78
         if (s.indexOf(' ') != -1
 293  
                 || s.indexOf('\t') != -1
 294  
                 || s.indexOf('\r') != -1
 295  
                 || s.indexOf('\n') != -1
 296  
                 || s.indexOf('"') != -1
 297  
                 || s.indexOf('(') != -1
 298  
                 || s.indexOf(')') != -1
 299  
                 || s.indexOf('{') != -1
 300  
                 || s.indexOf('}') != -1
 301  
                 || s.indexOf('=') != -1
 302  5
                 || s.indexOf(',') != -1
 303  5
                 || s.indexOf(';') != -1)
 304  
         {
 305  10
             s = StringUtils.replace(s, "\"", "\\\"");
 306  49
             s = "\"" + s + "\"";
 307  
         }
 308  
 
 309  78
         return s;
 310  
     }
 311  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.