Preferences.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /* Preferences -- Preference node containing key value entries and subnodes
  2. Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.util.prefs;
  32. import gnu.classpath.ServiceFactory;
  33. import gnu.java.util.prefs.NodeReader;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.io.OutputStream;
  37. import java.security.AccessController;
  38. import java.security.Permission;
  39. import java.security.PrivilegedAction;
  40. import java.util.Iterator;
  41. /**
  42. * Preference node containing key value entries and subnodes.
  43. * <p>
  44. * There are two preference node trees, a system tree which can be accessed
  45. * by calling <code>systemRoot()</code> containing system preferences usefull
  46. * for all users, and a user tree that can be accessed by calling
  47. * <code>userRoot()</code> containing preferences that can differ between
  48. * different users. How different users are identified is implementation
  49. * depended. It can be determined by Thread, Access Control Context or Subject.
  50. * <p>
  51. * This implementation uses the "java.util.prefs.PreferencesFactory" system
  52. * property to find a class that implement <code>PreferencesFactory</code>
  53. * and initialized that class (if it has a public no arguments contructor)
  54. * to get at the actual system or user root. If the system property is not set,
  55. * or the class cannot be initialized it uses the default implementation
  56. * <code>gnu.java.util.prefs.FileBasedFactory</code>.
  57. * <p>
  58. * Besides the two static method above to get the roots of the system and user
  59. * preference node trees there are also two convenience methods to access the
  60. * default preference node for a particular package an object is in. These are
  61. * <code>userNodeForPackage()</code> and <code>systemNodeForPackage()</code>.
  62. * Both methods take an Object as an argument so accessing preferences values
  63. * can be as easy as calling <code>Preferences.userNodeForPackage(this)</code>.
  64. * <p>
  65. * Note that if a security manager is installed all static methods check for
  66. * <code>RuntimePermission("preferences")</code>. But if this permission is
  67. * given to the code then it can access and change all (user) preference nodes
  68. * and entries. So you should be carefull not to store to sensitive information
  69. * or make security decissions based on preference values since there is no
  70. * more fine grained control over what preference values can be changed once
  71. * code has been given the correct runtime permission.
  72. * <p>
  73. * XXX
  74. *
  75. * @since 1.4
  76. * @author Mark Wielaard (mark@klomp.org)
  77. */
  78. public abstract class Preferences {
  79. // Static Fields
  80. /**
  81. * Default PreferencesFactory class used when the system property
  82. * "java.util.prefs.PreferencesFactory" is not set.
  83. */
  84. private static final String defaultFactoryClass
  85. = "gnu.java.util.prefs.FileBasedFactory";
  86. /** Permission needed to access system or user root. */
  87. private static final Permission prefsPermission
  88. = new RuntimePermission("preferences");
  89. /**
  90. * The preferences factory object that supplies the system and user root.
  91. * Set and returned by the getFactory() method.
  92. */
  93. private static PreferencesFactory factory;
  94. /** Maximum node name length. 80 characters. */
  95. public static final int MAX_NAME_LENGTH = 80;
  96. /** Maximum entry key length. 80 characters. */
  97. public static final int MAX_KEY_LENGTH = 80;
  98. /** Maximum entry value length. 8192 characters. */
  99. public static final int MAX_VALUE_LENGTH = 8192;
  100. // Constructors
  101. /**
  102. * Creates a new Preferences node. Can only be used by subclasses.
  103. * Empty implementation.
  104. */
  105. protected Preferences() {}
  106. // Static methods
  107. /**
  108. * Returns the system preferences root node containing usefull preferences
  109. * for all users. It is save to cache this value since it should always
  110. * return the same preference node.
  111. *
  112. * @return the root system preference node
  113. * @exception SecurityException when a security manager is installed and
  114. * the caller does not have <code>RuntimePermission("preferences")</code>.
  115. */
  116. public static Preferences systemRoot() throws SecurityException {
  117. // Get the preferences factory and check for permission
  118. PreferencesFactory factory = getFactory();
  119. return factory.systemRoot();
  120. }
  121. /**
  122. * Returns the user preferences root node containing preferences for the
  123. * the current user. How different users are identified is implementation
  124. * depended. It can be determined by Thread, Access Control Context or
  125. * Subject.
  126. *
  127. * @return the root user preference node
  128. * @exception SecurityException when a security manager is installed and
  129. * the caller does not have <code>RuntimePermission("preferences")</code>.
  130. */
  131. public static Preferences userRoot() throws SecurityException {
  132. // Get the preferences factory and check for permission
  133. PreferencesFactory factory = getFactory();
  134. return factory.userRoot();
  135. }
  136. /**
  137. * Private helper method for <code>systemRoot()</code> and
  138. * <code>userRoot()</code>. Checks security permission and instantiates the
  139. * correct factory if it has not yet been set.
  140. * <p>
  141. * When the preferences factory has not yet been set this method first
  142. * tries to get the system propery "java.util.prefs.PreferencesFactory"
  143. * and tries to initializes that class. If the system property is not set
  144. * or initialization fails it returns an instance of the default factory
  145. * <code>gnu.java.util.prefs.FileBasedPreferencesFactory</code>.
  146. *
  147. * @return the preferences factory to use
  148. * @exception SecurityException when a security manager is installed and
  149. * the caller does not have <code>RuntimePermission("preferences")</code>.
  150. */
  151. private static PreferencesFactory getFactory() throws SecurityException {
  152. // First check for permission
  153. SecurityManager sm = System.getSecurityManager();
  154. if (sm != null) {
  155. sm.checkPermission(prefsPermission);
  156. }
  157. // Get the factory
  158. if (factory == null) {
  159. // Caller might not have enough permissions
  160. factory = AccessController.doPrivileged(
  161. new PrivilegedAction<PreferencesFactory>() {
  162. public PreferencesFactory run() {
  163. PreferencesFactory pf = null;
  164. String className = System.getProperty
  165. ("java.util.prefs.PreferencesFactory");
  166. if (className != null) {
  167. try {
  168. Class fc = Class.forName(className);
  169. Object o = fc.newInstance();
  170. pf = (PreferencesFactory) o;
  171. } catch (ClassNotFoundException cnfe)
  172. {/*ignore*/}
  173. catch (InstantiationException ie)
  174. {/*ignore*/}
  175. catch (IllegalAccessException iae)
  176. {/*ignore*/}
  177. catch (ClassCastException cce)
  178. {/*ignore*/}
  179. }
  180. return pf;
  181. }
  182. });
  183. // Still no factory? Try to see if we have one defined
  184. // as a System Preference
  185. if (factory == null)
  186. {
  187. Iterator iter = ServiceFactory.lookupProviders
  188. (PreferencesFactory.class, null);
  189. if (iter != null && iter.hasNext())
  190. factory = (PreferencesFactory) iter.next();
  191. }
  192. // Still no factory? Use our default.
  193. if (factory == null)
  194. {
  195. try
  196. {
  197. Class cls = Class.forName (defaultFactoryClass);
  198. factory = (PreferencesFactory) cls.newInstance();
  199. }
  200. catch (Exception e)
  201. {
  202. throw new RuntimeException ("Couldn't load default factory"
  203. + " '"+ defaultFactoryClass +"'", e);
  204. }
  205. }
  206. }
  207. return factory;
  208. }
  209. /**
  210. * Returns the system preferences node for the package of a class.
  211. * The package node name of the class is determined by dropping the
  212. * final component of the fully qualified class name and
  213. * changing all '.' to '/' in the package name. If the class of the
  214. * object has no package then the package node name is "&lt;unnamed&gt;".
  215. * The returned node is <code>systemRoot().node(packageNodeName)</code>.
  216. *
  217. * @param c Object whose default system preference node is requested
  218. * @returns system preferences node that should be used by class c
  219. * @exception SecurityException when a security manager is installed and
  220. * the caller does not have <code>RuntimePermission("preferences")</code>.
  221. */
  222. public static Preferences systemNodeForPackage(Class<?> c)
  223. throws SecurityException
  224. {
  225. return nodeForPackage(c, systemRoot());
  226. }
  227. /**
  228. * Returns the user preferences node for the package of a class.
  229. * The package node name of the class is determined by dropping the
  230. * final component of the fully qualified class name and
  231. * changing all '.' to '/' in the package name. If the class of the
  232. * object has no package then the package node name is "&lt;unnamed&gt;".
  233. * The returned node is <code>userRoot().node(packageNodeName)</code>.
  234. *
  235. * @param c Object whose default userpreference node is requested
  236. * @returns userpreferences node that should be used by class c
  237. * @exception SecurityException when a security manager is installed and
  238. * the caller does not have <code>RuntimePermission("preferences")</code>.
  239. */
  240. public static Preferences userNodeForPackage(Class<?> c)
  241. throws SecurityException
  242. {
  243. return nodeForPackage(c, userRoot());
  244. }
  245. /**
  246. * Private helper method for <code>systemNodeForPackage()</code> and
  247. * <code>userNodeForPackage()</code>. Given the correct system or user
  248. * root it returns the correct Preference node for the package node name
  249. * of the given object.
  250. */
  251. private static Preferences nodeForPackage(Class c, Preferences root) {
  252. // Get the package path
  253. String className = c.getName();
  254. String packagePath;
  255. int index = className.lastIndexOf('.');
  256. if(index == -1) {
  257. packagePath = "<unnamed>";
  258. } else {
  259. packagePath = className.substring(0,index).replace('.','/');
  260. }
  261. return root.node(packagePath);
  262. }
  263. /**
  264. * Import preferences from the given input stream. This expects
  265. * preferences to be represented in XML as emitted by
  266. * {@link #exportNode(OutputStream)} and
  267. * {@link #exportSubtree(OutputStream)}.
  268. * @throws IOException if there is an error while reading
  269. * @throws InvalidPreferencesFormatException if the XML is not properly
  270. * formatted
  271. */
  272. public static void importPreferences(InputStream is)
  273. throws InvalidPreferencesFormatException,
  274. IOException
  275. {
  276. PreferencesFactory factory = getFactory();
  277. NodeReader reader = new NodeReader(is, factory);
  278. reader.importPreferences();
  279. }
  280. // abstract methods (identification)
  281. /**
  282. * Returns the absolute path name of this preference node.
  283. * The absolute path name of a node is the path name of its parent node
  284. * plus a '/' plus its own name. If the node is the root node and has no
  285. * parent then its name is "" and its absolute path name is "/".
  286. */
  287. public abstract String absolutePath();
  288. /**
  289. * Returns true if this node comes from the user preferences tree, false
  290. * if it comes from the system preferences tree.
  291. */
  292. public abstract boolean isUserNode();
  293. /**
  294. * Returns the name of this preferences node. The name of the node cannot
  295. * be null, can be mostly 80 characters and cannot contain any '/'
  296. * characters. The root node has as name "".
  297. */
  298. public abstract String name();
  299. /**
  300. * Returns the String given by
  301. * <code>
  302. * (isUserNode() ? "User":"System") + " Preference Node: " + absolutePath()
  303. * </code>
  304. */
  305. public abstract String toString();
  306. // abstract methods (navigation)
  307. /**
  308. * Returns all the direct sub nodes of this preferences node.
  309. * Needs access to the backing store to give a meaningfull answer.
  310. *
  311. * @exception BackingStoreException when the backing store cannot be
  312. * reached
  313. * @exception IllegalStateException when this node has been removed
  314. */
  315. public abstract String[] childrenNames() throws BackingStoreException;
  316. /**
  317. * Returns a sub node of this preferences node if the given path is
  318. * relative (does not start with a '/') or a sub node of the root
  319. * if the path is absolute (does start with a '/').
  320. *
  321. * @exception IllegalStateException if this node has been removed
  322. * @exception IllegalArgumentException if the path contains two or more
  323. * consecutive '/' characters, ends with a '/' charactor and is not the
  324. * string "/" (indicating the root node) or any name on the path is more
  325. * then 80 characters long
  326. */
  327. public abstract Preferences node(String path);
  328. /**
  329. * Returns true if the node that the path points to exists in memory or
  330. * in the backing store. Otherwise it returns false or an exception is
  331. * thrown. When this node is removed the only valid parameter is the
  332. * empty string (indicating this node), the return value in that case
  333. * will be false.
  334. *
  335. * @exception BackingStoreException when the backing store cannot be
  336. * reached
  337. * @exception IllegalStateException if this node has been removed
  338. * and the path is not the empty string (indicating this node)
  339. * @exception IllegalArgumentException if the path contains two or more
  340. * consecutive '/' characters, ends with a '/' charactor and is not the
  341. * string "/" (indicating the root node) or any name on the path is more
  342. * then 80 characters long
  343. */
  344. public abstract boolean nodeExists(String path)
  345. throws BackingStoreException;
  346. /**
  347. * Returns the parent preferences node of this node or null if this is
  348. * the root of the preferences tree.
  349. *
  350. * @exception IllegalStateException if this node has been removed
  351. */
  352. public abstract Preferences parent();
  353. // abstract methods (export)
  354. /**
  355. * Export this node, but not its descendants, as XML to the
  356. * indicated output stream. The XML will be encoded using UTF-8
  357. * and will use a specified document type:<br>
  358. * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
  359. * @param os the output stream to which the XML is sent
  360. * @throws BackingStoreException if preference data cannot be read
  361. * @throws IOException if an error occurs while writing the XML
  362. * @throws IllegalStateException if this node or an ancestor has been removed
  363. */
  364. public abstract void exportNode(OutputStream os)
  365. throws BackingStoreException,
  366. IOException;
  367. /**
  368. * Export this node and all its descendants as XML to the
  369. * indicated output stream. The XML will be encoded using UTF-8
  370. * and will use a specified document type:<br>
  371. * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
  372. * @param os the output stream to which the XML is sent
  373. * @throws BackingStoreException if preference data cannot be read
  374. * @throws IOException if an error occurs while writing the XML
  375. * @throws IllegalStateException if this node or an ancestor has been removed
  376. */
  377. public abstract void exportSubtree(OutputStream os)
  378. throws BackingStoreException,
  379. IOException;
  380. // abstract methods (preference entry manipulation)
  381. /**
  382. * Returns an (possibly empty) array with all the keys of the preference
  383. * entries of this node.
  384. *
  385. * @exception BackingStoreException when the backing store cannot be
  386. * reached
  387. * @exception IllegalStateException if this node has been removed
  388. */
  389. public abstract String[] keys() throws BackingStoreException;
  390. /**
  391. * Returns the value associated with the key in this preferences node. If
  392. * the default value of the key cannot be found in the preferences node
  393. * entries or something goes wrong with the backing store the supplied
  394. * default value is returned.
  395. *
  396. * @exception IllegalArgumentException if key is larger then 80 characters
  397. * @exception IllegalStateException if this node has been removed
  398. * @exception NullPointerException if key is null
  399. */
  400. public abstract String get(String key, String defaultVal);
  401. /**
  402. * Convenience method for getting the given entry as a boolean.
  403. * When the string representation of the requested entry is either
  404. * "true" or "false" (ignoring case) then that value is returned,
  405. * otherwise the given default boolean value is returned.
  406. *
  407. * @exception IllegalArgumentException if key is larger then 80 characters
  408. * @exception IllegalStateException if this node has been removed
  409. * @exception NullPointerException if key is null
  410. */
  411. public abstract boolean getBoolean(String key, boolean defaultVal);
  412. /**
  413. * Convenience method for getting the given entry as a byte array.
  414. * When the string representation of the requested entry is a valid
  415. * Base64 encoded string (without any other characters, such as newlines)
  416. * then the decoded Base64 string is returned as byte array,
  417. * otherwise the given default byte array value is returned.
  418. *
  419. * @exception IllegalArgumentException if key is larger then 80 characters
  420. * @exception IllegalStateException if this node has been removed
  421. * @exception NullPointerException if key is null
  422. */
  423. public abstract byte[] getByteArray(String key, byte[] defaultVal);
  424. /**
  425. * Convenience method for getting the given entry as a double.
  426. * When the string representation of the requested entry can be decoded
  427. * with <code>Double.parseDouble()</code> then that double is returned,
  428. * otherwise the given default double value is returned.
  429. *
  430. * @exception IllegalArgumentException if key is larger then 80 characters
  431. * @exception IllegalStateException if this node has been removed
  432. * @exception NullPointerException if key is null
  433. */
  434. public abstract double getDouble(String key, double defaultVal);
  435. /**
  436. * Convenience method for getting the given entry as a float.
  437. * When the string representation of the requested entry can be decoded
  438. * with <code>Float.parseFloat()</code> then that float is returned,
  439. * otherwise the given default float value is returned.
  440. *
  441. * @exception IllegalArgumentException if key is larger then 80 characters
  442. * @exception IllegalStateException if this node has been removed
  443. * @exception NullPointerException if key is null
  444. */
  445. public abstract float getFloat(String key, float defaultVal);
  446. /**
  447. * Convenience method for getting the given entry as an integer.
  448. * When the string representation of the requested entry can be decoded
  449. * with <code>Integer.parseInt()</code> then that integer is returned,
  450. * otherwise the given default integer value is returned.
  451. *
  452. * @exception IllegalArgumentException if key is larger then 80 characters
  453. * @exception IllegalStateException if this node has been removed
  454. * @exception NullPointerException if key is null
  455. */
  456. public abstract int getInt(String key, int defaultVal);
  457. /**
  458. * Convenience method for getting the given entry as a long.
  459. * When the string representation of the requested entry can be decoded
  460. * with <code>Long.parseLong()</code> then that long is returned,
  461. * otherwise the given default long value is returned.
  462. *
  463. * @exception IllegalArgumentException if key is larger then 80 characters
  464. * @exception IllegalStateException if this node has been removed
  465. * @exception NullPointerException if key is null
  466. */
  467. public abstract long getLong(String key, long defaultVal);
  468. /**
  469. * Sets the value of the given preferences entry for this node.
  470. * Key and value cannot be null, the key cannot exceed 80 characters
  471. * and the value cannot exceed 8192 characters.
  472. * <p>
  473. * The result will be immediatly visible in this VM, but may not be
  474. * immediatly written to the backing store.
  475. *
  476. * @exception NullPointerException if either key or value are null
  477. * @exception IllegalArgumentException if either key or value are to large
  478. * @exception IllegalStateException when this node has been removed
  479. */
  480. public abstract void put(String key, String value);
  481. /**
  482. * Convenience method for setting the given entry as a boolean.
  483. * The boolean is converted with <code>Boolean.toString(value)</code>
  484. * and then stored in the preference entry as that string.
  485. *
  486. * @exception NullPointerException if key is null
  487. * @exception IllegalArgumentException if the key length is to large
  488. * @exception IllegalStateException when this node has been removed
  489. */
  490. public abstract void putBoolean(String key, boolean value);
  491. /**
  492. * Convenience method for setting the given entry as an array of bytes.
  493. * The byte array is converted to a Base64 encoded string
  494. * and then stored in the preference entry as that string.
  495. * <p>
  496. * Note that a byte array encoded as a Base64 string will be about 1.3
  497. * times larger then the original length of the byte array, which means
  498. * that the byte array may not be larger about 6 KB.
  499. *
  500. * @exception NullPointerException if either key or value are null
  501. * @exception IllegalArgumentException if either key or value are to large
  502. * @exception IllegalStateException when this node has been removed
  503. */
  504. public abstract void putByteArray(String key, byte[] value);
  505. /**
  506. * Convenience method for setting the given entry as a double.
  507. * The double is converted with <code>Double.toString(double)</code>
  508. * and then stored in the preference entry as that string.
  509. *
  510. * @exception NullPointerException if the key is null
  511. * @exception IllegalArgumentException if the key length is to large
  512. * @exception IllegalStateException when this node has been removed
  513. */
  514. public abstract void putDouble(String key, double value);
  515. /**
  516. * Convenience method for setting the given entry as a float.
  517. * The float is converted with <code>Float.toString(float)</code>
  518. * and then stored in the preference entry as that string.
  519. *
  520. * @exception NullPointerException if the key is null
  521. * @exception IllegalArgumentException if the key length is to large
  522. * @exception IllegalStateException when this node has been removed
  523. */
  524. public abstract void putFloat(String key, float value);
  525. /**
  526. * Convenience method for setting the given entry as an integer.
  527. * The integer is converted with <code>Integer.toString(int)</code>
  528. * and then stored in the preference entry as that string.
  529. *
  530. * @exception NullPointerException if the key is null
  531. * @exception IllegalArgumentException if the key length is to large
  532. * @exception IllegalStateException when this node has been removed
  533. */
  534. public abstract void putInt(String key, int value);
  535. /**
  536. * Convenience method for setting the given entry as a long.
  537. * The long is converted with <code>Long.toString(long)</code>
  538. * and then stored in the preference entry as that string.
  539. *
  540. * @exception NullPointerException if the key is null
  541. * @exception IllegalArgumentException if the key length is to large
  542. * @exception IllegalStateException when this node has been removed
  543. */
  544. public abstract void putLong(String key, long value);
  545. /**
  546. * Removes the preferences entry from this preferences node.
  547. * <p>
  548. * The result will be immediatly visible in this VM, but may not be
  549. * immediatly written to the backing store.
  550. *
  551. * @exception NullPointerException if the key is null
  552. * @exception IllegalArgumentException if the key length is to large
  553. * @exception IllegalStateException when this node has been removed
  554. */
  555. public abstract void remove(String key);
  556. // abstract methods (preference node manipulation)
  557. /**
  558. * Removes all entries from this preferences node. May need access to the
  559. * backing store to get and clear all entries.
  560. * <p>
  561. * The result will be immediatly visible in this VM, but may not be
  562. * immediatly written to the backing store.
  563. *
  564. * @exception BackingStoreException when the backing store cannot be
  565. * reached
  566. * @exception IllegalStateException if this node has been removed
  567. */
  568. public abstract void clear() throws BackingStoreException;
  569. /**
  570. * Writes all preference changes on this and any subnode that have not
  571. * yet been written to the backing store. This has no effect on the
  572. * preference entries in this VM, but it makes sure that all changes
  573. * are visible to other programs (other VMs might need to call the
  574. * <code>sync()</code> method to actually see the changes to the backing
  575. * store.
  576. *
  577. * @exception BackingStoreException when the backing store cannot be
  578. * reached
  579. * @exception IllegalStateException if this node has been removed
  580. */
  581. public abstract void flush() throws BackingStoreException;
  582. /**
  583. * Writes and reads all preference changes to and from this and any
  584. * subnodes. This makes sure that all local changes are written to the
  585. * backing store and that all changes to the backing store are visible
  586. * in this preference node (and all subnodes).
  587. *
  588. * @exception BackingStoreException when the backing store cannot be
  589. * reached
  590. * @exception IllegalStateException if this node has been removed
  591. */
  592. public abstract void sync() throws BackingStoreException;
  593. /**
  594. * Removes this and all subnodes from the backing store and clears all
  595. * entries. After removal this instance will not be useable (except for
  596. * a few methods that don't throw a <code>InvalidStateException</code>),
  597. * even when a new node with the same path name is created this instance
  598. * will not be usable again. The root (system or user) may never be removed.
  599. * <p>
  600. * Note that according to the specification an implementation may delay
  601. * removal of the node from the backing store till the <code>flush()</code>
  602. * method is called. But the <code>flush()</code> method may throw a
  603. * <code>IllegalStateException</code> when the node has been removed.
  604. * So most implementations will actually remove the node and any subnodes
  605. * from the backing store immediatly.
  606. *
  607. * @exception BackingStoreException when the backing store cannot be
  608. * reached
  609. * @exception IllegalStateException if this node has already been removed
  610. * @exception UnsupportedOperationException if this is a root node
  611. */
  612. public abstract void removeNode() throws BackingStoreException;
  613. // abstract methods (listeners)
  614. public abstract void addNodeChangeListener(NodeChangeListener listener);
  615. public abstract void addPreferenceChangeListener
  616. (PreferenceChangeListener listener);
  617. public abstract void removeNodeChangeListener(NodeChangeListener listener);
  618. public abstract void removePreferenceChangeListener
  619. (PreferenceChangeListener listener);
  620. }