📄 abstractpreferences.java
字号:
} } /** * Removes all entries from this preferences node. May need access to the * backing store to get and clear all entries. * <p> * The result will be immediatly visible in this VM, but may not be * immediatly written to the backing store. * <p> * This implementation locks this node, checks that the node has not been * removed and calls <code>keys()</code> to get a complete array of keys * for this node. For every key found <code>removeSpi()</code> is called. * * @exception BackingStoreException when the backing store cannot be * reached * @exception IllegalStateException if this node has been removed */ public void clear() throws BackingStoreException { synchronized(lock) { if (isRemoved()) throw new IllegalStateException("Node Removed"); String[] keys = keys(); for (int i = 0; i < keys.length; i++) { removeSpi(keys[i]); } } } /** * Writes all preference changes on this and any subnode that have not * yet been written to the backing store. This has no effect on the * preference entries in this VM, but it makes sure that all changes * are visible to other programs (other VMs might need to call the * <code>sync()</code> method to actually see the changes to the backing * store. * <p> * Locks this node, calls the <code>flushSpi()</code> method, gets all * the (cached - already existing in this VM) subnodes and then calls * <code>flushSpi()</code> on every subnode with this node unlocked and * only that particular subnode locked. * * @exception BackingStoreException when the backing store cannot be * reached */ public void flush() throws BackingStoreException { flushNode(false); } /** * Writes and reads all preference changes to and from this and any * subnodes. This makes sure that all local changes are written to the * backing store and that all changes to the backing store are visible * in this preference node (and all subnodes). * <p> * Checks that this node is not removed, locks this node, calls the * <code>syncSpi()</code> method, gets all the subnodes and then calls * <code>syncSpi()</code> on every subnode with this node unlocked and * only that particular subnode locked. * * @exception BackingStoreException when the backing store cannot be * reached * @exception IllegalStateException if this node has been removed */ public void sync() throws BackingStoreException { flushNode(true); } /** * Private helper method that locks this node and calls either * <code>flushSpi()</code> if <code>sync</code> is false, or * <code>flushSpi()</code> if <code>sync</code> is true. Then it gets all * the currently cached subnodes. For every subnode it calls this method * recursively with this node no longer locked. * <p> * Called by either <code>flush()</code> or <code>sync()</code> */ private void flushNode(boolean sync) throws BackingStoreException { String[] keys = null; synchronized(lock) { if (sync) { syncSpi(); } else { flushSpi(); } keys = (String[]) childCache.keySet().toArray(); } if (keys != null) { for (int i = 0; i < keys.length; i++) { // Have to lock this node again to access the childCache AbstractPreferences subNode; synchronized(this) { subNode = (AbstractPreferences) childCache.get(keys[i]); } // The child could already have been removed from the cache if (subNode != null) { subNode.flushNode(sync); } } } } /** * Removes this and all subnodes from the backing store and clears all * entries. After removal this instance will not be useable (except for * a few methods that don't throw a <code>InvalidStateException</code>), * even when a new node with the same path name is created this instance * will not be usable again. * <p> * Checks that this is not a root node. If not it locks the parent node, * then locks this node and checks that the node has not yet been removed. * Then it makes sure that all subnodes of this node are in the child cache, * by calling <code>childSpi()</code> on any children not yet in the cache. * Then for all children it locks the subnode and removes it. After all * subnodes have been purged the child cache is cleared, this nodes removed * flag is set and any listeners are called. Finally this node is removed * from the child cache of the parent node. * * @exception BackingStoreException when the backing store cannot be * reached * @exception IllegalStateException if this node has already been removed * @exception UnsupportedOperationException if this is a root node */ public void removeNode() throws BackingStoreException { // Check if it is a root node if (parent == null) throw new UnsupportedOperationException("Cannot remove root node"); synchronized(parent) { synchronized(this) { if (isRemoved()) throw new IllegalStateException("Node Removed"); purge(); } parent.childCache.remove(name); } } /** * Private helper method used to completely remove this node. * Called by <code>removeNode</code> with the parent node and this node * locked. * <p> * Makes sure that all subnodes of this node are in the child cache, * by calling <code>childSpi()</code> on any children not yet in the * cache. Then for all children it locks the subnode and calls this method * on that node. After all subnodes have been purged the child cache is * cleared, this nodes removed flag is set and any listeners are called. */ private void purge() throws BackingStoreException { // Make sure all children have an AbstractPreferences node in cache String children[] = childrenNamesSpi(); for (int i = 0; i < children.length; i++) { if (childCache.get(children[i]) == null) childCache.put(children[i], childSpi(children[i])); } // purge all children Iterator i = childCache.values().iterator(); while (i.hasNext()) { AbstractPreferences node = (AbstractPreferences) i.next(); synchronized(node) { node.purge(); } } // Cache is empty now childCache.clear(); // remove this node removeNodeSpi(); removed = true; // XXX - check for listeners } // listener methods /** * XXX */ public void addNodeChangeListener(NodeChangeListener listener) { // XXX } public void addPreferenceChangeListener(PreferenceChangeListener listener) { // XXX } public void removeNodeChangeListener(NodeChangeListener listener) { // XXX } public void removePreferenceChangeListener (PreferenceChangeListener listener) { // XXX } // abstract spi methods /** * Returns the names of the sub nodes of this preference node. * This method only has to return any not yet cached child names, * but may return all names if that is easier. It must not return * null when there are no children, it has to return an empty array * in that case. Since this method must consult the backing store to * get all the sub node names it may throw a BackingStoreException. * <p> * Called by <code>childrenNames()</code> with this node locked. */ protected abstract String[] childrenNamesSpi() throws BackingStoreException; /** * Returns a child note with the given name. * This method is called by the <code>node()</code> method (indirectly * through the <code>getNode()</code> helper method) with this node locked * if a sub node with this name does not already exist in the child cache. * If the child node did not aleady exist in the backing store the boolean * field <code>newNode</code> of the returned node should be set. * <p> * Note that this method should even return a non-null child node if the * backing store is not available since it may not throw a * <code>BackingStoreException</code>. */ protected abstract AbstractPreferences childSpi(String name); /** * Returns an (possibly empty) array with all the keys of the preference * entries of this node. * <p> * Called by <code>keys()</code> with this node locked if this node has * not been removed. May throw an exception when the backing store cannot * be accessed. * * @exception BackingStoreException when the backing store cannot be * reached */ abstract protected String[] keysSpi() throws BackingStoreException; /** * Returns the value associated with the key in this preferences node or * null when the key does not exist in this preferences node. * <p> * Called by <code>key()</code> with this node locked after checking that * key is valid, not null and that the node has not been removed. * <code>key()</code> will catch any exceptions that this method throws. */ abstract protected String getSpi(String key); /** * Sets the value of the given preferences entry for this node. * The implementation is not required to propagate the change to the * backing store immediatly. It may not throw an exception when it tries * to write to the backing store and that operation fails, the failure * should be registered so a later invocation of <code>flush()</code> * or <code>sync()</code> can signal the failure. * <p> * Called by <code>put()</code> with this node locked after checking that * key and value are valid and non-null. */ abstract protected void putSpi(String key, String value); /** * Removes the given key entry from this preferences node. * The implementation is not required to propagate the change to the * backing store immediatly. It may not throw an exception when it tries * to write to the backing store and that operation fails, the failure * should be registered so a later invocation of <code>flush()</code> * or <code>sync()</code> can signal the failure. * <p> * Called by <code>remove()</code> with this node locked after checking * that the key is valid and non-null. */ abstract protected void removeSpi(String key); /** * Writes all entries of this preferences node that have not yet been * written to the backing store and possibly creates this node in the * backing store, if it does not yet exist. Should only write changes to * this node and not write changes to any subnodes. * Note that the node can be already removed in this VM. To check if * that is the case the implementation can call <code>isRemoved()</code>. * <p> * Called (indirectly) by <code>flush()</code> with this node locked. */ abstract protected void flushSpi() throws BackingStoreException; /** * Writes all entries of this preferences node that have not yet been * written to the backing store and reads any entries that have changed * in the backing store but that are not yet visible in this VM. * Should only sync this node and not change any of the subnodes. * Note that the node can be already removed in this VM. To check if * that is the case the implementation can call <code>isRemoved()</code>. * <p> * Called (indirectly) by <code>sync()</code> with this node locked. */ abstract protected void syncSpi() throws BackingStoreException; /** * Clears this node from this VM and removes it from the backing store. * After this method has been called the node is marked as removed. * <p> * Called (indirectly) by <code>removeNode()</code> with this node locked * after all the sub nodes of this node have already been removed. */ abstract protected void removeNodeSpi() throws BackingStoreException;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -