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

This page was automatically generated by Maven