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