aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/util/Properties.java
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>1999-04-07 14:42:40 +0000
committerTom Tromey <tromey@gcc.gnu.org>1999-04-07 14:42:40 +0000
commitee9dd3721be68b9fa63dea9aa5a1d86e66958cde (patch)
treed96801a16fdf03a5682ef98730fe333a46eef944 /libjava/java/util/Properties.java
parent140fa895c6b859f827fc4437b91775a82cd105fb (diff)
downloadgcc-ee9dd3721be68b9fa63dea9aa5a1d86e66958cde.zip
gcc-ee9dd3721be68b9fa63dea9aa5a1d86e66958cde.tar.gz
gcc-ee9dd3721be68b9fa63dea9aa5a1d86e66958cde.tar.bz2
Initial revision
From-SVN: r26263
Diffstat (limited to 'libjava/java/util/Properties.java')
-rw-r--r--libjava/java/util/Properties.java376
1 files changed, 376 insertions, 0 deletions
diff --git a/libjava/java/util/Properties.java b/libjava/java/util/Properties.java
new file mode 100644
index 0000000..aac7214
--- /dev/null
+++ b/libjava/java/util/Properties.java
@@ -0,0 +1,376 @@
+// Properties - Property list representation.
+
+/* Copyright (C) 1998, 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.util;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.PushbackReader;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date October 26, 1998.
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * Status: Complete to JDK 1.1.
+ */
+
+public class Properties extends Hashtable
+{
+ protected Properties defaults;
+
+ public String getProperty (String propName)
+ {
+ return getProperty (propName, null);
+ }
+
+ public String getProperty (String propName, String defVal)
+ {
+ String r = (String) get (propName);
+ if (r == null)
+ {
+ if (defaults != null)
+ r = defaults.getProperty(propName, defVal);
+ else
+ r = defVal;
+ }
+ return r;
+ }
+
+ public void list (PrintStream out)
+ {
+ Enumeration e = propertyNames ();
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+ String value = getProperty(key);
+ if (value != null)
+ {
+ if (value.length() > 40)
+ {
+ // JDK compatibility.
+ value = value.substring(0, 37) + "...";
+ }
+ out.print(key);
+ out.print("=");
+ out.println(value);
+ }
+ }
+ }
+
+ public void list (PrintWriter writer)
+ {
+ Enumeration e = propertyNames ();
+ while (e.hasMoreElements())
+ {
+ String key = (String) e.nextElement();
+ String value = getProperty(key);
+ if (value != null)
+ {
+ if (value.length() > 40)
+ {
+ // JDK compatibility.
+ value = value.substring(0, 37) + "...";
+ }
+ writer.print(key);
+ writer.print("=");
+ writer.println(value);
+ }
+ }
+ }
+
+ private final boolean skip_ws (PushbackReader reader) throws IOException
+ {
+ while (true)
+ {
+ int c = reader.read();
+ if (c == -1)
+ return false;
+ // FIXME: we use our own definition of whitespace.
+ // Character.isWhitespace includes newlines, which we don't
+ // want. Character.isSpaceChar doesn't include \t.
+ if (c == ' ' || c == '\t')
+ {
+ reader.unread(c);
+ return true;
+ }
+ }
+ }
+
+ // Note: this method needs to be rewritten for JDK 1.2.
+ // We rather arbitrarily decide that an EOF in the middle of a line
+ // means that the whole line should be ignored. The spec doesn't
+ // specifically address this, but this interpretation seems valid.
+ public synchronized void load (InputStream in) throws IOException
+ {
+ PushbackReader reader = new PushbackReader (new InputStreamReader (in));
+
+ StringBuffer key = new StringBuffer ();
+ StringBuffer value = new StringBuffer ();
+
+ nextLine:
+ while (true)
+ {
+ key.setLength(0);
+ value.setLength(0);
+
+ // Skip leading whitespace.
+ if (! skip_ws (reader))
+ return;
+
+ // Read key until key terminator.
+ boolean first_char = true;
+ int c;
+ while (true)
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == '\\')
+ {
+ first_char = false;
+ c = reader.read();
+ if (c == -1)
+ return;
+ }
+
+ // If we found a comment, just read to end of line and
+ // then keep going.
+ if (first_char == true && (c == '#' || c == '!'))
+ {
+ while (c != -1 && c != '\r' && c != '\n')
+ c = reader.read();
+ if (c == -1)
+ return;
+ continue nextLine;
+ }
+
+ if (c == '\r' || c == '\n')
+ {
+ if (first_char)
+ continue nextLine;
+ reader.unread(c);
+ break;
+ }
+ // FIXME: again, our own definitino of whitespace.
+ if (c == ' ' || c == '\t' || c == ':' || c == '=')
+ break;
+
+ first_char = false;
+ key.append(c);
+ }
+
+ // Found end of key. Skip whitespace. If the terminator
+ // was whitespace, also skip a single instance of a "real"
+ // terminator, and then more whitespace.
+ if (! skip_ws (reader))
+ return;
+ if (c != ':' && c != '=')
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == ':' || c == '=')
+ {
+ // Skip more whitespace.
+ if (! skip_ws (reader))
+ return;
+ }
+ else
+ reader.unread(c);
+ }
+
+ // Now read the value.
+ while (true)
+ {
+ c = reader.read();
+ if (c == -1)
+ return;
+ if (c == '\r' || c == '\n')
+ break;
+ if (c == '\\')
+ {
+ c = reader.read();
+ switch (c)
+ {
+ case -1:
+ return;
+ case 't':
+ c = '\t';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'u':
+ c = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ int x = reader.read();
+ if (x == -1)
+ return;
+ int d = Character.digit((char) x, 16);
+ // FIXME: what to do here? We call it an
+ // error.
+ if (d == -1)
+ throw new IOException ();
+ c <<= 4;
+ c |= d;
+ }
+ break;
+ default:
+ // Nothing.
+ }
+ }
+ else
+ value.append(c);
+ }
+
+ put (key.toString(), value.toString());
+ }
+ }
+
+ public Properties ()
+ {
+ defaults = null;
+ }
+
+ public Properties (Properties defs)
+ {
+ defaults = defs;
+ }
+
+ private final void addHashEntries (Hashtable base)
+ {
+ if (defaults != null)
+ defaults.addHashEntries(base);
+ Enumeration keys = keys ();
+ while (keys.hasMoreElements())
+ base.put(keys.nextElement(), base);
+ }
+
+ public Enumeration propertyNames ()
+ {
+ // We make a new Hashtable that holds all the keys. Then we
+ // return an enumeration for this hash. We do this because we
+ // don't want modifications to be reflected in the enumeration
+ // (per JCL), and because there doesn't seem to be a
+ // particularly better way to ensure that duplicates are
+ // ignored.
+ Hashtable t = new Hashtable ();
+ addHashEntries (t);
+ return t.keys();
+ }
+
+ public synchronized void save (OutputStream out, String comment)
+ {
+ // Use a buffer because writing a single string through
+ // OutputStreamWriter is fairly expensive.
+ BufferedWriter output
+ = new BufferedWriter (new OutputStreamWriter (out));
+ String newline = System.getProperty("line.separator");
+
+ try
+ {
+ if (comment != null)
+ {
+ // FIXME: what if COMMENT contains newlines?
+ output.write("#");
+ output.write(comment);
+ output.write(newline);
+ }
+ output.write("# ");
+ output.write(new Date().toString());
+ output.write(newline);
+
+ Enumeration keys = keys ();
+ while (keys.hasMoreElements())
+ {
+ String key = (String) keys.nextElement();
+ String value = (String) get (key);
+
+ // FIXME: JCL says that the key can contain many Unicode
+ // characters. But it also doesn't say we should encode
+ // it in any way.
+ // FIXME: if key contains ':', '=', or whitespace, must
+ // quote it here.
+ output.write(key);
+ output.write("=");
+
+ boolean leading = true;
+ for (int i = 0; i < value.length(); ++i)
+ {
+ boolean new_lead = false;
+ char c = value.charAt(i);
+ switch (c)
+ {
+ case '\n':
+ output.write("\\n");
+ break;
+ case '\r':
+ output.write("\\r");
+ break;
+ case '\t':
+ output.write("\\t");
+ break;
+ case '\\':
+ output.write("\\\\");
+ break;
+
+ case '#':
+ case '!':
+ case '=':
+ case ':':
+ output.write("\\");
+ output.write(c);
+ break;
+
+ case ' ':
+ new_lead = leading;
+ if (leading)
+ output.write("\\");
+ output.write(c);
+ break;
+
+ default:
+ if (c < '\u0020' || c > '\u007e')
+ {
+ output.write("\\u");
+ output.write(Character.forDigit(c >>> 12, 16));
+ output.write(Character.forDigit((c >>> 8) & 0xff,
+ 16));
+ output.write(Character.forDigit((c >>> 4) & 0xff,
+ 16));
+ output.write(Character.forDigit(c & 0xff, 16));
+ }
+ else
+ output.write(c);
+ }
+ leading = new_lead;
+ }
+ output.write(newline);
+ }
+
+ output.flush();
+ }
+ catch (IOException ignore)
+ {
+ }
+ }
+}