Properties.java revision 66e1a782c0ffafcb7c4226798d6ecc4cfc071916
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughesimport java.io.BufferedReader; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 23565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughesimport java.io.InputStreamReader; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStreamWriter; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.PrintStream; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.PrintWriter; 28565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughesimport java.io.Reader; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.StringReader; 30565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughesimport java.io.Writer; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.Charset; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.IllegalCharsetNameException; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.UnsupportedCharsetException; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.xml.parsers.DocumentBuilder; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.xml.parsers.DocumentBuilderFactory; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.xml.parsers.ParserConfigurationException; 3703c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughesimport org.w3c.dom.Document; 3803c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughesimport org.w3c.dom.Element; 3903c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughesimport org.w3c.dom.Node; 4003c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughesimport org.w3c.dom.NodeList; 4103c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughesimport org.w3c.dom.Text; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.EntityResolver; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.ErrorHandler; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.InputSource; 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.SAXException; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.SAXParseException; 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 49f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * A {@code Properties} object is a {@code Hashtable} where the keys and values 50f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * must be {@code String}s. Each property can have a default 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Properties} list which specifies the default 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * values to be used when a given key is not found in this {@code Properties} 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * instance. 54f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 5500ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * <a name="character_encoding"><h3>Character Encoding</h3></a> 5600ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * <p>Note that in some cases {@code Properties} uses ISO-8859-1 instead of UTF-8. 5700ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * ISO-8859-1 is only capable of representing a tiny subset of Unicode. 5800ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * Use either the {@code loadFromXML}/{@code storeToXML} methods (which use UTF-8 by 5900ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * default) or the {@code load}/{@code store} overloads that take 6000ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * an {@code OutputStreamWriter} (so you can supply a UTF-8 instance) instead. 6100ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Hashtable 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.System#getProperties 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 65f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonpublic class Properties extends Hashtable<Object, Object> { 66f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final long serialVersionUID = 4112578634029874840L; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private transient DocumentBuilder builder = null; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson private static final String PROP_DTD_NAME = "http://java.sun.com/dtd/properties.dtd"; 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson private static final String PROP_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " <!ELEMENT properties (comment?, entry*) >" 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " <!ATTLIST properties version CDATA #FIXED \"1.0\" >" 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " <!ELEMENT comment (#PCDATA) >" 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " <!ELEMENT entry (#PCDATA) >" 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " <!ATTLIST entry key CDATA #REQUIRED >"; 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The default values for keys not found in this {@code Properties} 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * instance. 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected Properties defaults; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int NONE = 0, SLASH = 1, UNICODE = 2, CONTINUE = 3, 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project KEY_DONE = 4, IGNORE = 5; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new {@code Properties} object. 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Properties() { 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(); 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new {@code Properties} object using the specified default 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Properties}. 99f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param properties 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the default {@code Properties}. 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Properties(Properties properties) { 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project defaults = properties; 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void dumpString(StringBuilder buffer, String string, boolean key) { 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int i = 0; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!key && i < string.length() && string.charAt(i) == ' ') { 110565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\ "); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project i++; 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (; i < string.length(); i++) { 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char ch = string.charAt(i); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (ch) { 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\t': 118565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\t"); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\n': 121565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\n"); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\f': 124565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\f"); 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\r': 127565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\r"); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project default: 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ("\\#!=:".indexOf(ch) >= 0 || (key && ch == ' ')) { 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append('\\'); 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (ch >= ' ' && ch <= '~') { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(ch); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String hex = Integer.toHexString(ch); 137565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("\\u"); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int j = 0; j < 4 - hex.length(); j++) { 139565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("0"); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(hex); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Searches for the property with the specified name. If the property is not 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * found, the default {@code Properties} are checked. If the property is not 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * found in the default {@code Properties}, {@code null} is returned. 151f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the property to find. 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the named property value, or {@code null} if it can't be found. 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getProperty(String name) { 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object result = super.get(name); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String property = result instanceof String ? (String) result : null; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (property == null && defaults != null) { 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project property = defaults.getProperty(name); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return property; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Searches for the property with the specified name. If the property is not 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * found, it looks in the default {@code Properties}. If the property is not 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * found in the default {@code Properties}, it returns the specified 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * default. 170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the property to find. 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param defaultValue 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the default value. 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the named property value. 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getProperty(String name, String defaultValue) { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object result = super.get(name); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String property = result instanceof String ? (String) result : null; 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (property == null && defaults != null) { 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project property = defaults.getProperty(name); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (property == null) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return defaultValue; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return property; 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Lists the mappings in this {@code Properties} to the specified 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code PrintStream} in a 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * human readable form. 193f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code PrintStream} to write the content to in human readable 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * form. 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void list(PrintStream out) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (out == null) { 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NullPointerException(); 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson StringBuilder buffer = new StringBuilder(80); 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Enumeration<?> keys = propertyNames(); 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (keys.hasMoreElements()) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String key = (String) keys.nextElement(); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(key); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append('='); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String property = (String) super.get(key); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Properties def = defaults; 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (property == null) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project property = (String) def.get(key); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project def = def.defaults; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (property.length() > 40) { 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(property.substring(0, 37)); 216565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("..."); 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(property); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.println(buffer.toString()); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.setLength(0); 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Lists the mappings in this {@code Properties} to the specified 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code PrintWriter} in a 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * human readable form. 229f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param writer 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code PrintWriter} to write the content to in human 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * readable form. 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void list(PrintWriter writer) { 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (writer == null) { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NullPointerException(); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 238a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson StringBuilder buffer = new StringBuilder(80); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Enumeration<?> keys = propertyNames(); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (keys.hasMoreElements()) { 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String key = (String) keys.nextElement(); 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(key); 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append('='); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String property = (String) super.get(key); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Properties def = defaults; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (property == null) { 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project property = (String) def.get(key); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project def = def.defaults; 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (property.length() > 40) { 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(property.substring(0, 37)); 252565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes buffer.append("..."); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(property); 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project writer.println(buffer.toString()); 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.setLength(0); 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 26200ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * Loads properties from the specified {@code InputStream}, assumed to be ISO-8859-1. 26300ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * See "<a href="#character_encoding">Character Encoding</a>". 26400ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * 265565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @param in the {@code InputStream} 266565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @throws IOException 267565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes */ 268565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes public synchronized void load(InputStream in) throws IOException { 269565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes if (in == null) { 270565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes throw new NullPointerException(); 271565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 27246ff2ede6c9f5ad431303d388986ec3d72b2fbd3Elliott Hughes load(new InputStreamReader(in, "ISO-8859-1")); 273565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 274565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes 275565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes /** 276565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * Loads properties from the specified {@code Reader}. 277565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * The properties file is interpreted according to the following rules: 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>Empty lines are ignored.</li> 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>Lines starting with either a "#" or a "!" are comment lines and are 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ignored.</li> 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A backslash at the end of the line escapes the following newline 283565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * character ("\r", "\n", "\r\n"). If there's whitespace after the 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * backslash it will just escape that whitespace instead of concatenating 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the lines. This does not apply to comment lines.</li> 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A property line consists of the key, the space between the key and 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the value, and the value. The key goes up to the first whitespace, "=" or 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ":" that is not escaped. The space between the key and the value contains 289565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * either one whitespace, one "=" or one ":" and any amount of additional 290565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * whitespace before and after that character. The value starts with the 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * first character after the space between the key and the value.</li> 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>Following escape sequences are recognized: "\ ", "\\", "\r", "\n", 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * "\!", "\#", "\t", "\b", "\f", and "\uXXXX" (unicode character).</li> 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 295f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 296565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @param in the {@code Reader} 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 298565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @since 1.6 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 300f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson @SuppressWarnings("fallthrough") 301565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes public synchronized void load(Reader in) throws IOException { 302f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (in == null) { 303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new NullPointerException(); 304f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int mode = NONE, unicode = 0, count = 0; 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char nextChar, buf[] = new char[40]; 307f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson int offset = 0, keyLength = -1, intVal; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean firstChar = true; 309142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson 310565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes BufferedReader br = new BufferedReader(in); 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 313565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes intVal = br.read(); 314f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (intVal == -1) { 315f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson break; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes nextChar = (char) intVal; 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset == buf.length) { 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char[] newBuf = new char[buf.length * 2]; 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.arraycopy(buf, 0, newBuf, 0, offset); 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf = newBuf; 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == UNICODE) { 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int digit = Character.digit(nextChar, 16); 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (digit >= 0) { 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unicode = (unicode << 4) + digit; 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (++count < 4) { 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (count <= 4) { 332565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes throw new IllegalArgumentException("Invalid Unicode sequence: illegal character"); 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf[offset++] = (char) unicode; 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (nextChar != '\n') { 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == SLASH) { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (nextChar) { 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\r': 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = CONTINUE; // Look for a following \n 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\n': 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = IGNORE; // Ignore whitespace on the next line 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 'b': 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextChar = '\b'; 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 'f': 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextChar = '\f'; 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 'n': 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextChar = '\n'; 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 'r': 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextChar = '\r'; 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 't': 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextChar = '\t'; 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case 'u': 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = UNICODE; 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unicode = count = 0; 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project switch (nextChar) { 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '#': 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '!': 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (firstChar) { 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 375565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes intVal = br.read(); 376f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (intVal == -1) { 377f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson break; 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson nextChar = (char) intVal; 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (nextChar == '\r' || nextChar == '\n') { 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\n': 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == CONTINUE) { // Part of a \r\n sequence 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = IGNORE; // Ignore whitespace on the next line 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 392f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // fall into the next case 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\r': 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project firstChar = true; 396a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson if (offset > 0 || (offset == 0 && keyLength == 0)) { 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (keyLength == -1) { 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = offset; 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String temp = new String(buf, 0, offset); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project put(temp.substring(0, keyLength), temp 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .substring(keyLength)); 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = -1; 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project offset = 0; 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '\\': 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == KEY_DONE) { 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = offset; 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = SLASH; 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case ':': 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project case '=': 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (keyLength == -1) { // if parsing the key 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = offset; 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (Character.isWhitespace(nextChar)) { 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == CONTINUE) { 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = IGNORE; 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if key length == 0 or value length == 0 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (offset == 0 || offset == keyLength || mode == IGNORE) { 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (keyLength == -1) { // if parsing the key 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = KEY_DONE; 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue; 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == IGNORE || mode == CONTINUE) { 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project firstChar = false; 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (mode == KEY_DONE) { 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project keyLength = offset; 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project mode = NONE; 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf[offset++] = nextChar; 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 446565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes if (mode == UNICODE && count <= 4) { 447565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes throw new IllegalArgumentException("Invalid Unicode sequence: expected format \\uxxxx"); 448565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 449f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (keyLength == -1 && offset > 0) { 450f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson keyLength = offset; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (keyLength >= 0) { 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String temp = new String(buf, 0, offset); 454565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes String key = temp.substring(0, keyLength); 455565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes String value = temp.substring(keyLength); 456565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes if (mode == SLASH) { 457565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes value += "\u0000"; 458565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 459565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes put(key, value); 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 464565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * Returns all of the property names (keys) in this {@code Properties} object. 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Enumeration<?> propertyNames() { 467565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes Hashtable<Object, Object> selected = new Hashtable<Object, Object>(); 468565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes selectProperties(selected, false); 469565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes return selected.keys(); 470565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 472565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes /** 473565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * Returns those property names (keys) in this {@code Properties} object for which 474565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * both key and value are strings. 475f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 476565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @return a set of keys in the property list 477565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @since 1.6 478565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes */ 479565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes public Set<String> stringPropertyNames() { 480866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes Hashtable<String, Object> stringProperties = new Hashtable<String, Object>(); 481565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes selectProperties(stringProperties, true); 482565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes return Collections.unmodifiableSet(stringProperties.keySet()); 483565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 484565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes 485866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes private <K> void selectProperties(Hashtable<K, Object> selectProperties, final boolean isStringOnly) { 486565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes if (defaults != null) { 487565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes defaults.selectProperties(selectProperties, isStringOnly); 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 489866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes Enumeration<Object> keys = keys(); 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (keys.hasMoreElements()) { 491866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes @SuppressWarnings("unchecked") 492866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes K key = (K) keys.nextElement(); 493866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes if (isStringOnly && !(key instanceof String)) { 494565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes // Only select property with string key and value 495866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes continue; 496565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 497866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes Object value = get(key); 498866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes selectProperties.put(key, value); 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Saves the mappings in this {@code Properties} to the specified {@code 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream}, putting the specified comment at the beginning. The output 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from this method is suitable for being read by the 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #load(InputStream)} method. 507f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out the {@code OutputStream} to write to. 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param comment the comment to add at the beginning. 510f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @throws ClassCastException if the key or value of a mapping is not a 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * String. 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @deprecated This method ignores any {@code IOException} thrown while 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * writing -- use {@link #store} instead for better exception 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handling. 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Deprecated 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void save(OutputStream out, String comment) { 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project store(out, comment); 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Maps the specified key to the specified value. If the key already exists, 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the old value is replaced. The key and value cannot be {@code null}. 527f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param name 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the key. 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param value 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the value. 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the old value mapped to the key, or {@code null}. 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object setProperty(String name, String value) { 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return put(name, value); 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 538565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes /** 53900ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * Stores properties to the specified {@code OutputStream}, using ISO-8859-1. 54000ccc7c466cf9f0c5b3df4d3276e1e4be0618f7fElliott Hughes * See "<a href="#character_encoding">Character Encoding</a>". 541f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 542565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @param out the {@code OutputStream} 543565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @param comment an optional comment to be written, or null 544565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @throws IOException 545565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @throws ClassCastException if a key or value is not a string 546565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes */ 547565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes public synchronized void store(OutputStream out, String comment) throws IOException { 54846ff2ede6c9f5ad431303d388986ec3d72b2fbd3Elliott Hughes store(new OutputStreamWriter(out, "ISO-8859-1"), comment); 549565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes } 550565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String lineSeparator; 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 554565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * Stores the mappings in this {@code Properties} object to {@code out}, 555565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * putting the specified comment at the beginning. 556f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 557bf87c56b39383f6b11c36c3cdc93df4b03fed914Brian Carlstrom * @param writer the {@code Writer} 558565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @param comment an optional comment to be written, or null 559565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @throws IOException 560565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @throws ClassCastException if a key or value is not a string 561565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes * @since 1.6 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 563565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes public synchronized void store(Writer writer, String comment) throws IOException { 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lineSeparator == null) { 565ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes lineSeparator = System.getProperty("line.separator"); 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (comment != null) { 569565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes writer.write("#"); 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project writer.write(comment); 571f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson writer.write(lineSeparator); 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 573565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes writer.write("#"); 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project writer.write(new Date().toString()); 575f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson writer.write(lineSeparator); 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 577565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes StringBuilder buffer = new StringBuilder(200); 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (Map.Entry<Object, Object> entry : entrySet()) { 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String key = (String) entry.getKey(); 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dumpString(buffer, key, true); 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append('='); 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dumpString(buffer, (String) entry.getValue(), false); 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.append(lineSeparator); 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project writer.write(buffer.toString()); 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buffer.setLength(0); 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project writer.flush(); 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Loads the properties from an {@code InputStream} containing the 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * properties in XML form. The XML document must begin with (and conform to) 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * following DOCTYPE: 594f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre> 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre> 598f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Also the content of the XML data must satisfy the DTD but the xml is not 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * validated against it. The DTD is not loaded from the SYSTEM ID. After 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this method returns the InputStream is not closed. 602f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in the InputStream containing the XML document. 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException in case an error occurs during a read operation. 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws InvalidPropertiesFormatException if the XML data is not a valid 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * properties file. 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 608f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public synchronized void loadFromXML(InputStream in) throws IOException, 609f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson InvalidPropertiesFormatException { 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NullPointerException(); 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 613f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (builder == null) { 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 616565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes // BEGIN android-removed: we still don't support validation. 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // factory.setValidating(true); 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // END android-removed 619f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project builder = factory.newDocumentBuilder(); 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ParserConfigurationException e) { 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e); 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 625f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project builder.setErrorHandler(new ErrorHandler() { 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void warning(SAXParseException e) throws SAXException { 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void error(SAXParseException e) throws SAXException { 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void fatalError(SAXParseException e) throws SAXException { 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 639f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project builder.setEntityResolver(new EntityResolver() { 641f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public InputSource resolveEntity(String publicId, 642f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson String systemId) throws SAXException, IOException { 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (systemId.equals(PROP_DTD_NAME)) { 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputSource result = new InputSource(new StringReader( 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project PROP_DTD)); 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result.setSystemId(PROP_DTD_NAME); 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 649f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson throw new SAXException("Invalid DOCTYPE declaration: " 650f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson + systemId); 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 654f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Document doc = builder.parse(in); 657f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson NodeList entries = doc.getElementsByTagName("entry"); 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (entries == null) { 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int entriesListLength = entries.getLength(); 662f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < entriesListLength; i++) { 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Element entry = (Element) entries.item(i); 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String key = entry.getAttribute("key"); 66666e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes String value = entry.getTextContent(); 667f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 669f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * key != null & value != null but key or(and) value can be 670f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * empty String 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project put(key, value); 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw e; 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (SAXException e) { 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new InvalidPropertiesFormatException(e); 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes all properties stored in this instance into the {@code 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream} in XML representation. The DOCTYPE is 684f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre> 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre> 688f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the comment is null, no comment is added to the output. UTF-8 is used 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as the encoding. The {@code OutputStream} is not closed at the end. A 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * call to this method is the same as a call to {@code storeToXML(os, 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * comment, "UTF-8")}. 693f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param os the {@code OutputStream} to write to. 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param comment the comment to add. If null, no comment is added. 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if an error occurs during writing to the output. 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 698f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson public void storeToXML(OutputStream os, String comment) throws IOException { 699565a85d06ab8bc321d39f12012468cdfb65f5cfeElliott Hughes storeToXML(os, comment, "UTF-8"); 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes all properties stored in this instance into the {@code 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream} in XML representation. The DOCTYPE is 705f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre> 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre> 709f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the comment is null, no comment is added to the output. The parameter 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code encoding} defines which encoding should be used. The {@code 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream} is not closed at the end. 713f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param os the {@code OutputStream} to write to. 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param comment the comment to add. If null, no comment is added. 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param encoding the code identifying the encoding that should be used to 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write into the {@code OutputStream}. 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if an error occurs during writing to the output. 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void storeToXML(OutputStream os, String comment, 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String encoding) throws IOException { 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null || encoding == null) { 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NullPointerException(); 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 726f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * We can write to XML file using encoding parameter but note that some 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * aliases for encodings are not supported by the XML parser. Thus we 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * have to know canonical name for encoding used to store data in XML 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * since the XML parser must recognize encoding name used to store data. 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 733f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String encodingCanonicalName; 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encodingCanonicalName = Charset.forName(encoding).name(); 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalCharsetNameException e) { 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.out.println("Warning: encoding name " + encoding 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " is illegal, using UTF-8 as default encoding"); 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encodingCanonicalName = "UTF-8"; 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (UnsupportedCharsetException e) { 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project System.out.println("Warning: encoding " + encoding 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " is not supported, using UTF-8 as default encoding"); 744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encodingCanonicalName = "UTF-8"; 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 747f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson PrintStream printStream = new PrintStream(os, false, 748f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson encodingCanonicalName); 749f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print("<?xml version=\"1.0\" encoding=\""); 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print(encodingCanonicalName); 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("\"?>"); 753f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print("<!DOCTYPE properties SYSTEM \""); 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print(PROP_DTD_NAME); 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("\">"); 757f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("<properties>"); 759f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (comment != null) { 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print("<comment>"); 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print(substitutePredefinedEntries(comment)); 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("</comment>"); 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (Map.Entry<Object, Object> entry : entrySet()) { 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String keyValue = (String) entry.getKey(); 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String entryValue = (String) entry.getValue(); 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print("<entry key=\""); 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print(substitutePredefinedEntries(keyValue)); 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print("\">"); 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.print(substitutePredefinedEntries(entryValue)); 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("</entry>"); 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.println("</properties>"); 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project printStream.flush(); 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 778f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String substitutePredefinedEntries(String s) { 78066e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes // substitution for predefined character entities to use them safely in XML. 78166e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes s = s.replaceAll("&", "&"); 78266e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes s = s.replaceAll("<", "<"); 78366e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes s = s.replaceAll(">", ">"); 78466e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes s = s.replaceAll("'", "'"); 78566e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes s = s.replaceAll("\"", """); 78666e1a782c0ffafcb7c4226798d6ecc4cfc071916Elliott Hughes return s; 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 789