📄 abstractpreferences.java
字号:
try { String value = get(key, null); if (value != null) result = Double.parseDouble(value); } catch (NumberFormatException e) { // Ignoring exception causes specified default to be returned } return result; } /** * Implements the <tt>putByteArray</tt> method as per the specification in * {@link Preferences#putByteArray(String,byte[])}. * * @param key key with which the string form of value is to be associated. * @param value value whose string form is to be associated with key. * @throws NullPointerException if key or value is <tt>null</tt>. * @throws IllegalArgumentException if key.length() exceeds MAX_KEY_LENGTH * or if value.length exceeds MAX_VALUE_LENGTH*3/4. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. */ public void putByteArray(String key, byte[] value) { put(key, Base64.byteArrayToBase64(value)); } /** * Implements the <tt>getByteArray</tt> method as per the specification in * {@link Preferences#getByteArray(String,byte[])}. * * @param key key whose associated value is to be returned as a byte array. * @param def the value to be returned in the event that this * preference node has no value associated with <tt>key</tt> * or the associated value cannot be interpreted as a byte array. * @return the byte array value represented by the string associated with * <tt>key</tt> in this preference node, or <tt>def</tt> if the * associated value does not exist or cannot be interpreted as * a byte array. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. * @throws NullPointerException if <tt>key</tt> is <tt>null</tt>. (A * <tt>null</tt> value for <tt>def</tt> <i>is</i> permitted.) */ public byte[] getByteArray(String key, byte[] def) { byte[] result = def; String value = get(key, null); try { if (value != null) result = Base64.base64ToByteArray(value); } catch (RuntimeException e) { // Ignoring exception causes specified default to be returned } return result; } /** * Implements the <tt>keys</tt> method as per the specification in * {@link Preferences#keys()}. * * <p>This implementation obtains this preference node's lock, checks that * the node has not been removed and invokes {@link #keysSpi()}. * * @return an array of the keys that have an associated value in 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. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. */ public String[] keys() throws BackingStoreException { synchronized(lock) { if (removed) throw new IllegalStateException("Node has been removed."); return keysSpi(); } } /** * Implements the <tt>children</tt> method as per the specification in * {@link Preferences#childrenNames()}. * * <p>This implementation obtains this preference node's lock, checks that * the node has not been removed, constructs a <tt>TreeSet</tt> initialized * to the names of children already cached (the children in this node's * "child-cache"), invokes {@link #childrenNamesSpi()}, and adds all of the * returned child-names into the set. The elements of the tree set are * dumped into a <tt>String</tt> array using the <tt>toArray</tt> method, * and this array is returned. * * @return 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. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. * @see #cachedChildren() */ public String[] childrenNames() throws BackingStoreException { synchronized(lock) { if (removed) throw new IllegalStateException("Node has been removed."); Set s = new TreeSet(kidCache.keySet()); String[] kids = childrenNamesSpi(); for(int i=0; i<kids.length; i++) s.add(kids[i]); return (String[]) s.toArray(EMPTY_STRING_ARRAY); } } private static final String[] EMPTY_STRING_ARRAY = new String[0]; /** * Returns all known unremoved children of this node. * * @return all known unremoved children of this node. */ protected final AbstractPreferences[] cachedChildren() { return (AbstractPreferences[]) kidCache.values(). toArray(EMPTY_ABSTRACT_PREFS_ARRAY); } private static final AbstractPreferences[] EMPTY_ABSTRACT_PREFS_ARRAY = new AbstractPreferences[0]; /** * Implements the <tt>parent</tt> method as per the specification in * {@link Preferences#parent()}. * * <p>This implementation obtains this preference node's lock, checks that * the node has not been removed and returns the parent value that was * passed to this node's constructor. * * @return the parent of this preference node. * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. */ public Preferences parent() { synchronized(lock) { if (removed) throw new IllegalStateException("Node has been removed."); return parent; } } /** * Implements the <tt>node</tt> method as per the specification in * {@link Preferences#node(String)}. * * <p>This implementation obtains this preference node's lock and checks * that the node has not been removed. If <tt>path</tt> is <tt>""</tt>, * this node is returned; if <tt>path</tt> is <tt>"/"</tt>, this node's * root is returned. If the first character in <tt>path</tt> is * not <tt>'/'</tt>, the implementation breaks <tt>path</tt> into * tokens and recursively traverses the path from this node to the * named node, "consuming" a name and a slash from <tt>path</tt> at * each step of the traversal. At each step, the current node is locked * and the node's child-cache is checked for the named node. If it is * not found, the name is checked to make sure its length does not * exceed <tt>MAX_NAME_LENGTH</tt>. Then the {@link #childSpi(String)} * method is invoked, and the result stored in this node's child-cache. * If the newly created <tt>Preferences</tt> object's {@link #newNode} * field is <tt>true</tt> and there are any node change listeners, * a notification event is enqueued for processing by the event dispatch * thread. * * <p>When there are no more tokens, the last value found in the * child-cache or returned by <tt>childSpi</tt> is returned by this * method. If during the traversal, two <tt>"/"</tt> tokens occur * consecutively, or the final token is <tt>"/"</tt> (rather than a name), * an appropriate <tt>IllegalArgumentException</tt> is thrown. * * <p> If the first character of <tt>path</tt> is <tt>'/'</tt> * (indicating an absolute path name name) this preference node's * lock is dropped prior to breaking <tt>path</tt> into tokens, and * this method recursively traverses the path starting from the root * (rather than starting from this node). The traversal is otherwise * identical to the one described for relative path names. Dropping * the lock on this node prior to commencing the traversal at the root * node is essential to avoid the possibility of deadlock, as per the * {@link #lock locking invariant}. * * @param path the path name of the preference node to return. * @return the specified preference node. * @throws IllegalArgumentException if the path name is invalid (i.e., * it contains multiple consecutive slash characters, or ends * with a slash character and is more than one character long). * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method. */ public Preferences node(String path) { synchronized(lock) { if (removed) throw new IllegalStateException("Node has been removed."); if (path.equals("")) return this; if (path.equals("/")) return root; if (path.charAt(0) != '/') return node(new StringTokenizer(path, "/", true)); } // Absolute path. Note that we've dropped our lock to avoid deadlock return root.node(new StringTokenizer(path.substring(1), "/", true)); } /** * tokenizer contains <name> {'/' <name>}* */ private Preferences node(StringTokenizer path) { String token = path.nextToken(); if (token.equals("/")) // Check for consecutive slashes throw new IllegalArgumentException("Consecutive slashes in path"); synchronized(lock) { AbstractPreferences child=(AbstractPreferences)kidCache.get(token); if (child == null) { if (token.length() > MAX_NAME_LENGTH) throw new IllegalArgumentException( "Node name " + token + " too long"); child = childSpi(token); if (child.newNode) enqueueNodeAddedEvent(child); kidCache.put(token, child); } if (!path.hasMoreTokens()) return child; path.nextToken(); // Consume slash if (!path.hasMoreTokens()) throw new IllegalArgumentException("Path ends with slash"); return child.node(path); } } /** * Implements the <tt>nodeExists</tt> method as per the specification in * {@link Preferences#nodeExists(String)}. * * <p>This implementation is very similar to {@link #node(String)}, * except that {@link #getChild(String)} is used instead of {@link * #childSpi(String)}. * * @param path the path name of the node whose existence is to be checked. * @return true if the specified node exists. * @throws BackingStoreException if this operation cannot be completed * due to a failure in the backing store, or inability to * communicate with it. * @throws IllegalArgumentException if the path name is invalid (i.e., * it contains multiple consecutive slash characters, or ends * with a slash character and is more than one character long). * @throws IllegalStateException if this node (or an ancestor) has been * removed with the {@link #removeNode()} method and * <tt>pathname</tt> is not the empty string (<tt>""</tt>). */ public boolean nodeExists(String path) throws BackingStoreException { synchronized(lock) { if (path.equals("")) return !removed; if (removed) throw new IllegalStateException("Node has been removed."); if (path.equals("/")) return true; if (path.charAt(0) != '/') return nodeExists(new StringTokenizer(path, "/", true)); } // Absolute path. Note that we've dropped our lock to avoid deadlock return root.nodeExists(new StringTokenizer(path.substring(1), "/", true)); } /** * tokenizer contains <name> {'/' <name>}* */ private boolean nodeExists(StringTokenizer path) throws BackingStoreException { String token = path.nextToken(); if (token.equals("/")) // Check for consecutive slashes throw new IllegalArgumentException("Consecutive slashes in path"); synchronized(lock) { AbstractPreferences child=(AbstractPreferences)kidCache.get(token); if (child == null) child = getChild(token); if (child==null) return false; if (!path.hasMoreTokens()) return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -