1 package org.masukomi.prefs;
2
3 import java.io.*;
4
5 import java.util.prefs.*;
6
7
8 /***
9 * <p>
10 * XMLPreferences provides developers with an easy means of utilizing local XML
11 * config files for their sofatware. Built around the standard java
12 * Preferences class, XMLPreferences provides you with all of the standard
13 * java.util.prefs.Preferences functionality combined with a user defined root
14 * directory and files that are lways stored in XML. XMLPreferences always
15 * reads and writes to XML files stored in the default format used by
16 * Preferences. This allows you the simplicity and known methods of the normal
17 * Preferences class combined with a Local XML file that users can edit, if
18 * needed, which makes it perfect for config files.
19 * </p>
20 *
21 * <p>
22 * Preferences will also be saved in the default Preferences tree, thus
23 * allowing classes calling the standard Preferences class to utilize the same
24 * information. However, should classes using Preferences modify that
25 * information it will not be saved to the local XML files. XMLPreferences
26 * will always load from the local directory and save to both AND, due to the
27 * Nature of the Preferences class the preferences stored in the local XML
28 * file wioll overwrite those stored in the default preferences tree. Local
29 * XML files will be named < class name% gt;. xml
30 * </p>
31 *
32 * <p>
33 * This software is copyright 2002 Kate Rhodes. <br>
34 * It is distributed under the MIT License which can be found at <a
35 * href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.
36 * php</a><br>
37 * Details on this package can be found at <a href="http://tools.masukomi.org/">http://tools.masukomi.org/</a><br>
38 * e-mail <tt>masukomi at masukomi dot org</tt> for questions or details
39 * </p>
40 *
41 * @author Kate Rhodes (e-mail masukomi at masukomi dot org)
42 *
43 * @see java.util.prefs.Preferences for a full description of functionality and
44 * XML data structure
45 */
46 public class XMLPreferences {
47 /***
48 * The path to where Preferences are stored locally. This defaults to
49 * System.getProperty("user.dir") + System.getProperty("line.separator") +
50 * "prefs";
51 */
52 static protected File preferencesRoot =
53 new File(System.getProperty("user.dir") + System.getProperty("file.separator")
54 + "prefs");
55
56 /***
57 * The internal Preferences object this class will be using for most of its
58 * functionality
59 */
60 protected Preferences myPreferences;
61
62 /*** allows the name of the user folder to be manually overridden
63 * for user systems that aren't related to the OS's idea of a user.
64 * NOT Currently implemented... merely a placeholder.
65 */
66 protected String user = null;
67
68 /***
69 * Constructor for XMLPreferences. By default this method will attempt to
70 * load the local XML file representing this Preferences object.
71 *
72 * @param internalPreferences the internal Preferences object to wrap XML
73 * functionality around.
74 */
75 public XMLPreferences(Preferences internalPreferences) {
76 loadInternalPrefs(internalPreferences, true);
77 }
78
79 /***
80 * Creates a new XMLPreferences object.
81 *
82 * @param internalPreferences the internal Preferences object to wrap XML
83 * functionality around.
84 * @param loadFromXML indicates if we should attempt to load this from a
85 * local XML file
86 */
87 public XMLPreferences(Preferences internalPreferences, boolean loadFromXML) {
88 loadInternalPrefs(internalPreferences, loadFromXML);
89 }
90
91 /***
92 * Constructor for XMLPreferences.
93 *
94 * @param xmlPreferences the internal Preferences object to wrap XML
95 * functionality around.
96 */
97 public XMLPreferences(XMLPreferences xmlPreferences) {
98 myPreferences = xmlPreferences.getPreferences();
99 }
100
101 /***
102 * Loads the internal preferences from the sytem preferences store or the
103 * local XML files. Also handles all errors.
104 *
105 * @param internalPreferences the internal Preferences object to wrap XML
106 * functionality around.
107 * @param loadFromXML indicates if we should attempt to load this from a
108 * local XML file
109 */
110 protected void loadInternalPrefs(
111 Preferences internalPreferences,
112 boolean loadFromXML) {
113 if (loadFromXML) {
114 File currentXML =
115 new File(getLocalXMLFilePath(internalPreferences));
116
117 if (currentXML.canRead()) {
118 // if we can read it it must Exist
119 try {
120 Preferences.importPreferences(new FileInputStream(currentXML));
121 myPreferences =
122 myPreferences.node(internalPreferences.name());
123 } catch (Exception e) {
124 // default functionality is to just work, so damn it, we'll use the internal one
125 myPreferences = internalPreferences;
126 }
127 }
128
129 myPreferences = internalPreferences;
130 } else {
131 myPreferences = internalPreferences;
132 }
133 }
134
135 /***
136 * Returns the current local directory that should hold the XML file
137 * corresponding to the Preferences object passed.
138 *
139 * @param p The preferences object whose local XML directory you wish to
140 * find.
141 *
142 * @return The absolute path to the local that should contain the XML file
143 * corresponding to the Preferences object passed.
144 */
145 protected static String getLocalXMLFileDir(Preferences p) {
146 String currentPath = getLocalXMLFilePath(p);
147
148 return currentPath.substring(
149 0,
150 currentPath.lastIndexOf(System.getProperty("file.separator")));
151 }
152
153 /***
154 * Returns the absolute path name of the XML File corresponding to the
155 * specified Preferences object. This does not validate the existence of
156 * the file, only tells you where it should be.
157 *
158 * @param p The Preferences node you wish to find the local representation
159 * of.
160 *
161 * @return an absolute path to the XML File corresponding to the specified
162 * Preferences object.
163 */
164 protected static String getLocalXMLFilePath(Preferences p) {
165 if (p == null) {
166 System.out.println("p was null");
167
168 return null;
169 }
170
171 StringBuffer fileNameBuffer = new StringBuffer(getPreferencesRoot());
172 fileNameBuffer.append(System.getProperty("file.separator"));
173
174 String subPath = p.absolutePath();
175
176 if (p.isUserNode()) {
177 fileNameBuffer.append("user");
178 fileNameBuffer.append(System.getProperty("file.separator"));
179 //if (this.user == null){
180 fileNameBuffer.append(System.getProperty("user.name"));
181 //} else {
182 // fileNameBuffer.append(user);
183 //}
184
185 } else {
186 fileNameBuffer.append("system");
187
188 }
189
190
191 subPath =
192 subPath.replaceAll(
193 "///",
194 "//" + System.getProperty("file.separator"));
195 fileNameBuffer.append(subPath);
196 fileNameBuffer.append(System.getProperty("file.separator"));
197 fileNameBuffer.append(p.name());
198
199 // that gets you the appropriate folder now we need a file name
200 fileNameBuffer.append(".xml");
201
202 return fileNameBuffer.toString();
203 }
204
205 /*
206 * Returns the absolute path name of the XML File corresponding to the
207 * package of the specified object.
208 *
209 * @return DOCUMENT ME!
210 */
211
212 /*private static String getLocalXMLFilePath(Class c) {
213 if (c.isArray()) {
214 throw new IllegalArgumentException("Arrays have no associated preferences node.");
215 }
216 String className = c.getName();
217 int pkgEndIndex = className.lastIndexOf('.');
218 if (pkgEndIndex < 0) {
219 return getPreferencesRoot() + "/<unnamed>";
220 }
221 String packageName = className.substring(0, pkgEndIndex);
222 StringBuffer fileNameBuffer = new StringBuffer(getPreferencesRoot());
223 fileNameBuffer.append("/");
224 fileNameBuffer.append(packageName.replace('.', '/'));
225 fileNameBuffer.append(".xml");
226 return fileNameBuffer.toString();
227 } */
228
229 /***
230 * Returns the root directory holding all of the XML preferences.
231 *
232 * @return the root directory holding all of the XML preferences.
233 */
234 public static String getPreferencesRoot() {
235 return preferencesRoot.toString();
236 }
237
238
239 /***
240 * Sets the local XML preferences root directory
241 *
242 * @param preferencesRoot the absolute path to the XML preferences root
243 * directory
244 */
245 public static void setPreferencesRoot(String preferencesRoot) {
246 XMLPreferences.preferencesRoot = new File(preferencesRoot);
247 }
248
249 ///////////////////////////////////////////////////////////////////////////
250 // The methods that follow are all wrappers around the standard Preferences methods
251 /***
252 * Returns this preference node's corresponding XML document's absolute path
253 * name.
254 *
255 * @return this preference node's absolute path name.
256 */
257 public String absolutePath(){
258 return absolutePath(true);
259 }
260 /***
261 * Returns this preference node's absolute path name.
262 * @param xmlPath if true the returned value will be that of the XML File
263 * that corresponds with this Preferences object. If false it will be the
264 * value returned from Preferences.absolutePath()
265 * @return this preference node's absolute path name.
266 */
267 public String absolutePath(boolean xmlPath){
268 if (xmlPath){
269 return getLocalXMLFilePath(myPreferences);
270 }
271 return myPreferences.absolutePath();
272 }
273
274 /***
275 * Registers the specified listener to receive <i>node change events</i>
276 * for this node. A node change event is generated when a child node is
277 * added to or removed from this node. (A single {@link #removeNode()}
278 * invocation results in multiple <i>node change events</i>, one for every
279 * node in the subtree rooted at the removed node.)
280 *
281 * <p>Events are only guaranteed for changes made within the same JVM
282 * as the registered listener, though some implementations may generate
283 * events for changes made outside this JVM. Events may be generated
284 * before the changes have become permanent. Events are not generated
285 * when indirect descendants of this node are added or removed; a
286 * caller desiring such events must register with each descendant.
287 *
288 * <p>Few guarantees can be made regarding node creation. Because nodes
289 * are created implicitly upon access, it may not be feasible for an
290 * implementation to determine whether a child node existed in the backing
291 * store prior to access (for example, because the backing store is
292 * unreachable or cached information is out of date). Under these
293 * circumstances, implementations are neither required to generate node
294 * change events nor prohibited from doing so.
295 *
296 * @param ncl The <tt>NodeChangeListener</tt> to add.
297 * @throws NullPointerException if <tt>ncl</tt> is null.
298 * @throws IllegalStateException if this node (or an ancestor) has been
299 * removed with the {@link #removeNode()} method.
300 * @see #removeNodeChangeListener(NodeChangeListener)
301 * @see #addPreferenceChangeListener(PreferenceChangeListener)
302 */
303 public void addNodeChangeListener(NodeChangeListener ncl) throws NullPointerException, IllegalStateException{
304 myPreferences.addNodeChangeListener(ncl);
305 }
306
307 /***
308 * Registers the specified listener to receive <i>preference change
309 * events</i> for this preference node. A preference change event is
310 * generated when a preference is added to this node, removed from this
311 * node, or when the value associated with a preference is changed.
312 * (Preference change events are <i>not</i> generated by the {@link
313 * #removeNode()} method, which generates a <i>node change event</i>.
314 * Preference change events <i>are</i> generated by the <tt>clear</tt>
315 * method.)
316 *
317 * <p>Events are only guaranteed for changes made within the same JVM
318 * as the registered listener, though some implementations may generate
319 * events for changes made outside this JVM. Events may be generated
320 * before the changes have been made persistent. Events are not generated
321 * when preferences are modified in descendants of this node; a caller
322 * desiring such events must register with each descendant.
323 *
324 * @param pcl The preference change listener to add.
325 * @throws NullPointerException if <tt>pcl</tt> is null.
326 * @throws IllegalStateException if this node (or an ancestor) has been
327 * removed with the {@link #removeNode()} method.
328 * @see #removePreferenceChangeListener(PreferenceChangeListener)
329 * @see #addNodeChangeListener(NodeChangeListener)
330 */
331 public void addPreferenceChangeListener(PreferenceChangeListener pcl) throws NullPointerException, IllegalStateException{
332 myPreferences.addPreferenceChangeListener(pcl);
333 }
334
335 /***
336 * Returns the names of the children of this preference node, relative to
337 * this node. (The returned array will be of size zero if this node has
338 * no children.)
339 *
340 * @return the names of the children of this preference node.
341 * @throws BackingStoreException if this operation cannot be completed
342 * due to a failure in the backing store, or inability to
343 * communicate with it.
344 * @throws IllegalStateException if this node (or an ancestor) has been
345 * removed with the {@link #removeNode()} method.
346 */
347 public String[] childrenNames() throws BackingStoreException, IllegalStateException {
348 return myPreferences.childrenNames();
349 }
350
351 /***
352 * Removes all of the preferences (key-value associations) in this
353 * preference node. This call has no effect on any descendants
354 * of this node.
355 *
356 * <p>If this implementation supports <i>stored defaults</i>, and this
357 * node in the preferences hierarchy contains any such defaults,
358 * the stored defaults will be "exposed" by this call, in the sense that
359 * they will be returned by succeeding calls to <tt>get</tt>.
360 *
361 * @throws BackingStoreException if this operation cannot be completed
362 * due to a failure in the backing store, or inability to
363 * communicate with it.
364 * @throws IllegalStateException if this node (or an ancestor) has been
365 * removed with the {@link #removeNode()} method.
366 * @see #removeNode()
367 */
368 public void clear() throws BackingStoreException, IllegalStateException {
369 myPreferences.clear();
370 }
371
372 /***
373 * Emits on the specified output stream an XML document representing all
374 * of the preferences contained in this node (but not its descendants).
375 * This XML document is, in effect, an offline backup of the node.
376 *
377 * <p>When using XMLPreferences you need only call this if you wish to
378 * export your Preferences to a location other than the default one.
379 * Otherwise XML will be exported every time {@link #flush()} is called.</p>
380 *
381 * <p>The XML document will have the following DOCTYPE declaration:
382 * <pre>
383 * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
384 * </pre>
385 * The UTF-8 character encoding will be used.
386 *
387 * <p>This method is an exception to the general rule that the results of
388 * concurrently executing multiple methods in this class yields
389 * results equivalent to some serial execution. If the preferences
390 * at this node are modified concurrently with an invocation of this
391 * method, the exported preferences comprise a "fuzzy snapshot" of the
392 * preferences contained in the node; some of the concurrent modifications
393 * may be reflected in the exported data while others may not.
394 *
395 * @param os the output stream on which to emit the XML document.
396 * @throws IOException if writing to the specified output stream
397 * results in an <tt>IOException</tt>.
398 * @throws BackingStoreException if preference data cannot be read from
399 * backing store.
400 * @see #importPreferences(InputStream)
401 * @throws IllegalStateException if this node (or an ancestor) has been
402 * removed with the {@link #removeNode()} method.
403 */
404 public void exportNode(OutputStream os)
405 throws IOException, BackingStoreException,
406 IllegalStateException {
407 myPreferences.exportNode(os);
408 }
409
410 /***
411 * Emits an XML document representing all of the preferences contained
412 * in this node and all of its descendants. This XML document is, in
413 * effect, an offline backup of the subtree rooted at the node.
414 *
415 * <p>The XML document will have the following DOCTYPE declaration:
416 * <pre>
417 * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
418 * </pre>
419 * The UTF-8 character encoding will be used.
420 *
421 * <p>This method is an exception to the general rule that the results of
422 * concurrently executing multiple methods in this class yields
423 * results equivalent to some serial execution. If the preferences
424 * or nodes in the subtree rooted at this node are modified concurrently
425 * with an invocation of this method, the exported preferences comprise a
426 * "fuzzy snapshot" of the subtree; some of the concurrent modifications
427 * may be reflected in the exported data while others may not.
428 *
429 * @param os the output stream on which to emit the XML document.
430 * @throws IOException if writing to the specified output stream
431 * results in an <tt>IOException</tt>.
432 * @throws BackingStoreException if preference data cannot be read from
433 * backing store.
434 * @throws IllegalStateException if this node (or an ancestor) has been
435 * removed with the {@link #removeNode()} method.
436 * @see #importPreferences(InputStream)
437 * @see #exportNode(OutputStream)
438 */
439 public void exportSubtree(OutputStream os)
440 throws BackingStoreException, IllegalStateException,
441 IOException {
442 myPreferences.exportSubtree(os);
443 }
444
445 /***
446 * Forces any changes in the contents of this preference node and its
447 * descendants to the persistent store.
448 *
449 * @throws BackingStoreException - if this operation cannot be completed due to a failure in the backing store, or inability to communicate with it.
450 * @throws IOException - If errrors were encountered trying to create a new
451 * FileOutputStream to write the new XML doc to.
452 * @throws FileNotFoundException - If the directory to export the XML to was
453 * not found and not able to be created
454 * @throws IllegalStateException - if this node (or an ancestor) has been
455 * removed with the removeNode() method.
456 */
457 public void flush()
458 throws BackingStoreException, IOException, FileNotFoundException, IllegalStateException {
459 myPreferences.flush();
460
461 FileOutputStream fos;
462
463 try {
464 fos = new FileOutputStream(getLocalXMLFilePath(myPreferences));
465 myPreferences.exportNode(fos);
466 fos.close();
467 } catch (FileNotFoundException e) {
468 File xmlPackageDir = new File(getLocalXMLFileDir(myPreferences));
469
470 if (xmlPackageDir.mkdirs()) {
471 fos = new FileOutputStream(getLocalXMLFilePath(myPreferences));
472 myPreferences.exportNode(fos);
473 fos.close();
474 } else {
475 throw new FileNotFoundException(e.toString());
476 }
477 }
478 }
479
480 /***
481 * Returns the value associated with the specified key in this preference
482 * node. Returns the specified default if there is no value associated
483 * with the key, or the backing store is inaccessible.
484 *
485 * <p>Some implementations may store default values in their backing
486 * stores. If there is no value associated with the specified key
487 * but there is such a <i>stored default</i>, it is returned in
488 * preference to the specified default.
489 *
490 * @param key key whose associated value is to be returned.
491 * @param def the value to be returned in the event that this
492 * preference node has no value associated with <tt>key</tt>.
493 * @return the value associated with <tt>key</tt>, or <tt>def</tt>
494 * if no value is associated with <tt>key</tt>, or the backing
495 * store is inaccessible.
496 * @throws IllegalStateException if this node (or an ancestor) has been
497 * removed with the {@link #removeNode()} method.
498 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>. (A
499 * <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.)
500 */
501 public String get(String key, String def)
502 throws IllegalStateException, NullPointerException {
503 return myPreferences.get(key, def);
504 }
505
506 /***
507 * Returns the boolean value represented by the string associated with the
508 * specified key in this preference node. Valid strings
509 * are <tt>"true"</tt>, which represents true, and <tt>"false"</tt>, which
510 * represents false. Case is ignored, so, for example, <tt>"TRUE"</tt>
511 * and <tt>"False"</tt> are also valid. This method is intended for use in
512 * conjunction with {@link #putBoolean}.
513 *
514 * <p>Returns the specified default if there is no value
515 * associated with the key, the backing store is inaccessible, or if the
516 * associated value is something other than <tt>"true"</tt> or
517 * <tt>"false"</tt>, ignoring case.
518 *
519 * <p>If the implementation supports <i>stored defaults</i> and such a
520 * default exists and is accessible, it is used in preference to the
521 * specified default, unless the stored default is something other than
522 * <tt>"true"</tt> or <tt>"false"</tt>, ignoring case, in which case the
523 * specified default is used.
524 *
525 * @param key key whose associated value is to be returned as a boolean.
526 * @param def the value to be returned in the event that this
527 * preference node has no value associated with <tt>key</tt>
528 * or the associated value cannot be interpreted as a boolean,
529 * or the backing store is inaccessible.
530 * @return the boolean value represented by the string associated with
531 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
532 * associated value does not exist or cannot be interpreted as
533 * a boolean.
534 * @throws IllegalStateException if this node (or an ancestor) has been
535 * removed with the {@link #removeNode()} method.
536 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
537 * @see #get(String,String)
538 * @see #putBoolean(String,boolean)
539 */
540 public boolean getBoolean(String key, boolean def)
541 throws IllegalStateException, NullPointerException {
542 return myPreferences.getBoolean(key, def);
543 }
544
545 /***
546 * Returns the byte array value represented by the string associated with
547 * the specified key in this preference node. Valid strings are
548 * <i>Base64</i> encoded binary data, as defined in <a
549 * href=http://www.ietf.org/rfc/rfc2045.txt>RFC 2045</a>, Section 6.8,
550 * with one minor change: the string must consist solely of characters
551 * from the <i>Base64 Alphabet</i>; no newline characters or
552 * extraneous characters are permitted. This method is intended for use
553 * in conjunction with {@link #putByteArray}.
554 *
555 * <p>Returns the specified default if there is no value
556 * associated with the key, the backing store is inaccessible, or if the
557 * associated value is not a valid Base64 encoded byte array
558 * (as defined above).
559 *
560 * <p>If the implementation supports <i>stored defaults</i> and such a
561 * default exists and is accessible, it is used in preference to the
562 * specified default, unless the stored default is not a valid Base64
563 * encoded byte array (as defined above), in which case the
564 * specified default is used.
565 *
566 * @param key key whose associated value is to be returned as a byte array.
567 * @param def the value to be returned in the event that this
568 * preference node has no value associated with <tt>key</tt>
569 * or the associated value cannot be interpreted as a byte array,
570 * or the backing store is inaccessible.
571 * @return the byte array value represented by the string associated with
572 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
573 * associated value does not exist or cannot be interpreted as
574 * a byte array.
575 * @throws IllegalStateException if this node (or an ancestor) has been
576 * removed with the {@link #removeNode()} method.
577 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>. (A
578 * <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.)
579 * @see #get(String,String)
580 * @see #putByteArray(String,byte[])
581 */
582 public byte[] getByteArray(String key, byte[] def)
583 throws IllegalStateException, NullPointerException {
584 return myPreferences.getByteArray(key, def);
585 }
586
587 /***
588 * Returns the double value represented by the string associated with the
589 * specified key in this preference node. The string is converted to an
590 * integer as by {@link Double#parseDouble(String)}. Returns the specified
591 * default if there is no value associated with the key, the backing store
592 * is inaccessible, or if <tt>Double.parseDouble(String)</tt> would throw a
593 * {@link NumberFormatException} if the associated value were passed.
594 * This method is intended for use in conjunction with {@link #putDouble}.
595 *
596 * <p>If the implementation supports <i>stored defaults</i> and such a
597 * default exists, is accessible, and could be converted to a double
598 * with <tt>Double.parseDouble</tt>, this double is returned in preference
599 * to the specified default.
600 *
601 * @param key key whose associated value is to be returned as a double.
602 * @param def the value to be returned in the event that this
603 * preference node has no value associated with <tt>key</tt>
604 * or the associated value cannot be interpreted as a double,
605 * or the backing store is inaccessible.
606 * @return the double value represented by the string associated with
607 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
608 * associated value does not exist or cannot be interpreted as
609 * a double.
610 * @throws IllegalStateException if this node (or an ancestor) has been
611 * removed with the {@link #removeNode()} method.
612 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
613 * @see #putDouble(String,double)
614 * @see #get(String,String)
615 */
616 public double getDouble(String key, double def)
617 throws IllegalStateException, NullPointerException {
618 return myPreferences.getDouble(key, def);
619 }
620
621 /***
622 * Returns the float value represented by the string associated with the
623 * specified key in this preference node. The string is converted to an
624 * integer as by {@link Float#parseFloat(String)}. Returns the specified
625 * default if there is no value associated with the key, the backing store
626 * is inaccessible, or if <tt>Float.parseFloat(String)</tt> would throw a
627 * {@link NumberFormatException} if the associated value were passed.
628 * This method is intended for use in conjunction with {@link #putFloat}.
629 *
630 * <p>If the implementation supports <i>stored defaults</i> and such a
631 * default exists, is accessible, and could be converted to a float
632 * with <tt>Float.parseFloat</tt>, this float is returned in preference to
633 * the specified default.
634 *
635 * @param key key whose associated value is to be returned as a float.
636 * @param def the value to be returned in the event that this
637 * preference node has no value associated with <tt>key</tt>
638 * or the associated value cannot be interpreted as a float,
639 * or the backing store is inaccessible.
640 * @return the float value represented by the string associated with
641 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
642 * associated value does not exist or cannot be interpreted as
643 * a float.
644 * @throws IllegalStateException if this node (or an ancestor) has been
645 * removed with the {@link #removeNode()} method.
646 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
647 * @see #putFloat(String,float)
648 * @see #get(String,String)
649 */
650 public float getFloat(String key, float def)
651 throws IllegalStateException, NullPointerException {
652 return myPreferences.getFloat(key, def);
653 }
654
655 /***
656 * Returns the int value represented by the string associated with the
657 * specified key in this preference node. The string is converted to
658 * an integer as by {@link Integer#parseInt(String)}. Returns the
659 * specified default if there is no value associated with the key,
660 * the backing store is inaccessible, or if
661 * <tt>Integer.parseInt(String)</tt> would throw a {@link
662 * NumberFormatException} if the associated value were passed. This
663 * method is intended for use in conjunction with {@link #putInt}.
664 *
665 * <p>If the implementation supports <i>stored defaults</i> and such a
666 * default exists, is accessible, and could be converted to an int
667 * with <tt>Integer.parseInt</tt>, this int is returned in preference to
668 * the specified default.
669 *
670 * @param key key whose associated value is to be returned as an int.
671 * @param def the value to be returned in the event that this
672 * preference node has no value associated with <tt>key</tt>
673 * or the associated value cannot be interpreted as an int,
674 * or the backing store is inaccessible.
675 * @return the int value represented by the string associated with
676 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
677 * associated value does not exist or cannot be interpreted as
678 * an int.
679 * @throws IllegalStateException if this node (or an ancestor) has been
680 * removed with the {@link #removeNode()} method.
681 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
682 * @see #putInt(String,int)
683 * @see #get(String,String)
684 */
685 public int getInt(String key, int def)
686 throws IllegalStateException, NullPointerException {
687 return myPreferences.getInt(key, def);
688 }
689
690 /***
691 * Returns the long value represented by the string associated with the
692 * specified key in this preference node. The string is converted to
693 * a long as by {@link Long#parseLong(String)}. Returns the
694 * specified default if there is no value associated with the key,
695 * the backing store is inaccessible, or if
696 * <tt>Long.parseLong(String)</tt> would throw a {@link
697 * NumberFormatException} if the associated value were passed. This
698 * method is intended for use in conjunction with {@link #putLong}.
699 *
700 * <p>If the implementation supports <i>stored defaults</i> and such a
701 * default exists, is accessible, and could be converted to a long
702 * with <tt>Long.parseLong</tt>, this long is returned in preference to
703 * the specified default.
704 *
705 * @param key key whose associated value is to be returned as a long.
706 * @param def the value to be returned in the event that this
707 * preference node has no value associated with <tt>key</tt>
708 * or the associated value cannot be interpreted as a long,
709 * or the backing store is inaccessible.
710 * @return the long value represented by the string associated with
711 * <tt>key</tt> in this preference node, or <tt>def</tt> if the
712 * associated value does not exist or cannot be interpreted as
713 * a long.
714 * @throws IllegalStateException if this node (or an ancestor) has been
715 * removed with the {@link #removeNode()} method.
716 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
717 * @see #putLong(String,long)
718 * @see #get(String,String)
719 */
720 public long getLong(String key, long def)
721 throws IllegalStateException, NullPointerException {
722 return myPreferences.getLong(key, def);
723 }
724
725 /***
726 * Returns the internal preferences associated with this XMLPreferences
727 * object
728 *
729 * @return Preferences the internal preferences associated with this
730 * XMLPreferences object
731 */
732 public Preferences getPreferences() {
733 return myPreferences;
734 }
735
736
737 /***
738 * Returns the value associated with the specified key in this preference
739 * node. Returns the specified default if there is no value associated
740 * with the key, or the backing store is inaccessible.
741 *
742 * <p>While not a method contained in java.util.prefs.Preferences this
743 * method was added because I kept trying to call it as a result of all the
744 * other methods being typed</p>
745 *
746 * <p>Some implementations may store default values in their backing
747 * stores. If there is no value associated with the specified key
748 * but there is such a <i>stored default</i>, it is returned in
749 * preference to the specified default.</p>
750 *
751 * <p><b>Future Enhancements:</b> The main enhancement I wish to add is the
752 * ability to store class specific preferences instead of just Package
753 * specific ones</p>
754 *
755 * @param key key whose associated value is to be returned.
756 * @param def the value to be returned in the event that this
757 * preference node has no value associated with <tt>key</tt>.
758 * @return the value associated with <tt>key</tt>, or <tt>def</tt>
759 * if no value is associated with <tt>key</tt>, or the backing
760 * store is inaccessible.
761 * @throws IllegalStateException if this node (or an ancestor) has been
762 * removed with the {@link #removeNode()} method.
763 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>. (A
764 * <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.)
765 */
766 public String getString(String key, String def) throws IllegalStateException, NullPointerException{
767 return get(key, def);
768 }
769
770 /***
771 * Imports all of the preferences represented by the XML document on the
772 * specified input stream. The document may represent user preferences or
773 * system preferences. If it represents user preferences, the preferences
774 * will be imported into the calling user's preference tree (even if they
775 * originally came from a different user's preference tree). If any of
776 * the preferences described by the document inhabit preference nodes that
777 * do not exist, the nodes will be created.
778 *
779 * <p>The XML document must have the following DOCTYPE declaration:
780 * <pre>
781 * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
782 * </pre>
783 * (This method is designed for use in conjunction with
784 * {@link #exportNode(OutputStream)} and
785 * {@link #exportSubtree(OutputStream)}.
786 *
787 * <p>This method is an exception to the general rule that the results of
788 * concurrently executing multiple methods in this class yields
789 * results equivalent to some serial execution. The method behaves
790 * as if implemented on top of the other public methods in this class,
791 * notably {@link #node(String)} and {@link #put(String, String)}.
792 *
793 * @param is the input stream from which to read the XML document.
794 * @throws IOException if reading from the specified output stream
795 * results in an <tt>IOException</tt>.
796 * @throws InvalidPreferencesFormatException Data on input stream does not
797 * constitute a valid XML document with the mandated document type.
798 * @throws SecurityException If a security manager is present and
799 * it denies <tt>RuntimePermission("preferences")</tt>.
800 * @see RuntimePermission
801 */
802 static public void importPreferences(InputStream is)
803 throws IOException,
804 InvalidPreferencesFormatException {
805 Preferences.importPreferences(is);
806 }
807
808 /***
809 * Returns <tt>true</tt> if this preference node is in the user
810 * preference tree, <tt>false</tt> if it's in the system preference tree.
811 *
812 * @return <tt>true</tt> if this preference node is in the user
813 * preference tree, <tt>false</tt> if it's in the system
814 * preference tree.
815 */
816 public boolean isUserNode() {
817 return myPreferences.isUserNode();
818 }
819
820 /***
821 * Returns all of the keys that have an associated value in this
822 * preference node. (The returned array will be of size zero if
823 * this node has no preferences.)
824 *
825 * <p>If the implementation supports <i>stored defaults</i> and there
826 * are any such defaults at this node that have not been overridden,
827 * by explicit preferences, the defaults are returned in the array in
828 * addition to any explicit preferences.
829 *
830 * @return an array of the keys that have an associated value in this
831 * preference node.
832 * @throws BackingStoreException if this operation cannot be completed
833 * due to a failure in the backing store, or inability to
834 * communicate with it.
835 * @throws IllegalStateException if this node (or an ancestor) has been
836 * removed with the {@link #removeNode()} method.
837 */
838 public String[] keys() throws BackingStoreException, IllegalStateException {
839 return myPreferences.keys();
840 }
841
842 /***
843 * Returns this preference node's name, relative to its parent.
844 *
845 * @return this preference node's name, relative to its parent.
846 */
847 public String name() {
848 return myPreferences.name();
849 }
850
851 /***
852 * Returns the named preference node in the same tree as this node,
853 * creating it and any of its ancestors if they do not already exist.
854 * Accepts a relative or absolute path name. Relative path names
855 * (which do not begin with the slash character <tt>('/')</tt>) are
856 * interpreted relative to this preference node.
857 *
858 * <p>If the returned node did not exist prior to this call, this node and
859 * any ancestors that were created by this call are not guaranteed
860 * to become permanent until the <tt>flush</tt> method is called on
861 * the returned node (or one of its ancestors or descendants).
862 *
863 * @param pathName the path name of the preference node to return.
864 * @return the specified preference node.
865 * @throws IllegalArgumentException if the path name is invalid (i.e.,
866 * it contains multiple consecutive slash characters, or ends
867 * with a slash character and is more than one character long).
868 * @throws NullPointerException if path name is <tt>null</tt>.
869 * @throws IllegalStateException if this node (or an ancestor) has been
870 * removed with the {@link #removeNode()} method.
871 * @see #flush()
872 */
873 public XMLPreferences node(String pathName)
874 throws IllegalArgumentException, NullPointerException,
875 IllegalStateException {
876 XMLPreferences newPrefs =
877 new XMLPreferences(myPreferences.node(pathName));
878
879 return newPrefs;
880 }
881
882 /***
883 * Returns true if the named preference node exists in the same tree
884 * as this node. Relative path names (which do not begin with the slash
885 * character <tt>('/')</tt>) are interpreted relative to this preference
886 * node.
887 *
888 * <p>If this node (or an ancestor) has already been removed with the
889 * {@link #removeNode()} method, it <i>is</i> legal to invoke this method,
890 * but only with the path name <tt>""</tt>; the invocation will return
891 * <tt>false</tt>. Thus, the idiom <tt>p.nodeExists("")</tt> may be
892 * used to test whether <tt>p</tt> has been removed.
893 *
894 * @param pathName the path name of the node whose existence
895 * is to be checked.
896 * @return true if the specified node exists.
897 * @throws BackingStoreException if this operation cannot be completed
898 * due to a failure in the backing store, or inability to
899 * communicate with it.
900 * @throws IllegalArgumentException if the path name is invalid (i.e.,
901 * it contains multiple consecutive slash characters, or ends
902 * with a slash character and is more than one character long).
903 * @throws NullPointerException if path name is <tt>null</tt>.
904 * @throws IllegalStateException if this node (or an ancestor) has been
905 * removed with the {@link #removeNode()} method and
906 * <tt>pathName</tt> is not the empty string (<tt>""</tt>).
907 */
908 public boolean nodeExists(String pathName) throws BackingStoreException {
909 File xmlFile;
910 if (pathName.startsWith("/")){
911 xmlFile = new File(pathName);
912 } else {
913 xmlFile = new File(getLocalXMLFileDir(myPreferences) + System.getProperty("user.dir") + pathName);
914 }
915 if (xmlFile.exists()){
916 return true;
917 } else {
918 return myPreferences.nodeExists(pathName);
919 }
920 }
921
922 /***
923 * Returns the parent of this preference node, or <tt>null</tt> if this is
924 * the root.
925 *
926 * @return the parent of this preference node.
927 * @throws IllegalStateException if this node (or an ancestor) has been
928 * removed with the {@link #removeNode()} method.
929 */
930 public XMLPreferences parent()
931 throws IllegalStateException,
932 InvalidPreferencesFormatException, IOException {
933 //find it
934 Preferences newPrefs = myPreferences.parent();
935 String path = getLocalXMLFilePath(newPrefs);
936 File parentXML = new File(path);
937
938 //load it
939 if (parentXML.exists()) {
940 // whoot. Load it baby.
941 Preferences.importPreferences(new FileInputStream(parentXML));
942
943 // reload those
944 newPrefs = newPrefs.node(newPrefs.name());
945 }
946
947 //bundle it and ship it off
948 return new XMLPreferences(newPrefs);
949 }
950
951 /***
952 * Associates the specified value with the specified key in this
953 * preference node.
954 *
955 * @param key key with which the specified value is to be associated.
956 * @param value value to be associated with the specified key.
957 * @throws NullPointerException if key or value is <tt>null</tt>.
958 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
959 * <tt>MAX_KEY_LENGTH</tt> or if <tt>value.length</tt> exceeds
960 * <tt>MAX_VALUE_LENGTH</tt>.
961 * @throws IllegalStateException if this node (or an ancestor) has been
962 * removed with the {@link #removeNode()} method.
963 */
964 public void put(String key, String value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
965 myPreferences.put(key, value);
966 }
967
968 /***
969 * Associates a string representing the specified boolean value with the
970 * specified key in this preference node. The associated string is
971 * <tt>"true"</tt> if the value is true, and <tt>"false"</tt> if it is
972 * false. This method is intended for use in conjunction with
973 * {@link #getBoolean}.
974 *
975 * @param key key with which the string form of value is to be associated.
976 * @param value value whose string form is to be associated with key.
977 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
978 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
979 * <tt>MAX_KEY_LENGTH</tt>.
980 * @throws IllegalStateException if this node (or an ancestor) has been
981 * removed with the {@link #removeNode()} method.
982 * @see #getBoolean(String,boolean)
983 * @see #get(String,String)
984 */
985 public void putBoolean(String key, boolean value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
986 myPreferences.putBoolean(key, value);
987 }
988
989 /***
990 * Associates a string representing the specified byte array with the
991 * specified key in this preference node. The associated string is
992 * the <i>Base64</i> encoding of the byte array, as defined in <a
993 * href=http://www.ietf.org/rfc/rfc2045.txt>RFC 2045</a>, Section 6.8,
994 * with one minor change: the string will consist solely of characters
995 * from the <i>Base64 Alphabet</i>; it will not contain any newline
996 * characters. Note that the maximum length of the byte array is limited
997 * to three quarters of <tt>MAX_VALUE_LENGTH</tt> so that the length
998 * of the Base64 encoded String does not exceed <tt>MAX_VALUE_LENGTH</tt>.
999 * This method is intended for use in conjunction with
1000 * {@link #getByteArray}.
1001 *
1002 * @param key key with which the string form of value is to be associated.
1003 * @param value value whose string form is to be associated with key.
1004 * @throws NullPointerException if key or value is <tt>null</tt>.
1005 * @throws IllegalArgumentException if key.length() exceeds MAX_KEY_LENGTH
1006 * or if value.length exceeds MAX_VALUE_LENGTH*3/4.
1007 * @throws IllegalStateException if this node (or an ancestor) has been
1008 * removed with the {@link #removeNode()} method.
1009 * @see #getByteArray(String,byte[])
1010 * @see #get(String,String)
1011 */
1012 public void putByteArray(String key, byte[] value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
1013 myPreferences.putByteArray(key, value);
1014 }
1015
1016 /***
1017 * Associates a string representing the specified double value with the
1018 * specified key in this preference node. The associated string is the
1019 * one that would be returned if the double value were passed to
1020 * {@link Double#toString(double)}. This method is intended for use in
1021 * conjunction with {@link #getDouble}.
1022 *
1023 * @param key key with which the string form of value is to be associated.
1024 * @param value value whose string form is to be associated with key.
1025 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
1026 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
1027 * <tt>MAX_KEY_LENGTH</tt>.
1028 * @throws IllegalStateException if this node (or an ancestor) has been
1029 * removed with the {@link #removeNode()} method.
1030 * @see #getDouble(String,double)
1031 */
1032 public void putDouble(String key, double value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
1033 myPreferences.putDouble(key, value);
1034 }
1035
1036 /***
1037 * Associates a string representing the specified float value with the
1038 * specified key in this preference node. The associated string is the
1039 * one that would be returned if the float value were passed to
1040 * {@link Float#toString(float)}. This method is intended for use in
1041 * conjunction with {@link #getFloat}.
1042 *
1043 * @param key key with which the string form of value is to be associated.
1044 * @param value value whose string form is to be associated with key.
1045 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
1046 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
1047 * <tt>MAX_KEY_LENGTH</tt>.
1048 * @throws IllegalStateException if this node (or an ancestor) has been
1049 * removed with the {@link #removeNode()} method.
1050 * @see #getFloat(String,float)
1051 */
1052 public void putFloat(String key, float value) throws NullPointerException, IllegalArgumentException, NullPointerException{
1053 myPreferences.putFloat(key, value);
1054 }
1055
1056 /***
1057 * Associates a string representing the specified int value with the
1058 * specified key in this preference node. The associated string is the
1059 * one that would be returned if the int value were passed to
1060 * {@link Integer#toString(int)}. This method is intended for use in
1061 * conjunction with {@link #getInt}.
1062 *
1063 * @param key key with which the string form of value is to be associated.
1064 * @param value value whose string form is to be associated with key.
1065 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
1066 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
1067 * <tt>MAX_KEY_LENGTH</tt>.
1068 * @throws IllegalStateException if this node (or an ancestor) has been
1069 * removed with the {@link #removeNode()} method.
1070 * @see #getInt(String,int)
1071 */
1072 public void putInt(String key, int value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
1073 myPreferences.putInt(key, value);
1074 }
1075
1076 /***
1077 * Associates a string representing the specified long value with the
1078 * specified key in this preference node. The associated string is the
1079 * one that would be returned if the long value were passed to
1080 * {@link Long#toString(long)}. This method is intended for use in
1081 * conjunction with {@link #getLong}.
1082 *
1083 * @param key key with which the string form of value is to be associated.
1084 * @param value value whose string form is to be associated with key.
1085 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
1086 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
1087 * <tt>MAX_KEY_LENGTH</tt>.
1088 * @throws IllegalStateException if this node (or an ancestor) has been
1089 * removed with the {@link #removeNode()} method.
1090 * @see #getLong(String,long)
1091 */
1092 public void putLong(String key, long value) throws IllegalStateException{
1093 myPreferences.putLong(key, value);
1094 }
1095 /***
1096 * Associates the specified value with the specified key in this
1097 * preference node.
1098 * <p>While not a method contained in java.util.prefs.Preferences this
1099 * method was added because I kept trying to call it as a result of all the
1100 * other methods being typed</p>
1101 *
1102 * @param key key with which the specified value is to be associated.
1103 * @param value value to be associated with the specified key.
1104 * @throws NullPointerException if key or value is <tt>null</tt>.
1105 * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
1106 * <tt>MAX_KEY_LENGTH</tt> or if <tt>value.length</tt> exceeds
1107 * <tt>MAX_VALUE_LENGTH</tt>.
1108 * @throws IllegalStateException if this node (or an ancestor) has been
1109 * removed with the {@link #removeNode()} method.
1110 */
1111 public void putString(String key, String value) throws NullPointerException, IllegalArgumentException, IllegalStateException{
1112 myPreferences.put(key, value);
1113 }
1114
1115 /***
1116 * Removes the value associated with the specified key in this preference
1117 * node, if any.
1118 *
1119 * <p>If this implementation supports <i>stored defaults</i>, and there is
1120 * such a default for the specified preference, the stored default will be
1121 * "exposed" by this call, in the sense that it will be returned
1122 * by a succeeding call to <tt>get</tt>.
1123 *
1124 * @param key key whose mapping is to be removed from the preference node.
1125 * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
1126 * @throws IllegalStateException if this node (or an ancestor) has been
1127 * removed with the {@link #removeNode()} method.
1128 */
1129 public void remove(String key) {
1130 myPreferences.remove(key);
1131 }
1132
1133 /***
1134 * Removes this preference node and all of its descendants, invalidating
1135 * any preferences contained in the removed nodes. Once a node has been
1136 * removed, attempting any method other than {@link #name()},
1137 * {@link #absolutePath()}, {@link #isUserNode()}, {@link #flush()} or
1138 * {@link #node(String) nodeExists("")} on the corresponding
1139 * <tt>Preferences</tt> instance will fail with an
1140 * <tt>IllegalStateException</tt>. (The methods defined on {@link Object}
1141 * can still be invoked on a node after it has been removed; they will not
1142 * throw <tt>IllegalStateException</tt>.)
1143 *
1144 * <p>The removal is not guaranteed to be persistent until the
1145 * <tt>flush</tt> method is called on this node (or an ancestor).
1146 *
1147 * <p>If this implementation supports <i>stored defaults</i>, removing a
1148 * node exposes any stored defaults at or below this node. Thus, a
1149 * subsequent call to <tt>nodeExists</tt> on this node's path name may
1150 * return <tt>true</tt>, and a subsequent call to <tt>node</tt> on this
1151 * path name may may return a (different) <tt>Preferences</tt> instance
1152 * representing a non-empty collection of preferences and/or children.
1153 *
1154 * @throws IllegalStateException if this node (or an ancestor) has already
1155 * been removed with the {@link #removeNode()} method.
1156 * @throws UnsupportedOperationException if this method is invoked on
1157 * the root node.
1158 * @see #flush()
1159 */
1160 public void removeNode()
1161 throws IllegalStateException, UnsupportedOperationException,
1162 BackingStoreException {
1163 // delete the local files
1164 removeLocalXMLNode(myPreferences);
1165
1166 // now delete it in the system's store.
1167 myPreferences.removeNode();
1168 }
1169
1170 /***
1171 * Deletes the Local XML Preferences files representing the specified
1172 * Preferences file and the XML files representing all of its children.
1173 * This will NOT remove the corresponding Preferences from the standard
1174 * Preferences store.
1175 *
1176 * @param currentNode the Preferences file whose XML counterpart and its
1177 * children you wish to delete.
1178 */
1179 private void removeLocalXMLNode(Preferences currentNode) {
1180 // delete the current file
1181 File currentNodeFile = new File(getLocalXMLFilePath(currentNode));
1182
1183 if (currentNodeFile.exists()) {
1184 currentNodeFile.delete();
1185 }
1186
1187 // now delete its children
1188 try {
1189 String[] childrenNames = myPreferences.childrenNames();
1190
1191 if (childrenNames.length > 0) {
1192 // gah. alright delete those too, if they Exist locally
1193 for (int i = 0; i < childrenNames.length; i++) {
1194 removeLocalXMLNode(myPreferences.node(childrenNames[i]));
1195 }
1196 }
1197 } catch (BackingStoreException e) {
1198 // umm... yeah, skip it
1199 }
1200 }
1201
1202 /***
1203 * Removes the specified <tt>NodeChangeListener</tt>, so it no longer
1204 * receives change events.
1205 *
1206 * @param ncl The <tt>NodeChangeListener</tt> to remove.
1207 * @throws IllegalArgumentException if <tt>ncl</tt> was not a registered
1208 * <tt>NodeChangeListener</tt> on this node.
1209 * @throws IllegalStateException if this node (or an ancestor) has been
1210 * removed with the {@link #removeNode()} method.
1211 * @see #addNodeChangeListener(NodeChangeListener)
1212 */
1213 public void removeNodeChangeListener(NodeChangeListener ncl) throws IllegalArgumentException, IllegalStateException{
1214 myPreferences.removeNodeChangeListener(ncl);
1215 }
1216
1217 /***
1218 * Removes the specified preference change listener, so it no longer
1219 * receives preference change events.
1220 *
1221 * @param pcl The preference change listener to remove.
1222 * @throws IllegalArgumentException if <tt>pcl</tt> was not a registered
1223 * preference change listener on this node.
1224 * @throws IllegalStateException if this node (or an ancestor) has been
1225 * removed with the {@link #removeNode()} method.
1226 * @see #addPreferenceChangeListener(PreferenceChangeListener)
1227 */
1228 public void removePreferenceChangeListener(PreferenceChangeListener pcl) throws IllegalArgumentException, IllegalStateException {
1229 myPreferences.removePreferenceChangeListener(pcl);
1230 }
1231
1232 /***
1233 * Ensures that future reads from this preference node and its
1234 * descendants reflect any changes that were committed to the persistent
1235 * store (from any VM) prior to the <tt>sync</tt> invocation. As a
1236 * side-effect, forces any changes in the contents of this preference node
1237 * and its descendants to the persistent store, as if the <tt>flush</tt>
1238 * method had been invoked on this node.
1239 *
1240 * @throws BackingStoreException if this operation cannot be completed
1241 * due to a failure in the backing store, or inability to
1242 * communicate with it.
1243 * @throws IllegalStateException if this node (or an ancestor) has been
1244 * removed with the {@link #removeNode()} method.
1245 * @see #flush()
1246 */
1247 public void sync() throws BackingStoreException, IllegalStateException {
1248 myPreferences.sync();
1249 }
1250
1251 /***
1252 * Returns the preference node from the system preference tree that is
1253 * associated (by convention) with the specified class's package. The
1254 * convention is as follows: the absolute path name of the node is the
1255 * fully qualified package name, preceded by a slash (<tt>'/'</tt>), and
1256 * with each period (<tt>'.'</tt>) replaced by a slash. For example the
1257 * absolute path name of the node associated with the class
1258 * <tt>com.acme.widget</tt> is <tt>/com/acme/widget</tt>.
1259 *
1260 * <p>This convention does not apply to the unnamed package, whose
1261 * associated preference node is <tt><unnamed></tt>. This node
1262 * is not intended for long term use, but for convenience in the early
1263 * development of programs that do not yet belong to a package, and
1264 * for "throwaway" programs. <i>Valuable data should not be stored
1265 * at this node as it is shared by all programs that use it.</i>
1266 *
1267 * <p>A class <tt>Foo</tt> wishing to access preferences pertaining to its
1268 * package can obtain a preference node as follows: <pre>
1269 * static Preferences prefs = Preferences.systemNodeForPackage(Foo.class);
1270 * </pre>
1271 * This idiom obviates the need for using a string to describe the
1272 * preferences node and decreases the likelihood of a run-time failure.
1273 * (If the class name is is misspelled, it will typically result in a
1274 * compile-time error.)
1275 *
1276 * <p>Invoking this method will result in the creation of the returned
1277 * node and its ancestors if they do not already exist. If the returned
1278 * node did not exist prior to this call, this node and any ancestors that
1279 * were created by this call are not guaranteed to become permanent until
1280 * the <tt>flush</tt> method is called on the returned node (or one of its
1281 * ancestors or descendants).
1282 *
1283 * @param c the class for whose package a system preference node is desired.
1284 * @return the system preference node associated with the package of which
1285 * <tt>c</tt> is a member.
1286 * @throws NullPointerException if <tt>c</tt> is <tt>null</tt>.
1287 * @throws SecurityException if a security manager is present and
1288 * it denies <tt>RuntimePermission("preferences")</tt>.
1289 * @see RuntimePermission
1290 */
1291 static public XMLPreferences systemNodeForPackage(Class c) {
1292 Preferences newPrefs = Preferences.systemNodeForPackage(c);
1293
1294 return new XMLPreferences(newPrefs);
1295 }
1296
1297 /***
1298 * Returns the root preference node for the system.
1299 *
1300 * @return the root preference node for the system.
1301 * @throws SecurityException If a security manager is present and
1302 * it denies <tt>RuntimePermission("preferences")</tt>.
1303 * @see RuntimePermission
1304 */
1305 static public XMLPreferences systemRoot() throws SecurityException{
1306 return new XMLPreferences(Preferences.systemRoot());
1307 }
1308
1309 /***
1310 * Returns an absolute path to the XML file representing this Preferences
1311 * node.
1312 *
1313 * @see java.lang.Object#toString()
1314 */
1315 public String toString() {
1316 return toString(true);
1317 }
1318
1319 /***
1320 * Returns either an absolute path to the XML file representing this
1321 * Preferences node (if xmlPath is true) or the default
1322 * Preferences.toString () String (if xmlPath is false);
1323 *
1324 * @param xmlPath indicates if the return valuse should be that of the XML
1325 * File representing this Preferences node (true) or the result of
1326 * calling Preferences. toString() on this node.
1327 *
1328 * @return String
1329 *
1330 * @see http://java.sun.com/j2se/1.4/docs/api/java/util/prefs/Preferences.
1331 * html#toString()
1332 */
1333 public String toString(boolean xmlPath) {
1334 if (xmlPath) {
1335 return getLocalXMLFilePath(myPreferences);
1336 }
1337
1338 return myPreferences.toString();
1339 }
1340
1341 /***
1342 * Returns the preference node from the calling user's preference tree
1343 * that is associated (by convention) with the specified class's package.
1344 * The convention is as follows: the absolute path name of the node is the
1345 * fully qualified package name, preceded by a slash (<tt>'/'</tt>), and
1346 * with each period (<tt>'.'</tt>) replaced by a slash. For example the
1347 * absolute path name of the node associated with the class
1348 * <tt>com.acme.widget</tt> is <tt>/com/acme/widget</tt>.
1349 *
1350 * <p>This convention does not apply to the unnamed package, whose
1351 * associated preference node is <tt><unnamed></tt>. This node
1352 * is not intended for long term use, but for convenience in the early
1353 * development of programs that do not yet belong to a package, and
1354 * for "throwaway" programs. <i>Valuable data should not be stored
1355 * at this node as it is shared by all programs that use it.</i>
1356 *
1357 * <p>A class <tt>Foo</tt> wishing to access preferences pertaining to its
1358 * package can obtain a preference node as follows: <pre>
1359 * static Preferences prefs = Preferences.userNodeForPackage(Foo.class);
1360 * </pre>
1361 * This idiom obviates the need for using a string to describe the
1362 * preferences node and decreases the likelihood of a run-time failure.
1363 * (If the class name is is misspelled, it will typically result in a
1364 * compile-time error.)
1365 *
1366 * <p>Invoking this method will result in the creation of the returned
1367 * node and its ancestors if they do not already exist. If the returned
1368 * node did not exist prior to this call, this node and any ancestors that
1369 * were created by this call are not guaranteed to become permanent until
1370 * the <tt>flush</tt> method is called on the returned node (or one of its
1371 * ancestors or descendants).
1372 *
1373 * @param c the class for whose package a user preference node is desired.
1374 * @return the user preference node associated with the package of which
1375 * <tt>c</tt> is a member.
1376 * @throws NullPointerException if <tt>c</tt> is <tt>null</tt>.
1377 * @throws SecurityException if a security manager is present and
1378 * it denies <tt>RuntimePermission("preferences")</tt>.
1379 * @see RuntimePermission
1380 */
1381 public static XMLPreferences userNodeForPackage(Class c)
1382 throws IOException,
1383 InvalidPreferencesFormatException {
1384 //try{
1385 // Preferences.importPreferences(new FileInputStream(getLocalXMLFilePath(c)));
1386 //} catch (FileNotFoundException e){
1387 // default functionality is to jsut work and create a new one.
1388 // actual file will be created on flush()
1389 //}
1390 return new XMLPreferences(Preferences.userNodeForPackage(c));
1391 }
1392
1393 /***
1394 * Returns the root preference node for the calling user.
1395 *
1396 * @return the root preference node for the calling user.
1397 * @throws SecurityException If a security manager is present and
1398 * it denies <tt>RuntimePermission("preferences")</tt>.
1399 * @see RuntimePermission
1400 */
1401 static public XMLPreferences userRoot() throws SecurityException{
1402 return new XMLPreferences(Preferences.userRoot());
1403 }
1404 }
1405
This page was automatically generated by Maven