Propertiespublic class Properties extends Hashtable A {@code Properties} object is a {@code Hashtable} where the keys and values
must be {@code String}s. Each property can have a default
{@code Properties} list which specifies the default
values to be used when a given key is not found in this {@code Properties}
instance. |
Fields Summary |
---|
private static final long | serialVersionUID | private transient DocumentBuilder | builder | private static final String | PROP_DTD_NAME | private static final String | PROP_DTD | protected Properties | defaultsThe default values for keys not found in this {@code Properties}
instance. | private static final int | NONE | private static final int | SLASH | private static final int | UNICODE | private static final int | CONTINUE | private static final int | KEY_DONE | private static final int | IGNORE | private static String | lineSeparator |
Constructors Summary |
---|
public Properties()Constructs a new {@code Properties} object.
super();
| public Properties(Properties properties)Constructs a new {@code Properties} object using the specified default
{@code Properties}.
defaults = properties;
|
Methods Summary |
---|
private void | dumpString(java.lang.StringBuilder buffer, java.lang.String string, boolean key)
int i = 0;
if (!key && i < string.length() && string.charAt(i) == ' ") {
buffer.append("\\ "); //$NON-NLS-1$
i++;
}
for (; i < string.length(); i++) {
char ch = string.charAt(i);
switch (ch) {
case '\t":
buffer.append("\\t"); //$NON-NLS-1$
break;
case '\n":
buffer.append("\\n"); //$NON-NLS-1$
break;
case '\f":
buffer.append("\\f"); //$NON-NLS-1$
break;
case '\r":
buffer.append("\\r"); //$NON-NLS-1$
break;
default:
if ("\\#!=:".indexOf(ch) >= 0 || (key && ch == ' ")) {
buffer.append('\\");
}
if (ch >= ' " && ch <= '~") {
buffer.append(ch);
} else {
String hex = Integer.toHexString(ch);
buffer.append("\\u"); //$NON-NLS-1$
for (int j = 0; j < 4 - hex.length(); j++) {
buffer.append("0"); //$NON-NLS-1$
}
buffer.append(hex);
}
}
}
| public java.lang.String | getProperty(java.lang.String name)Searches for the property with the specified name. If the property is not
found, the default {@code Properties} are checked. If the property is not
found in the default {@code Properties}, {@code null} is returned.
Object result = super.get(name);
String property = result instanceof String ? (String) result : null;
if (property == null && defaults != null) {
property = defaults.getProperty(name);
}
return property;
| public java.lang.String | getProperty(java.lang.String name, java.lang.String defaultValue)Searches for the property with the specified name. If the property is not
found, it looks in the default {@code Properties}. If the property is not
found in the default {@code Properties}, it returns the specified
default.
Object result = super.get(name);
String property = result instanceof String ? (String) result : null;
if (property == null && defaults != null) {
property = defaults.getProperty(name);
}
if (property == null) {
return defaultValue;
}
return property;
| private java.lang.String | getTextContent(org.w3c.dom.Node node)
String result = (node instanceof Text ? ((Text) node).getData() : "");
Node child = node.getFirstChild();
while (child != null) {
result = result + getTextContent(child);
child = child.getNextSibling();
}
return result;
| public void | list(java.io.PrintStream out)Lists the mappings in this {@code Properties} to the specified
{@code PrintStream} in a
human readable form.
if (out == null) {
throw new NullPointerException();
}
StringBuffer buffer = new StringBuffer(80);
Enumeration<?> keys = propertyNames();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
buffer.append(key);
buffer.append('=");
String property = (String) super.get(key);
Properties def = defaults;
while (property == null) {
property = (String) def.get(key);
def = def.defaults;
}
if (property.length() > 40) {
buffer.append(property.substring(0, 37));
buffer.append("..."); //$NON-NLS-1$
} else {
buffer.append(property);
}
out.println(buffer.toString());
buffer.setLength(0);
}
| public void | list(java.io.PrintWriter writer)Lists the mappings in this {@code Properties} to the specified
{@code PrintWriter} in a
human readable form.
if (writer == null) {
throw new NullPointerException();
}
StringBuffer buffer = new StringBuffer(80);
Enumeration<?> keys = propertyNames();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
buffer.append(key);
buffer.append('=");
String property = (String) super.get(key);
Properties def = defaults;
while (property == null) {
property = (String) def.get(key);
def = def.defaults;
}
if (property.length() > 40) {
buffer.append(property.substring(0, 37));
buffer.append("..."); //$NON-NLS-1$
} else {
buffer.append(property);
}
writer.println(buffer.toString());
buffer.setLength(0);
}
| public synchronized void | load(java.io.InputStream in)Loads properties from the specified {@code InputStream}. The encoding is
ISO8859-1. The {@code Properties} file is interpreted according to the
following rules:
- Empty lines are ignored.
- Lines starting with either a "#" or a "!" are comment lines and are
ignored.
- A backslash at the end of the line escapes the following newline
character ("\r", "\n", "\r\n"). If there's a whitespace after the
backslash it will just escape that whitespace instead of concatenating
the lines. This does not apply to comment lines.
- A property line consists of the key, the space between the key and
the value, and the value. The key goes up to the first whitespace, "=" or
":" that is not escaped. The space between the key and the value contains
either one whitespace, one "=" or one ":" and any number of additional
whitespaces before and after that character. The value starts with the
first character after the space between the key and the value.
- Following escape sequences are recognized: "\ ", "\\", "\r", "\n",
"\!", "\#", "\t", "\b", "\f", and "\uXXXX" (unicode character).
int mode = NONE, unicode = 0, count = 0;
char nextChar, buf[] = new char[40];
int offset = 0, keyLength = -1;
boolean firstChar = true;
byte[] inbuf = new byte[256];
int inbufCount = 0, inbufPos = 0;
while (true) {
if (inbufPos == inbufCount) {
if ((inbufCount = in.read(inbuf)) == -1) {
break;
}
inbufPos = 0;
}
nextChar = (char) (inbuf[inbufPos++] & 0xff);
if (offset == buf.length) {
char[] newBuf = new char[buf.length * 2];
System.arraycopy(buf, 0, newBuf, 0, offset);
buf = newBuf;
}
if (mode == UNICODE) {
int digit = Character.digit(nextChar, 16);
// BEGIN android-changed
// copied from newer version of Harmony
if (digit >= 0) {
unicode = (unicode << 4) + digit;
if (++count < 4) {
continue;
}
} else if (count <= 4) {
// luni.09=Invalid Unicode sequence: illegal character
throw new IllegalArgumentException(Messages.getString("luni.09"));
}
// END android-changed
mode = NONE;
buf[offset++] = (char) unicode;
if (nextChar != '\n") {
continue;
}
}
if (mode == SLASH) {
mode = NONE;
switch (nextChar) {
case '\r":
mode = CONTINUE; // Look for a following \n
continue;
case '\n":
mode = IGNORE; // Ignore whitespace on the next line
continue;
case 'b":
nextChar = '\b";
break;
case 'f":
nextChar = '\f";
break;
case 'n":
nextChar = '\n";
break;
case 'r":
nextChar = '\r";
break;
case 't":
nextChar = '\t";
break;
case 'u":
mode = UNICODE;
unicode = count = 0;
continue;
}
} else {
switch (nextChar) {
case '#":
case '!":
if (firstChar) {
while (true) {
if (inbufPos == inbufCount) {
if ((inbufCount = in.read(inbuf)) == -1) {
inbufPos = -1;
break;
}
inbufPos = 0;
}
nextChar = (char) inbuf[inbufPos++]; // & 0xff
// not
// required
if (nextChar == '\r" || nextChar == '\n") {
break;
}
}
continue;
}
break;
case '\n":
if (mode == CONTINUE) { // Part of a \r\n sequence
mode = IGNORE; // Ignore whitespace on the next line
continue;
}
// fall into the next case
case '\r":
mode = NONE;
firstChar = true;
if (offset > 0) {
if (keyLength == -1) {
keyLength = offset;
}
String temp = new String(buf, 0, offset);
put(temp.substring(0, keyLength), temp
.substring(keyLength));
}
keyLength = -1;
offset = 0;
continue;
case '\\":
if (mode == KEY_DONE) {
keyLength = offset;
}
mode = SLASH;
continue;
case ':":
case '=":
if (keyLength == -1) { // if parsing the key
mode = NONE;
keyLength = offset;
continue;
}
break;
}
if (Character.isWhitespace(nextChar)) {
if (mode == CONTINUE) {
mode = IGNORE;
}
// if key length == 0 or value length == 0
if (offset == 0 || offset == keyLength || mode == IGNORE) {
continue;
}
if (keyLength == -1) { // if parsing the key
mode = KEY_DONE;
continue;
}
}
if (mode == IGNORE || mode == CONTINUE) {
mode = NONE;
}
}
firstChar = false;
if (mode == KEY_DONE) {
keyLength = offset;
mode = NONE;
}
buf[offset++] = nextChar;
}
// BEGIN android-added
// copied from a newer version of Harmony
if (mode == UNICODE && count <= 4) {
// luni.08=Invalid Unicode sequence: expected format \\uxxxx
throw new IllegalArgumentException(Messages.getString("luni.08"));
}
// END android-added
if (keyLength >= 0) {
String temp = new String(buf, 0, offset);
put(temp.substring(0, keyLength), temp.substring(keyLength));
}
| public synchronized void | loadFromXML(java.io.InputStream in)Loads the properties from an {@code InputStream} containing the
properties in XML form. The XML document must begin with (and conform to)
following DOCTYPE:
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
Also the content of the XML data must satisfy the DTD but the xml is not
validated against it. The DTD is not loaded from the SYSTEM ID. After
this method returns the InputStream is not closed.
if (in == null) {
throw new NullPointerException();
}
if (builder == null) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// BEGIN android-removed
// factory.setValidating(true);
// END android-removed
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new Error(e);
}
builder.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
throw e;
}
public void error(SAXParseException e) throws SAXException {
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
});
builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if (systemId.equals(PROP_DTD_NAME)) {
InputSource result = new InputSource(new StringReader(
PROP_DTD));
result.setSystemId(PROP_DTD_NAME);
return result;
}
throw new SAXException(
"Invalid DOCTYPE declaration: " + systemId);
}
});
}
try {
Document doc = builder.parse(in);
NodeList entries = doc.getElementsByTagName("entry");
if (entries == null) {
return;
}
int entriesListLength = entries.getLength();
for (int i = 0; i < entriesListLength; i++) {
Element entry = (Element) entries.item(i);
String key = entry.getAttribute("key");
// BEGIN android-removed
// String value = entry.getTextContent();
// END android-removed
// BEGIN android-added
String value = getTextContent(entry);
// END android-added
/*
* key != null & value != null
* but key or(and) value can be empty String
*/
put(key, value);
}
} catch (IOException e) {
throw e;
} catch (SAXException e) {
throw new InvalidPropertiesFormatException(e);
}
| public java.util.Enumeration | propertyNames()Returns all of the property names that this {@code Properties} object
contains.
if (defaults == null) {
return keys();
}
Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults.size() + size());
Enumeration<?> keys = defaults.propertyNames();
while (keys.hasMoreElements()) {
set.put(keys.nextElement(), set);
}
keys = keys();
while (keys.hasMoreElements()) {
set.put(keys.nextElement(), set);
}
return set.keys();
| public void | save(java.io.OutputStream out, java.lang.String comment)Saves the mappings in this {@code Properties} to the specified {@code
OutputStream}, putting the specified comment at the beginning. The output
from this method is suitable for being read by the
{@link #load(InputStream)} method.
try {
store(out, comment);
} catch (IOException e) {
}
| public java.lang.Object | setProperty(java.lang.String name, java.lang.String value)Maps the specified key to the specified value. If the key already exists,
the old value is replaced. The key and value cannot be {@code null}.
return put(name, value);
| public synchronized void | store(java.io.OutputStream out, java.lang.String comment)Stores the mappings in this {@code Properties} to the specified {@code
OutputStream}, putting the specified comment at the beginning. The output
from this method is suitable for being read by the
{@link #load(InputStream)} method.
if (lineSeparator == null) {
lineSeparator = AccessController
.doPrivileged(new PriviAction<String>("line.separator")); //$NON-NLS-1$
}
StringBuilder buffer = new StringBuilder(200);
OutputStreamWriter writer = new OutputStreamWriter(out, "ISO8859_1"); //$NON-NLS-1$
if (comment != null) {
writer.write("#"); //$NON-NLS-1$
writer.write(comment);
writer.write(lineSeparator);
}
writer.write("#"); //$NON-NLS-1$
writer.write(new Date().toString());
writer.write(lineSeparator);
for (Map.Entry<Object, Object> entry : entrySet()) {
String key = (String) entry.getKey();
dumpString(buffer, key, true);
buffer.append('=");
dumpString(buffer, (String) entry.getValue(), false);
buffer.append(lineSeparator);
writer.write(buffer.toString());
buffer.setLength(0);
}
writer.flush();
| public void | storeToXML(java.io.OutputStream os, java.lang.String comment)Writes all properties stored in this instance into the {@code
OutputStream} in XML representation. The DOCTYPE is
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
If the comment is null, no comment is added to the output. UTF-8 is used
as the encoding. The {@code OutputStream} is not closed at the end. A
call to this method is the same as a call to {@code storeToXML(os,
comment, "UTF-8")}.
storeToXML(os, comment, "UTF-8");
| public synchronized void | storeToXML(java.io.OutputStream os, java.lang.String comment, java.lang.String encoding)Writes all properties stored in this instance into the {@code
OutputStream} in XML representation. The DOCTYPE is
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
If the comment is null, no comment is added to the output. The parameter
{@code encoding} defines which encoding should be used. The {@code
OutputStream} is not closed at the end.
if (os == null || encoding == null) {
throw new NullPointerException();
}
/*
* We can write to XML file using encoding parameter but note that some
* aliases for encodings are not supported by the XML parser. Thus we
* have to know canonical name for encoding used to store data in XML
* since the XML parser must recognize encoding name used to store data.
*/
String encodingCanonicalName;
try {
encodingCanonicalName = Charset.forName(encoding).name();
} catch (IllegalCharsetNameException e) {
System.out.println("Warning: encoding name " + encoding
+ " is illegal, using UTF-8 as default encoding");
encodingCanonicalName = "UTF-8";
} catch (UnsupportedCharsetException e) {
System.out.println("Warning: encoding " + encoding
+ " is not supported, using UTF-8 as default encoding");
encodingCanonicalName = "UTF-8";
}
PrintStream printStream = new PrintStream(os, false, encodingCanonicalName);
printStream.print("<?xml version=\"1.0\" encoding=\"");
printStream.print(encodingCanonicalName);
printStream.println("\"?>");
printStream.print("<!DOCTYPE properties SYSTEM \"");
printStream.print(PROP_DTD_NAME);
printStream.println("\">");
printStream.println("<properties>");
if (comment != null) {
printStream.print("<comment>");
printStream.print(substitutePredefinedEntries(comment));
printStream.println("</comment>");
}
for (Map.Entry<Object, Object> entry : entrySet()) {
String keyValue = (String) entry.getKey();
String entryValue = (String) entry.getValue();
printStream.print("<entry key=\"");
printStream.print(substitutePredefinedEntries(keyValue));
printStream.print("\">");
printStream.print(substitutePredefinedEntries(entryValue));
printStream.println("</entry>");
}
printStream.println("</properties>");
printStream.flush();
| private java.lang.String | substitutePredefinedEntries(java.lang.String s)
/*
* substitution for predefined character entities
* to use them safely in XML
*/
return s.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\u0027", "'")
.replaceAll("\"", """);
|
|