1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.util.prefs;
28 
29 import java.io.InputStream;
30 import java.io.IOException;
31 import java.io.OutputStream;
32 import java.security.AccessController;
33 import java.security.Permission;
34 import java.security.PrivilegedAction;
35 import java.util.Iterator;
36 import java.util.ServiceLoader;
37 import java.util.ServiceConfigurationError;
38 
39 // These imports needed only as a workaround for a JavaDoc bug
40 import java.lang.RuntimePermission;
41 import java.lang.Integer;
42 import java.lang.Long;
43 import java.lang.Float;
44 import java.lang.Double;
45 
46 /**
47  * A node in a hierarchical collection of preference data.  This class
48  * allows applications to store and retrieve user and system
49  * preference and configuration data.  This data is stored
50  * persistently in an implementation-dependent backing store.  Typical
51  * implementations include flat files, OS-specific registries,
52  * directory servers and SQL databases.  The user of this class needn't
53  * be concerned with details of the backing store.
54  *
55  * <p>There are two separate trees of preference nodes, one for user
56  * preferences and one for system preferences.  Each user has a separate user
57  * preference tree, and all users in a given system share the same system
58  * preference tree.  The precise description of "user" and "system" will vary
59  * from implementation to implementation.  Typical information stored in the
60  * user preference tree might include font choice, color choice, or preferred
61  * window location and size for a particular application.  Typical information
62  * stored in the system preference tree might include installation
63  * configuration data for an application.
64  *
65  * <p>Nodes in a preference tree are named in a similar fashion to
66  * directories in a hierarchical file system.   Every node in a preference
67  * tree has a <i>node name</i> (which is not necessarily unique),
68  * a unique <i>absolute path name</i>, and a path name <i>relative</i> to each
69  * ancestor including itself.
70  *
71  * <p>The root node has a node name of the empty string ("").  Every other
72  * node has an arbitrary node name, specified at the time it is created.  The
73  * only restrictions on this name are that it cannot be the empty string, and
74  * it cannot contain the slash character ('/').
75  *
76  * <p>The root node has an absolute path name of <tt>"/"</tt>.  Children of
77  * the root node have absolute path names of <tt>"/" + </tt><i>&lt;node
78  * name&gt;</i>.  All other nodes have absolute path names of <i>&lt;parent's
79  * absolute path name&gt;</i><tt> + "/" + </tt><i>&lt;node name&gt;</i>.
80  * Note that all absolute path names begin with the slash character.
81  *
82  * <p>A node <i>n</i>'s path name relative to its ancestor <i>a</i>
83  * is simply the string that must be appended to <i>a</i>'s absolute path name
84  * in order to form <i>n</i>'s absolute path name, with the initial slash
85  * character (if present) removed.  Note that:
86  * <ul>
87  * <li>No relative path names begin with the slash character.
88  * <li>Every node's path name relative to itself is the empty string.
89  * <li>Every node's path name relative to its parent is its node name (except
90  * for the root node, which does not have a parent).
91  * <li>Every node's path name relative to the root is its absolute path name
92  * with the initial slash character removed.
93  * </ul>
94  *
95  * <p>Note finally that:
96  * <ul>
97  * <li>No path name contains multiple consecutive slash characters.
98  * <li>No path name with the exception of the root's absolute path name
99  * ends in the slash character.
100  * <li>Any string that conforms to these two rules is a valid path name.
101  * </ul>
102  *
103  * <p>All of the methods that modify preferences data are permitted to operate
104  * asynchronously; they may return immediately, and changes will eventually
105  * propagate to the persistent backing store with an implementation-dependent
106  * delay.  The <tt>flush</tt> method may be used to synchronously force
107  * updates to the backing store.  Normal termination of the Java Virtual
108  * Machine will <i>not</i> result in the loss of pending updates -- an explicit
109  * <tt>flush</tt> invocation is <i>not</i> required upon termination to ensure
110  * that pending updates are made persistent.
111  *
112  * <p>All of the methods that read preferences from a <tt>Preferences</tt>
113  * object require the invoker to provide a default value.  The default value is
114  * returned if no value has been previously set <i>or if the backing store is
115  * unavailable</i>.  The intent is to allow applications to operate, albeit
116  * with slightly degraded functionality, even if the backing store becomes
117  * unavailable.  Several methods, like <tt>flush</tt>, have semantics that
118  * prevent them from operating if the backing store is unavailable.  Ordinary
119  * applications should have no need to invoke any of these methods, which can
120  * be identified by the fact that they are declared to throw {@link
121  * BackingStoreException}.
122  *
123  * <p>The methods in this class may be invoked concurrently by multiple threads
124  * in a single JVM without the need for external synchronization, and the
125  * results will be equivalent to some serial execution.  If this class is used
126  * concurrently <i>by multiple JVMs</i> that store their preference data in
127  * the same backing store, the data store will not be corrupted, but no
128  * other guarantees are made concerning the consistency of the preference
129  * data.
130  *
131  * <p>This class contains an export/import facility, allowing preferences
132  * to be "exported" to an XML document, and XML documents representing
133  * preferences to be "imported" back into the system.  This facility
134  * may be used to back up all or part of a preference tree, and
135  * subsequently restore from the backup.
136  *
137  * <p>The XML document has the following DOCTYPE declaration:
138  * <pre>{@code
139  * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
140  * }</pre>
141  * Note that the system URI (http://java.sun.com/dtd/preferences.dtd) is
142  * <i>not</i> accessed when exporting or importing preferences; it merely
143  * serves as a string to uniquely identify the DTD, which is:
144  * <pre>{@code
145  *    <?xml version="1.0" encoding="UTF-8"?>
146  *
147  *    <!-- DTD for a Preferences tree. -->
148  *
149  *    <!-- The preferences element is at the root of an XML document
150  *         representing a Preferences tree. -->
151  *    <!ELEMENT preferences (root)>
152  *
153  *    <!-- The preferences element contains an optional version attribute,
154  *          which specifies version of DTD. -->
155  *    <!ATTLIST preferences EXTERNAL_XML_VERSION CDATA "0.0" >
156  *
157  *    <!-- The root element has a map representing the root's preferences
158  *         (if any), and one node for each child of the root (if any). -->
159  *    <!ELEMENT root (map, node*) >
160  *
161  *    <!-- Additionally, the root contains a type attribute, which
162  *         specifies whether it's the system or user root. -->
163  *    <!ATTLIST root
164  *              type (system|user) #REQUIRED >
165  *
166  *    <!-- Each node has a map representing its preferences (if any),
167  *         and one node for each child (if any). -->
168  *    <!ELEMENT node (map, node*) >
169  *
170  *    <!-- Additionally, each node has a name attribute -->
171  *    <!ATTLIST node
172  *              name CDATA #REQUIRED >
173  *
174  *    <!-- A map represents the preferences stored at a node (if any). -->
175  *    <!ELEMENT map (entry*) >
176  *
177  *    <!-- An entry represents a single preference, which is simply
178  *          a key-value pair. -->
179  *    <!ELEMENT entry EMPTY >
180  *    <!ATTLIST entry
181  *              key   CDATA #REQUIRED
182  *              value CDATA #REQUIRED >
183  * }</pre>
184  *
185  * Every <tt>Preferences</tt> implementation must have an associated {@link
186  * PreferencesFactory} implementation.  Every Java(TM) SE implementation must provide
187  * some means of specifying which <tt>PreferencesFactory</tt> implementation
188  * is used to generate the root preferences nodes.  This allows the
189  * administrator to replace the default preferences implementation with an
190  * alternative implementation.
191  *
192  * <p>Implementation note: In Sun's JRE, the <tt>PreferencesFactory</tt>
193  * implementation is located as follows:
194  *
195  * <ol>
196  *
197  * <li><p>If the system property
198  * <tt>java.util.prefs.PreferencesFactory</tt> is defined, then it is
199  * taken to be the fully-qualified name of a class implementing the
200  * <tt>PreferencesFactory</tt> interface.  The class is loaded and
201  * instantiated; if this process fails then an unspecified error is
202  * thrown.</p></li>
203  *
204  * <li><p> If a <tt>PreferencesFactory</tt> implementation class file
205  * has been installed in a jar file that is visible to the
206  * {@link java.lang.ClassLoader#getSystemClassLoader system class loader},
207  * and that jar file contains a provider-configuration file named
208  * <tt>java.util.prefs.PreferencesFactory</tt> in the resource
209  * directory <tt>META-INF/services</tt>, then the first class name
210  * specified in that file is taken.  If more than one such jar file is
211  * provided, the first one found will be used.  The class is loaded
212  * and instantiated; if this process fails then an unspecified error
213  * is thrown.  </p></li>
214  *
215  * <li><p>Finally, if neither the above-mentioned system property nor
216  * an extension jar file is provided, then the system-wide default
217  * <tt>PreferencesFactory</tt> implementation for the underlying
218  * platform is loaded and instantiated.</p></li>
219  *
220  * </ol>
221  *
222  * @author  Josh Bloch
223  * @since   1.4
224  */
225 public abstract class Preferences {
226 
227     // Android-changed: Allow Preferences.factory to be set by tests.
228     // private static final PreferencesFactory factory = factory();
229     private static PreferencesFactory factory = factory();
230 
231     // BEGIN Android-changed: Logic for constructing the default Preferences factory.
232     /*
233     private static PreferencesFactory factory() {
234         // 1. Try user-specified system property
235         String factoryName = AccessController.doPrivileged(
236             new PrivilegedAction<String>() {
237                 public String run() {
238                     return System.getProperty(
239                         "java.util.prefs.PreferencesFactory");}});
240         if (factoryName != null) {
241             // FIXME: This code should be run in a doPrivileged and
242             // not use the context classloader, to avoid being
243             // dependent on the invoking thread.
244             // Checking AllPermission also seems wrong.
245             try {
246                 return (PreferencesFactory)
247                     Class.forName(factoryName, false,
248                                   ClassLoader.getSystemClassLoader())
249                     .newInstance();
250             } catch (Exception ex) {
251                 try {
252                     // workaround for javaws, plugin,
253                     // load factory class using non-system classloader
254                     SecurityManager sm = System.getSecurityManager();
255                     if (sm != null) {
256                         sm.checkPermission(new java.security.AllPermission());
257                     }
258                     return (PreferencesFactory)
259                         Class.forName(factoryName, false,
260                                       Thread.currentThread()
261                                       .getContextClassLoader())
262                         .newInstance();
263                 } catch (Exception e) {
264                     throw new InternalError(
265                         "Can't instantiate Preferences factory "
266                         + factoryName, e);
267                 }
268             }
269         }
270 
271         return AccessController.doPrivileged(
272             new PrivilegedAction<PreferencesFactory>() {
273                 public PreferencesFactory run() {
274                     return factory1();}});
275     }
276 
277     private static PreferencesFactory factory1() {
278         // 2. Try service provider interface
279         Iterator<PreferencesFactory> itr = ServiceLoader
280             .load(PreferencesFactory.class, ClassLoader.getSystemClassLoader())
281             .iterator();
282 
283         // choose first provider instance
284         while (itr.hasNext()) {
285             try {
286                 return itr.next();
287             } catch (ServiceConfigurationError sce) {
288                 if (sce.getCause() instanceof SecurityException) {
289                     // Ignore the security exception, try the next provider
290                     continue;
291                 }
292                 throw sce;
293             }
294         }
295 
296         // 3. Use platform-specific system-wide default
297         String osName = System.getProperty("os.name");
298         String platformFactory;
299         if (osName.startsWith("Windows")) {
300             platformFactory = "java.util.prefs.WindowsPreferencesFactory";
301         } else if (osName.contains("OS X")) {
302             platformFactory = "java.util.prefs.MacOSXPreferencesFactory";
303         } else {
304             platformFactory = "java.util.prefs.FileSystemPreferencesFactory";
305         }
306         try {
307             return (PreferencesFactory)
308                 Class.forName(platformFactory, false,
309                               Preferences.class.getClassLoader()).newInstance();
310         } catch (Exception e) {
311             throw new InternalError(
312                 "Can't instantiate platform default Preferences factory "
313                 + platformFactory, e);
314         }
315     }
316     */
factory()317     private static PreferencesFactory factory() {
318         // Try the system property first...
319         PreferencesFactory result = ServiceLoader.loadFromSystemProperty(PreferencesFactory.class);
320         if (result != null) {
321             return result;
322         }
323         // Then use ServiceLoader for META-INF/services/...
324         for (PreferencesFactory impl : ServiceLoader.load(PreferencesFactory.class)) {
325             return impl;
326         }
327         // Finally return a default...
328         return new FileSystemPreferencesFactory();
329     }
330     // END Android-changed: Logic for constructing the default Preferences factory.
331 
332     // BEGIN Android-added: Allow Preferences.factory to be set by tests.
333     /** @hide for testing only. */
setPreferencesFactory(PreferencesFactory pf)334     public static PreferencesFactory setPreferencesFactory(PreferencesFactory pf) {
335         PreferencesFactory previous = factory;
336         factory = pf;
337         return previous;
338     }
339     // END Android-added: Allow Preferences.factory to be set by tests.
340 
341     /**
342      * Maximum length of string allowed as a key (80 characters).
343      */
344     public static final int MAX_KEY_LENGTH = 80;
345 
346     /**
347      * Maximum length of string allowed as a value (8192 characters).
348      */
349     public static final int MAX_VALUE_LENGTH = 8*1024;
350 
351     /**
352      * Maximum length of a node name (80 characters).
353      */
354     public static final int MAX_NAME_LENGTH = 80;
355 
356     // Android-added: Document Android's security restrictions on system/user preferences.
357     /**
358      * <strong>WARNING:</strong> On Android, the Preference nodes
359      * corresponding to the "system" and "user" preferences are stored in sections
360      * of the file system that are inaccessible to apps. Further, allowing apps to set
361      * "system wide" preferences is contrary to android's security model.
362      *
363      * Returns the preference node from the calling user's preference tree
364      * that is associated (by convention) with the specified class's package.
365      * The convention is as follows: the absolute path name of the node is the
366      * fully qualified package name, preceded by a slash (<tt>'/'</tt>), and
367      * with each period (<tt>'.'</tt>) replaced by a slash.  For example the
368      * absolute path name of the node associated with the class
369      * <tt>com.acme.widget.Foo</tt> is <tt>/com/acme/widget</tt>.
370      *
371      * <p>This convention does not apply to the unnamed package, whose
372      * associated preference node is <tt>&lt;unnamed&gt;</tt>.  This node
373      * is not intended for long term use, but for convenience in the early
374      * development of programs that do not yet belong to a package, and
375      * for "throwaway" programs.  <i>Valuable data should not be stored
376      * at this node as it is shared by all programs that use it.</i>
377      *
378      * <p>A class <tt>Foo</tt> wishing to access preferences pertaining to its
379      * package can obtain a preference node as follows: <pre>
380      *    static Preferences prefs = Preferences.userNodeForPackage(Foo.class);
381      * </pre>
382      * This idiom obviates the need for using a string to describe the
383      * preferences node and decreases the likelihood of a run-time failure.
384      * (If the class name is misspelled, it will typically result in a
385      * compile-time error.)
386      *
387      * <p>Invoking this method will result in the creation of the returned
388      * node and its ancestors if they do not already exist.  If the returned
389      * node did not exist prior to this call, this node and any ancestors that
390      * were created by this call are not guaranteed to become permanent until
391      * the <tt>flush</tt> method is called on the returned node (or one of its
392      * ancestors or descendants).
393      *
394      * @param c the class for whose package a user preference node is desired.
395      * @return the user preference node associated with the package of which
396      *         <tt>c</tt> is a member.
397      * @throws NullPointerException if <tt>c</tt> is <tt>null</tt>.
398      * @throws SecurityException if a security manager is present and
399      *         it denies <tt>RuntimePermission("preferences")</tt>.
400      * @see    RuntimePermission
401      */
userNodeForPackage(Class<?> c)402     public static Preferences userNodeForPackage(Class<?> c) {
403         return userRoot().node(nodeName(c));
404     }
405 
406     // Android-added: Document Android's security restrictions on system/user preferences.
407     /**
408      * <strong>WARNING:</strong> On Android, the Preference nodes
409      * corresponding to the "system" and "user" preferences are stored in sections
410      * of the file system that are inaccessible to apps. Further, allowing apps to set
411      * "system wide" preferences is contrary to android's security model.
412      *
413      * Returns the preference node from the system preference tree that is
414      * associated (by convention) with the specified class's package.  The
415      * convention is as follows: the absolute path name of the node is the
416      * fully qualified package name, preceded by a slash (<tt>'/'</tt>), and
417      * with each period (<tt>'.'</tt>) replaced by a slash.  For example the
418      * absolute path name of the node associated with the class
419      * <tt>com.acme.widget.Foo</tt> is <tt>/com/acme/widget</tt>.
420      *
421      * <p>This convention does not apply to the unnamed package, whose
422      * associated preference node is <tt>&lt;unnamed&gt;</tt>.  This node
423      * is not intended for long term use, but for convenience in the early
424      * development of programs that do not yet belong to a package, and
425      * for "throwaway" programs.  <i>Valuable data should not be stored
426      * at this node as it is shared by all programs that use it.</i>
427      *
428      * <p>A class <tt>Foo</tt> wishing to access preferences pertaining to its
429      * package can obtain a preference node as follows: <pre>
430      *  static Preferences prefs = Preferences.systemNodeForPackage(Foo.class);
431      * </pre>
432      * This idiom obviates the need for using a string to describe the
433      * preferences node and decreases the likelihood of a run-time failure.
434      * (If the class name is misspelled, it will typically result in a
435      * compile-time error.)
436      *
437      * <p>Invoking this method will result in the creation of the returned
438      * node and its ancestors if they do not already exist.  If the returned
439      * node did not exist prior to this call, this node and any ancestors that
440      * were created by this call are not guaranteed to become permanent until
441      * the <tt>flush</tt> method is called on the returned node (or one of its
442      * ancestors or descendants).
443      *
444      * @param c the class for whose package a system preference node is desired.
445      * @return the system preference node associated with the package of which
446      *         <tt>c</tt> is a member.
447      * @throws NullPointerException if <tt>c</tt> is <tt>null</tt>.
448      * @throws SecurityException if a security manager is present and
449      *         it denies <tt>RuntimePermission("preferences")</tt>.
450      * @see    RuntimePermission
451      */
systemNodeForPackage(Class<?> c)452     public static Preferences systemNodeForPackage(Class<?> c) {
453         return systemRoot().node(nodeName(c));
454     }
455 
456     /**
457      * Returns the absolute path name of the node corresponding to the package
458      * of the specified object.
459      *
460      * @throws IllegalArgumentException if the package has node preferences
461      *         node associated with it.
462      */
nodeName(Class<?> c)463     private static String nodeName(Class<?> c) {
464         if (c.isArray())
465             throw new IllegalArgumentException(
466                 "Arrays have no associated preferences node.");
467         String className = c.getName();
468         int pkgEndIndex = className.lastIndexOf('.');
469         if (pkgEndIndex < 0)
470             return "/<unnamed>";
471         String packageName = className.substring(0, pkgEndIndex);
472         return "/" + packageName.replace('.', '/');
473     }
474 
475     /**
476      * This permission object represents the permission required to get
477      * access to the user or system root (which in turn allows for all
478      * other operations).
479      */
480     private static Permission prefsPerm = new RuntimePermission("preferences");
481 
482     // Android-added: Document Android's security restrictions on system/user preferences.
483     /**
484      * <strong>WARNING:</strong> On Android, the Preference nodes
485      * corresponding to the "system" and "user" preferences are stored in sections
486      * of the file system that are inaccessible to apps. Further, allowing apps to set
487      * "system wide" preferences is contrary to android's security model.
488      *
489      * Returns the root preference node for the calling user.
490      *
491      * @return the root preference node for the calling user.
492      * @throws SecurityException If a security manager is present and
493      *         it denies <tt>RuntimePermission("preferences")</tt>.
494      * @see    RuntimePermission
495      */
userRoot()496     public static Preferences userRoot() {
497         SecurityManager security = System.getSecurityManager();
498         if (security != null)
499             security.checkPermission(prefsPerm);
500 
501         return factory.userRoot();
502     }
503 
504     // Android-added: Document Android's security restrictions on system/user preferences.
505     /**
506      * <strong>WARNING:</strong> On Android, the Preference nodes
507      * corresponding to the "system" and "user" preferences are stored in sections
508      * of the file system that are inaccessible to apps. Further, allowing apps to set
509      * "system wide" preferences is contrary to android's security model.
510      *
511      * Returns the root preference node for the system.
512      *
513      * @return the root preference node for the system.
514      * @throws SecurityException If a security manager is present and
515      *         it denies <tt>RuntimePermission("preferences")</tt>.
516      * @see    RuntimePermission
517      */
systemRoot()518     public static Preferences systemRoot() {
519         SecurityManager security = System.getSecurityManager();
520         if (security != null)
521             security.checkPermission(prefsPerm);
522 
523         return factory.systemRoot();
524     }
525 
526     /**
527      * Sole constructor. (For invocation by subclass constructors, typically
528      * implicit.)
529      */
Preferences()530     protected Preferences() {
531     }
532 
533     /**
534      * Associates the specified value with the specified key in this
535      * preference node.
536      *
537      * @param key key with which the specified value is to be associated.
538      * @param value value to be associated with the specified key.
539      * @throws NullPointerException if key or value is <tt>null</tt>.
540      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
541      *       <tt>MAX_KEY_LENGTH</tt> or if <tt>value.length</tt> exceeds
542      *       <tt>MAX_VALUE_LENGTH</tt>.
543      * @throws IllegalStateException if this node (or an ancestor) has been
544      *         removed with the {@link #removeNode()} method.
545      */
put(String key, String value)546     public abstract void put(String key, String value);
547 
548     /**
549      * Returns the value associated with the specified key in this preference
550      * node.  Returns the specified default if there is no value associated
551      * with the key, or the backing store is inaccessible.
552      *
553      * <p>Some implementations may store default values in their backing
554      * stores.  If there is no value associated with the specified key
555      * but there is such a <i>stored default</i>, it is returned in
556      * preference to the specified default.
557      *
558      * @param key key whose associated value is to be returned.
559      * @param def the value to be returned in the event that this
560      *        preference node has no value associated with <tt>key</tt>.
561      * @return the value associated with <tt>key</tt>, or <tt>def</tt>
562      *         if no value is associated with <tt>key</tt>, or the backing
563      *         store is inaccessible.
564      * @throws IllegalStateException if this node (or an ancestor) has been
565      *         removed with the {@link #removeNode()} method.
566      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.  (A
567      *         <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.)
568      */
get(String key, String def)569     public abstract String get(String key, String def);
570 
571     /**
572      * Removes the value associated with the specified key in this preference
573      * node, if any.
574      *
575      * <p>If this implementation supports <i>stored defaults</i>, and there is
576      * such a default for the specified preference, the stored default will be
577      * "exposed" by this call, in the sense that it will be returned
578      * by a succeeding call to <tt>get</tt>.
579      *
580      * @param key key whose mapping is to be removed from the preference node.
581      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
582      * @throws IllegalStateException if this node (or an ancestor) has been
583      *         removed with the {@link #removeNode()} method.
584      */
remove(String key)585     public abstract void remove(String key);
586 
587     /**
588      * Removes all of the preferences (key-value associations) in this
589      * preference node.  This call has no effect on any descendants
590      * of this node.
591      *
592      * <p>If this implementation supports <i>stored defaults</i>, and this
593      * node in the preferences hierarchy contains any such defaults,
594      * the stored defaults will be "exposed" by this call, in the sense that
595      * they will be returned by succeeding calls to <tt>get</tt>.
596      *
597      * @throws BackingStoreException if this operation cannot be completed
598      *         due to a failure in the backing store, or inability to
599      *         communicate with it.
600      * @throws IllegalStateException if this node (or an ancestor) has been
601      *         removed with the {@link #removeNode()} method.
602      * @see #removeNode()
603      */
clear()604     public abstract void clear() throws BackingStoreException;
605 
606     /**
607      * Associates a string representing the specified int value with the
608      * specified key in this preference node.  The associated string is the
609      * one that would be returned if the int value were passed to
610      * {@link Integer#toString(int)}.  This method is intended for use in
611      * conjunction with {@link #getInt}.
612      *
613      * @param key key with which the string form of value is to be associated.
614      * @param value value whose string form is to be associated with key.
615      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
616      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
617      *         <tt>MAX_KEY_LENGTH</tt>.
618      * @throws IllegalStateException if this node (or an ancestor) has been
619      *         removed with the {@link #removeNode()} method.
620      * @see #getInt(String,int)
621      */
putInt(String key, int value)622     public abstract void putInt(String key, int value);
623 
624     /**
625      * Returns the int value represented by the string associated with the
626      * specified key in this preference node.  The string is converted to
627      * an integer as by {@link Integer#parseInt(String)}.  Returns the
628      * specified default if there is no value associated with the key,
629      * the backing store is inaccessible, or if
630      * <tt>Integer.parseInt(String)</tt> would throw a {@link
631      * NumberFormatException} if the associated value were passed.  This
632      * method is intended for use in conjunction with {@link #putInt}.
633      *
634      * <p>If the implementation supports <i>stored defaults</i> and such a
635      * default exists, is accessible, and could be converted to an int
636      * with <tt>Integer.parseInt</tt>, this int is returned in preference to
637      * the specified default.
638      *
639      * @param key key whose associated value is to be returned as an int.
640      * @param def the value to be returned in the event that this
641      *        preference node has no value associated with <tt>key</tt>
642      *        or the associated value cannot be interpreted as an int,
643      *        or the backing store is inaccessible.
644      * @return the int value represented by the string associated with
645      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
646      *         associated value does not exist or cannot be interpreted as
647      *         an int.
648      * @throws IllegalStateException if this node (or an ancestor) has been
649      *         removed with the {@link #removeNode()} method.
650      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
651      * @see #putInt(String,int)
652      * @see #get(String,String)
653      */
getInt(String key, int def)654     public abstract int getInt(String key, int def);
655 
656     /**
657      * Associates a string representing the specified long value with the
658      * specified key in this preference node.  The associated string is the
659      * one that would be returned if the long value were passed to
660      * {@link Long#toString(long)}.  This method is intended for use in
661      * conjunction with {@link #getLong}.
662      *
663      * @param key key with which the string form of value is to be associated.
664      * @param value value whose string form is to be associated with key.
665      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
666      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
667      *         <tt>MAX_KEY_LENGTH</tt>.
668      * @throws IllegalStateException if this node (or an ancestor) has been
669      *         removed with the {@link #removeNode()} method.
670      * @see #getLong(String,long)
671      */
putLong(String key, long value)672     public abstract void putLong(String key, long value);
673 
674     /**
675      * Returns the long value represented by the string associated with the
676      * specified key in this preference node.  The string is converted to
677      * a long as by {@link Long#parseLong(String)}.  Returns the
678      * specified default if there is no value associated with the key,
679      * the backing store is inaccessible, or if
680      * <tt>Long.parseLong(String)</tt> would throw a {@link
681      * NumberFormatException} if the associated value were passed.  This
682      * method is intended for use in conjunction with {@link #putLong}.
683      *
684      * <p>If the implementation supports <i>stored defaults</i> and such a
685      * default exists, is accessible, and could be converted to a long
686      * with <tt>Long.parseLong</tt>, this long is returned in preference to
687      * the specified default.
688      *
689      * @param key key whose associated value is to be returned as a long.
690      * @param def the value to be returned in the event that this
691      *        preference node has no value associated with <tt>key</tt>
692      *        or the associated value cannot be interpreted as a long,
693      *        or the backing store is inaccessible.
694      * @return the long value represented by the string associated with
695      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
696      *         associated value does not exist or cannot be interpreted as
697      *         a long.
698      * @throws IllegalStateException if this node (or an ancestor) has been
699      *         removed with the {@link #removeNode()} method.
700      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
701      * @see #putLong(String,long)
702      * @see #get(String,String)
703      */
getLong(String key, long def)704     public abstract long getLong(String key, long def);
705 
706     /**
707      * Associates a string representing the specified boolean value with the
708      * specified key in this preference node.  The associated string is
709      * <tt>"true"</tt> if the value is true, and <tt>"false"</tt> if it is
710      * false.  This method is intended for use in conjunction with
711      * {@link #getBoolean}.
712      *
713      * @param key key with which the string form of value is to be associated.
714      * @param value value whose string form is to be associated with key.
715      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
716      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
717      *         <tt>MAX_KEY_LENGTH</tt>.
718      * @throws IllegalStateException if this node (or an ancestor) has been
719      *         removed with the {@link #removeNode()} method.
720      * @see #getBoolean(String,boolean)
721      * @see #get(String,String)
722      */
putBoolean(String key, boolean value)723     public abstract void putBoolean(String key, boolean value);
724 
725     /**
726      * Returns the boolean value represented by the string associated with the
727      * specified key in this preference node.  Valid strings
728      * are <tt>"true"</tt>, which represents true, and <tt>"false"</tt>, which
729      * represents false.  Case is ignored, so, for example, <tt>"TRUE"</tt>
730      * and <tt>"False"</tt> are also valid.  This method is intended for use in
731      * conjunction with {@link #putBoolean}.
732      *
733      * <p>Returns the specified default if there is no value
734      * associated with the key, the backing store is inaccessible, or if the
735      * associated value is something other than <tt>"true"</tt> or
736      * <tt>"false"</tt>, ignoring case.
737      *
738      * <p>If the implementation supports <i>stored defaults</i> and such a
739      * default exists and is accessible, it is used in preference to the
740      * specified default, unless the stored default is something other than
741      * <tt>"true"</tt> or <tt>"false"</tt>, ignoring case, in which case the
742      * specified default is used.
743      *
744      * @param key key whose associated value is to be returned as a boolean.
745      * @param def the value to be returned in the event that this
746      *        preference node has no value associated with <tt>key</tt>
747      *        or the associated value cannot be interpreted as a boolean,
748      *        or the backing store is inaccessible.
749      * @return the boolean value represented by the string associated with
750      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
751      *         associated value does not exist or cannot be interpreted as
752      *         a boolean.
753      * @throws IllegalStateException if this node (or an ancestor) has been
754      *         removed with the {@link #removeNode()} method.
755      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
756      * @see #get(String,String)
757      * @see #putBoolean(String,boolean)
758      */
getBoolean(String key, boolean def)759     public abstract boolean getBoolean(String key, boolean def);
760 
761     /**
762      * Associates a string representing the specified float value with the
763      * specified key in this preference node.  The associated string is the
764      * one that would be returned if the float value were passed to
765      * {@link Float#toString(float)}.  This method is intended for use in
766      * conjunction with {@link #getFloat}.
767      *
768      * @param key key with which the string form of value is to be associated.
769      * @param value value whose string form is to be associated with key.
770      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
771      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
772      *         <tt>MAX_KEY_LENGTH</tt>.
773      * @throws IllegalStateException if this node (or an ancestor) has been
774      *         removed with the {@link #removeNode()} method.
775      * @see #getFloat(String,float)
776      */
putFloat(String key, float value)777     public abstract void putFloat(String key, float value);
778 
779     /**
780      * Returns the float value represented by the string associated with the
781      * specified key in this preference node.  The string is converted to an
782      * integer as by {@link Float#parseFloat(String)}.  Returns the specified
783      * default if there is no value associated with the key, the backing store
784      * is inaccessible, or if <tt>Float.parseFloat(String)</tt> would throw a
785      * {@link NumberFormatException} if the associated value were passed.
786      * This method is intended for use in conjunction with {@link #putFloat}.
787      *
788      * <p>If the implementation supports <i>stored defaults</i> and such a
789      * default exists, is accessible, and could be converted to a float
790      * with <tt>Float.parseFloat</tt>, this float is returned in preference to
791      * the specified default.
792      *
793      * @param key key whose associated value is to be returned as a float.
794      * @param def the value to be returned in the event that this
795      *        preference node has no value associated with <tt>key</tt>
796      *        or the associated value cannot be interpreted as a float,
797      *        or the backing store is inaccessible.
798      * @return the float value represented by the string associated with
799      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
800      *         associated value does not exist or cannot be interpreted as
801      *         a float.
802      * @throws IllegalStateException if this node (or an ancestor) has been
803      *         removed with the {@link #removeNode()} method.
804      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
805      * @see #putFloat(String,float)
806      * @see #get(String,String)
807      */
getFloat(String key, float def)808     public abstract float getFloat(String key, float def);
809 
810     /**
811      * Associates a string representing the specified double value with the
812      * specified key in this preference node.  The associated string is the
813      * one that would be returned if the double value were passed to
814      * {@link Double#toString(double)}.  This method is intended for use in
815      * conjunction with {@link #getDouble}.
816      *
817      * @param key key with which the string form of value is to be associated.
818      * @param value value whose string form is to be associated with key.
819      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
820      * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds
821      *         <tt>MAX_KEY_LENGTH</tt>.
822      * @throws IllegalStateException if this node (or an ancestor) has been
823      *         removed with the {@link #removeNode()} method.
824      * @see #getDouble(String,double)
825      */
putDouble(String key, double value)826     public abstract void putDouble(String key, double value);
827 
828     /**
829      * Returns the double value represented by the string associated with the
830      * specified key in this preference node.  The string is converted to an
831      * integer as by {@link Double#parseDouble(String)}.  Returns the specified
832      * default if there is no value associated with the key, the backing store
833      * is inaccessible, or if <tt>Double.parseDouble(String)</tt> would throw a
834      * {@link NumberFormatException} if the associated value were passed.
835      * This method is intended for use in conjunction with {@link #putDouble}.
836      *
837      * <p>If the implementation supports <i>stored defaults</i> and such a
838      * default exists, is accessible, and could be converted to a double
839      * with <tt>Double.parseDouble</tt>, this double is returned in preference
840      * to the specified default.
841      *
842      * @param key key whose associated value is to be returned as a double.
843      * @param def the value to be returned in the event that this
844      *        preference node has no value associated with <tt>key</tt>
845      *        or the associated value cannot be interpreted as a double,
846      *        or the backing store is inaccessible.
847      * @return the double value represented by the string associated with
848      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
849      *         associated value does not exist or cannot be interpreted as
850      *         a double.
851      * @throws IllegalStateException if this node (or an ancestor) has been
852      *         removed with the {@link #removeNode()} method.
853      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.
854      * @see #putDouble(String,double)
855      * @see #get(String,String)
856      */
getDouble(String key, double def)857     public abstract double getDouble(String key, double def);
858 
859     /**
860      * Associates a string representing the specified byte array with the
861      * specified key in this preference node.  The associated string is
862      * the <i>Base64</i> encoding of the byte array, as defined in <a
863      * href=http://www.ietf.org/rfc/rfc2045.txt>RFC 2045</a>, Section 6.8,
864      * with one minor change: the string will consist solely of characters
865      * from the <i>Base64 Alphabet</i>; it will not contain any newline
866      * characters.  Note that the maximum length of the byte array is limited
867      * to three quarters of <tt>MAX_VALUE_LENGTH</tt> so that the length
868      * of the Base64 encoded String does not exceed <tt>MAX_VALUE_LENGTH</tt>.
869      * This method is intended for use in conjunction with
870      * {@link #getByteArray}.
871      *
872      * @param key key with which the string form of value is to be associated.
873      * @param value value whose string form is to be associated with key.
874      * @throws NullPointerException if key or value is <tt>null</tt>.
875      * @throws IllegalArgumentException if key.length() exceeds MAX_KEY_LENGTH
876      *         or if value.length exceeds MAX_VALUE_LENGTH*3/4.
877      * @throws IllegalStateException if this node (or an ancestor) has been
878      *         removed with the {@link #removeNode()} method.
879      * @see #getByteArray(String,byte[])
880      * @see #get(String,String)
881      */
putByteArray(String key, byte[] value)882     public abstract void putByteArray(String key, byte[] value);
883 
884     /**
885      * Returns the byte array value represented by the string associated with
886      * the specified key in this preference node.  Valid strings are
887      * <i>Base64</i> encoded binary data, as defined in <a
888      * href=http://www.ietf.org/rfc/rfc2045.txt>RFC 2045</a>, Section 6.8,
889      * with one minor change: the string must consist solely of characters
890      * from the <i>Base64 Alphabet</i>; no newline characters or
891      * extraneous characters are permitted.  This method is intended for use
892      * in conjunction with {@link #putByteArray}.
893      *
894      * <p>Returns the specified default if there is no value
895      * associated with the key, the backing store is inaccessible, or if the
896      * associated value is not a valid Base64 encoded byte array
897      * (as defined above).
898      *
899      * <p>If the implementation supports <i>stored defaults</i> and such a
900      * default exists and is accessible, it is used in preference to the
901      * specified default, unless the stored default is not a valid Base64
902      * encoded byte array (as defined above), in which case the
903      * specified default is used.
904      *
905      * @param key key whose associated value is to be returned as a byte array.
906      * @param def the value to be returned in the event that this
907      *        preference node has no value associated with <tt>key</tt>
908      *        or the associated value cannot be interpreted as a byte array,
909      *        or the backing store is inaccessible.
910      * @return the byte array value represented by the string associated with
911      *         <tt>key</tt> in this preference node, or <tt>def</tt> if the
912      *         associated value does not exist or cannot be interpreted as
913      *         a byte array.
914      * @throws IllegalStateException if this node (or an ancestor) has been
915      *         removed with the {@link #removeNode()} method.
916      * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>.  (A
917      *         <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.)
918      * @see #get(String,String)
919      * @see #putByteArray(String,byte[])
920      */
getByteArray(String key, byte[] def)921     public abstract byte[] getByteArray(String key, byte[] def);
922 
923     /**
924      * Returns all of the keys that have an associated value in this
925      * preference node.  (The returned array will be of size zero if
926      * this node has no preferences.)
927      *
928      * <p>If the implementation supports <i>stored defaults</i> and there
929      * are any such defaults at this node that have not been overridden,
930      * by explicit preferences, the defaults are returned in the array in
931      * addition to any explicit preferences.
932      *
933      * @return an array of the keys that have an associated value in this
934      *         preference node.
935      * @throws BackingStoreException if this operation cannot be completed
936      *         due to a failure in the backing store, or inability to
937      *         communicate with it.
938      * @throws IllegalStateException if this node (or an ancestor) has been
939      *         removed with the {@link #removeNode()} method.
940      */
keys()941     public abstract String[] keys() throws BackingStoreException;
942 
943     /**
944      * Returns the names of the children of this preference node, relative to
945      * this node.  (The returned array will be of size zero if this node has
946      * no children.)
947      *
948      * @return the names of the children of this preference node.
949      * @throws BackingStoreException if this operation cannot be completed
950      *         due to a failure in the backing store, or inability to
951      *         communicate with it.
952      * @throws IllegalStateException if this node (or an ancestor) has been
953      *         removed with the {@link #removeNode()} method.
954      */
childrenNames()955     public abstract String[] childrenNames() throws BackingStoreException;
956 
957     /**
958      * Returns the parent of this preference node, or <tt>null</tt> if this is
959      * the root.
960      *
961      * @return the parent of this preference node.
962      * @throws IllegalStateException if this node (or an ancestor) has been
963      *         removed with the {@link #removeNode()} method.
964      */
parent()965     public abstract Preferences parent();
966 
967     /**
968      * Returns the named preference node in the same tree as this node,
969      * creating it and any of its ancestors if they do not already exist.
970      * Accepts a relative or absolute path name.  Relative path names
971      * (which do not begin with the slash character <tt>('/')</tt>) are
972      * interpreted relative to this preference node.
973      *
974      * <p>If the returned node did not exist prior to this call, this node and
975      * any ancestors that were created by this call are not guaranteed
976      * to become permanent until the <tt>flush</tt> method is called on
977      * the returned node (or one of its ancestors or descendants).
978      *
979      * @param pathName the path name of the preference node to return.
980      * @return the specified preference node.
981      * @throws IllegalArgumentException if the path name is invalid (i.e.,
982      *         it contains multiple consecutive slash characters, or ends
983      *         with a slash character and is more than one character long).
984      * @throws NullPointerException if path name is <tt>null</tt>.
985      * @throws IllegalStateException if this node (or an ancestor) has been
986      *         removed with the {@link #removeNode()} method.
987      * @see #flush()
988      */
node(String pathName)989     public abstract Preferences node(String pathName);
990 
991     /**
992      * Returns true if the named preference node exists in the same tree
993      * as this node.  Relative path names (which do not begin with the slash
994      * character <tt>('/')</tt>) are interpreted relative to this preference
995      * node.
996      *
997      * <p>If this node (or an ancestor) has already been removed with the
998      * {@link #removeNode()} method, it <i>is</i> legal to invoke this method,
999      * but only with the path name <tt>""</tt>; the invocation will return
1000      * <tt>false</tt>.  Thus, the idiom <tt>p.nodeExists("")</tt> may be
1001      * used to test whether <tt>p</tt> has been removed.
1002      *
1003      * @param pathName the path name of the node whose existence
1004      *        is to be checked.
1005      * @return true if the specified node exists.
1006      * @throws BackingStoreException if this operation cannot be completed
1007      *         due to a failure in the backing store, or inability to
1008      *         communicate with it.
1009      * @throws IllegalArgumentException if the path name is invalid (i.e.,
1010      *         it contains multiple consecutive slash characters, or ends
1011      *         with a slash character and is more than one character long).
1012      * @throws NullPointerException if path name is <tt>null</tt>.
1013      * @throws IllegalStateException if this node (or an ancestor) has been
1014      *         removed with the {@link #removeNode()} method and
1015      *         <tt>pathName</tt> is not the empty string (<tt>""</tt>).
1016      */
nodeExists(String pathName)1017     public abstract boolean nodeExists(String pathName)
1018         throws BackingStoreException;
1019 
1020     /**
1021      * Removes this preference node and all of its descendants, invalidating
1022      * any preferences contained in the removed nodes.  Once a node has been
1023      * removed, attempting any method other than {@link #name()},
1024      * {@link #absolutePath()}, {@link #isUserNode()}, {@link #flush()} or
1025      * {@link #node(String) nodeExists("")} on the corresponding
1026      * <tt>Preferences</tt> instance will fail with an
1027      * <tt>IllegalStateException</tt>.  (The methods defined on {@link Object}
1028      * can still be invoked on a node after it has been removed; they will not
1029      * throw <tt>IllegalStateException</tt>.)
1030      *
1031      * <p>The removal is not guaranteed to be persistent until the
1032      * <tt>flush</tt> method is called on this node (or an ancestor).
1033      *
1034      * <p>If this implementation supports <i>stored defaults</i>, removing a
1035      * node exposes any stored defaults at or below this node.  Thus, a
1036      * subsequent call to <tt>nodeExists</tt> on this node's path name may
1037      * return <tt>true</tt>, and a subsequent call to <tt>node</tt> on this
1038      * path name may return a (different) <tt>Preferences</tt> instance
1039      * representing a non-empty collection of preferences and/or children.
1040      *
1041      * @throws BackingStoreException if this operation cannot be completed
1042      *         due to a failure in the backing store, or inability to
1043      *         communicate with it.
1044      * @throws IllegalStateException if this node (or an ancestor) has already
1045      *         been removed with the {@link #removeNode()} method.
1046      * @throws UnsupportedOperationException if this method is invoked on
1047      *         the root node.
1048      * @see #flush()
1049      */
removeNode()1050     public abstract void removeNode() throws BackingStoreException;
1051 
1052     /**
1053      * Returns this preference node's name, relative to its parent.
1054      *
1055      * @return this preference node's name, relative to its parent.
1056      */
name()1057     public abstract String name();
1058 
1059     /**
1060      * Returns this preference node's absolute path name.
1061      *
1062      * @return this preference node's absolute path name.
1063      */
absolutePath()1064     public abstract String absolutePath();
1065 
1066     /**
1067      * Returns <tt>true</tt> if this preference node is in the user
1068      * preference tree, <tt>false</tt> if it's in the system preference tree.
1069      *
1070      * @return <tt>true</tt> if this preference node is in the user
1071      *         preference tree, <tt>false</tt> if it's in the system
1072      *         preference tree.
1073      */
isUserNode()1074     public abstract boolean isUserNode();
1075 
1076     /**
1077      * Returns a string representation of this preferences node,
1078      * as if computed by the expression:<tt>(this.isUserNode() ? "User" :
1079      * "System") + " Preference Node: " + this.absolutePath()</tt>.
1080      */
toString()1081     public abstract String toString();
1082 
1083     /**
1084      * Forces any changes in the contents of this preference node and its
1085      * descendants to the persistent store.  Once this method returns
1086      * successfully, it is safe to assume that all changes made in the
1087      * subtree rooted at this node prior to the method invocation have become
1088      * permanent.
1089      *
1090      * <p>Implementations are free to flush changes into the persistent store
1091      * at any time.  They do not need to wait for this method to be called.
1092      *
1093      * <p>When a flush occurs on a newly created node, it is made persistent,
1094      * as are any ancestors (and descendants) that have yet to be made
1095      * persistent.  Note however that any preference value changes in
1096      * ancestors are <i>not</i> guaranteed to be made persistent.
1097      *
1098      * <p> If this method is invoked on a node that has been removed with
1099      * the {@link #removeNode()} method, flushSpi() is invoked on this node,
1100      * but not on others.
1101      *
1102      * @throws BackingStoreException if this operation cannot be completed
1103      *         due to a failure in the backing store, or inability to
1104      *         communicate with it.
1105      * @see    #sync()
1106      */
flush()1107     public abstract void flush() throws BackingStoreException;
1108 
1109     /**
1110      * Ensures that future reads from this preference node and its
1111      * descendants reflect any changes that were committed to the persistent
1112      * store (from any VM) prior to the <tt>sync</tt> invocation.  As a
1113      * side-effect, forces any changes in the contents of this preference node
1114      * and its descendants to the persistent store, as if the <tt>flush</tt>
1115      * method had been invoked on this node.
1116      *
1117      * @throws BackingStoreException if this operation cannot be completed
1118      *         due to a failure in the backing store, or inability to
1119      *         communicate with it.
1120      * @throws IllegalStateException if this node (or an ancestor) has been
1121      *         removed with the {@link #removeNode()} method.
1122      * @see    #flush()
1123      */
sync()1124     public abstract void sync() throws BackingStoreException;
1125 
1126     /**
1127      * Registers the specified listener to receive <i>preference change
1128      * events</i> for this preference node.  A preference change event is
1129      * generated when a preference is added to this node, removed from this
1130      * node, or when the value associated with a preference is changed.
1131      * (Preference change events are <i>not</i> generated by the {@link
1132      * #removeNode()} method, which generates a <i>node change event</i>.
1133      * Preference change events <i>are</i> generated by the <tt>clear</tt>
1134      * method.)
1135      *
1136      * <p>Events are only guaranteed for changes made within the same JVM
1137      * as the registered listener, though some implementations may generate
1138      * events for changes made outside this JVM.  Events may be generated
1139      * before the changes have been made persistent.  Events are not generated
1140      * when preferences are modified in descendants of this node; a caller
1141      * desiring such events must register with each descendant.
1142      *
1143      * @param pcl The preference change listener to add.
1144      * @throws NullPointerException if <tt>pcl</tt> is null.
1145      * @throws IllegalStateException if this node (or an ancestor) has been
1146      *         removed with the {@link #removeNode()} method.
1147      * @see #removePreferenceChangeListener(PreferenceChangeListener)
1148      * @see #addNodeChangeListener(NodeChangeListener)
1149      */
addPreferenceChangeListener( PreferenceChangeListener pcl)1150     public abstract void addPreferenceChangeListener(
1151         PreferenceChangeListener pcl);
1152 
1153     /**
1154      * Removes the specified preference change listener, so it no longer
1155      * receives preference change events.
1156      *
1157      * @param pcl The preference change listener to remove.
1158      * @throws IllegalArgumentException if <tt>pcl</tt> was not a registered
1159      *         preference change listener on this node.
1160      * @throws IllegalStateException if this node (or an ancestor) has been
1161      *         removed with the {@link #removeNode()} method.
1162      * @see #addPreferenceChangeListener(PreferenceChangeListener)
1163      */
removePreferenceChangeListener( PreferenceChangeListener pcl)1164     public abstract void removePreferenceChangeListener(
1165         PreferenceChangeListener pcl);
1166 
1167     /**
1168      * Registers the specified listener to receive <i>node change events</i>
1169      * for this node.  A node change event is generated when a child node is
1170      * added to or removed from this node.  (A single {@link #removeNode()}
1171      * invocation results in multiple <i>node change events</i>, one for every
1172      * node in the subtree rooted at the removed node.)
1173      *
1174      * <p>Events are only guaranteed for changes made within the same JVM
1175      * as the registered listener, though some implementations may generate
1176      * events for changes made outside this JVM.  Events may be generated
1177      * before the changes have become permanent.  Events are not generated
1178      * when indirect descendants of this node are added or removed; a
1179      * caller desiring such events must register with each descendant.
1180      *
1181      * <p>Few guarantees can be made regarding node creation.  Because nodes
1182      * are created implicitly upon access, it may not be feasible for an
1183      * implementation to determine whether a child node existed in the backing
1184      * store prior to access (for example, because the backing store is
1185      * unreachable or cached information is out of date).  Under these
1186      * circumstances, implementations are neither required to generate node
1187      * change events nor prohibited from doing so.
1188      *
1189      * @param ncl The <tt>NodeChangeListener</tt> to add.
1190      * @throws NullPointerException if <tt>ncl</tt> is null.
1191      * @throws IllegalStateException if this node (or an ancestor) has been
1192      *         removed with the {@link #removeNode()} method.
1193      * @see #removeNodeChangeListener(NodeChangeListener)
1194      * @see #addPreferenceChangeListener(PreferenceChangeListener)
1195      */
addNodeChangeListener(NodeChangeListener ncl)1196     public abstract void addNodeChangeListener(NodeChangeListener ncl);
1197 
1198     /**
1199      * Removes the specified <tt>NodeChangeListener</tt>, so it no longer
1200      * receives change events.
1201      *
1202      * @param ncl The <tt>NodeChangeListener</tt> to remove.
1203      * @throws IllegalArgumentException if <tt>ncl</tt> was not a registered
1204      *         <tt>NodeChangeListener</tt> on this node.
1205      * @throws IllegalStateException if this node (or an ancestor) has been
1206      *         removed with the {@link #removeNode()} method.
1207      * @see #addNodeChangeListener(NodeChangeListener)
1208      */
removeNodeChangeListener(NodeChangeListener ncl)1209     public abstract void removeNodeChangeListener(NodeChangeListener ncl);
1210 
1211     /**
1212      * Emits on the specified output stream an XML document representing all
1213      * of the preferences contained in this node (but not its descendants).
1214      * This XML document is, in effect, an offline backup of the node.
1215      *
1216      * <p>The XML document will have the following DOCTYPE declaration:
1217      * <pre>{@code
1218      * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
1219      * }</pre>
1220      * The UTF-8 character encoding will be used.
1221      *
1222      * <p>This method is an exception to the general rule that the results of
1223      * concurrently executing multiple methods in this class yields
1224      * results equivalent to some serial execution.  If the preferences
1225      * at this node are modified concurrently with an invocation of this
1226      * method, the exported preferences comprise a "fuzzy snapshot" of the
1227      * preferences contained in the node; some of the concurrent modifications
1228      * may be reflected in the exported data while others may not.
1229      *
1230      * @param os the output stream on which to emit the XML document.
1231      * @throws IOException if writing to the specified output stream
1232      *         results in an <tt>IOException</tt>.
1233      * @throws BackingStoreException if preference data cannot be read from
1234      *         backing store.
1235      * @see    #importPreferences(InputStream)
1236      * @throws IllegalStateException if this node (or an ancestor) has been
1237      *         removed with the {@link #removeNode()} method.
1238      */
exportNode(OutputStream os)1239     public abstract void exportNode(OutputStream os)
1240         throws IOException, BackingStoreException;
1241 
1242     /**
1243      * Emits an XML document representing all of the preferences contained
1244      * in this node and all of its descendants.  This XML document is, in
1245      * effect, an offline backup of the subtree rooted at the node.
1246      *
1247      * <p>The XML document will have the following DOCTYPE declaration:
1248      * <pre>{@code
1249      * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
1250      * }</pre>
1251      * The UTF-8 character encoding will be used.
1252      *
1253      * <p>This method is an exception to the general rule that the results of
1254      * concurrently executing multiple methods in this class yields
1255      * results equivalent to some serial execution.  If the preferences
1256      * or nodes in the subtree rooted at this node are modified concurrently
1257      * with an invocation of this method, the exported preferences comprise a
1258      * "fuzzy snapshot" of the subtree; some of the concurrent modifications
1259      * may be reflected in the exported data while others may not.
1260      *
1261      * @param os the output stream on which to emit the XML document.
1262      * @throws IOException if writing to the specified output stream
1263      *         results in an <tt>IOException</tt>.
1264      * @throws BackingStoreException if preference data cannot be read from
1265      *         backing store.
1266      * @throws IllegalStateException if this node (or an ancestor) has been
1267      *         removed with the {@link #removeNode()} method.
1268      * @see    #importPreferences(InputStream)
1269      * @see    #exportNode(OutputStream)
1270      */
exportSubtree(OutputStream os)1271     public abstract void exportSubtree(OutputStream os)
1272         throws IOException, BackingStoreException;
1273 
1274     /**
1275      * Imports all of the preferences represented by the XML document on the
1276      * specified input stream.  The document may represent user preferences or
1277      * system preferences.  If it represents user preferences, the preferences
1278      * will be imported into the calling user's preference tree (even if they
1279      * originally came from a different user's preference tree).  If any of
1280      * the preferences described by the document inhabit preference nodes that
1281      * do not exist, the nodes will be created.
1282      *
1283      * <p>The XML document must have the following DOCTYPE declaration:
1284      * <pre>{@code
1285      * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
1286      * }</pre>
1287      * (This method is designed for use in conjunction with
1288      * {@link #exportNode(OutputStream)} and
1289      * {@link #exportSubtree(OutputStream)}.
1290      *
1291      * <p>This method is an exception to the general rule that the results of
1292      * concurrently executing multiple methods in this class yields
1293      * results equivalent to some serial execution.  The method behaves
1294      * as if implemented on top of the other public methods in this class,
1295      * notably {@link #node(String)} and {@link #put(String, String)}.
1296      *
1297      * @param is the input stream from which to read the XML document.
1298      * @throws IOException if reading from the specified input stream
1299      *         results in an <tt>IOException</tt>.
1300      * @throws InvalidPreferencesFormatException Data on input stream does not
1301      *         constitute a valid XML document with the mandated document type.
1302      * @throws SecurityException If a security manager is present and
1303      *         it denies <tt>RuntimePermission("preferences")</tt>.
1304      * @see    RuntimePermission
1305      */
importPreferences(InputStream is)1306     public static void importPreferences(InputStream is)
1307         throws IOException, InvalidPreferencesFormatException
1308     {
1309         XmlSupport.importPreferences(is);
1310     }
1311 }
1312