--- old/make/lib/CoreLibraries.gmk 2014-02-09 17:05:50.689428841 +0000 +++ new/make/lib/CoreLibraries.gmk 2014-02-09 17:05:50.437428847 +0000 @@ -123,6 +123,7 @@ $(JDK_TOPDIR)/src/share/native/java/security \ $(JDK_TOPDIR)/src/share/native/common \ $(JDK_TOPDIR)/src/share/native/sun/misc \ + $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/misc \ $(JDK_TOPDIR)/src/share/native/sun/reflect \ $(JDK_TOPDIR)/src/share/native/java/util \ $(JDK_TOPDIR)/src/share/native/java/util/concurrent/atomic \ @@ -187,7 +188,7 @@ LIBRARY := java, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBJAVA_SRC_DIRS), \ - EXCLUDES := fdlibm/src zip, \ + EXCLUDES := fdlibm/src zip prefs, \ EXCLUDE_FILES := $(LIBJAVA_EXCLUDE_FILES), \ LANG := C, \ OPTIMIZATION := HIGH, \ @@ -285,6 +286,41 @@ ########################################################################################## +ifeq ($(OPENJDK_TARGET_OS), macosx) + LIBPREF_SRC_DIRS := $(JDK_TOPDIR)/src/macosx/native/java/util/prefs +else + LIBPREF_SRC_DIRS := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/java/util/prefs +endif + +$(eval $(call SetupNativeCompilation,BUILD_LIBPREFS, \ + LIBRARY := prefs, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(LIBPREF_SRC_DIRS), \ + LANG := C, \ + OPTIMIZATION := HIGH, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libprefs/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LDFLAGS_SUFFIX_linux := -ljvm -ljava, \ + LDFLAGS_SUFFIX_solaris := -ljvm -ljava -lc, \ + LDFLAGS_SUFFIX_aix := -ljvm -ljava, \ + LDFLAGS_SUFFIX_windows := advapi32.lib, \ + LDFLAGS_SUFFIX_macosx := -ljvm -framework CoreFoundation, \ + VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \ + RC_FLAGS := $(RC_FLAGS) \ + -D "JDK_FNAME=prefs.dll" \ + -D "JDK_INTERNAL_NAME=prefs" \ + -D "JDK_FTYPE=0x2L", \ + OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libprefs, \ + DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) + +$(BUILD_LIBPREFS): $(BUILD_LIBJAVA) + +BUILD_LIBRARIES += $(BUILD_LIBPREFS) + +########################################################################################## + $(eval $(call SetupNativeCompilation,BUILD_LIBUNPACK, \ LIBRARY := unpack, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ --- old/make/lib/PlatformLibraries.gmk 2014-02-09 17:05:51.333428826 +0000 +++ new/make/lib/PlatformLibraries.gmk 2014-02-09 17:05:51.081428832 +0000 @@ -95,7 +95,6 @@ LIBOSX_DIRS := \ $(JDK_TOPDIR)/src/macosx/native/com/apple/concurrent \ - $(JDK_TOPDIR)/src/macosx/native/java/util \ $(JDK_TOPDIR)/src/macosx/native/com/apple/eio \ $(JDK_TOPDIR)/src/macosx/native/apple/security \ $(JDK_TOPDIR)/src/macosx/native/apple/launcher --- old/make/lib/SecurityLibraries.gmk 2014-02-09 17:05:52.133428808 +0000 +++ new/make/lib/SecurityLibraries.gmk 2014-02-09 17:05:51.877428814 +0000 @@ -128,8 +128,13 @@ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib else ifeq ($(OPENJDK_TARGET_OS), macosx) BUILD_LIBKRB5_NAME := osxkrb5 - BUILD_LIBKRB5_SRC := $(JDK_TOPDIR)/src/share/native/sun/security/krb5 - BUILD_LIBKRB5_LIBS := -framework Kerberos + BUILD_LIBKRB5_SRC := $(JDK_TOPDIR)/src/share/native/sun/security/krb5 \ + $(JDK_TOPDIR)/src/macosx/native/sun/security/krb5 + BUILD_LIBKRB5_LIBS := -F/System/Library/Frameworks/JavaVM.framework/Frameworks \ + -framework JavaNativeFoundation \ + -framework Cocoa \ + -framework SystemConfiguration \ + -framework Kerberos endif ifneq ($(BUILD_LIBKRB5_NAME), ) @@ -140,8 +145,9 @@ LANG := C, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(JDK_TOPDIR)/src/share/native/sun/security/krb5 \ - -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/security/krb5, \ + -I$(JDK_TOPDIR)/src/share/native/sun/security/krb5, \ + CFLAGS_windows := -I$(JDK_TOPDIR)/src/windows/native/sun/security/krb5, \ + CFLAGS_macosx := -F/System/Library/Frameworks/JavaVM.framework/Frameworks, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_SUFFIX := $(BUILD_LIBKRB5_LIBS), \ --- old/make/mapfiles/libjava/mapfile-vers 2014-02-09 17:05:52.961428789 +0000 +++ new/make/mapfiles/libjava/mapfile-vers 2014-02-09 17:05:52.709428795 +0000 @@ -236,10 +236,6 @@ Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; - Java_java_util_prefs_FileSystemPreferences_chmod; - Java_java_util_prefs_FileSystemPreferences_lockFile0; - Java_java_util_prefs_FileSystemPreferences_unlockFile0; - Java_java_util_logging_FileHandler_isSetUID; Java_sun_misc_MessageUtils_toStderr; Java_sun_misc_MessageUtils_toStdout; Java_sun_misc_NativeSignalHandler_handle0; @@ -274,17 +270,13 @@ Java_sun_misc_Version_getJvmVersionInfo; Java_sun_misc_Version_getJvmSpecialVersion; Java_sun_misc_VM_latestUserDefinedLoader; + Java_sun_misc_VM_isSetUID; Java_sun_misc_VM_initialize; Java_sun_misc_VMSupport_initAgentProperties; # ZipFile.c needs this one throwFileNotFoundException; -# Java_sun_misc_VM_getState; threads.c -# Java_sun_misc_VM_threadsSuspended; threads.c -# Java_sun_misc_VM_unsuspendSomeThreads; threads.c -# Java_sun_misc_VM_unsuspendThreads; threads.c - # Outcalls from libjvm done using dlsym(). VerifyClassCodes; --- old/make/profile-includes.txt 2014-02-09 17:05:53.601428774 +0000 +++ new/make/profile-includes.txt 2014-02-09 17:05:53.349428780 +0000 @@ -130,6 +130,7 @@ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)management.diz \ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)npt$(SHARED_LIBRARY_SUFFIX) \ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)npt.diz \ + $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)prefs$(SHARED_LIBRARY_SUFFIX) \ $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)sctp$(SHARED_LIBRARY_SUFFIX) \ jvm.hprof.txt \ management-agent.jar \ --- old/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java 2014-02-09 17:05:54.245428759 +0000 +++ new/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java 2014-02-09 17:05:53.989428765 +0000 @@ -82,7 +82,7 @@ java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { - System.loadLibrary("osx"); + System.loadLibrary("prefs"); return null; } }); --- old/src/share/classes/java/util/logging/FileHandler.java 2014-02-09 17:05:54.901428744 +0000 +++ new/src/share/classes/java/util/logging/FileHandler.java 2014-02-09 17:05:54.637428750 +0000 @@ -535,7 +535,7 @@ continue; } else if (ch2 == 'h') { file = new File(System.getProperty("user.home")); - if (isSetUID()) { + if (sun.misc.VM.isSetUID()) { // Ok, we are in a set UID program. For safety's sake // we disallow attempts to open files relative to %h. throw new IOException("can't use %h in set UID program"); @@ -669,9 +669,4 @@ lastException = ex; } } - - /** - * check if we are in a set UID program. - */ - private static native boolean isSetUID(); } --- old/src/share/classes/sun/misc/VM.java 2014-02-09 17:05:55.557428729 +0000 +++ new/src/share/classes/sun/misc/VM.java 2014-02-09 17:05:55.289428735 +0000 @@ -367,6 +367,11 @@ */ public static native ClassLoader latestUserDefinedLoader(); + /** + * Returns {@code true} if we are in a set UID program. + */ + public static native boolean isSetUID(); + static { initialize(); } --- old/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java 2014-02-09 17:05:56.209428714 +0000 +++ new/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java 2014-02-09 17:05:55.941428720 +0000 @@ -42,7 +42,7 @@ public Boolean run() { String osname = System.getProperty("os.name"); if (osname.contains("OS X")) { - System.loadLibrary("osx"); + System.loadLibrary("osxkrb5"); return true; } return false; --- old/src/solaris/classes/java/util/prefs/FileSystemPreferences.java 2014-02-09 17:05:56.861428699 +0000 +++ new/src/solaris/classes/java/util/prefs/FileSystemPreferences.java 2014-02-09 17:05:56.593428705 +0000 @@ -48,6 +48,15 @@ * @since 1.4 */ class FileSystemPreferences extends AbstractPreferences { + + static { + PrivilegedAction load = () -> { + System.loadLibrary("prefs"); + return null; + }; + AccessController.doPrivileged(load); + } + /** * Sync interval in seconds. */ @@ -868,7 +877,7 @@ /** * Returns the node name corresponding to the specified directory name. - * (Inverts the transformation of dirName(String). + * (Inverts the transformation of dirName(String). */ private static String nodeName(String dirName) { if (dirName.charAt(0) != '_') --- old/src/windows/classes/java/util/prefs/WindowsPreferences.java 2014-02-09 17:05:57.525428684 +0000 +++ new/src/windows/classes/java/util/prefs/WindowsPreferences.java 2014-02-09 17:05:57.253428690 +0000 @@ -29,6 +29,9 @@ import java.util.TreeMap; import java.util.StringTokenizer; import java.io.ByteArrayOutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; + import sun.util.logging.PlatformLogger; /** @@ -45,6 +48,14 @@ class WindowsPreferences extends AbstractPreferences{ + static { + PrivilegedAction load = () -> { + System.loadLibrary("prefs"); + return null; + }; + AccessController.doPrivileged(load); + } + /** * Logger for error messages */ --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/make/mapfiles/libprefs/mapfile-vers 2014-02-09 17:05:57.909428675 +0000 @@ -0,0 +1,36 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + Java_java_util_prefs_FileSystemPreferences_chmod; + Java_java_util_prefs_FileSystemPreferences_lockFile0; + Java_java_util_prefs_FileSystemPreferences_unlockFile0; + + local: + *; +}; --- old/src/macosx/native/java/util/MacOSXPreferencesFile.m 2014-02-09 17:05:58.861428653 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,999 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - Hierarchical storage layout: - - - / - - foo - /foo's value - foo/ - - bar - /foo/bar's value - - - - - Java pref nodes are stored in several different files. Pref nodes - with at least three components in the node name (e.g. /com/MyCompany/MyApp/) - are stored in a CF prefs file with the first three components as the name. - This way, all preferences for MyApp end up in com.MyCompany.MyApp.plist . - Pref nodes with shorter names are stored in com.apple.java.util.prefs.plist - - The filesystem is assumed to be case-insensitive (like HFS+). - Java pref node names are case-sensitive. If two pref node names differ - only in case, they may end up in the same pref file. This is ok - because the CF keys identifying the node span the entire absolute path - to the node and are case-sensitive. - - Java node names may contain '.' . When mapping to the CF file name, - these dots are left as-is, even though '/' is mapped to '.' . - This is ok because the CF key contains the correct node name. -*/ - - - -#include - -#include "jni_util.h" -#include "jlong.h" -#include "jvm.h" - - -// Throw an OutOfMemoryError with the given message. -static void throwOutOfMemoryError(JNIEnv *env, const char *msg) -{ - static jclass exceptionClass = NULL; - jclass c; - - if (exceptionClass) { - c = exceptionClass; - } else { - c = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); - if ((*env)->ExceptionOccurred(env)) return; - exceptionClass = (*env)->NewGlobalRef(env, c); - } - - (*env)->ThrowNew(env, c, msg); -} - - -// throwIfNull macro -// If var is NULL, throw an OutOfMemoryError and goto badvar. -// var must be a variable. env must be the current JNIEnv. -// fixme throw BackingStoreExceptions sometimes? -#define throwIfNull(var, msg) \ - do { \ - if (var == NULL) { \ - throwOutOfMemoryError(env, msg); \ - goto bad##var; \ - } \ - } while (0) - - -// Converts CFNumber, CFBoolean, CFString to CFString -// returns NULL if value is of some other type -// throws and returns NULL on memory error -// result must be released (even if value was already a CFStringRef) -// value must not be null -static CFStringRef copyToCFString(JNIEnv *env, CFTypeRef value) -{ - CFStringRef result; - CFTypeID type; - - type = CFGetTypeID(value); - - if (type == CFStringGetTypeID()) { - result = (CFStringRef)CFRetain(value); - } - else if (type == CFBooleanGetTypeID()) { - // Java Preferences API expects "true" and "false" for boolean values. - result = CFStringCreateCopy(NULL, (value == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false")); - throwIfNull(result, "copyToCFString failed"); - } - else if (type == CFNumberGetTypeID()) { - CFNumberRef number = (CFNumberRef) value; - if (CFNumberIsFloatType(number)) { - double d; - CFNumberGetValue(number, kCFNumberDoubleType, &d); - result = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), d); - throwIfNull(result, "copyToCFString failed"); - } - else { - long l; - CFNumberGetValue(number, kCFNumberLongType, &l); - result = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), l); - throwIfNull(result, "copyToCFString failed"); - } - } - else { - // unknown type - return NULL - result = NULL; - } - - badresult: - return result; -} - - -// Create a Java string from the given CF string. -// returns NULL if cfString is NULL -// throws and returns NULL on memory error -static jstring toJavaString(JNIEnv *env, CFStringRef cfString) -{ - if (cfString == NULL) { - return NULL; - } else { - jstring javaString = NULL; - - CFIndex length = CFStringGetLength(cfString); - const UniChar *constchars = CFStringGetCharactersPtr(cfString); - if (constchars) { - javaString = (*env)->NewString(env, constchars, length); - } else { - UniChar *chars = malloc(length * sizeof(UniChar)); - throwIfNull(chars, "toJavaString failed"); - CFStringGetCharacters(cfString, CFRangeMake(0, length), chars); - javaString = (*env)->NewString(env, chars, length); - free(chars); - } - badchars: - return javaString; - } -} - - - -// Create a CF string from the given Java string. -// returns NULL if javaString is NULL -// throws and returns NULL on memory error -static CFStringRef toCF(JNIEnv *env, jstring javaString) -{ - if (javaString == NULL) { - return NULL; - } else { - CFStringRef result = NULL; - jsize length = (*env)->GetStringLength(env, javaString); - const jchar *chars = (*env)->GetStringChars(env, javaString, NULL); - throwIfNull(chars, "toCF failed"); - result = - CFStringCreateWithCharacters(NULL, (const UniChar *)chars, length); - (*env)->ReleaseStringChars(env, javaString, chars); - throwIfNull(result, "toCF failed"); - badchars: - badresult: - return result; - } -} - - -// Create an empty Java string array of the given size. -// Throws and returns NULL on error. -static jarray createJavaStringArray(JNIEnv *env, CFIndex count) -{ - static jclass stringClass = NULL; - jclass c; - - if (stringClass) { - c = stringClass; - } else { - c = (*env)->FindClass(env, "java/lang/String"); - if ((*env)->ExceptionOccurred(env)) return NULL; - stringClass = (*env)->NewGlobalRef(env, c); - } - - return (*env)->NewObjectArray(env, count, c, NULL); // AWT_THREADING Safe (known object) -} - - -// Java accessors for CF constants. -JNIEXPORT jlong JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_currentUser(JNIEnv *env, - jobject klass) -{ - return ptr_to_jlong(kCFPreferencesCurrentUser); -} - -JNIEXPORT jlong JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_anyUser(JNIEnv *env, jobject klass) -{ - return ptr_to_jlong(kCFPreferencesAnyUser); -} - -JNIEXPORT jlong JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_currentHost(JNIEnv *env, - jobject klass) -{ - return ptr_to_jlong(kCFPreferencesCurrentHost); -} - -JNIEXPORT jlong JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_anyHost(JNIEnv *env, jobject klass) -{ - return ptr_to_jlong(kCFPreferencesAnyHost); -} - - -// Create an empty node. -// Does not store the node in any prefs file. -// returns NULL on memory error -static CFMutableDictionaryRef createEmptyNode(void) -{ - return CFDictionaryCreateMutable(NULL, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); -} - - -// Create a string that consists of path minus its last component. -// path must end with '/' -// The result will end in '/' (unless path itself is '/') -static CFStringRef copyParentOf(CFStringRef path) -{ - CFRange searchRange; - CFRange slashRange; - CFRange parentRange; - Boolean found; - - searchRange = CFRangeMake(0, CFStringGetLength(path) - 1); - found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, - kCFCompareBackwards, &slashRange); - if (!found) return CFSTR(""); - parentRange = CFRangeMake(0, slashRange.location + 1); // include '/' - return CFStringCreateWithSubstring(NULL, path, parentRange); -} - - -// Create a string that consists of path's last component. -// path must end with '/' -// The result will end in '/'. -// The result will not start with '/' (unless path itself is '/') -static CFStringRef copyChildOf(CFStringRef path) -{ - CFRange searchRange; - CFRange slashRange; - CFRange childRange; - Boolean found; - CFIndex length = CFStringGetLength(path); - - searchRange = CFRangeMake(0, length - 1); - found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, - kCFCompareBackwards, &slashRange); - if (!found) return CFSTR(""); - childRange = CFRangeMake(slashRange.location + 1, - length - slashRange.location - 1); // skip '/' - return CFStringCreateWithSubstring(NULL, path, childRange); -} - - -// Return the first three components of path, with leading and trailing '/'. -// If path does not have three components, return NULL. -// path must begin and end in '/' -static CFStringRef copyFirstThreeComponentsOf(CFStringRef path) -{ - CFRange searchRange; - CFRange slashRange; - CFRange prefixRange; - CFStringRef prefix; - Boolean found; - CFIndex length = CFStringGetLength(path); - - searchRange = CFRangeMake(1, length - 1); // skip leading '/' - found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, - &slashRange); - if (!found) return NULL; // no second slash! - - searchRange = CFRangeMake(slashRange.location + 1, - length - slashRange.location - 1); - found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, - &slashRange); - if (!found) return NULL; // no third slash! - - searchRange = CFRangeMake(slashRange.location + 1, - length - slashRange.location - 1); - found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, - &slashRange); - if (!found) return NULL; // no fourth slash! - - prefixRange = CFRangeMake(0, slashRange.location + 1); // keep last '/' - prefix = CFStringCreateWithSubstring(NULL, path, prefixRange); - - return prefix; -} - - -// Copy the CFPreferences key and value at the base of path's tree. -// path must end in '/' -// topKey or topValue may be NULL -// Returns NULL on error or if there is no tree for path in this file. -static void copyTreeForPath(CFStringRef path, CFStringRef name, - CFStringRef user, CFStringRef host, - CFStringRef *topKey, CFDictionaryRef *topValue) -{ - CFStringRef key; - CFPropertyListRef value; - - if (topKey) *topKey = NULL; - if (topValue) *topValue = NULL; - - if (CFEqual(name, CFSTR("com.apple.java.util.prefs"))) { - // Top-level file. Only key "/" is an acceptable root. - key = (CFStringRef) CFRetain(CFSTR("/")); - } else { - // Second-level file. Key must be the first three components of path. - key = copyFirstThreeComponentsOf(path); - if (!key) return; - } - - value = CFPreferencesCopyValue(key, name, user, host); - if (value) { - if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { - // (key, value) is acceptable - if (topKey) *topKey = (CFStringRef)CFRetain(key); - if (topValue) *topValue = (CFDictionaryRef)CFRetain(value); - } - CFRelease(value); - } - CFRelease(key); -} - - -// Find the node for path in the given tree. -// Returns NULL on error or if path doesn't have a node in this tree. -// path must end in '/' -static CFDictionaryRef copyNodeInTree(CFStringRef path, CFStringRef topKey, - CFDictionaryRef topValue) -{ - CFMutableStringRef p; - CFDictionaryRef result = NULL; - - p = CFStringCreateMutableCopy(NULL, 0, path); - if (!p) return NULL; - CFStringDelete(p, CFRangeMake(0, CFStringGetLength(topKey))); - result = topValue; - - while (CFStringGetLength(p) > 0) { - CFDictionaryRef child; - CFStringRef part = NULL; - CFRange slashRange = CFStringFind(p, CFSTR("/"), 0); - // guaranteed to succeed because path must end in '/' - CFRange partRange = CFRangeMake(0, slashRange.location + 1); - part = CFStringCreateWithSubstring(NULL, p, partRange); - if (!part) { result = NULL; break; } - CFStringDelete(p, partRange); - - child = CFDictionaryGetValue(result, part); - CFRelease(part); - if (child && CFGetTypeID(child) == CFDictionaryGetTypeID()) { - // continue search - result = child; - } else { - // didn't find target node - result = NULL; - break; - } - } - - CFRelease(p); - if (result) return (CFDictionaryRef)CFRetain(result); - else return NULL; -} - - -// Return a retained copy of the node at path from the given file. -// path must end in '/' -// returns NULL if node doesn't exist. -// returns NULL if the value for key "path" isn't a valid node. -static CFDictionaryRef copyNodeIfPresent(CFStringRef path, CFStringRef name, - CFStringRef user, CFStringRef host) -{ - CFStringRef topKey; - CFDictionaryRef topValue; - CFDictionaryRef result; - - copyTreeForPath(path, name, user, host, &topKey, &topValue); - if (!topKey) return NULL; - - result = copyNodeInTree(path, topKey, topValue); - - CFRelease(topKey); - if (topValue) CFRelease(topValue); - return result; -} - - -// Create a new tree that would store path in the given file. -// Only the root of the tree is created, not all of the links leading to path. -// returns NULL on error -static void createTreeForPath(CFStringRef path, CFStringRef name, - CFStringRef user, CFStringRef host, - CFStringRef *outTopKey, - CFMutableDictionaryRef *outTopValue) -{ - *outTopKey = NULL; - *outTopValue = NULL; - - // if name is "com.apple.java.util.prefs" then create tree "/" - // else create tree "/foo/bar/baz/" - // "com.apple.java.util.prefs.plist" is also in MacOSXPreferences.java - if (CFEqual(name, CFSTR("com.apple.java.util.prefs"))) { - *outTopKey = CFSTR("/"); - *outTopValue = createEmptyNode(); - } else { - CFStringRef prefix = copyFirstThreeComponentsOf(path); - if (prefix) { - *outTopKey = prefix; - *outTopValue = createEmptyNode(); - } - } -} - - -// Return a mutable copy of the tree containing path and the dict for -// path itself. *outTopKey and *outTopValue can be used to write the -// modified tree back to the prefs file. -// *outTopKey and *outTopValue must be released iff the actual return -// value is not NULL. -static CFMutableDictionaryRef -copyMutableNode(CFStringRef path, CFStringRef name, - CFStringRef user, CFStringRef host, - CFStringRef *outTopKey, - CFMutableDictionaryRef *outTopValue) -{ - CFStringRef topKey = NULL; - CFDictionaryRef oldTopValue = NULL; - CFMutableDictionaryRef topValue; - CFMutableDictionaryRef result = NULL; - CFMutableStringRef p; - - if (outTopKey) *outTopKey = NULL; - if (outTopValue) *outTopValue = NULL; - - copyTreeForPath(path, name, user, host, &topKey, &oldTopValue); - if (!topKey) { - createTreeForPath(path, name, user, host, &topKey, &topValue); - } else { - topValue = (CFMutableDictionaryRef) - CFPropertyListCreateDeepCopy(NULL, (CFPropertyListRef)oldTopValue, - kCFPropertyListMutableContainers); - } - if (!topValue) goto badtopValue; - - p = CFStringCreateMutableCopy(NULL, 0, path); - if (!p) goto badp; - CFStringDelete(p, CFRangeMake(0, CFStringGetLength(topKey))); - result = topValue; - - while (CFStringGetLength(p) > 0) { - CFMutableDictionaryRef child; - CFStringRef part = NULL; - CFRange slashRange = CFStringFind(p, CFSTR("/"), 0); - // guaranteed to succeed because path must end in '/' - CFRange partRange = CFRangeMake(0, slashRange.location + 1); - part = CFStringCreateWithSubstring(NULL, p, partRange); - if (!part) { result = NULL; break; } - CFStringDelete(p, partRange); - - child = (CFMutableDictionaryRef)CFDictionaryGetValue(result, part); - if (child && CFGetTypeID(child) == CFDictionaryGetTypeID()) { - // continue search - result = child; - } else { - // didn't find target node - add it and continue - child = createEmptyNode(); - if (!child) { CFRelease(part); result = NULL; break; } - CFDictionaryAddValue(result, part, child); - result = child; - } - CFRelease(part); - } - - if (result) { - *outTopKey = (CFStringRef)CFRetain(topKey); - *outTopValue = (CFMutableDictionaryRef)CFRetain(topValue); - CFRetain(result); - } - - CFRelease(p); - badp: - CFRelease(topValue); - badtopValue: - if (topKey) CFRelease(topKey); - if (oldTopValue) CFRelease(oldTopValue); - return result; -} - - -JNIEXPORT jboolean JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_addNode -(JNIEnv *env, jobject klass, jobject jpath, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFDictionaryRef node = NULL; - jboolean neededNewNode = false; - - if (!path || !name) goto badparams; - - node = copyNodeIfPresent(path, name, user, host); - - if (node) { - neededNewNode = false; - CFRelease(node); - } else { - CFStringRef topKey = NULL; - CFMutableDictionaryRef topValue = NULL; - - neededNewNode = true; - - // copyMutableNode creates the node if necessary - node = copyMutableNode(path, name, user, host, &topKey, &topValue); - throwIfNull(node, "copyMutableNode failed"); - - CFPreferencesSetValue(topKey, topValue, name, user, host); - - CFRelease(node); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - } - - badnode: - badparams: - if (path) CFRelease(path); - if (name) CFRelease(name); - - return neededNewNode; -} - - -JNIEXPORT void JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_removeNode -(JNIEnv *env, jobject klass, jobject jpath, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFStringRef parentName; - CFStringRef childName; - CFDictionaryRef constParent; - - if (!path || !name) goto badparams; - - parentName = copyParentOf(path); - throwIfNull(parentName, "copyParentOf failed"); - childName = copyChildOf(path); - throwIfNull(childName, "copyChildOf failed"); - - // root node is not allowed to be removed, so parentName is never empty - - constParent = copyNodeIfPresent(parentName, name, user, host); - if (constParent && CFDictionaryContainsKey(constParent, childName)) { - CFStringRef topKey; - CFMutableDictionaryRef topValue; - CFMutableDictionaryRef parent; - - parent = copyMutableNode(parentName, name, user, host, - &topKey, &topValue); - throwIfNull(parent, "copyMutableNode failed"); - - CFDictionaryRemoveValue(parent, childName); - CFPreferencesSetValue(topKey, topValue, name, user, host); - - CFRelease(parent); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - } else { - // might be trying to remove the root itself in a non-root file - CFStringRef topKey; - CFDictionaryRef topValue; - copyTreeForPath(path, name, user, host, &topKey, &topValue); - if (topKey) { - if (CFEqual(topKey, path)) { - CFPreferencesSetValue(topKey, NULL, name, user, host); - } - - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - } - } - - - badparent: - if (constParent) CFRelease(constParent); - CFRelease(childName); - badchildName: - CFRelease(parentName); - badparentName: - badparams: - if (path) CFRelease(path); - if (name) CFRelease(name); -} - - -// child must end with '/' -JNIEXPORT Boolean JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_addChildToNode -(JNIEnv *env, jobject klass, jobject jpath, jobject jchild, - jobject jname, jlong juser, jlong jhost) -{ - // like addNode, but can put a three-level-deep dict into the root file - CFStringRef path = toCF(env, jpath); - CFStringRef child = toCF(env, jchild); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFMutableDictionaryRef parent; - CFDictionaryRef node; - CFStringRef topKey; - CFMutableDictionaryRef topValue; - Boolean beforeAdd = false; - - if (!path || !child || !name) goto badparams; - - node = createEmptyNode(); - throwIfNull(node, "createEmptyNode failed"); - - // 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); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - badparent: - CFRelease(node); - badnode: - badparams: - if (path) CFRelease(path); - if (child) CFRelease(child); - if (name) CFRelease(name); - return beforeAdd; -} - - -JNIEXPORT void JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_removeChildFromNode -(JNIEnv *env, jobject klass, jobject jpath, jobject jchild, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef child = toCF(env, jchild); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFDictionaryRef constParent; - - if (!path || !child || !name) goto badparams; - - constParent = copyNodeIfPresent(path, name, user, host); - if (constParent && CFDictionaryContainsKey(constParent, child)) { - CFStringRef topKey; - CFMutableDictionaryRef topValue; - CFMutableDictionaryRef parent; - - parent = copyMutableNode(path, name, user, host, &topKey, &topValue); - throwIfNull(parent, "copyMutableNode failed"); - - CFDictionaryRemoveValue(parent, child); - CFPreferencesSetValue(topKey, topValue, name, user, host); - - CFRelease(parent); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - } - - badparent: - if (constParent) CFRelease(constParent); - badparams: - if (path) CFRelease(path); - if (child) CFRelease(child); - if (name) CFRelease(name); -} - - - -JNIEXPORT void JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_addKeyToNode -(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, jobject jvalue, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef key = toCF(env, jkey); - CFStringRef value = toCF(env, jvalue); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFMutableDictionaryRef node = NULL; - CFStringRef topKey; - CFMutableDictionaryRef topValue; - - if (!path || !key || !value || !name) goto badparams; - - // fixme optimization: check whether old value and new value are identical - node = copyMutableNode(path, name, user, host, &topKey, &topValue); - throwIfNull(node, "copyMutableNode failed"); - - CFDictionarySetValue(node, key, value); - CFPreferencesSetValue(topKey, topValue, name, user, host); - - CFRelease(node); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - - badnode: - badparams: - if (path) CFRelease(path); - if (key) CFRelease(key); - if (value) CFRelease(value); - if (name) CFRelease(name); -} - - -JNIEXPORT void JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_removeKeyFromNode -(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef key = toCF(env, jkey); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFDictionaryRef constNode; - - if (!path || !key || !name) goto badparams; - - constNode = copyNodeIfPresent(path, name, user, host); - if (constNode && CFDictionaryContainsKey(constNode, key)) { - CFStringRef topKey; - CFMutableDictionaryRef topValue; - CFMutableDictionaryRef node; - - node = copyMutableNode(path, name, user, host, &topKey, &topValue); - throwIfNull(node, "copyMutableNode failed"); - - CFDictionaryRemoveValue(node, key); - CFPreferencesSetValue(topKey, topValue, name, user, host); - - CFRelease(node); - if (topKey) CFRelease(topKey); - if (topValue) CFRelease(topValue); - } - - badnode: - if (constNode) CFRelease(constNode); - badparams: - if (path) CFRelease(path); - if (key) CFRelease(key); - if (name) CFRelease(name); -} - - -// path must end in '/' -JNIEXPORT jstring JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_getKeyFromNode -(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, - jobject jname, jlong juser, jlong jhost) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef key = toCF(env, jkey); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFPropertyListRef value; - CFDictionaryRef node; - jstring result = NULL; - - if (!path || !key || !name) goto badparams; - - node = copyNodeIfPresent(path, name, user, host); - if (node) { - value = (CFPropertyListRef)CFDictionaryGetValue(node, key); - if (!value) { - // key doesn't exist, or other error - no Java errors available - result = NULL; - } else { - CFStringRef cfString = copyToCFString(env, value); - if ((*env)->ExceptionOccurred(env)) { - // memory error in copyToCFString - result = NULL; - } else if (cfString == NULL) { - // bogus value type in prefs file - no Java errors available - result = NULL; - } else { - // good cfString - result = toJavaString(env, cfString); - CFRelease(cfString); - } - } - CFRelease(node); - } - - badparams: - if (path) CFRelease(path); - if (key) CFRelease(key); - if (name) CFRelease(name); - - return result; -} - - -typedef struct { - jarray result; - JNIEnv *env; - CFIndex used; - Boolean allowSlash; -} BuildJavaArrayArgs; - -// CFDictionary applier function that builds an array of Java strings -// from a CFDictionary of CFPropertyListRefs. -// If args->allowSlash, only strings that end in '/' are added to the array, -// with the slash removed. Otherwise, only strings that do not end in '/' -// are added. -// args->result must already exist and be large enough to hold all -// strings from the dictionary. -// After complete application, args->result may not be full because -// some of the dictionary values weren't convertible to string. In -// this case, args->used will be the count of used elements. -static void BuildJavaArrayFn(const void *key, const void *value, void *context) -{ - BuildJavaArrayArgs *args = (BuildJavaArrayArgs *)context; - CFPropertyListRef propkey = (CFPropertyListRef)key; - CFStringRef cfString = NULL; - JNIEnv *env = args->env; - - if ((*env)->ExceptionOccurred(env)) return; // already failed - - cfString = copyToCFString(env, propkey); - if ((*env)->ExceptionOccurred(env)) { - // memory error in copyToCFString - } else if (!cfString) { - // bogus value type in prefs file - no Java errors available - } else if (args->allowSlash != CFStringHasSuffix(cfString, CFSTR("/"))) { - // wrong suffix - ignore - } else { - // good cfString - jstring javaString; - if (args->allowSlash) { - CFRange range = CFRangeMake(0, CFStringGetLength(cfString) - 1); - CFStringRef s = CFStringCreateWithSubstring(NULL, cfString, range); - CFRelease(cfString); - cfString = s; - } - if (CFStringGetLength(cfString) <= 0) goto bad; // ignore empty - javaString = toJavaString(env, cfString); - if ((*env)->ExceptionOccurred(env)) goto bad; - (*env)->SetObjectArrayElement(env, args->result,args->used,javaString); - if ((*env)->ExceptionOccurred(env)) goto bad; - args->used++; - } - - bad: - if (cfString) CFRelease(cfString); -} - - -static jarray getStringsForNode(JNIEnv *env, jobject klass, jobject jpath, - jobject jname, jlong juser, jlong jhost, - Boolean allowSlash) -{ - CFStringRef path = toCF(env, jpath); - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - CFDictionaryRef node; - jarray result = NULL; - CFIndex count; - - if (!path || !name) goto badparams; - - node = copyNodeIfPresent(path, name, user, host); - if (!node) { - result = createJavaStringArray(env, 0); - } else { - count = CFDictionaryGetCount(node); - result = createJavaStringArray(env, count); - if (result) { - BuildJavaArrayArgs args; - args.result = result; - args.env = env; - args.used = 0; - args.allowSlash = allowSlash; - CFDictionaryApplyFunction(node, BuildJavaArrayFn, &args); - if (!(*env)->ExceptionOccurred(env)) { - // array construction succeeded - if (args.used < count) { - // finished array is smaller than expected. - // Make a new array of precisely the right size. - jarray newresult = createJavaStringArray(env, args.used); - if (newresult) { - JVM_ArrayCopy(env,0, result,0, newresult,0, args.used); - result = newresult; - } - } - } - } - - CFRelease(node); - } - - badparams: - if (path) CFRelease(path); - if (name) CFRelease(name); - - return result; -} - - -JNIEXPORT jarray JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_getKeysForNode -(JNIEnv *env, jobject klass, jobject jpath, - jobject jname, jlong juser, jlong jhost) -{ - return getStringsForNode(env, klass, jpath, jname, juser, jhost, false); -} - -JNIEXPORT jarray JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_getChildrenForNode -(JNIEnv *env, jobject klass, jobject jpath, - jobject jname, jlong juser, jlong jhost) -{ - return getStringsForNode(env, klass, jpath, jname, juser, jhost, true); -} - - -// Returns false on error instead of throwing. -JNIEXPORT jboolean JNICALL -Java_java_util_prefs_MacOSXPreferencesFile_synchronize -(JNIEnv *env, jobject klass, - jstring jname, jlong juser, jlong jhost) -{ - CFStringRef name = toCF(env, jname); - CFStringRef user = (CFStringRef)jlong_to_ptr(juser); - CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); - jboolean result = 0; - - if (name) { - result = CFPreferencesSynchronize(name, user, host); - CFRelease(name); - } - - return result; -} --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/macosx/native/java/util/prefs/MacOSXPreferencesFile.m 2014-02-09 17:05:58.521428661 +0000 @@ -0,0 +1,999 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + Hierarchical storage layout: + + + / + + foo + /foo's value + foo/ + + bar + /foo/bar's value + + + + + Java pref nodes are stored in several different files. Pref nodes + with at least three components in the node name (e.g. /com/MyCompany/MyApp/) + are stored in a CF prefs file with the first three components as the name. + This way, all preferences for MyApp end up in com.MyCompany.MyApp.plist . + Pref nodes with shorter names are stored in com.apple.java.util.prefs.plist + + The filesystem is assumed to be case-insensitive (like HFS+). + Java pref node names are case-sensitive. If two pref node names differ + only in case, they may end up in the same pref file. This is ok + because the CF keys identifying the node span the entire absolute path + to the node and are case-sensitive. + + Java node names may contain '.' . When mapping to the CF file name, + these dots are left as-is, even though '/' is mapped to '.' . + This is ok because the CF key contains the correct node name. +*/ + + + +#include + +#include "jni_util.h" +#include "jlong.h" +#include "jvm.h" + + +// Throw an OutOfMemoryError with the given message. +static void throwOutOfMemoryError(JNIEnv *env, const char *msg) +{ + static jclass exceptionClass = NULL; + jclass c; + + if (exceptionClass) { + c = exceptionClass; + } else { + c = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); + if ((*env)->ExceptionOccurred(env)) return; + exceptionClass = (*env)->NewGlobalRef(env, c); + } + + (*env)->ThrowNew(env, c, msg); +} + + +// throwIfNull macro +// If var is NULL, throw an OutOfMemoryError and goto badvar. +// var must be a variable. env must be the current JNIEnv. +// fixme throw BackingStoreExceptions sometimes? +#define throwIfNull(var, msg) \ + do { \ + if (var == NULL) { \ + throwOutOfMemoryError(env, msg); \ + goto bad##var; \ + } \ + } while (0) + + +// Converts CFNumber, CFBoolean, CFString to CFString +// returns NULL if value is of some other type +// throws and returns NULL on memory error +// result must be released (even if value was already a CFStringRef) +// value must not be null +static CFStringRef copyToCFString(JNIEnv *env, CFTypeRef value) +{ + CFStringRef result; + CFTypeID type; + + type = CFGetTypeID(value); + + if (type == CFStringGetTypeID()) { + result = (CFStringRef)CFRetain(value); + } + else if (type == CFBooleanGetTypeID()) { + // Java Preferences API expects "true" and "false" for boolean values. + result = CFStringCreateCopy(NULL, (value == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false")); + throwIfNull(result, "copyToCFString failed"); + } + else if (type == CFNumberGetTypeID()) { + CFNumberRef number = (CFNumberRef) value; + if (CFNumberIsFloatType(number)) { + double d; + CFNumberGetValue(number, kCFNumberDoubleType, &d); + result = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), d); + throwIfNull(result, "copyToCFString failed"); + } + else { + long l; + CFNumberGetValue(number, kCFNumberLongType, &l); + result = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), l); + throwIfNull(result, "copyToCFString failed"); + } + } + else { + // unknown type - return NULL + result = NULL; + } + + badresult: + return result; +} + + +// Create a Java string from the given CF string. +// returns NULL if cfString is NULL +// throws and returns NULL on memory error +static jstring toJavaString(JNIEnv *env, CFStringRef cfString) +{ + if (cfString == NULL) { + return NULL; + } else { + jstring javaString = NULL; + + CFIndex length = CFStringGetLength(cfString); + const UniChar *constchars = CFStringGetCharactersPtr(cfString); + if (constchars) { + javaString = (*env)->NewString(env, constchars, length); + } else { + UniChar *chars = malloc(length * sizeof(UniChar)); + throwIfNull(chars, "toJavaString failed"); + CFStringGetCharacters(cfString, CFRangeMake(0, length), chars); + javaString = (*env)->NewString(env, chars, length); + free(chars); + } + badchars: + return javaString; + } +} + + + +// Create a CF string from the given Java string. +// returns NULL if javaString is NULL +// throws and returns NULL on memory error +static CFStringRef toCF(JNIEnv *env, jstring javaString) +{ + if (javaString == NULL) { + return NULL; + } else { + CFStringRef result = NULL; + jsize length = (*env)->GetStringLength(env, javaString); + const jchar *chars = (*env)->GetStringChars(env, javaString, NULL); + throwIfNull(chars, "toCF failed"); + result = + CFStringCreateWithCharacters(NULL, (const UniChar *)chars, length); + (*env)->ReleaseStringChars(env, javaString, chars); + throwIfNull(result, "toCF failed"); + badchars: + badresult: + return result; + } +} + + +// Create an empty Java string array of the given size. +// Throws and returns NULL on error. +static jarray createJavaStringArray(JNIEnv *env, CFIndex count) +{ + static jclass stringClass = NULL; + jclass c; + + if (stringClass) { + c = stringClass; + } else { + c = (*env)->FindClass(env, "java/lang/String"); + if ((*env)->ExceptionOccurred(env)) return NULL; + stringClass = (*env)->NewGlobalRef(env, c); + } + + return (*env)->NewObjectArray(env, count, c, NULL); // AWT_THREADING Safe (known object) +} + + +// Java accessors for CF constants. +JNIEXPORT jlong JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_currentUser(JNIEnv *env, + jobject klass) +{ + return ptr_to_jlong(kCFPreferencesCurrentUser); +} + +JNIEXPORT jlong JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_anyUser(JNIEnv *env, jobject klass) +{ + return ptr_to_jlong(kCFPreferencesAnyUser); +} + +JNIEXPORT jlong JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_currentHost(JNIEnv *env, + jobject klass) +{ + return ptr_to_jlong(kCFPreferencesCurrentHost); +} + +JNIEXPORT jlong JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_anyHost(JNIEnv *env, jobject klass) +{ + return ptr_to_jlong(kCFPreferencesAnyHost); +} + + +// Create an empty node. +// Does not store the node in any prefs file. +// returns NULL on memory error +static CFMutableDictionaryRef createEmptyNode(void) +{ + return CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); +} + + +// Create a string that consists of path minus its last component. +// path must end with '/' +// The result will end in '/' (unless path itself is '/') +static CFStringRef copyParentOf(CFStringRef path) +{ + CFRange searchRange; + CFRange slashRange; + CFRange parentRange; + Boolean found; + + searchRange = CFRangeMake(0, CFStringGetLength(path) - 1); + found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, + kCFCompareBackwards, &slashRange); + if (!found) return CFSTR(""); + parentRange = CFRangeMake(0, slashRange.location + 1); // include '/' + return CFStringCreateWithSubstring(NULL, path, parentRange); +} + + +// Create a string that consists of path's last component. +// path must end with '/' +// The result will end in '/'. +// The result will not start with '/' (unless path itself is '/') +static CFStringRef copyChildOf(CFStringRef path) +{ + CFRange searchRange; + CFRange slashRange; + CFRange childRange; + Boolean found; + CFIndex length = CFStringGetLength(path); + + searchRange = CFRangeMake(0, length - 1); + found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, + kCFCompareBackwards, &slashRange); + if (!found) return CFSTR(""); + childRange = CFRangeMake(slashRange.location + 1, + length - slashRange.location - 1); // skip '/' + return CFStringCreateWithSubstring(NULL, path, childRange); +} + + +// Return the first three components of path, with leading and trailing '/'. +// If path does not have three components, return NULL. +// path must begin and end in '/' +static CFStringRef copyFirstThreeComponentsOf(CFStringRef path) +{ + CFRange searchRange; + CFRange slashRange; + CFRange prefixRange; + CFStringRef prefix; + Boolean found; + CFIndex length = CFStringGetLength(path); + + searchRange = CFRangeMake(1, length - 1); // skip leading '/' + found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, + &slashRange); + if (!found) return NULL; // no second slash! + + searchRange = CFRangeMake(slashRange.location + 1, + length - slashRange.location - 1); + found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, + &slashRange); + if (!found) return NULL; // no third slash! + + searchRange = CFRangeMake(slashRange.location + 1, + length - slashRange.location - 1); + found = CFStringFindWithOptions(path, CFSTR("/"), searchRange, 0, + &slashRange); + if (!found) return NULL; // no fourth slash! + + prefixRange = CFRangeMake(0, slashRange.location + 1); // keep last '/' + prefix = CFStringCreateWithSubstring(NULL, path, prefixRange); + + return prefix; +} + + +// Copy the CFPreferences key and value at the base of path's tree. +// path must end in '/' +// topKey or topValue may be NULL +// Returns NULL on error or if there is no tree for path in this file. +static void copyTreeForPath(CFStringRef path, CFStringRef name, + CFStringRef user, CFStringRef host, + CFStringRef *topKey, CFDictionaryRef *topValue) +{ + CFStringRef key; + CFPropertyListRef value; + + if (topKey) *topKey = NULL; + if (topValue) *topValue = NULL; + + if (CFEqual(name, CFSTR("com.apple.java.util.prefs"))) { + // Top-level file. Only key "/" is an acceptable root. + key = (CFStringRef) CFRetain(CFSTR("/")); + } else { + // Second-level file. Key must be the first three components of path. + key = copyFirstThreeComponentsOf(path); + if (!key) return; + } + + value = CFPreferencesCopyValue(key, name, user, host); + if (value) { + if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { + // (key, value) is acceptable + if (topKey) *topKey = (CFStringRef)CFRetain(key); + if (topValue) *topValue = (CFDictionaryRef)CFRetain(value); + } + CFRelease(value); + } + CFRelease(key); +} + + +// Find the node for path in the given tree. +// Returns NULL on error or if path doesn't have a node in this tree. +// path must end in '/' +static CFDictionaryRef copyNodeInTree(CFStringRef path, CFStringRef topKey, + CFDictionaryRef topValue) +{ + CFMutableStringRef p; + CFDictionaryRef result = NULL; + + p = CFStringCreateMutableCopy(NULL, 0, path); + if (!p) return NULL; + CFStringDelete(p, CFRangeMake(0, CFStringGetLength(topKey))); + result = topValue; + + while (CFStringGetLength(p) > 0) { + CFDictionaryRef child; + CFStringRef part = NULL; + CFRange slashRange = CFStringFind(p, CFSTR("/"), 0); + // guaranteed to succeed because path must end in '/' + CFRange partRange = CFRangeMake(0, slashRange.location + 1); + part = CFStringCreateWithSubstring(NULL, p, partRange); + if (!part) { result = NULL; break; } + CFStringDelete(p, partRange); + + child = CFDictionaryGetValue(result, part); + CFRelease(part); + if (child && CFGetTypeID(child) == CFDictionaryGetTypeID()) { + // continue search + result = child; + } else { + // didn't find target node + result = NULL; + break; + } + } + + CFRelease(p); + if (result) return (CFDictionaryRef)CFRetain(result); + else return NULL; +} + + +// Return a retained copy of the node at path from the given file. +// path must end in '/' +// returns NULL if node doesn't exist. +// returns NULL if the value for key "path" isn't a valid node. +static CFDictionaryRef copyNodeIfPresent(CFStringRef path, CFStringRef name, + CFStringRef user, CFStringRef host) +{ + CFStringRef topKey; + CFDictionaryRef topValue; + CFDictionaryRef result; + + copyTreeForPath(path, name, user, host, &topKey, &topValue); + if (!topKey) return NULL; + + result = copyNodeInTree(path, topKey, topValue); + + CFRelease(topKey); + if (topValue) CFRelease(topValue); + return result; +} + + +// Create a new tree that would store path in the given file. +// Only the root of the tree is created, not all of the links leading to path. +// returns NULL on error +static void createTreeForPath(CFStringRef path, CFStringRef name, + CFStringRef user, CFStringRef host, + CFStringRef *outTopKey, + CFMutableDictionaryRef *outTopValue) +{ + *outTopKey = NULL; + *outTopValue = NULL; + + // if name is "com.apple.java.util.prefs" then create tree "/" + // else create tree "/foo/bar/baz/" + // "com.apple.java.util.prefs.plist" is also in MacOSXPreferences.java + if (CFEqual(name, CFSTR("com.apple.java.util.prefs"))) { + *outTopKey = CFSTR("/"); + *outTopValue = createEmptyNode(); + } else { + CFStringRef prefix = copyFirstThreeComponentsOf(path); + if (prefix) { + *outTopKey = prefix; + *outTopValue = createEmptyNode(); + } + } +} + + +// Return a mutable copy of the tree containing path and the dict for +// path itself. *outTopKey and *outTopValue can be used to write the +// modified tree back to the prefs file. +// *outTopKey and *outTopValue must be released iff the actual return +// value is not NULL. +static CFMutableDictionaryRef +copyMutableNode(CFStringRef path, CFStringRef name, + CFStringRef user, CFStringRef host, + CFStringRef *outTopKey, + CFMutableDictionaryRef *outTopValue) +{ + CFStringRef topKey = NULL; + CFDictionaryRef oldTopValue = NULL; + CFMutableDictionaryRef topValue; + CFMutableDictionaryRef result = NULL; + CFMutableStringRef p; + + if (outTopKey) *outTopKey = NULL; + if (outTopValue) *outTopValue = NULL; + + copyTreeForPath(path, name, user, host, &topKey, &oldTopValue); + if (!topKey) { + createTreeForPath(path, name, user, host, &topKey, &topValue); + } else { + topValue = (CFMutableDictionaryRef) + CFPropertyListCreateDeepCopy(NULL, (CFPropertyListRef)oldTopValue, + kCFPropertyListMutableContainers); + } + if (!topValue) goto badtopValue; + + p = CFStringCreateMutableCopy(NULL, 0, path); + if (!p) goto badp; + CFStringDelete(p, CFRangeMake(0, CFStringGetLength(topKey))); + result = topValue; + + while (CFStringGetLength(p) > 0) { + CFMutableDictionaryRef child; + CFStringRef part = NULL; + CFRange slashRange = CFStringFind(p, CFSTR("/"), 0); + // guaranteed to succeed because path must end in '/' + CFRange partRange = CFRangeMake(0, slashRange.location + 1); + part = CFStringCreateWithSubstring(NULL, p, partRange); + if (!part) { result = NULL; break; } + CFStringDelete(p, partRange); + + child = (CFMutableDictionaryRef)CFDictionaryGetValue(result, part); + if (child && CFGetTypeID(child) == CFDictionaryGetTypeID()) { + // continue search + result = child; + } else { + // didn't find target node - add it and continue + child = createEmptyNode(); + if (!child) { CFRelease(part); result = NULL; break; } + CFDictionaryAddValue(result, part, child); + result = child; + } + CFRelease(part); + } + + if (result) { + *outTopKey = (CFStringRef)CFRetain(topKey); + *outTopValue = (CFMutableDictionaryRef)CFRetain(topValue); + CFRetain(result); + } + + CFRelease(p); + badp: + CFRelease(topValue); + badtopValue: + if (topKey) CFRelease(topKey); + if (oldTopValue) CFRelease(oldTopValue); + return result; +} + + +JNIEXPORT jboolean JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_addNode +(JNIEnv *env, jobject klass, jobject jpath, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFDictionaryRef node = NULL; + jboolean neededNewNode = false; + + if (!path || !name) goto badparams; + + node = copyNodeIfPresent(path, name, user, host); + + if (node) { + neededNewNode = false; + CFRelease(node); + } else { + CFStringRef topKey = NULL; + CFMutableDictionaryRef topValue = NULL; + + neededNewNode = true; + + // copyMutableNode creates the node if necessary + node = copyMutableNode(path, name, user, host, &topKey, &topValue); + throwIfNull(node, "copyMutableNode failed"); + + CFPreferencesSetValue(topKey, topValue, name, user, host); + + CFRelease(node); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + } + + badnode: + badparams: + if (path) CFRelease(path); + if (name) CFRelease(name); + + return neededNewNode; +} + + +JNIEXPORT void JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_removeNode +(JNIEnv *env, jobject klass, jobject jpath, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFStringRef parentName; + CFStringRef childName; + CFDictionaryRef constParent; + + if (!path || !name) goto badparams; + + parentName = copyParentOf(path); + throwIfNull(parentName, "copyParentOf failed"); + childName = copyChildOf(path); + throwIfNull(childName, "copyChildOf failed"); + + // root node is not allowed to be removed, so parentName is never empty + + constParent = copyNodeIfPresent(parentName, name, user, host); + if (constParent && CFDictionaryContainsKey(constParent, childName)) { + CFStringRef topKey; + CFMutableDictionaryRef topValue; + CFMutableDictionaryRef parent; + + parent = copyMutableNode(parentName, name, user, host, + &topKey, &topValue); + throwIfNull(parent, "copyMutableNode failed"); + + CFDictionaryRemoveValue(parent, childName); + CFPreferencesSetValue(topKey, topValue, name, user, host); + + CFRelease(parent); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + } else { + // might be trying to remove the root itself in a non-root file + CFStringRef topKey; + CFDictionaryRef topValue; + copyTreeForPath(path, name, user, host, &topKey, &topValue); + if (topKey) { + if (CFEqual(topKey, path)) { + CFPreferencesSetValue(topKey, NULL, name, user, host); + } + + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + } + } + + + badparent: + if (constParent) CFRelease(constParent); + CFRelease(childName); + badchildName: + CFRelease(parentName); + badparentName: + badparams: + if (path) CFRelease(path); + if (name) CFRelease(name); +} + + +// child must end with '/' +JNIEXPORT Boolean JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_addChildToNode +(JNIEnv *env, jobject klass, jobject jpath, jobject jchild, + jobject jname, jlong juser, jlong jhost) +{ + // like addNode, but can put a three-level-deep dict into the root file + CFStringRef path = toCF(env, jpath); + CFStringRef child = toCF(env, jchild); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFMutableDictionaryRef parent; + CFDictionaryRef node; + CFStringRef topKey; + CFMutableDictionaryRef topValue; + Boolean beforeAdd = false; + + if (!path || !child || !name) goto badparams; + + node = createEmptyNode(); + throwIfNull(node, "createEmptyNode failed"); + + // 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); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + badparent: + CFRelease(node); + badnode: + badparams: + if (path) CFRelease(path); + if (child) CFRelease(child); + if (name) CFRelease(name); + return beforeAdd; +} + + +JNIEXPORT void JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_removeChildFromNode +(JNIEnv *env, jobject klass, jobject jpath, jobject jchild, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef child = toCF(env, jchild); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFDictionaryRef constParent; + + if (!path || !child || !name) goto badparams; + + constParent = copyNodeIfPresent(path, name, user, host); + if (constParent && CFDictionaryContainsKey(constParent, child)) { + CFStringRef topKey; + CFMutableDictionaryRef topValue; + CFMutableDictionaryRef parent; + + parent = copyMutableNode(path, name, user, host, &topKey, &topValue); + throwIfNull(parent, "copyMutableNode failed"); + + CFDictionaryRemoveValue(parent, child); + CFPreferencesSetValue(topKey, topValue, name, user, host); + + CFRelease(parent); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + } + + badparent: + if (constParent) CFRelease(constParent); + badparams: + if (path) CFRelease(path); + if (child) CFRelease(child); + if (name) CFRelease(name); +} + + + +JNIEXPORT void JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_addKeyToNode +(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, jobject jvalue, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef key = toCF(env, jkey); + CFStringRef value = toCF(env, jvalue); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFMutableDictionaryRef node = NULL; + CFStringRef topKey; + CFMutableDictionaryRef topValue; + + if (!path || !key || !value || !name) goto badparams; + + // fixme optimization: check whether old value and new value are identical + node = copyMutableNode(path, name, user, host, &topKey, &topValue); + throwIfNull(node, "copyMutableNode failed"); + + CFDictionarySetValue(node, key, value); + CFPreferencesSetValue(topKey, topValue, name, user, host); + + CFRelease(node); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + + badnode: + badparams: + if (path) CFRelease(path); + if (key) CFRelease(key); + if (value) CFRelease(value); + if (name) CFRelease(name); +} + + +JNIEXPORT void JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_removeKeyFromNode +(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef key = toCF(env, jkey); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFDictionaryRef constNode; + + if (!path || !key || !name) goto badparams; + + constNode = copyNodeIfPresent(path, name, user, host); + if (constNode && CFDictionaryContainsKey(constNode, key)) { + CFStringRef topKey; + CFMutableDictionaryRef topValue; + CFMutableDictionaryRef node; + + node = copyMutableNode(path, name, user, host, &topKey, &topValue); + throwIfNull(node, "copyMutableNode failed"); + + CFDictionaryRemoveValue(node, key); + CFPreferencesSetValue(topKey, topValue, name, user, host); + + CFRelease(node); + if (topKey) CFRelease(topKey); + if (topValue) CFRelease(topValue); + } + + badnode: + if (constNode) CFRelease(constNode); + badparams: + if (path) CFRelease(path); + if (key) CFRelease(key); + if (name) CFRelease(name); +} + + +// path must end in '/' +JNIEXPORT jstring JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_getKeyFromNode +(JNIEnv *env, jobject klass, jobject jpath, jobject jkey, + jobject jname, jlong juser, jlong jhost) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef key = toCF(env, jkey); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFPropertyListRef value; + CFDictionaryRef node; + jstring result = NULL; + + if (!path || !key || !name) goto badparams; + + node = copyNodeIfPresent(path, name, user, host); + if (node) { + value = (CFPropertyListRef)CFDictionaryGetValue(node, key); + if (!value) { + // key doesn't exist, or other error - no Java errors available + result = NULL; + } else { + CFStringRef cfString = copyToCFString(env, value); + if ((*env)->ExceptionOccurred(env)) { + // memory error in copyToCFString + result = NULL; + } else if (cfString == NULL) { + // bogus value type in prefs file - no Java errors available + result = NULL; + } else { + // good cfString + result = toJavaString(env, cfString); + CFRelease(cfString); + } + } + CFRelease(node); + } + + badparams: + if (path) CFRelease(path); + if (key) CFRelease(key); + if (name) CFRelease(name); + + return result; +} + + +typedef struct { + jarray result; + JNIEnv *env; + CFIndex used; + Boolean allowSlash; +} BuildJavaArrayArgs; + +// CFDictionary applier function that builds an array of Java strings +// from a CFDictionary of CFPropertyListRefs. +// If args->allowSlash, only strings that end in '/' are added to the array, +// with the slash removed. Otherwise, only strings that do not end in '/' +// are added. +// args->result must already exist and be large enough to hold all +// strings from the dictionary. +// After complete application, args->result may not be full because +// some of the dictionary values weren't convertible to string. In +// this case, args->used will be the count of used elements. +static void BuildJavaArrayFn(const void *key, const void *value, void *context) +{ + BuildJavaArrayArgs *args = (BuildJavaArrayArgs *)context; + CFPropertyListRef propkey = (CFPropertyListRef)key; + CFStringRef cfString = NULL; + JNIEnv *env = args->env; + + if ((*env)->ExceptionOccurred(env)) return; // already failed + + cfString = copyToCFString(env, propkey); + if ((*env)->ExceptionOccurred(env)) { + // memory error in copyToCFString + } else if (!cfString) { + // bogus value type in prefs file - no Java errors available + } else if (args->allowSlash != CFStringHasSuffix(cfString, CFSTR("/"))) { + // wrong suffix - ignore + } else { + // good cfString + jstring javaString; + if (args->allowSlash) { + CFRange range = CFRangeMake(0, CFStringGetLength(cfString) - 1); + CFStringRef s = CFStringCreateWithSubstring(NULL, cfString, range); + CFRelease(cfString); + cfString = s; + } + if (CFStringGetLength(cfString) <= 0) goto bad; // ignore empty + javaString = toJavaString(env, cfString); + if ((*env)->ExceptionOccurred(env)) goto bad; + (*env)->SetObjectArrayElement(env, args->result,args->used,javaString); + if ((*env)->ExceptionOccurred(env)) goto bad; + args->used++; + } + + bad: + if (cfString) CFRelease(cfString); +} + + +static jarray getStringsForNode(JNIEnv *env, jobject klass, jobject jpath, + jobject jname, jlong juser, jlong jhost, + Boolean allowSlash) +{ + CFStringRef path = toCF(env, jpath); + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + CFDictionaryRef node; + jarray result = NULL; + CFIndex count; + + if (!path || !name) goto badparams; + + node = copyNodeIfPresent(path, name, user, host); + if (!node) { + result = createJavaStringArray(env, 0); + } else { + count = CFDictionaryGetCount(node); + result = createJavaStringArray(env, count); + if (result) { + BuildJavaArrayArgs args; + args.result = result; + args.env = env; + args.used = 0; + args.allowSlash = allowSlash; + CFDictionaryApplyFunction(node, BuildJavaArrayFn, &args); + if (!(*env)->ExceptionOccurred(env)) { + // array construction succeeded + if (args.used < count) { + // finished array is smaller than expected. + // Make a new array of precisely the right size. + jarray newresult = createJavaStringArray(env, args.used); + if (newresult) { + JVM_ArrayCopy(env,0, result,0, newresult,0, args.used); + result = newresult; + } + } + } + } + + CFRelease(node); + } + + badparams: + if (path) CFRelease(path); + if (name) CFRelease(name); + + return result; +} + + +JNIEXPORT jarray JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_getKeysForNode +(JNIEnv *env, jobject klass, jobject jpath, + jobject jname, jlong juser, jlong jhost) +{ + return getStringsForNode(env, klass, jpath, jname, juser, jhost, false); +} + +JNIEXPORT jarray JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_getChildrenForNode +(JNIEnv *env, jobject klass, jobject jpath, + jobject jname, jlong juser, jlong jhost) +{ + return getStringsForNode(env, klass, jpath, jname, juser, jhost, true); +} + + +// Returns false on error instead of throwing. +JNIEXPORT jboolean JNICALL +Java_java_util_prefs_MacOSXPreferencesFile_synchronize +(JNIEnv *env, jobject klass, + jstring jname, jlong juser, jlong jhost) +{ + CFStringRef name = toCF(env, jname); + CFStringRef user = (CFStringRef)jlong_to_ptr(juser); + CFStringRef host = (CFStringRef)jlong_to_ptr(jhost); + jboolean result = 0; + + if (name) { + result = CFPreferencesSynchronize(name, user, host); + CFRelease(name); + } + + return result; +} --- old/src/macosx/native/java/util/SCDynamicStoreConfig.m 2014-02-09 17:05:59.421428640 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#import -#import -#import - - -@interface JNFVectorCoercion : NSObject { } -@end - -@implementation JNFVectorCoercion - -- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { - static JNF_CLASS_CACHE(jc_Vector, "java/util/Vector"); - static JNF_CTOR_CACHE(jm_Vector_ctor, jc_Vector, "(I)V"); - static JNF_MEMBER_CACHE(jm_Vector_add, jc_Vector, "add", "(Ljava/lang/Object;)Z"); - - NSArray *nsArray = (NSArray *)obj; - jobject javaArray = JNFNewObject(env, jm_Vector_ctor, (jint)[nsArray count]); - - for (id obj in nsArray) { - jobject jobj = [coercer coerceNSObject:obj withEnv:env usingCoercer:coercer]; - JNFCallBooleanMethod(env, javaArray, jm_Vector_add, jobj); - if (jobj != NULL) (*env)->DeleteLocalRef(env, jobj); - } - - return javaArray; -} - -- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { - return nil; -} - -@end - - -@interface JNFHashtableCoercion : NSObject { } -@end - -@implementation JNFHashtableCoercion - -- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { - static JNF_CLASS_CACHE(jc_Hashtable, "java/util/Hashtable"); - static JNF_CTOR_CACHE(jm_Hashtable_ctor, jc_Hashtable, "()V"); - static JNF_MEMBER_CACHE(jm_Hashtable_put, jc_Hashtable, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - - NSDictionary *nsDict = (NSDictionary *)obj; - NSEnumerator *keyEnum = [nsDict keyEnumerator]; - - jobject jHashTable = JNFNewObject(env, jm_Hashtable_ctor); - - id key = nil; - while ((key = [keyEnum nextObject]) != nil) { - jobject jkey = [coercer coerceNSObject:key withEnv:env usingCoercer:coercer]; - - id value = [nsDict objectForKey:key]; - jobject jvalue = [coercer coerceNSObject:value withEnv:env usingCoercer:coercer]; - - JNFCallObjectMethod(env, jHashTable, jm_Hashtable_put, jkey, jvalue); - - if (jkey != NULL) (*env)->DeleteLocalRef(env, jkey); - if (jvalue != NULL) (*env)->DeleteLocalRef(env, jvalue); - } - - return jHashTable; -} - -- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { - return nil; -} - -@end - - - -NSDictionary *realmConfigsForRealms(SCDynamicStoreRef store, NSArray *realms) { - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - - for (NSString *realm in realms) { - CFTypeRef realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:@"Kerberos:%@", realm]); - - if (CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) { - return nil; - } - - [dict setObject:(NSArray *)realmInfo forKey:realm]; - CFRelease(realmInfo); - } - - return dict; -} - - -#define KERBEROS_DEFAULT_REALMS @"Kerberos-Default-Realms" -#define KERBEROS_DEFAULT_REALM_MAPPINGS @"Kerberos-Domain-Realm-Mappings" - -void _SCDynamicStoreCallBack(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) { - NSArray *keys = (NSArray *)changedKeys; - if ([keys count] == 0) return; - if (![keys containsObject:KERBEROS_DEFAULT_REALMS] && ![keys containsObject:KERBEROS_DEFAULT_REALM_MAPPINGS]) return; - - JNFPerformEnvBlock(JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon, ^(JNIEnv *env) { - static JNF_CLASS_CACHE(jc_Config, "sun/security/krb5/Config"); - static JNF_STATIC_MEMBER_CACHE(jm_Config_refresh, jc_Config, "refresh", "()V"); - JNFCallStaticVoidMethod(env, jm_Config_refresh); - }); -} - -/* - * Class: sun_security_krb5_SCDynamicStoreConfig - * Method: installNotificationCallback - */ -JNIEXPORT void JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_installNotificationCallback(JNIEnv *env, jclass klass) { - -JNF_COCOA_ENTER(env); - - SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java"), _SCDynamicStoreCallBack, NULL); - if (store == NULL) { - return; - } - - NSArray *keys = [NSArray arrayWithObjects:KERBEROS_DEFAULT_REALMS, KERBEROS_DEFAULT_REALM_MAPPINGS, nil]; - SCDynamicStoreSetNotificationKeys(store, (CFArrayRef) keys, NULL); - - CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); - if (rls != NULL) { - CFRunLoopAddSource(CFRunLoopGetMain(), rls, kCFRunLoopDefaultMode); - CFRelease(rls); - } - - CFRelease(store); - -JNF_COCOA_EXIT(env); - -} - -/* - * Class: sun_security_krb5_SCDynamicStoreConfig - * Method: getKerberosConfig - * Signature: ()Ljava/util/Hashtable; - */ -JNIEXPORT jobject JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_getKerberosConfig(JNIEnv *env, jclass klass) { - jobject jHashTable = NULL; - -JNF_COCOA_ENTER(env); - - SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java-kerberos"), NULL, NULL); - if (store == NULL) { - return NULL; - } - - CFTypeRef realms = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALMS); - if (realms == NULL || CFGetTypeID(realms) != CFArrayGetTypeID()) { - if (realms) CFRelease(realms); - CFRelease(store); - return NULL; - } - - CFTypeRef realmMappings = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALM_MAPPINGS); - - if (realmMappings == NULL || CFGetTypeID(realmMappings) != CFArrayGetTypeID()) { - if (realmMappings) CFRelease(realmMappings); - CFRelease(realms); - CFRelease(store); - return NULL; - } - - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - - if (CFArrayGetCount(realms) > 0) { - NSDictionary *defaultRealmsDict = [NSDictionary dictionaryWithObject:[(NSArray *)realms objectAtIndex:0] forKey:@"default_realm"]; - [dict setObject:defaultRealmsDict forKey:@"libdefaults"]; - - NSDictionary *realmConfigs = realmConfigsForRealms(store, (NSArray *)realms); - [dict setObject:realmConfigs forKey:@"realms"]; - } - CFRelease(realms); - CFRelease(store); - - if (CFArrayGetCount(realmMappings) > 0) { - [dict setObject:[(NSArray *)realmMappings objectAtIndex:0] forKey:@"domain_realm"]; - } - CFRelease(realmMappings); - - - // create and load a coercer with all of the different coercions to convert each type of object - JNFTypeCoercer *coercer = [[[JNFTypeCoercer alloc] init] autorelease]; - [JNFDefaultCoercions addStringCoercionTo:coercer]; - [JNFDefaultCoercions addNumberCoercionTo:coercer]; - [coercer addCoercion:[[[JNFHashtableCoercion alloc] init] autorelease] forNSClass:[NSDictionary class] javaClass:@"java/util/Map"]; - [coercer addCoercion:[[[JNFVectorCoercion alloc] init] autorelease] forNSClass:[NSArray class] javaClass:@"java/util/List"]; - - // convert Cocoa graph to Java graph - jHashTable = [coercer coerceNSObject:dict withEnv:env]; - -JNF_COCOA_EXIT(env); - - return jHashTable; -} --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/macosx/native/sun/security/krb5/SCDynamicStoreConfig.m 2014-02-09 17:05:59.077428648 +0000 @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#import +#import +#import + + +@interface JNFVectorCoercion : NSObject { } +@end + +@implementation JNFVectorCoercion + +- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { + static JNF_CLASS_CACHE(jc_Vector, "java/util/Vector"); + static JNF_CTOR_CACHE(jm_Vector_ctor, jc_Vector, "(I)V"); + static JNF_MEMBER_CACHE(jm_Vector_add, jc_Vector, "add", "(Ljava/lang/Object;)Z"); + + NSArray *nsArray = (NSArray *)obj; + jobject javaArray = JNFNewObject(env, jm_Vector_ctor, (jint)[nsArray count]); + + for (id obj in nsArray) { + jobject jobj = [coercer coerceNSObject:obj withEnv:env usingCoercer:coercer]; + JNFCallBooleanMethod(env, javaArray, jm_Vector_add, jobj); + if (jobj != NULL) (*env)->DeleteLocalRef(env, jobj); + } + + return javaArray; +} + +- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { + return nil; +} + +@end + + +@interface JNFHashtableCoercion : NSObject { } +@end + +@implementation JNFHashtableCoercion + +- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { + static JNF_CLASS_CACHE(jc_Hashtable, "java/util/Hashtable"); + static JNF_CTOR_CACHE(jm_Hashtable_ctor, jc_Hashtable, "()V"); + static JNF_MEMBER_CACHE(jm_Hashtable_put, jc_Hashtable, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + NSDictionary *nsDict = (NSDictionary *)obj; + NSEnumerator *keyEnum = [nsDict keyEnumerator]; + + jobject jHashTable = JNFNewObject(env, jm_Hashtable_ctor); + + id key = nil; + while ((key = [keyEnum nextObject]) != nil) { + jobject jkey = [coercer coerceNSObject:key withEnv:env usingCoercer:coercer]; + + id value = [nsDict objectForKey:key]; + jobject jvalue = [coercer coerceNSObject:value withEnv:env usingCoercer:coercer]; + + JNFCallObjectMethod(env, jHashTable, jm_Hashtable_put, jkey, jvalue); + + if (jkey != NULL) (*env)->DeleteLocalRef(env, jkey); + if (jvalue != NULL) (*env)->DeleteLocalRef(env, jvalue); + } + + return jHashTable; +} + +- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer { + return nil; +} + +@end + + + +NSDictionary *realmConfigsForRealms(SCDynamicStoreRef store, NSArray *realms) { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + + for (NSString *realm in realms) { + CFTypeRef realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:@"Kerberos:%@", realm]); + + if (CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) { + return nil; + } + + [dict setObject:(NSArray *)realmInfo forKey:realm]; + CFRelease(realmInfo); + } + + return dict; +} + + +#define KERBEROS_DEFAULT_REALMS @"Kerberos-Default-Realms" +#define KERBEROS_DEFAULT_REALM_MAPPINGS @"Kerberos-Domain-Realm-Mappings" + +void _SCDynamicStoreCallBack(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) { + NSArray *keys = (NSArray *)changedKeys; + if ([keys count] == 0) return; + if (![keys containsObject:KERBEROS_DEFAULT_REALMS] && ![keys containsObject:KERBEROS_DEFAULT_REALM_MAPPINGS]) return; + + JNFPerformEnvBlock(JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon, ^(JNIEnv *env) { + static JNF_CLASS_CACHE(jc_Config, "sun/security/krb5/Config"); + static JNF_STATIC_MEMBER_CACHE(jm_Config_refresh, jc_Config, "refresh", "()V"); + JNFCallStaticVoidMethod(env, jm_Config_refresh); + }); +} + +/* + * Class: sun_security_krb5_SCDynamicStoreConfig + * Method: installNotificationCallback + */ +JNIEXPORT void JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_installNotificationCallback(JNIEnv *env, jclass klass) { + +JNF_COCOA_ENTER(env); + + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java"), _SCDynamicStoreCallBack, NULL); + if (store == NULL) { + return; + } + + NSArray *keys = [NSArray arrayWithObjects:KERBEROS_DEFAULT_REALMS, KERBEROS_DEFAULT_REALM_MAPPINGS, nil]; + SCDynamicStoreSetNotificationKeys(store, (CFArrayRef) keys, NULL); + + CFRunLoopSourceRef rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); + if (rls != NULL) { + CFRunLoopAddSource(CFRunLoopGetMain(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + } + + CFRelease(store); + +JNF_COCOA_EXIT(env); + +} + +/* + * Class: sun_security_krb5_SCDynamicStoreConfig + * Method: getKerberosConfig + * Signature: ()Ljava/util/Hashtable; + */ +JNIEXPORT jobject JNICALL Java_sun_security_krb5_SCDynamicStoreConfig_getKerberosConfig(JNIEnv *env, jclass klass) { + jobject jHashTable = NULL; + +JNF_COCOA_ENTER(env); + + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("java-kerberos"), NULL, NULL); + if (store == NULL) { + return NULL; + } + + CFTypeRef realms = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALMS); + if (realms == NULL || CFGetTypeID(realms) != CFArrayGetTypeID()) { + if (realms) CFRelease(realms); + CFRelease(store); + return NULL; + } + + CFTypeRef realmMappings = SCDynamicStoreCopyValue(store, (CFStringRef) KERBEROS_DEFAULT_REALM_MAPPINGS); + + if (realmMappings == NULL || CFGetTypeID(realmMappings) != CFArrayGetTypeID()) { + if (realmMappings) CFRelease(realmMappings); + CFRelease(realms); + CFRelease(store); + return NULL; + } + + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + + if (CFArrayGetCount(realms) > 0) { + NSDictionary *defaultRealmsDict = [NSDictionary dictionaryWithObject:[(NSArray *)realms objectAtIndex:0] forKey:@"default_realm"]; + [dict setObject:defaultRealmsDict forKey:@"libdefaults"]; + + NSDictionary *realmConfigs = realmConfigsForRealms(store, (NSArray *)realms); + [dict setObject:realmConfigs forKey:@"realms"]; + } + CFRelease(realms); + CFRelease(store); + + if (CFArrayGetCount(realmMappings) > 0) { + [dict setObject:[(NSArray *)realmMappings objectAtIndex:0] forKey:@"domain_realm"]; + } + CFRelease(realmMappings); + + + // create and load a coercer with all of the different coercions to convert each type of object + JNFTypeCoercer *coercer = [[[JNFTypeCoercer alloc] init] autorelease]; + [JNFDefaultCoercions addStringCoercionTo:coercer]; + [JNFDefaultCoercions addNumberCoercionTo:coercer]; + [coercer addCoercion:[[[JNFHashtableCoercion alloc] init] autorelease] forNSClass:[NSDictionary class] javaClass:@"java/util/Map"]; + [coercer addCoercion:[[[JNFVectorCoercion alloc] init] autorelease] forNSClass:[NSArray class] javaClass:@"java/util/List"]; + + // convert Cocoa graph to Java graph + jHashTable = [coercer coerceNSObject:dict withEnv:env]; + +JNF_COCOA_EXIT(env); + + return jHashTable; +} --- old/src/solaris/native/java/util/FileSystemPreferences.c 2014-02-09 17:05:59.993428627 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris/Linux platform specific code to support the Prefs API. - */ - -#include -#include -#include -#include -#include -#include -#include "jni_util.h" - -JNIEXPORT jint JNICALL -Java_java_util_prefs_FileSystemPreferences_chmod(JNIEnv *env, - jclass thisclass, jstring java_fname, jint permission) { - const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL); - int result = -1; - if (fname) { - result = chmod(fname, permission); - if (result != 0) - result = errno; - JNU_ReleaseStringPlatformChars(env, java_fname, fname); - } - return (jint) result; -} - -#if defined(_ALLBSD_SOURCE) -typedef struct flock FLOCK; -#else -typedef struct flock64 FLOCK; -#endif - -/** - * Try to open a named lock file. - * The result is a cookie that can be used later to unlock the file. - * On failure the result is zero. - */ -JNIEXPORT jintArray JNICALL -Java_java_util_prefs_FileSystemPreferences_lockFile0(JNIEnv *env, - jclass thisclass, jstring java_fname, jint permission, jboolean shared) { - const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL); - int fd, rc; - int result[2]; - jintArray javaResult = NULL; - int old_umask; - FLOCK fl; - - if (!fname) - return javaResult; - - fl.l_whence = SEEK_SET; - fl.l_len = 0; - fl.l_start = 0; - if (shared == JNI_TRUE) { - fl.l_type = F_RDLCK; - } else { - fl.l_type = F_WRLCK; - } - - if (shared == JNI_TRUE) { - fd = open(fname, O_RDONLY, 0); - } else { - old_umask = umask(0); - fd = open(fname, O_WRONLY|O_CREAT, permission); - result[1] = errno; - umask(old_umask); - } - - if (fd < 0) { - result[0] = 0; - } else { -#if defined(_ALLBSD_SOURCE) - rc = fcntl(fd, F_SETLK, &fl); -#else - rc = fcntl(fd, F_SETLK64, &fl); -#endif - result[1] = errno; - if (rc < 0) { - result[0]= 0; - close(fd); - } else { - result[0] = fd; - } - } - JNU_ReleaseStringPlatformChars(env, java_fname, fname); - javaResult = (*env)->NewIntArray(env,2); - if (javaResult) - (*env)->SetIntArrayRegion(env, javaResult, 0, 2, result); - return javaResult; -} - - -/** - * Try to unlock a lock file, using a cookie returned by lockFile. - */ -JNIEXPORT jint JNICALL -Java_java_util_prefs_FileSystemPreferences_unlockFile0(JNIEnv *env, - jclass thisclass, jint fd) { - - int rc; - FLOCK fl; - fl.l_whence = SEEK_SET; - fl.l_len = 0; - fl.l_start = 0; - fl.l_type = F_UNLCK; - -#if defined(_ALLBSD_SOURCE) - rc = fcntl(fd, F_SETLK, &fl); -#else - rc = fcntl(fd, F_SETLK64, &fl); -#endif - - if (rc < 0) { - close(fd); - return (jint)errno; - } - rc = close(fd); - if (rc < 0) { - return (jint) errno; - } - return 0; -} --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/solaris/native/java/util/prefs/FileSystemPreferences.c 2014-02-09 17:05:59.633428636 +0000 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Solaris/Linux platform specific code to support the Prefs API. + */ + +#include +#include +#include +#include +#include +#include +#include "jni_util.h" + +JNIEXPORT jint JNICALL +Java_java_util_prefs_FileSystemPreferences_chmod(JNIEnv *env, + jclass thisclass, jstring java_fname, jint permission) { + const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL); + int result = -1; + if (fname) { + result = chmod(fname, permission); + if (result != 0) + result = errno; + JNU_ReleaseStringPlatformChars(env, java_fname, fname); + } + return (jint) result; +} + +#if defined(_ALLBSD_SOURCE) +typedef struct flock FLOCK; +#else +typedef struct flock64 FLOCK; +#endif + +/** + * Try to open a named lock file. + * The result is a cookie that can be used later to unlock the file. + * On failure the result is zero. + */ +JNIEXPORT jintArray JNICALL +Java_java_util_prefs_FileSystemPreferences_lockFile0(JNIEnv *env, + jclass thisclass, jstring java_fname, jint permission, jboolean shared) { + const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL); + int fd, rc; + int result[2]; + jintArray javaResult = NULL; + int old_umask; + FLOCK fl; + + if (!fname) + return javaResult; + + fl.l_whence = SEEK_SET; + fl.l_len = 0; + fl.l_start = 0; + if (shared == JNI_TRUE) { + fl.l_type = F_RDLCK; + } else { + fl.l_type = F_WRLCK; + } + + if (shared == JNI_TRUE) { + fd = open(fname, O_RDONLY, 0); + } else { + old_umask = umask(0); + fd = open(fname, O_WRONLY|O_CREAT, permission); + result[1] = errno; + umask(old_umask); + } + + if (fd < 0) { + result[0] = 0; + } else { +#if defined(_ALLBSD_SOURCE) + rc = fcntl(fd, F_SETLK, &fl); +#else + rc = fcntl(fd, F_SETLK64, &fl); +#endif + result[1] = errno; + if (rc < 0) { + result[0]= 0; + close(fd); + } else { + result[0] = fd; + } + } + JNU_ReleaseStringPlatformChars(env, java_fname, fname); + javaResult = (*env)->NewIntArray(env,2); + if (javaResult) + (*env)->SetIntArrayRegion(env, javaResult, 0, 2, result); + return javaResult; +} + + +/** + * Try to unlock a lock file, using a cookie returned by lockFile. + */ +JNIEXPORT jint JNICALL +Java_java_util_prefs_FileSystemPreferences_unlockFile0(JNIEnv *env, + jclass thisclass, jint fd) { + + int rc; + FLOCK fl; + fl.l_whence = SEEK_SET; + fl.l_len = 0; + fl.l_start = 0; + fl.l_type = F_UNLCK; + +#if defined(_ALLBSD_SOURCE) + rc = fcntl(fd, F_SETLK, &fl); +#else + rc = fcntl(fd, F_SETLK64, &fl); +#endif + + if (rc < 0) { + close(fd); + return (jint)errno; + } + rc = close(fd); + if (rc < 0) { + return (jint) errno; + } + return 0; +} --- old/src/solaris/native/java/util/logging.c 2014-02-09 17:06:00.557428614 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Solaris/Linux specific code to support logging. - */ - -#include -#include "jni_util.h" - - -JNIEXPORT jboolean JNICALL -Java_java_util_logging_FileHandler_isSetUID(JNIEnv *env, jclass thisclass) { - - /* Return true if we are in a set UID or set GID process. */ - if (getuid() != geteuid() || getgid() != getegid()) { - return JNI_TRUE; - } - return JNI_FALSE; -} --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/solaris/native/sun/misc/VM_md.c 2014-02-09 17:06:00.197428623 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include "jni_util.h" + + +JNIEXPORT jboolean JNICALL +Java_sun_misc_VM_isSetUID(JNIEnv *env, jclass thisclass) { + + /* Return true if we are in a set UID or set GID process. */ + if (getuid() != geteuid() || getgid() != getegid()) { + return JNI_TRUE; + } + return JNI_FALSE; +} --- old/src/windows/native/java/util/WindowsPreferences.c 2014-02-09 17:06:01.301428597 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include -#ifdef __cplusplus -extern "C" { -#endif - JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegOpenKey - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey, jint securityMask) { - HKEY handle; - char* str; - int tmp[2]; - int errorCode=-1; - jintArray result; - str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); - errorCode = RegOpenKeyEx((HKEY)hKey, str, 0, securityMask, &handle); - (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); - tmp[0]= (int) handle; - tmp[1]= errorCode; - result = (*env)->NewIntArray(env,2); - (*env)->SetIntArrayRegion(env, result, 0, 2, tmp); - return result; - } - - JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCloseKey - (JNIEnv* env, jclass this_class, jint hKey) { - return (jint) RegCloseKey((HKEY) hKey); - }; - - JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCreateKeyEx - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) { - HKEY handle; - char* str; - int tmp[3]; - DWORD lpdwDisposition; - int errorCode; - jintArray result; - str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); - errorCode = RegCreateKeyEx((HKEY)hKey, str, 0, NULL, - REG_OPTION_NON_VOLATILE, KEY_READ, - NULL, &handle, &lpdwDisposition); - (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); - tmp[0]= (int) handle; - tmp[1]= errorCode; - tmp[2]= lpdwDisposition; - result = (*env)->NewIntArray(env,3); - (*env)->SetIntArrayRegion(env, result, 0, 3, tmp); - return result; - } - - JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteKey - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) { - char* str; - int result; - str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); - result = RegDeleteKey((HKEY)hKey, str); - (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); - return result; - - }; - - JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegFlushKey - (JNIEnv* env, jclass this_class, jint hKey) { - return RegFlushKey ((HKEY)hKey); - } - - JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryValueEx - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) { - char* valueNameStr; - char* buffer; - jbyteArray result; - DWORD valueType; - DWORD valueSize; - valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); - if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, NULL, - &valueSize) != ERROR_SUCCESS) { - (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); - return NULL; - } - - buffer = (char*)malloc(valueSize); - - if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, buffer, - &valueSize) != ERROR_SUCCESS) { - free(buffer); - (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); - return NULL; - } - - if (valueType == REG_SZ) { - result = (*env)->NewByteArray(env, valueSize); - (*env)->SetByteArrayRegion(env, result, 0, valueSize, buffer); - } else { - result = NULL; - } - free(buffer); - (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); - return result; - } - - - - - JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegSetValueEx - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName, jbyteArray data) { - char* valueNameStr; - char* dataStr; - int size = -1; - int nameSize = -1; - int error_code = -1; - if ((valueName == NULL)||(data == NULL)) {return -1;} - size = (*env)->GetArrayLength(env, data); - dataStr = (*env)->GetByteArrayElements(env, data, NULL); - valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); - error_code = RegSetValueEx((HKEY)hKey, valueNameStr, 0, - REG_SZ, dataStr, size); - (*env)->ReleaseByteArrayElements(env, data, dataStr, 0); - (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); - return error_code; - } - - JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteValue - (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) { - char* valueNameStr; - int error_code = -1; - if (valueName == NULL) {return -1;} - valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); - error_code = RegDeleteValue((HKEY)hKey, valueNameStr); - (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); - return error_code; - } - - JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryInfoKey - (JNIEnv* env, jclass this_class, jint hKey) { - jintArray result; - int tmp[5]; - int valuesNumber = -1; - int maxValueNameLength = -1; - int maxSubKeyLength = -1; - int subKeysNumber = -1; - int errorCode = -1; - errorCode = RegQueryInfoKey((HKEY)hKey, NULL, NULL, NULL, - &subKeysNumber, &maxSubKeyLength, NULL, - &valuesNumber, &maxValueNameLength, - NULL, NULL, NULL); - tmp[0]= subKeysNumber; - tmp[1]= (int)errorCode; - tmp[2]= valuesNumber; - tmp[3]= maxSubKeyLength; - tmp[4]= maxValueNameLength; - result = (*env)->NewIntArray(env,5); - (*env)->SetIntArrayRegion(env, result, 0, 5, tmp); - return result; - } - - JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumKeyEx - (JNIEnv* env, jclass this_class, jint hKey , jint subKeyIndex, jint maxKeyLength) { - int size = maxKeyLength; - jbyteArray result; - char* buffer = NULL; - buffer = (char*)malloc(maxKeyLength); - if (RegEnumKeyEx((HKEY) hKey, subKeyIndex, buffer, &size, NULL, NULL, - NULL, NULL) != ERROR_SUCCESS){ - free(buffer); - return NULL; - } - result = (*env)->NewByteArray(env, size + 1); - (*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer); - free(buffer); - return result; - } - - JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumValue - (JNIEnv* env, jclass this_class, jint hKey , jint valueIndex, jint maxValueNameLength){ - int size = maxValueNameLength; - jbyteArray result; - char* buffer = NULL; - int error_code; - buffer = (char*)malloc(maxValueNameLength); - error_code = RegEnumValue((HKEY) hKey, valueIndex, buffer, - &size, NULL, NULL, NULL, NULL); - if (error_code!= ERROR_SUCCESS){ - free(buffer); - return NULL; - } - result = (*env)->NewByteArray(env, size + 1); - (*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer); - free(buffer); - return result; - } - - -#ifdef __cplusplus -} -#endif --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/windows/native/java/util/prefs/WindowsPreferences.c 2014-02-09 17:06:00.933428606 +0000 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegOpenKey + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey, jint securityMask) { + HKEY handle; + char* str; + int tmp[2]; + int errorCode=-1; + jintArray result; + str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); + errorCode = RegOpenKeyEx((HKEY)hKey, str, 0, securityMask, &handle); + (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); + tmp[0]= (int) handle; + tmp[1]= errorCode; + result = (*env)->NewIntArray(env,2); + (*env)->SetIntArrayRegion(env, result, 0, 2, tmp); + return result; + } + + JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCloseKey + (JNIEnv* env, jclass this_class, jint hKey) { + return (jint) RegCloseKey((HKEY) hKey); + }; + + JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegCreateKeyEx + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) { + HKEY handle; + char* str; + int tmp[3]; + DWORD lpdwDisposition; + int errorCode; + jintArray result; + str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); + errorCode = RegCreateKeyEx((HKEY)hKey, str, 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_READ, + NULL, &handle, &lpdwDisposition); + (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); + tmp[0]= (int) handle; + tmp[1]= errorCode; + tmp[2]= lpdwDisposition; + result = (*env)->NewIntArray(env,3); + (*env)->SetIntArrayRegion(env, result, 0, 3, tmp); + return result; + } + + JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteKey + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey) { + char* str; + int result; + str = (*env)->GetByteArrayElements(env, lpSubKey, NULL); + result = RegDeleteKey((HKEY)hKey, str); + (*env)->ReleaseByteArrayElements(env, lpSubKey, str, 0); + return result; + + }; + + JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegFlushKey + (JNIEnv* env, jclass this_class, jint hKey) { + return RegFlushKey ((HKEY)hKey); + } + + JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryValueEx + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) { + char* valueNameStr; + char* buffer; + jbyteArray result; + DWORD valueType; + DWORD valueSize; + valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); + if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, NULL, + &valueSize) != ERROR_SUCCESS) { + (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); + return NULL; + } + + buffer = (char*)malloc(valueSize); + + if (RegQueryValueEx((HKEY)hKey, valueNameStr, NULL, &valueType, buffer, + &valueSize) != ERROR_SUCCESS) { + free(buffer); + (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); + return NULL; + } + + if (valueType == REG_SZ) { + result = (*env)->NewByteArray(env, valueSize); + (*env)->SetByteArrayRegion(env, result, 0, valueSize, buffer); + } else { + result = NULL; + } + free(buffer); + (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); + return result; + } + + + + + JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegSetValueEx + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName, jbyteArray data) { + char* valueNameStr; + char* dataStr; + int size = -1; + int nameSize = -1; + int error_code = -1; + if ((valueName == NULL)||(data == NULL)) {return -1;} + size = (*env)->GetArrayLength(env, data); + dataStr = (*env)->GetByteArrayElements(env, data, NULL); + valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); + error_code = RegSetValueEx((HKEY)hKey, valueNameStr, 0, + REG_SZ, dataStr, size); + (*env)->ReleaseByteArrayElements(env, data, dataStr, 0); + (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); + return error_code; + } + + JNIEXPORT jint JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegDeleteValue + (JNIEnv* env, jclass this_class, jint hKey, jbyteArray valueName) { + char* valueNameStr; + int error_code = -1; + if (valueName == NULL) {return -1;} + valueNameStr = (*env)->GetByteArrayElements(env, valueName, NULL); + error_code = RegDeleteValue((HKEY)hKey, valueNameStr); + (*env)->ReleaseByteArrayElements(env, valueName, valueNameStr, 0); + return error_code; + } + + JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegQueryInfoKey + (JNIEnv* env, jclass this_class, jint hKey) { + jintArray result; + int tmp[5]; + int valuesNumber = -1; + int maxValueNameLength = -1; + int maxSubKeyLength = -1; + int subKeysNumber = -1; + int errorCode = -1; + errorCode = RegQueryInfoKey((HKEY)hKey, NULL, NULL, NULL, + &subKeysNumber, &maxSubKeyLength, NULL, + &valuesNumber, &maxValueNameLength, + NULL, NULL, NULL); + tmp[0]= subKeysNumber; + tmp[1]= (int)errorCode; + tmp[2]= valuesNumber; + tmp[3]= maxSubKeyLength; + tmp[4]= maxValueNameLength; + result = (*env)->NewIntArray(env,5); + (*env)->SetIntArrayRegion(env, result, 0, 5, tmp); + return result; + } + + JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumKeyEx + (JNIEnv* env, jclass this_class, jint hKey , jint subKeyIndex, jint maxKeyLength) { + int size = maxKeyLength; + jbyteArray result; + char* buffer = NULL; + buffer = (char*)malloc(maxKeyLength); + if (RegEnumKeyEx((HKEY) hKey, subKeyIndex, buffer, &size, NULL, NULL, + NULL, NULL) != ERROR_SUCCESS){ + free(buffer); + return NULL; + } + result = (*env)->NewByteArray(env, size + 1); + (*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer); + free(buffer); + return result; + } + + JNIEXPORT jbyteArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegEnumValue + (JNIEnv* env, jclass this_class, jint hKey , jint valueIndex, jint maxValueNameLength){ + int size = maxValueNameLength; + jbyteArray result; + char* buffer = NULL; + int error_code; + buffer = (char*)malloc(maxValueNameLength); + error_code = RegEnumValue((HKEY) hKey, valueIndex, buffer, + &size, NULL, NULL, NULL, NULL); + if (error_code!= ERROR_SUCCESS){ + free(buffer); + return NULL; + } + result = (*env)->NewByteArray(env, size + 1); + (*env)->SetByteArrayRegion(env, result, 0, size + 1, buffer); + free(buffer); + return result; + } + + +#ifdef __cplusplus +} +#endif --- old/src/windows/native/java/util/logging.c 2014-02-09 17:06:01.865428584 +0000 +++ /dev/null 2013-11-25 15:01:06.400581647 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * Win32 specific code to support logging. - */ - -#include "jni_util.h" - - -JNIEXPORT jboolean JNICALL -Java_java_util_logging_FileHandler_isSetUID(JNIEnv *env, jclass thisclass) { - - /* There is no set UID on Windows. */ - return JNI_FALSE; -} --- /dev/null 2013-11-25 15:01:06.400581647 +0000 +++ new/src/windows/native/sun/misc/VM_md.c 2014-02-09 17:06:01.501428593 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni_util.h" + + +JNIEXPORT jboolean JNICALL +Java_sun_misc_VM_isSetUID(JNIEnv *env, jclass thisclass) { + + /* There is no set UID on Windows. */ + return JNI_FALSE; +}