1 |
/* java.util.Properties |
/* Properties.java -- a set of persistent properties |
2 |
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
40 |
import java.io.*; |
import java.io.*; |
41 |
|
|
42 |
/** |
/** |
43 |
|
* A set of persistent properties, which can be saved or loaded from a stream. |
44 |
|
* A property list may also contain defaults, searched if the main list |
45 |
|
* does not contain a property for a given key. |
46 |
|
* |
47 |
* An example of a properties file for the german language is given |
* An example of a properties file for the german language is given |
48 |
* here. This extends the example given in ListResourceBundle. |
* here. This extends the example given in ListResourceBundle. |
49 |
* Create a file MyResource_de.properties with the following contents |
* Create a file MyResource_de.properties with the following contents |
50 |
* and put it in the CLASSPATH. (The character |
* and put it in the CLASSPATH. (The character |
51 |
* <code>\</code><code>u00e4</code> is the german ä) |
* <code>\</code><code>u00e4</code> is the german ä) |
52 |
* |
* |
53 |
* <pre> |
* <pre> |
54 |
* s1=3 |
* s1=3 |
55 |
* s2=MeineDisk |
* s2=MeineDisk |
75 |
* this, you should use the <code>get/setProperty</code> method instead |
* this, you should use the <code>get/setProperty</code> method instead |
76 |
* of <code>get/put</code>. |
* of <code>get/put</code>. |
77 |
* |
* |
78 |
* @see PropertyResourceBundle |
* Properties are saved in ISO 8859-1 encoding, using Unicode escapes with |
79 |
|
* a single <code>u</code> for any character which cannot be represented. |
80 |
|
* |
81 |
* @author Jochen Hoenicke |
* @author Jochen Hoenicke |
82 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
83 |
|
* @see PropertyResourceBundle |
84 |
|
* @status updated to 1.4 |
85 |
*/ |
*/ |
86 |
public class Properties extends Hashtable |
public class Properties extends Hashtable |
87 |
{ |
{ |
88 |
/** |
/** |
89 |
* The property list that contains default values for any keys not |
* The property list that contains default values for any keys not |
90 |
* in this property list. |
* in this property list. |
91 |
|
* |
92 |
|
* @serial the default properties |
93 |
*/ |
*/ |
94 |
protected Properties defaults; |
protected Properties defaults; |
95 |
|
|
96 |
|
/** |
97 |
|
* Compatible with JDK 1.0+. |
98 |
|
*/ |
99 |
private static final long serialVersionUID = 4112578634029874840L; |
private static final long serialVersionUID = 4112578634029874840L; |
100 |
|
|
101 |
/** |
/** |
102 |
* Creates a new empty property list. |
* Creates a new empty property list with no default values. |
103 |
*/ |
*/ |
104 |
public Properties() |
public Properties() |
105 |
{ |
{ |
108 |
|
|
109 |
/** |
/** |
110 |
* Create a new empty property list with the specified default values. |
* Create a new empty property list with the specified default values. |
111 |
* @param defaults a Properties object containing the default values. |
* |
112 |
|
* @param defaults a Properties object containing the default values |
113 |
*/ |
*/ |
114 |
public Properties(Properties defaults) |
public Properties(Properties defaults) |
115 |
{ |
{ |
117 |
} |
} |
118 |
|
|
119 |
/** |
/** |
120 |
|
* Adds the given key/value pair to this properties. This calls |
121 |
|
* the hashtable method put. |
122 |
|
* |
123 |
|
* @param key the key for this property |
124 |
|
* @param value the value for this property |
125 |
|
* @return The old value for the given key |
126 |
|
* @see #getProperty(String) |
127 |
|
* @since 1.2 |
128 |
|
*/ |
129 |
|
public Object setProperty(String key, String value) |
130 |
|
{ |
131 |
|
return put(key, value); |
132 |
|
} |
133 |
|
|
134 |
|
/** |
135 |
* Reads a property list from an input stream. The stream should |
* Reads a property list from an input stream. The stream should |
136 |
* have the following format: <br> |
* have the following format: <br> |
137 |
* |
* |
150 |
* |
* |
151 |
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a |
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a |
152 |
* space), and unicode characters with the |
* space), and unicode characters with the |
153 |
* <code>\</code><code>u</code>xxxx notation are detected, and |
* <code>\\u</code><em>xxxx</em> notation are detected, and |
154 |
* converted to the corresponding single character. <br> |
* converted to the corresponding single character. <br> |
155 |
* |
* |
156 |
* <pre> |
* <pre> |
162 |
* weekdays: Sunday,Monday,Tuesday,Wednesday,\ |
* weekdays: Sunday,Monday,Tuesday,Wednesday,\ |
163 |
* Thursday,Friday,Saturday |
* Thursday,Friday,Saturday |
164 |
* # The safest way to include a space at the end of a value: |
* # The safest way to include a space at the end of a value: |
165 |
* label = Name:\<code></code>u0020 |
* label = Name:\\u0020 |
166 |
* </pre> |
* </pre> |
167 |
* |
* |
168 |
* @param in the input stream |
* @param in the input stream |
169 |
* @exception IOException if an error occurred when reading |
* @throws IOException if an error occurred when reading the input |
170 |
* from the input. */ |
*/ |
171 |
public void load(InputStream inStream) throws IOException |
public void load(InputStream inStream) throws IOException |
172 |
{ |
{ |
173 |
// The spec says that the file must be encoded using ISO-8859-1. |
// The spec says that the file must be encoded using ISO-8859-1. |
174 |
BufferedReader reader = |
BufferedReader reader = |
175 |
new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1")); |
new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1")); |
176 |
String line; |
String line; |
177 |
|
|
178 |
while ((line = reader.readLine()) != null) |
while ((line = reader.readLine()) != null) |
179 |
{ |
{ |
180 |
char c = 0; |
char c = 0; |
181 |
int pos = 0; |
int pos = 0; |
182 |
while (pos < line.length() |
while (pos < line.length() |
183 |
&& Character.isWhitespace(c = line.charAt(pos))) |
&& Character.isWhitespace(c = line.charAt(pos))) |
184 |
pos++; |
pos++; |
185 |
|
|
186 |
// If line is empty or begins with a comment character, |
// If line is empty or begins with a comment character, |
187 |
// skip this line. |
// skip this line. |
188 |
if (pos == line.length() || c == '#' || c == '!') |
if (pos == line.length() || c == '#' || c == '!') |
189 |
continue; |
continue; |
190 |
|
|
191 |
// The characters up to the next Whitespace, ':', or '=' |
// The characters up to the next Whitespace, ':', or '=' |
192 |
// describe the key. But look for escape sequences. |
// describe the key. But look for escape sequences. |
193 |
StringBuffer key = new StringBuffer(); |
StringBuffer key = new StringBuffer(); |
194 |
while (pos < line.length() |
while (pos < line.length() |
195 |
&& !Character.isWhitespace(c = line.charAt(pos++)) |
&& ! Character.isWhitespace(c = line.charAt(pos++)) |
196 |
&& c != '=' && c != ':') |
&& c != '=' && c != ':') |
197 |
{ |
{ |
198 |
if (c == '\\') |
if (c == '\\') |
199 |
{ |
{ |
200 |
if (pos == line.length()) |
if (pos == line.length()) |
201 |
{ |
{ |
202 |
// The line continues on the next line. |
// The line continues on the next line. |
203 |
line = reader.readLine(); |
line = reader.readLine(); |
204 |
pos = 0; |
pos = 0; |
205 |
while (pos < line.length() |
while (pos < line.length() |
206 |
&& Character.isWhitespace(c = line.charAt(pos))) |
&& Character.isWhitespace(c = line.charAt(pos))) |
207 |
pos++; |
pos++; |
208 |
} |
} |
209 |
else |
else |
210 |
{ |
{ |
211 |
c = line.charAt(pos++); |
c = line.charAt(pos++); |
212 |
switch (c) |
switch (c) |
213 |
{ |
{ |
214 |
case 'n': |
case 'n': |
215 |
key.append('\n'); |
key.append('\n'); |
216 |
break; |
break; |
217 |
case 't': |
case 't': |
218 |
key.append('\t'); |
key.append('\t'); |
219 |
break; |
break; |
220 |
case 'r': |
case 'r': |
221 |
key.append('\r'); |
key.append('\r'); |
222 |
break; |
break; |
223 |
case 'u': |
case 'u': |
224 |
if (pos + 4 <= line.length()) |
if (pos + 4 <= line.length()) |
225 |
{ |
{ |
226 |
char uni = (char) Integer.parseInt |
char uni = (char) Integer.parseInt |
227 |
(line.substring(pos, pos + 4), 16); |
(line.substring(pos, pos + 4), 16); |
228 |
key.append(uni); |
key.append(uni); |
229 |
pos += 4; |
pos += 4; |
230 |
} // else throw exception? |
} // else throw exception? |
231 |
break; |
break; |
232 |
default: |
default: |
233 |
key.append(c); |
key.append(c); |
234 |
break; |
break; |
235 |
} |
} |
236 |
} |
} |
237 |
} |
} |
238 |
else |
else |
239 |
key.append(c); |
key.append(c); |
240 |
} |
} |
241 |
|
|
242 |
boolean isDelim = (c == ':' || c == '='); |
boolean isDelim = (c == ':' || c == '='); |
243 |
while (pos < line.length() |
while (pos < line.length() |
244 |
&& Character.isWhitespace(c = line.charAt(pos))) |
&& Character.isWhitespace(c = line.charAt(pos))) |
245 |
pos++; |
pos++; |
246 |
|
|
247 |
if (!isDelim && (c == ':' || c == '=')) |
if (! isDelim && (c == ':' || c == '=')) |
248 |
{ |
{ |
249 |
pos++; |
pos++; |
250 |
while (pos < line.length() |
while (pos < line.length() |
251 |
&& Character.isWhitespace(c = line.charAt(pos))) |
&& Character.isWhitespace(c = line.charAt(pos))) |
252 |
pos++; |
pos++; |
253 |
} |
} |
254 |
|
|
255 |
StringBuffer element = new StringBuffer(line.length() - pos); |
StringBuffer element = new StringBuffer(line.length() - pos); |
256 |
while (pos < line.length()) |
while (pos < line.length()) |
257 |
{ |
{ |
258 |
c = line.charAt(pos++); |
c = line.charAt(pos++); |
259 |
if (c == '\\') |
if (c == '\\') |
260 |
{ |
{ |
261 |
if (pos == line.length()) |
if (pos == line.length()) |
262 |
{ |
{ |
263 |
// The line continues on the next line. |
// The line continues on the next line. |
264 |
line = reader.readLine(); |
line = reader.readLine(); |
265 |
pos = 0; |
pos = 0; |
266 |
while (pos < line.length() |
while (pos < line.length() |
267 |
&& Character.isWhitespace(c = line.charAt(pos))) |
&& Character.isWhitespace(c = line.charAt(pos))) |
268 |
pos++; |
pos++; |
269 |
element.ensureCapacity(line.length() - pos + |
element.ensureCapacity(line.length() - pos + |
270 |
element.length()); |
element.length()); |
271 |
} |
} |
272 |
else |
else |
273 |
{ |
{ |
274 |
c = line.charAt(pos++); |
c = line.charAt(pos++); |
275 |
switch (c) |
switch (c) |
276 |
{ |
{ |
277 |
case 'n': |
case 'n': |
278 |
element.append('\n'); |
element.append('\n'); |
279 |
break; |
break; |
280 |
case 't': |
case 't': |
281 |
element.append('\t'); |
element.append('\t'); |
282 |
break; |
break; |
283 |
case 'r': |
case 'r': |
284 |
element.append('\r'); |
element.append('\r'); |
285 |
break; |
break; |
286 |
case 'u': |
case 'u': |
287 |
if (pos + 4 <= line.length()) |
if (pos + 4 <= line.length()) |
288 |
{ |
{ |
289 |
char uni = (char) Integer.parseInt |
char uni = (char) Integer.parseInt |
290 |
(line.substring(pos, pos + 4), 16); |
(line.substring(pos, pos + 4), 16); |
291 |
element.append(uni); |
element.append(uni); |
292 |
pos += 4; |
pos += 4; |
293 |
} // else throw exception? |
} // else throw exception? |
294 |
break; |
break; |
295 |
default: |
default: |
296 |
element.append(c); |
element.append(c); |
297 |
break; |
break; |
298 |
} |
} |
299 |
} |
} |
300 |
} |
} |
301 |
else |
else |
302 |
element.append(c); |
element.append(c); |
303 |
} |
} |
304 |
put(key.toString(), element.toString()); |
put(key.toString(), element.toString()); |
305 |
} |
} |
306 |
} |
} |
307 |
|
|
308 |
/** |
/** |
309 |
* Calls <code>store(OutputStream out, String header)</code> and |
* Calls <code>store(OutputStream out, String header)</code> and |
310 |
* ignores the IOException that may be thrown. |
* ignores the IOException that may be thrown. |
311 |
* @deprecated use store instead. |
* |
312 |
* @exception ClassCastException if this property contains any key or |
* @param out the stream to write to |
313 |
* value that isn't a string. |
* @param header a description of the property list |
314 |
|
* @throws ClassCastException if this property contains any key or |
315 |
|
* value that are not strings |
316 |
|
* @deprecated use {@link #store(OutputStream, String)} instead |
317 |
*/ |
*/ |
318 |
public void save(OutputStream out, String header) |
public void save(OutputStream out, String header) |
319 |
{ |
{ |
320 |
try |
try |
321 |
{ |
{ |
322 |
store(out, header); |
store(out, header); |
323 |
} |
} |
324 |
catch (IOException ex) |
catch (IOException ex) |
325 |
{ |
{ |
327 |
} |
} |
328 |
|
|
329 |
/** |
/** |
330 |
* Writes the key/value pairs to the given output stream. <br> |
* Writes the key/value pairs to the given output stream, in a format |
331 |
|
* suitable for <code>load</code>. <br> |
332 |
* |
* |
333 |
* If header is not null, this method writes a comment containing |
* If header is not null, this method writes a comment containing |
334 |
* the header as first line to the stream. The next line (or first |
* the header as first line to the stream. The next line (or first |
342 |
* preceeded by a backslash. Spaces are preceded with a backslash, |
* preceeded by a backslash. Spaces are preceded with a backslash, |
343 |
* if and only if they are at the beginning of the key. Characters |
* if and only if they are at the beginning of the key. Characters |
344 |
* that are not in the ascii range 33 to 127 are written in the |
* that are not in the ascii range 33 to 127 are written in the |
345 |
* <code>\</code><code>u</code>xxxx Form. |
* <code>\</code><code>u</code>xxxx Form.<br> |
346 |
|
* |
347 |
|
* Following the listing, the output stream is flushed but left open. |
348 |
* |
* |
349 |
* @param out the output stream |
* @param out the output stream |
350 |
* @param header the header written in the first line, may be null. |
* @param header the header written in the first line, may be null |
351 |
* @exception ClassCastException if this property contains any key or |
* @throws ClassCastException if this property contains any key or |
352 |
* value that isn't a string. |
* value that isn't a string |
353 |
|
* @throws IOException if writing to the stream fails |
354 |
|
* @throws NullPointerException if out is null |
355 |
|
* @since 1.2 |
356 |
*/ |
*/ |
357 |
public void store(OutputStream out, String header) throws IOException |
public void store(OutputStream out, String header) throws IOException |
358 |
{ |
{ |
359 |
// The spec says that the file must be encoded using ISO-8859-1. |
// The spec says that the file must be encoded using ISO-8859-1. |
360 |
PrintWriter writer |
PrintWriter writer |
361 |
= new PrintWriter(new OutputStreamWriter (out, "ISO-8859-1")); |
= new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1")); |
362 |
if (header != null) |
if (header != null) |
363 |
writer.println("#" + header); |
writer.println("#" + header); |
364 |
writer.println("#" + new Date().toString()); |
writer.println("#" + new Date()); |
365 |
list(writer); |
list(writer); |
366 |
writer.flush(); |
writer.flush(); |
367 |
} |
} |
368 |
|
|
369 |
/** |
/** |
|
* Adds the given key/value pair to this properties. This calls |
|
|
* the hashtable method put. |
|
|
* @param key the key for this property |
|
|
* @param value the value for this property |
|
|
* @return The old value for the given key. |
|
|
* @since JDK1.2 */ |
|
|
public Object setProperty(String key, String value) |
|
|
{ |
|
|
return put(key, value); |
|
|
} |
|
|
|
|
|
/** |
|
370 |
* Gets the property with the specified key in this property list. |
* Gets the property with the specified key in this property list. |
371 |
* If the key is not found, the default property list is searched. |
* If the key is not found, the default property list is searched. |
372 |
* If the property is not found in default or the default of |
* If the property is not found in the default, null is returned. |
373 |
* default, null is returned. |
* |
374 |
* @param key The key for this property. |
* @param key The key for this property |
375 |
* @param defaulValue A default value |
* @return the value for the given key, or null if not found |
376 |
* @return The value for the given key, or null if not found. |
* @throws ClassCastException if this property contains any key or |
377 |
* @exception ClassCastException if this property contains any key or |
* value that isn't a string |
378 |
* value that isn't a string. |
* @see #defaults |
379 |
|
* @see #setProperty(String, String) |
380 |
|
* @see #getProperty(String, String) |
381 |
*/ |
*/ |
382 |
public String getProperty(String key) |
public String getProperty(String key) |
383 |
{ |
{ |
387 |
/** |
/** |
388 |
* Gets the property with the specified key in this property list. If |
* Gets the property with the specified key in this property list. If |
389 |
* the key is not found, the default property list is searched. If the |
* the key is not found, the default property list is searched. If the |
390 |
* property is not found in default or the default of default, the |
* property is not found in the default, the specified defaultValue is |
391 |
* specified defaultValue is returned. |
* returned. |
392 |
* @param key The key for this property. |
* |
393 |
|
* @param key The key for this property |
394 |
* @param defaulValue A default value |
* @param defaulValue A default value |
395 |
* @return The value for the given key. |
* @return The value for the given key |
396 |
* @exception ClassCastException if this property contains any key or |
* @throws ClassCastException if this property contains any key or |
397 |
* value that isn't a string. |
* value that isn't a string |
398 |
|
* @see #defaults |
399 |
|
* @see #setProperty(String, String) |
400 |
*/ |
*/ |
401 |
public String getProperty(String key, String defaultValue) |
public String getProperty(String key, String defaultValue) |
402 |
{ |
{ |
404 |
// Eliminate tail recursion. |
// Eliminate tail recursion. |
405 |
do |
do |
406 |
{ |
{ |
407 |
String value = (String) prop.get(key); |
String value = (String) prop.get(key); |
408 |
if (value != null) |
if (value != null) |
409 |
return value; |
return value; |
410 |
prop = prop.defaults; |
prop = prop.defaults; |
411 |
} |
} |
412 |
while (prop != null); |
while (prop != null); |
413 |
return defaultValue; |
return defaultValue; |
414 |
} |
} |
415 |
|
|
|
private final void addHashEntries(Hashtable base) |
|
|
{ |
|
|
if (defaults != null) |
|
|
defaults.addHashEntries(base); |
|
|
Enumeration keys = keys(); |
|
|
while (keys.hasMoreElements()) |
|
|
base.put(keys.nextElement(), base); |
|
|
} |
|
|
|
|
416 |
/** |
/** |
417 |
* Returns an enumeration of all keys in this property list, including |
* Returns an enumeration of all keys in this property list, including |
418 |
* the keys in the default property list. |
* the keys in the default property list. |
419 |
|
* |
420 |
|
* @return an Enumeration of all defined keys |
421 |
*/ |
*/ |
422 |
public Enumeration propertyNames() |
public Enumeration propertyNames() |
423 |
{ |
{ |
433 |
} |
} |
434 |
|
|
435 |
/** |
/** |
436 |
|
* Writes the key/value pairs to the given print stream. They are |
437 |
|
* written in the way described in the method store. This does not visit |
438 |
|
* the keys in the default properties. |
439 |
|
* |
440 |
|
* @param out the stream, where the key/value pairs are written to |
441 |
|
* @throws ClassCastException if this property contains any key or |
442 |
|
* value that isn't a string |
443 |
|
* @see #store(OutputStream, String) |
444 |
|
*/ |
445 |
|
public void list(PrintStream out) |
446 |
|
{ |
447 |
|
Enumeration keys = keys(); |
448 |
|
Enumeration elts = elements(); |
449 |
|
while (keys.hasMoreElements()) |
450 |
|
{ |
451 |
|
String key = (String) keys.nextElement(); |
452 |
|
String elt = (String) elts.nextElement(); |
453 |
|
String output = formatForOutput(key, elt); |
454 |
|
out.println(output); |
455 |
|
} |
456 |
|
} |
457 |
|
|
458 |
|
/** |
459 |
|
* Writes the key/value pairs to the given print writer. They are |
460 |
|
* written in the way, described in the method store. |
461 |
|
* |
462 |
|
* @param out the writer, where the key/value pairs are written to |
463 |
|
* @throws ClassCastException if this property contains any key or |
464 |
|
* value that isn't a string |
465 |
|
* @see #store(OutputStream, String) |
466 |
|
* @see #list(PrintStream) |
467 |
|
* @since 1.1 |
468 |
|
*/ |
469 |
|
public void list(PrintWriter out) |
470 |
|
{ |
471 |
|
Enumeration keys = keys(); |
472 |
|
Enumeration elts = elements(); |
473 |
|
while (keys.hasMoreElements()) |
474 |
|
{ |
475 |
|
String key = (String) keys.nextElement(); |
476 |
|
String elt = (String) elts.nextElement(); |
477 |
|
String output = formatForOutput(key, elt); |
478 |
|
out.println(output); |
479 |
|
} |
480 |
|
} |
481 |
|
|
482 |
|
/** |
483 |
* Formats a key/value pair for output in a properties file. |
* Formats a key/value pair for output in a properties file. |
484 |
* See store for a description of the format. |
* See store for a description of the format. |
485 |
* @param key the key. |
* |
486 |
* @param value the value. |
* @param key the key |
487 |
* @see #store |
* @param value the value |
488 |
|
* @see #store(OutputStream, String) |
489 |
*/ |
*/ |
490 |
private String formatForOutput(String key, String value) |
private String formatForOutput(String key, String value) |
491 |
{ |
{ |
495 |
boolean head = true; |
boolean head = true; |
496 |
for (int i = 0; i < key.length(); i++) |
for (int i = 0; i < key.length(); i++) |
497 |
{ |
{ |
498 |
char c = key.charAt(i); |
char c = key.charAt(i); |
499 |
switch (c) |
switch (c) |
500 |
{ |
{ |
501 |
case '\n': |
case '\n': |
502 |
result.append("\\n"); |
result.append("\\n"); |
503 |
break; |
break; |
504 |
case '\r': |
case '\r': |
505 |
result.append("\\r"); |
result.append("\\r"); |
506 |
break; |
break; |
507 |
case '\t': |
case '\t': |
508 |
result.append("\\t"); |
result.append("\\t"); |
509 |
break; |
break; |
510 |
case '\\': |
case '\\': |
511 |
result.append("\\\\"); |
result.append("\\\\"); |
512 |
break; |
break; |
513 |
case '!': |
case '!': |
514 |
result.append("\\!"); |
result.append("\\!"); |
515 |
break; |
break; |
516 |
case '#': |
case '#': |
517 |
result.append("\\#"); |
result.append("\\#"); |
518 |
break; |
break; |
519 |
case '=': |
case '=': |
520 |
result.append("\\="); |
result.append("\\="); |
521 |
break; |
break; |
522 |
case ':': |
case ':': |
523 |
result.append("\\:"); |
result.append("\\:"); |
524 |
break; |
break; |
525 |
case ' ': |
case ' ': |
526 |
result.append("\\ "); |
result.append("\\ "); |
527 |
break; |
break; |
528 |
default: |
default: |
529 |
if (c < 32 || c > '~') |
if (c < 32 || c > '~') |
530 |
{ |
{ |
531 |
String hex = Integer.toHexString(c); |
String hex = Integer.toHexString(c); |
532 |
result.append("\\u0000".substring(0, 6 - hex.length())); |
result.append("\\u0000".substring(0, 6 - hex.length())); |
533 |
result.append(hex); |
result.append(hex); |
534 |
} |
} |
535 |
else |
else |
536 |
result.append(c); |
result.append(c); |
537 |
} |
} |
538 |
if (c != 32) |
if (c != 32) |
539 |
head = false; |
head = false; |
540 |
} |
} |
541 |
result.append('='); |
result.append('='); |
542 |
head = true; |
head = true; |
543 |
for (int i = 0; i < value.length(); i++) |
for (int i = 0; i < value.length(); i++) |
544 |
{ |
{ |
545 |
char c = value.charAt(i); |
char c = value.charAt(i); |
546 |
switch (c) |
switch (c) |
547 |
{ |
{ |
548 |
case '\n': |
case '\n': |
549 |
result.append("\\n"); |
result.append("\\n"); |
550 |
break; |
break; |
551 |
case '\r': |
case '\r': |
552 |
result.append("\\r"); |
result.append("\\r"); |
553 |
break; |
break; |
554 |
case '\t': |
case '\t': |
555 |
result.append("\\t"); |
result.append("\\t"); |
556 |
break; |
break; |
557 |
case '\\': |
case '\\': |
558 |
result.append("\\\\"); |
result.append("\\\\"); |
559 |
break; |
break; |
560 |
case '!': |
case '!': |
561 |
result.append("\\!"); |
result.append("\\!"); |
562 |
break; |
break; |
563 |
case '#': |
case '#': |
564 |
result.append("\\#"); |
result.append("\\#"); |
565 |
break; |
break; |
566 |
case ' ': |
case ' ': |
567 |
result.append(head ? "\\ " : " "); |
result.append(head ? "\\ " : " "); |
568 |
break; |
break; |
569 |
default: |
default: |
570 |
if (c < 32 || c > '~') |
if (c < 32 || c > '~') |
571 |
{ |
{ |
572 |
String hex = Integer.toHexString(c); |
String hex = Integer.toHexString(c); |
573 |
result.append("\\u0000".substring(0, 6 - hex.length())); |
result.append("\\u0000".substring(0, 6 - hex.length())); |
574 |
result.append(hex); |
result.append(hex); |
575 |
} |
} |
576 |
else |
else |
577 |
result.append(c); |
result.append(c); |
578 |
} |
} |
579 |
if (c != 32) |
if (c != 32) |
580 |
head = false; |
head = false; |
581 |
} |
} |
582 |
return result.toString(); |
return result.toString(); |
583 |
} |
} |
584 |
|
|
585 |
/** |
/** |
586 |
* Writes the key/value pairs to the given print stream. They are |
* Recursively grabs the keys from the default properties. |
587 |
* written in the way, described in the method store. |
* |
588 |
* @param out the stream, where the key/value pairs are written to. |
* @param base the hashtable to place the keys in |
|
* @exception ClassCastException if this property contains any key or |
|
|
* value that isn't a string. |
|
|
* @see #store |
|
|
*/ |
|
|
public void list(PrintStream out) |
|
|
{ |
|
|
Enumeration keys = keys(); |
|
|
Enumeration elts = elements(); |
|
|
while (keys.hasMoreElements()) |
|
|
{ |
|
|
String key = (String) keys.nextElement(); |
|
|
String elt = (String) elts.nextElement(); |
|
|
String output = formatForOutput(key, elt); |
|
|
out.println(output); |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
|
* Writes the key/value pairs to the given print writer. They are |
|
|
* written in the way, described in the method store. |
|
|
* @param out the writer, where the key/value pairs are written to. |
|
|
* @exception ClassCastException if this property contains any key or |
|
|
* value that isn't a string. |
|
|
* @see #store |
|
|
* @see #list(java.io.PrintStream) |
|
|
* @since JDK1.1 |
|
589 |
*/ |
*/ |
590 |
public void list(PrintWriter out) |
private final void addHashEntries(Hashtable base) |
591 |
{ |
{ |
592 |
|
if (defaults != null) |
593 |
|
defaults.addHashEntries(base); |
594 |
Enumeration keys = keys(); |
Enumeration keys = keys(); |
|
Enumeration elts = elements(); |
|
595 |
while (keys.hasMoreElements()) |
while (keys.hasMoreElements()) |
596 |
{ |
base.put(keys.nextElement(), base); |
|
String key = (String) keys.nextElement(); |
|
|
String elt = (String) elts.nextElement(); |
|
|
String output = formatForOutput(key, elt); |
|
|
out.println(output); |
|
|
} |
|
597 |
} |
} |
598 |
} |
} |