1 // Properties - Property list representation.
3 /* Copyright (C) 1998, 1999 Red Hat, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 import java.io.BufferedWriter;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.InputStreamReader;
17 import java.io.OutputStream;
18 import java.io.OutputStreamWriter;
19 import java.io.PrintStream;
20 import java.io.PrintWriter;
21 import java.io.PushbackReader;
24 * @author Tom Tromey <tromey@cygnus.com>
25 * @date October 26, 1998.
28 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
29 * Status: Complete to JDK 1.1.
32 public class Properties extends Hashtable
34 protected Properties defaults;
36 public String getProperty (String propName)
38 return getProperty (propName, null);
41 public String getProperty (String propName, String defVal)
43 String r = (String) get (propName);
47 r = defaults.getProperty(propName, defVal);
54 public void list (PrintStream out)
56 Enumeration e = propertyNames ();
57 while (e.hasMoreElements())
59 String key = (String) e.nextElement();
60 String value = getProperty(key);
63 if (value.length() > 40)
66 value = value.substring(0, 37) + "...";
75 public void list (PrintWriter writer)
77 Enumeration e = propertyNames ();
78 while (e.hasMoreElements())
80 String key = (String) e.nextElement();
81 String value = getProperty(key);
84 if (value.length() > 40)
87 value = value.substring(0, 37) + "...";
91 writer.println(value);
96 private final boolean skip_ws (PushbackReader reader) throws IOException
100 int c = reader.read();
103 // FIXME: we use our own definition of whitespace.
104 // Character.isWhitespace includes newlines, which we don't
105 // want. Character.isSpaceChar doesn't include \t.
106 if (c != ' ' && c != '\t')
114 // Note: this method needs to be rewritten for JDK 1.2.
115 // We rather arbitrarily decide that an EOF in the middle of a line
116 // means that the whole line should be ignored. The spec doesn't
117 // specifically address this, but this interpretation seems valid.
118 public synchronized void load (InputStream in) throws IOException
120 PushbackReader reader = new PushbackReader (new InputStreamReader (in));
122 StringBuffer key = new StringBuffer ();
123 StringBuffer value = new StringBuffer ();
131 // Skip leading whitespace.
132 if (! skip_ws (reader))
135 // Read key until key terminator.
136 boolean first_char = true;
151 // If we found a comment, just read to end of line and
153 if (first_char == true && (c == '#' || c == '!'))
155 while (c != -1 && c != '\r' && c != '\n')
162 if (c == '\r' || c == '\n')
169 // FIXME: again, our own definition of whitespace.
170 if (c == ' ' || c == '\t' || c == ':' || c == '=')
174 key.append((char) c);
177 // Found end of key. Skip whitespace. If the terminator
178 // was whitespace, also skip a single instance of a "real"
179 // terminator, and then more whitespace.
180 if (! skip_ws (reader))
182 if (c != ':' && c != '=')
187 if (c == ':' || c == '=')
189 // Skip more whitespace.
190 if (! skip_ws (reader))
197 // Now read the value.
203 if (c == '\r' || c == '\n')
223 for (int i = 0; i < 4; ++i)
225 int x = reader.read();
228 int d = Character.digit((char) x, 16);
229 // We follow JDK here: invalid characters
230 // are treated as terminators.
233 value.append((char) c);
245 value.append((char) c);
248 put (key.toString(), value.toString());
257 public Properties (Properties defs)
262 private final void addHashEntries (Hashtable base)
264 if (defaults != null)
265 defaults.addHashEntries(base);
266 Enumeration keys = keys ();
267 while (keys.hasMoreElements())
268 base.put(keys.nextElement(), base);
271 public Enumeration propertyNames ()
273 // We make a new Hashtable that holds all the keys. Then we
274 // return an enumeration for this hash. We do this because we
275 // don't want modifications to be reflected in the enumeration
276 // (per JCL), and because there doesn't seem to be a
277 // particularly better way to ensure that duplicates are
279 Hashtable t = new Hashtable ();
284 public synchronized void save (OutputStream out, String comment)
286 // Use a buffer because writing a single string through
287 // OutputStreamWriter is fairly expensive.
288 BufferedWriter output
289 = new BufferedWriter (new OutputStreamWriter (out));
290 String newline = System.getProperty("line.separator");
296 // We just lose if COMMENT contains a newline. This is
297 // what JDK 1.1 does.
299 output.write(comment);
300 output.write(newline);
303 output.write(new Date().toString());
304 output.write(newline);
306 Enumeration keys = keys ();
307 while (keys.hasMoreElements())
309 String key = (String) keys.nextElement();
310 String value = (String) get (key);
312 // FIXME: JCL says that the key can contain many Unicode
313 // characters. But it also doesn't say we should encode
315 // FIXME: if key contains ':', '=', or whitespace, must
316 // quote it here. Note that JDK 1.1 does not do this.
320 boolean leading = true;
321 for (int i = 0; i < value.length(); ++i)
323 boolean new_lead = false;
324 char c = value.charAt(i);
337 output.write("\\\\");
356 if (c < '\u0020' || c > '\u007e')
359 output.write(Character.forDigit(c >>> 12, 16));
360 output.write(Character.forDigit((c >>> 8) & 0xff,
362 output.write(Character.forDigit((c >>> 4) & 0xff,
364 output.write(Character.forDigit(c & 0xff, 16));
371 output.write(newline);
376 catch (IOException ignore)