--- old/src/macosx/classes/java/util/prefs/MacOSXPreferences.java 2012-07-11 16:11:10.000000000 -0700 +++ new/src/macosx/classes/java/util/prefs/MacOSXPreferences.java 2012-07-11 16:11:10.000000000 -0700 @@ -29,28 +29,28 @@ class MacOSXPreferences extends AbstractPreferences { // fixme need security checks? - + // CF preferences file name for Java nodes with short names // This value is also in MacOSXPreferencesFile.c private static final String defaultAppName = "com.apple.java.util.prefs"; - + // true if this node is a child of userRoot or is userRoot private boolean isUser; - + // true if this node is userRoot or systemRoot private boolean isRoot; - + // CF's storage location for this node and its keys private MacOSXPreferencesFile file; - + // absolutePath() + "/" private String path; - + // User root and system root nodes private static MacOSXPreferences userRoot = null; private static MacOSXPreferences systemRoot = null; - - + + // Returns user root node, creating it if necessary. // Called by MacOSXPreferencesFactory static synchronized Preferences getUserRoot() { @@ -59,8 +59,8 @@ } return userRoot; } - - + + // Returns system root node, creating it if necessary. // Called by MacOSXPreferencesFactory static synchronized Preferences getSystemRoot() { @@ -69,40 +69,44 @@ } return systemRoot; } - - + + // Create a new root node. Called by getUserRoot() and getSystemRoot() // Synchronization is provided by the caller. - private MacOSXPreferences(boolean newIsUser) - { - super(null, ""); - isUser = newIsUser; - isRoot = true; - - initFields(); + private MacOSXPreferences(boolean newIsUser) { + this(null, "", false, true, newIsUser); } - - + + // Create a new non-root node with the given parent. // Called by childSpi(). - private MacOSXPreferences(MacOSXPreferences parent, String name) - { - super(parent, name); - isUser = isUserNode(); - isRoot = false; - - initFields(); + private MacOSXPreferences(MacOSXPreferences parent, String name) { + this(parent, name, false, false, false); } - - - private void initFields() + + private MacOSXPreferences(MacOSXPreferences parent, String name, + boolean isNew) + { + this(parent, name, isNew, false, false); + } + + private MacOSXPreferences(MacOSXPreferences parent, String name, + boolean isNew, boolean isRoot, boolean isUser) { + super(parent, name); + this.isRoot = isRoot; + if (isRoot) + this.isUser = isUser; + else + this.isUser = isUserNode(); path = isRoot ? absolutePath() : absolutePath() + "/"; file = cfFileForNode(isUser); - newNode = file.addNode(path); + if (isNew) + newNode = isNew; + else + newNode = file.addNode(path); } - // Create and return the MacOSXPreferencesFile for this node. // Does not write anything to the file. private MacOSXPreferencesFile cfFileForNode(boolean isUser) @@ -117,7 +121,7 @@ pos = name.indexOf('/', pos+1); if (pos == -1) break; } - + if (pos == -1) { // fewer than three components - use default name name = defaultAppName; @@ -129,25 +133,25 @@ name = name.replace('/', '.'); name = name.toLowerCase(); } - + return MacOSXPreferencesFile.getFile(name, isUser); } - - + + // AbstractPreferences implementation @Override protected void putSpi(String key, String value) { file.addKeyToNode(path, key, value); } - + // AbstractPreferences implementation @Override protected String getSpi(String key) { return file.getKeyFromNode(path, key); } - + // AbstractPreferences implementation @Override protected void removeSpi(String key) @@ -155,12 +159,12 @@ Objects.requireNonNull(key, "Specified key cannot be null"); file.removeKeyFromNode(path, key); } - - + + // AbstractPreferences implementation @Override protected void removeNodeSpi() - throws BackingStoreException + throws BackingStoreException { // Disallow flush or sync between these two operations // (they may be manipulating two different files) @@ -169,34 +173,34 @@ file.removeNode(path); } } - + // Erase knowledge about a child of this node. Called by removeNodeSpi. private void removeChild(String child) { file.removeChildFromNode(path, child); } - - + + // AbstractPreferences implementation @Override protected String[] childrenNamesSpi() - throws BackingStoreException + throws BackingStoreException { String[] result = file.getChildrenForNode(path); if (result == null) throw new BackingStoreException("Couldn't get list of children for node '" + path + "'"); return result; } - + // AbstractPreferences implementation @Override protected String[] keysSpi() - throws BackingStoreException + throws BackingStoreException { String[] result = file.getKeysForNode(path); if (result == null) throw new BackingStoreException("Couldn't get list of keys for node '" + path + "'"); return result; } - + // AbstractPreferences implementation @Override protected AbstractPreferences childSpi(String name) @@ -204,15 +208,15 @@ // Add to parent's child list here and disallow sync // because parent and child might be in different files. synchronized(MacOSXPreferencesFile.class) { - file.addChildToNode(path, name); - return new MacOSXPreferences(this, name); + boolean isNew = file.addChildToNode(path, name); + return new MacOSXPreferences(this, name, isNew); } } - + // AbstractPreferences override @Override public void flush() - throws BackingStoreException + throws BackingStoreException { // Flush should *not* check for removal, unlike sync, but should // prevent simultaneous removal. @@ -223,19 +227,19 @@ } } } - + // AbstractPreferences implementation @Override protected void flushSpi() - throws BackingStoreException + throws BackingStoreException { // nothing here - overridden flush() doesn't call this } - + // AbstractPreferences override @Override public void sync() - throws BackingStoreException + throws BackingStoreException { synchronized(lock) { if (isRemoved()) @@ -252,11 +256,11 @@ } } } - + // AbstractPreferences implementation @Override protected void syncSpi() - throws BackingStoreException + throws BackingStoreException { // nothing here - overridden sync() doesn't call this } --- old/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java 2012-07-11 16:11:11.000000000 -0700 +++ new/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java 2012-07-11 16:11:11.000000000 -0700 @@ -360,11 +360,11 @@ } } - void addChildToNode(String path, String child) + boolean addChildToNode(String path, String child) { synchronized(MacOSXPreferencesFile.class) { markChanged(); - addChildToNode(path, child+"/", appName, user, host); + return addChildToNode(path, child+"/", appName, user, host); } } @@ -433,7 +433,7 @@ addNode(String path, String name, long user, long host); private static final native void removeNode(String path, String name, long user, long host); - private static final native void + private static final native boolean addChildToNode(String path, String child, String name, long user, long host); private static final native void --- old/src/macosx/native/java/util/MacOSXPreferencesFile.m 2012-07-11 16:11:12.000000000 -0700 +++ new/src/macosx/native/java/util/MacOSXPreferencesFile.m 2012-07-11 16:11:11.000000000 -0700 @@ -641,7 +641,7 @@ // child must end with '/' -JNIEXPORT void JNICALL +JNIEXPORT Boolean JNICALL Java_java_util_prefs_MacOSXPreferencesFile_addChildToNode (JNIEnv *env, jobject klass, jobject jpath, jobject jchild, jobject jname, jlong juser, jlong jhost) @@ -656,6 +656,7 @@ CFDictionaryRef node; CFStringRef topKey; CFMutableDictionaryRef topValue; + Boolean beforeAdd = false; if (!path || !child || !name) goto badparams; @@ -665,9 +666,12 @@ // copyMutableNode creates the node if necessary parent = copyMutableNode(path, name, user, host, &topKey, &topValue); throwIfNull(parent, "copyMutableNode failed"); - + beforeAdd = CFDictionaryContainsKey(parent, child); CFDictionaryAddValue(parent, child, node); - + if (!beforeAdd) + beforeAdd = CFDictionaryContainsKey(parent, child); + else + beforeAdd = false; CFPreferencesSetValue(topKey, topValue, name, user, host); CFRelease(parent); @@ -680,6 +684,7 @@ if (path) CFRelease(path); if (child) CFRelease(child); if (name) CFRelease(name); + return beforeAdd; } --- old/test/ProblemList.txt 2012-07-11 16:11:12.000000000 -0700 +++ new/test/ProblemList.txt 2012-07-11 16:11:12.000000000 -0700 @@ -400,8 +400,4 @@ # 7041639, Solaris DSA keypair generation bug java/util/TimeZone/TimeZoneDatePermissionCheck.sh solaris-all -# 7150557 -java/util/prefs/RemoveReadOnlyNode.java macosx-all -java/util/prefs/RemoveUnregedListener.java macosx-all - ############################################################################