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

📄 abstractpreferences.java

📁 java源代码 请看看啊 提点宝贵的意见
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     * returned array will be of size zero if this node has no children.)     * This method need not return the names of any nodes already cached,     * but may do so without harm.     *     * <p>This method is invoked with the lock on this node held.     *     * <p>If this node throws a <tt>BackingStoreException</tt>, the exception     * will propagate out beyond the enclosing {@link #childrenNames()}     * invocation.     *     * @return an array containing the names of the children of this     *         preference node.     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     */    protected abstract String[] childrenNamesSpi()        throws BackingStoreException;    /**      * Returns the named child if it exists, or <tt>null</tt> if it does not.     * It is guaranteed that <tt>nodeName</tt> is non-null, non-empty,     * does not contain the slash character ('/'), and is no longer than     * {@link #MAX_NAME_LENGTH} characters.  Also, it is guaranteed     * that this node has not been removed.  (The implementor needn't check     * for any of these things if he chooses to override this method.)     *     * <p>Finally, it is guaranteed that the named node has not been returned     * by a previous invocation of this method or {@link #childSpi} after the     * last time that it was removed.  In other words, a cached value will     * always be used in preference to invoking this method.  (The implementor     * needn't maintain his own cache of previously returned children if he     * chooses to override this method.)     *     * <p>This implementation obtains this preference node's lock, invokes     * {@link #childrenNames()} to get an array of the names of this node's     * children, and iterates over the array comparing the name of each child     * with the specified node name.  If a child node has the correct name,     * the {@link #childSpi(String)} method is invoked and the resulting     * node is returned.  If the iteration completes without finding the     * specified name, <tt>null</tt> is returned.     *     * @param nodeName name of the child to be searched for.     * @return the named child if it exists, or null if it does not.     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     */    protected AbstractPreferences getChild(String nodeName)            throws BackingStoreException {        synchronized(lock) {            // assert kidCache.get(nodeName)==null;            String[] kidNames = childrenNames();            for (int i=0; i<kidNames.length; i++)                if (kidNames[i].equals(nodeName))                    return childSpi(kidNames[i]);        }        return null;    }    /**      * Returns the named child of this preference node, creating it if it does     * not already exist.  It is guaranteed that <tt>name</tt> is non-null,     * non-empty, does not contain the slash character ('/'), and is no longer     * than {@link #MAX_NAME_LENGTH} characters.  Also, it is guaranteed that     * this node has not been removed.  (The implementor needn't check for any     * of these things.)     *     * <p>Finally, it is guaranteed that the named node has not been returned     * by a previous invocation of this method or {@link #getChild(String)}     * after the last time that it was removed.  In other words, a cached     * value will always be used in preference to invoking this method.     * Subclasses need not maintain their own cache of previously returned     * children.     *     * <p>The implementer must ensure that the returned node has not been     * removed.  If a like-named child of this node was previously removed, the     * implementer must return a newly constructed <tt>AbstractPreferences</tt>     * node; once removed, an <tt>AbstractPreferences</tt> node     * cannot be "resuscitated."     *      * <p>If this method causes a node to be created, this node is not     * guaranteed to be persistent until the <tt>flush</tt> method is      * invoked on this node or one of its ancestors (or descendants).     *     * <p>This method is invoked with the lock on this node held.     *     * @param name The name of the child node to return, relative to     *        this preference node.     * @return The named child node.     */    protected abstract AbstractPreferences childSpi(String name);    /**     * Returns the absolute path name of this preferences node.     */    public String toString() {        return (this.isUserNode() ? "User" : "System") +               " Preference Node: " + this.absolutePath();    }    /**     * Implements the <tt>sync</tt> method as per the specification in     * {@link Preferences#sync()}.     *     * <p>This implementation calls a recursive helper method that locks this     * node, invokes syncSpi() on it, unlocks this node, and recursively     * invokes this method on each "cached child."  A cached child is a child     * of this node that has been created in this VM and not subsequently     * removed.  In effect, this method does a depth first traversal of the     * "cached subtree" rooted at this node, calling syncSpi() on each node in     * the subTree while only that node is locked. Note that syncSpi() is     * invoked top-down.     *     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     * @throws IllegalStateException if this node (or an ancestor) has been     *         removed with the {@link #removeNode()} method.     * @see #flush()     */    public void sync() throws BackingStoreException {               sync2();    }    private void sync2() throws BackingStoreException {        AbstractPreferences[] cachedKids;        synchronized(lock) {	    if (removed) 		throw new IllegalStateException("Node has been removed");            	    syncSpi();	    cachedKids = cachedChildren();        }        for (int i=0; i<cachedKids.length; i++)            cachedKids[i].sync2();    }    /**     * This method is invoked with this node locked.  The contract of this     * method is to synchronize any cached preferences stored at this node     * with any stored in the backing store.  (It is perfectly possible that     * this node does not exist on the backing store, either because it has     * been deleted by another VM, or because it has not yet been created.)     * Note that this method should <i>not</i> synchronize the preferences in     * any subnodes of this node.  If the backing store naturally syncs an     * entire subtree at once, the implementer is encouraged to override     * sync(), rather than merely overriding this method.     *     * <p>If this node throws a <tt>BackingStoreException</tt>, the exception     * will propagate out beyond the enclosing {@link #sync()} invocation.     *     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     */    protected abstract void syncSpi() throws BackingStoreException;    /**     * Implements the <tt>flush</tt> method as per the specification in     * {@link Preferences#flush()}.     *     * <p>This implementation calls a recursive helper method that locks this     * node, invokes flushSpi() on it, unlocks this node, and recursively     * invokes this method on each "cached child."  A cached child is a child     * of this node that has been created in this VM and not subsequently     * removed.  In effect, this method does a depth first traversal of the     * "cached subtree" rooted at this node, calling flushSpi() on each node in     * the subTree while only that node is locked. Note that flushSpi() is     * invoked top-down.     *     * <p> If this method is invoked on a node that has been removed with      * the {@link #removeNode()} method, flushSpi() is invoked on this node,      * but not on others.     *     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     * @see #flush()     */    public void flush() throws BackingStoreException {        flush2();    }    private void flush2() throws BackingStoreException {        AbstractPreferences[] cachedKids;		synchronized(lock) {	    flushSpi();	    if(removed) 		return;            cachedKids = cachedChildren();        }	        for (int i = 0; i < cachedKids.length; i++)            cachedKids[i].flush2();    }    /**     * This method is invoked with this node locked.  The contract of this     * method is to force any cached changes in the contents of this     * preference node to the backing store, guaranteeing their persistence.     * (It is perfectly possible that this node does not exist on the backing     * store, either because it has been deleted by another VM, or because it     * has not yet been created.)  Note that this method should <i>not</i>     * flush the preferences in any subnodes of this node.  If the backing     * store naturally flushes an entire subtree at once, the implementer is     * encouraged to override flush(), rather than merely overriding this     * method.     *     * <p>If this node throws a <tt>BackingStoreException</tt>, the exception     * will propagate out beyond the enclosing {@link #flush()} invocation.     *     * @throws BackingStoreException if this operation cannot be completed     *         due to a failure in the backing store, or inability to      *         communicate with it.     */    protected abstract void flushSpi() throws BackingStoreException;    /**     * Returns <tt>true</tt> iff this node (or an ancestor) has been     * removed with the {@link #removeNode()} method.  This method     * locks this node prior to returning the contents of the private     * field used to track this state.     *     * @return <tt>true</tt> iff this node (or an ancestor) has been     *       removed with the {@link #removeNode()} method.     */    protected boolean isRemoved() {        synchronized(lock) {            return removed;        }    }    /**     * Queue of pending notification events.  When a preference or node     * change event for which there are one or more listeners occurs,     * it is placed on this queue and the queue is notified.  A background     * thread waits on this queue and delivers the events.  This decouples     * event delivery from preference activity, greatly simplifying     * locking and reducing opportunity for deadlock.     */    private static final List eventQueue = new LinkedList();    /**     * These two classes are used to distinguish NodeChangeEvents on     * eventQueue so the event dispatch thread knows whether to call     * childAdded or childRemoved.     */    private class NodeAddedEvent extends NodeChangeEvent {        NodeAddedEvent(Preferences parent, Preferences child) {            super(parent, child);        }    }    private class NodeRemovedEvent extends NodeChangeEvent {        NodeRemovedEvent(Preferences parent, Preferences child) {            super(parent, child);        }    }    /**     * A single background thread ("the event notification thread") monitors     * the event queue and delivers events that are placed on the queue.     */    private static class EventDispatchThread extends Thread {        public void run() {            while(true) {                // Wait on eventQueue till an event is present                EventObject event = null;                synchronized(eventQueue) {                    try {                        while (eventQueue.isEmpty())                             eventQueue.wait();                        event = (EventObject) eventQueue.remove(0);                    } catch (InterruptedException e) {                        // XXX Log "Event dispatch thread interrupted. Exiting"                        return;                    }                }                // Now we have event & hold no locks; deliver evt to listeners                AbstractPreferences src=(AbstractPreferences)event.getSource();                if (event instanceof PreferenceChangeEvent) {                    PreferenceChangeEvent pce = (PreferenceChangeEvent)event;                    PreferenceChangeListener[] listeners = src.prefListeners();                    for (int i=0; i<listeners.length; i++)                        listeners[i].preferenceChange(pce);                } else {                    NodeChangeEvent nce = (NodeChangeEvent)event;                    NodeChangeListener[] listeners = src.nodeListeners();                    if (nce instanceof NodeAddedEvent) {                        for (int i=0; i<listeners.length; i++)                            listeners[i].childAdded(nce);

⌨️ 快捷键说明

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