⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractpreferences.java

📁 java源代码 请看看啊 提点宝贵的意见
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* * @(#)AbstractPreferences.java	1.17 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util.prefs;import java.util.*;import java.io.*;import java.security.AccessController;import java.security.PrivilegedAction;// These imports needed only as a workaround for a JavaDoc bugimport java.lang.Integer;import java.lang.Long;import java.lang.Float;import java.lang.Double;/** * This class provides a skeletal implementation of the {@link Preferences} * class, greatly easing the task of implementing it. * * <p><strong>This class is for <tt>Preferences</tt> implementers only. * Normal users of the <tt>Preferences</tt> facility should have no need to * consult this documentation.  The {@link Preferences} documentation * should suffice.</strong> * * <p>Implementors must override the nine abstract service-provider interface * (SPI) methods: {@link #getSpi(String)}, {@link #putSpi(String,String)}, * {@link #removeSpi(String)}, {@link #childSpi(String)}, {@link * #removeNodeSpi()}, {@link #keysSpi()}, {@link #childrenNamesSpi()}, {@link * #syncSpi()} and {@link #flushSpi()}.  All of the concrete methods specify * precisely how they are implemented atop these SPI methods.  The implementor * may, at his discretion, override one or more of the concrete methods if the * default implementation is unsatisfactory for any reason, such as * performance. * * <p>The SPI methods fall into three groups concerning exception * behavior. The <tt>getSpi</tt> method should never throw exceptions, but it * doesn't really matter, as any exception thrown by this method will be * intercepted by {@link #get(String,String)}, which will return the specified * default value to the caller.  The <tt>removeNodeSpi, keysSpi, * childrenNamesSpi, syncSpi</tt> and <tt>flushSpi</tt> methods are specified * to throw {@link BackingStoreException}, and the implementation is required * to throw this checked exception if it is unable to perform the operation. * The exception propagates outward, causing the corresponding API method * to fail. * * <p>The remaining SPI methods {@link #putSpi(String,String)}, {@link * #removeSpi(String)} and {@link #childSpi(String)} have more complicated * exception behavior.  They are not specified to throw * <tt>BackingStoreException</tt>, as they can generally obey their contracts * even if the backing store is unavailable.  This is true because they return * no information and their effects are not required to become permanent until * a subsequent call to {Preferences#flush()} or * {Preferences#sync()}. Generally speaking, these SPI methods should not * throw exceptions.  In some implementations, there may be circumstances * under which these calls cannot even enqueue the requested operation for * later processing.  Even under these circumstances it is generally better to * simply ignore the invocation and return, rather than throwing an an * exception.  Under these circumstances, however, all subsequent invocations * of <tt>flush()</tt> and <tt>sync</tt> should return <tt>false</tt>, as * returning <tt>true</tt> would imply that all previous operations had * successfully been made permanent. * * <p>There is one circumstance under which <tt>putSpi, removeSpi and * childSpi</tt> <i>should</i> throw an exception: if the caller lacks * sufficient privileges on the underlying operating system to perform the * requested operation.  This will, for instance, occur on most systems * if a non-privileged user attempts to modify system preferences. * (The required privileges will vary from implementation to * implementation.  On some implementations, they are the right to modify the * contents of some directory in the file system; on others they are the right * to modify contents of some key in a registry.)  Under any of these * circumstances, it would generally be undesirable to let the program * continue executing as if these operations would become permanent at a later * time.  While implementations are not required to throw an exception under * these circumstances, they are encouraged to do so.  A {@link * SecurityException} would be appropriate. * * <p>Most of the SPI methods require the implementation to read or write * information at a preferences node.  The implementor should beware of the * fact that another VM may have concurrently deleted this node from the * backing store.  It is the implementation's responsibility to recreate the * node if it has been deleted. * * <p>Implementation note: In Sun's default <tt>Preferences</tt> * implementations, the user's identity is inherited from the underlying * operating system and does not change for the lifetime of the virtual * machine.  It is recognized that server-side <tt>Preferences</tt> * implementations may have the user identity change from request to request, * implicitly passed to <tt>Preferences</tt> methods via the use of a * static {@link ThreadLocal} instance.  Authors of such implementations are * <i>strongly</i> encouraged to determine the user at the time preferences * are accessed (for example by the {@link #get(String,String)} or {@link * #put(String,String)} method) rather than permanently associating a user * with each <tt>Preferences</tt> instance.  The latter behavior conflicts * with normal <tt>Preferences</tt> usage and would lead to great confusion. * * @author  Josh Bloch * @version 1.17, 01/23/03 * @see     Preferences * @since   1.4 */public abstract class AbstractPreferences extends Preferences {    /**     * Our name relative to parent.     */    private final String name;    /**     * Our absolute path name.     */    private final String absolutePath;    /**     * Our parent node.     */    final AbstractPreferences parent;    /**     * Our root node.     */    private final AbstractPreferences root; // Relative to this node    /**     * This field should be <tt>true</tt> if this node did not exist in the     * backing store prior to the creation of this object.  The field     * is initialized to false, but may be set to true by a subclass     * constructor (and should not be modified thereafter).  This field     * indicates whether a node change event should be fired when     * creation is complete.     */    protected boolean newNode = false;    /**     * All known unremoved children of this node.  (This "cache" is consulted     * prior to calling childSpi() or getChild().     */    private Map kidCache  = new HashMap();    /**     * This field is used to keep track of whether or not this node has     * been removed.  Once it's set to true, it will never be reset to false.     */    private boolean removed = false;    /**     * Registered preference change listeners.     */    private PreferenceChangeListener[] prefListeners =         new PreferenceChangeListener[0];    /**     * Registered node change listeners.     */    private NodeChangeListener[] nodeListeners = new NodeChangeListener[0];    /**     * An object whose monitor is used to lock this node.  This object     * is used in preference to the node itself to reduce the likelihood of     * intentional or unintentional denial of service due to a locked node.     * To avoid deadlock, a node is <i>never</i> locked by a thread that     * holds a lock on a descendant of that node.     */    protected final Object lock = new Object();    /**     * Creates a preference node with the specified parent and the specified     * name relative to its parent.     *     * @param parent the parent of this preference node, or null if this     *               is the root.     * @param name the name of this preference node, relative to its parent,     *             or <tt>""</tt> if this is the root.     * @throws IllegalArgumentException if <tt>name</tt> contains a slash     *          (<tt>'/'</tt>),  or <tt>parent</tt> is <tt>null</tt> and     *          name isn't <tt>""</tt>.       */    protected AbstractPreferences(AbstractPreferences parent, String name) {        if (parent==null) {            if (!name.equals(""))                throw new IllegalArgumentException("Root name '"+name+                                                   "' must be \"\"");            this.absolutePath = "/";            root = this;        } else {            if (name.indexOf('/') != -1)                throw new IllegalArgumentException("Name '" + name +                                                 "' contains '/'");            if (name.equals(""))              throw new IllegalArgumentException("Illegal name: empty string");            root = parent.root;            absolutePath = (parent==root ? "/" + name                            		 : parent.absolutePath() + "/" + name);        }        this.name = name;        this.parent = parent;    }    /**     * Implements the <tt>put</tt> method as per the specification in     * {@link Preferences#put(String,String)}.     *     * <p>This implementation checks that the key and value are legal,     * obtains this preference node's lock, checks that the node     * has not been removed, invokes {@link #putSpi(String,String)}, and if     * there are any preference change listeners, enqueues a notification     * event for processing by the event dispatch thread.     *     * @param key key with which the specified value is to be associated.     * @param value value to be associated with the specified key.     * @throws NullPointerException if key or value is <tt>null</tt>.     * @throws IllegalArgumentException if <tt>key.length()</tt> exceeds     *       <tt>MAX_KEY_LENGTH</tt> or if <tt>value.length</tt> exceeds     *       <tt>MAX_VALUE_LENGTH</tt>.     * @throws IllegalStateException if this node (or an ancestor) has been     *         removed with the {@link #removeNode()} method.     */    public void put(String key, String value) {        if (key==null || value==null)            throw new NullPointerException();        if (key.length() > MAX_KEY_LENGTH)            throw new IllegalArgumentException("Key too long: "+key);        if (value.length() > MAX_VALUE_LENGTH)            throw new IllegalArgumentException("Value too long: "+value);        synchronized(lock) {            if (removed)                throw new IllegalStateException("Node has been removed.");            putSpi(key, value);            enqueuePreferenceChangeEvent(key, value);        }    }    /**     * Implements the <tt>get</tt> method as per the specification in     * {@link Preferences#get(String,String)}.     *     * <p>This implementation first checks to see if <tt>key</tt> is     * <tt>null</tt> throwing a <tt>NullPointerException</tt> if this is     * the case.  Then it obtains this preference node's lock,     * checks that the node has not been removed, invokes {@link     * #getSpi(String)}, and returns the result, unless the <tt>getSpi</tt>     * invocation returns <tt>null</tt> or throws an exception, in which case     * this invocation returns <tt>def</tt>.     *     * @param key key whose associated value is to be returned.     * @param def the value to be returned in the event that this     *        preference node has no value associated with <tt>key</tt>.     * @return the value associated with <tt>key</tt>, or <tt>def</tt>     *         if no value is associated with <tt>key</tt>.     * @throws IllegalStateException if this node (or an ancestor) has been     *         removed with the {@link #removeNode()} method.     * @throws NullPointerException if key is <tt>null</tt>.  (A      *         <tt>null</tt> default <i>is</i> permitted.)     */    public String get(String key, String def) {        if (key==null)            throw new NullPointerException("Null key");        synchronized(lock) {            if (removed)                throw new IllegalStateException("Node has been removed.");            String result = null;            try {                result = getSpi(key);            } catch (Exception e) {                // Ignoring exception causes default to be returned            }            return (result==null ? def : result);        }    }    /**     * Implements the <tt>remove(String)</tt> method as per the specification     * in {@link Preferences#remove(String)}.     *     * <p>This implementation obtains this preference node's lock,     * checks that the node has not been removed, invokes     * {@link #removeSpi(String)} and if there are any preference     * change listeners, enqueues a notification event for processing by the     * event dispatch thread.     *     * @param key key whose mapping is to be removed from the preference node.     * @throws IllegalStateException if this node (or an ancestor) has been     *         removed with the {@link #removeNode()} method.     */    public void remove(String key) {        synchronized(lock) {            if (removed)                throw new IllegalStateException("Node has been removed.");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -