Home » openjdk-7 » java » util » prefs » [javadoc | source]

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

Home » openjdk-7 » java » util » prefs » [javadoc | source]