--- old/src/java.base/macosx/native/libjava/java_props_macosx.c 2016-06-20 15:50:17.000000000 -0700 +++ new/src/java.base/macosx/native/libjava/java_props_macosx.c 2016-06-20 15:50:17.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -23,10 +23,10 @@ * questions. */ -#include #include #include #include +#include #include #include @@ -35,18 +35,6 @@ #include "java_props_macosx.h" -// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded -static void *getJRSFramework() { - static void *jrsFwk = NULL; -#ifndef STATIC_BUILD -// JavaRuntimeSupport doesn't support static Java runtimes - if (jrsFwk == NULL) { - jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); - } -#endif - return jrsFwk; -} - char *getPosixLocale(int cat) { char *lc = setlocale(cat, NULL); if ((lc == NULL) || (strcmp(lc, "C") == 0)) { @@ -61,18 +49,73 @@ switch (cat) { case LC_MESSAGES: { - void *jrsFwk = getJRSFramework(); - if (jrsFwk == NULL) return NULL; - - char *(*JRSCopyPrimaryLanguage)() = dlsym(jrsFwk, "JRSCopyPrimaryLanguage"); - char *primaryLanguage = JRSCopyPrimaryLanguage ? JRSCopyPrimaryLanguage() : NULL; - if (primaryLanguage == NULL) return NULL; - - char *(*JRSCopyCanonicalLanguageForPrimaryLanguage)(char *) = dlsym(jrsFwk, "JRSCopyCanonicalLanguageForPrimaryLanguage"); - char *canonicalLanguage = JRSCopyCanonicalLanguageForPrimaryLanguage ? JRSCopyCanonicalLanguageForPrimaryLanguage(primaryLanguage) : NULL; - free (primaryLanguage); + // get preferred language code + CFArrayRef languages = CFLocaleCopyPreferredLanguages(); + if (languages == NULL) { + return NULL; + } + if (CFArrayGetCount(languages) <= 0) { + CFRelease(languages); + return NULL; + } + + CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); + if (primaryLanguage == NULL) { + CFRelease(languages); + return NULL; + } + char languageString[LOCALEIDLENGTH]; + if (CFStringGetCString(primaryLanguage, languageString, + LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) { + CFRelease(languages); + return NULL; + } + CFRelease(languages); + + // Language IDs use the language designators and (optional) region + // and script designators of BCP 47. So possible formats are: + // + // "en" (language designator only) + // "en-GB" (language with region designator) + // "zh-Hans" (language with ISO 15924 script designator) + // "zh-Hans_HK" (language with both script and region designator) + // + // In the case of a region designator (but no script designator), we + // convert to ISO 639 by changing '-' to '_'. + char* scriptOrRegion = strchr(languageString, '-'); + if (scriptOrRegion != NULL) { + // If we find '_' later, that indicates a script+region + // (e.g. zh-Hans_HK), and we should not convert '-' to '_'. + if (!strchr(scriptOrRegion, '_')) { + if (strlen(scriptOrRegion) == 3) { + // The '-' is followed by a 2 character region designator, + // so we should convert '-' to '_'. + assert(scriptOrRegion[1] >= 'A' && scriptOrRegion[1] <= 'Z' && + scriptOrRegion[2] >= 'A' && scriptOrRegion[2] <= 'Z'); + *scriptOrRegion = '_'; // BCP 47 lang-region -> ISO_639-1 + } + // Otherwise, we have a 4-character script designator + // (e.g. zh-Hans), and the '-' should be left as is. + } + } + + const char* retVal = languageString; - return canonicalLanguage; + // Special case for Portuguese in Brazil: + // The language code needs the "_BR" region code (to distinguish it + // from Portuguese in Portugal), but this is missing when using the + // "Portuguese (Brazil)" language. + // If language is "pt" and the current locale is pt_BR, return pt_BR. + char localeString[LOCALEIDLENGTH]; + if (strcmp(retVal, "pt") == 0) { + if (CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()), + localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) { + if (strcmp(localeString, "pt_BR") == 0) { + retVal = localeString; + } + } + } + return strdup(retVal); } break; default: @@ -92,14 +135,6 @@ char *setupMacOSXLocale(int cat) { char * ret = getMacOSXLocale(cat); - if (cat == LC_MESSAGES && ret != NULL) { - void *jrsFwk = getJRSFramework(); - if (jrsFwk != NULL) { - void (*JRSSetDefaultLocalization)(char *) = dlsym(jrsFwk, "JRSSetDefaultLocalization"); - if (JRSSetDefaultLocalization) JRSSetDefaultLocalization(ret); - } - } - if (ret == NULL) { return getPosixLocale(cat); } else { @@ -126,22 +161,35 @@ return 0; } +// 10.9 SDK does not include the NSOperatingSystemVersion struct. +// For now, create our own +typedef struct { + NSInteger majorVersion; + NSInteger minorVersion; + NSInteger patchVersion; +} OSVerStruct; + void setOSNameAndVersion(java_props_t *sprops) { - /* Don't rely on JRSCopyOSName because there's no guarantee the value will - * remain the same, or even if the JRS functions will continue to be part of - * Mac OS X. So hardcode os_name, and fill in os_version if we can. - */ + // Hardcode os_name, and fill in os_version sprops->os_name = strdup("Mac OS X"); + + char* osVersionCStr = NULL; + // Mac OS 10.9 includes the [NSProcessInfo operatingSystemVersion] function, + // but it's not in the 10.9 SDK. So, call it via objc_msgSend_stret. + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { + OSVerStruct (*procInfoFn)(id rec, SEL sel) = (OSVerStruct(*)(id, SEL))objc_msgSend_stret; + OSVerStruct osVer = procInfoFn([NSProcessInfo processInfo], + @selector(operatingSystemVersion)); + NSString *nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", + (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; + // Copy out the char* + osVersionCStr = strdup([nsVerStr UTF8String]); + } - void *jrsFwk = getJRSFramework(); - if (jrsFwk != NULL) { - char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion"); - if (copyOSVersion != NULL) { - sprops->os_version = copyOSVersion(); - return; - } + if (osVersionCStr == NULL) { + osVersionCStr = strdup("Unknown"); } - sprops->os_version = strdup("Unknown"); + sprops->os_version = osVersionCStr; } --- old/src/java.base/unix/native/libjava/locale_str.h 2016-06-20 15:50:18.000000000 -0700 +++ new/src/java.base/unix/native/libjava/locale_str.h 2016-06-20 15:50:18.000000000 -0700 @@ -135,6 +135,17 @@ "sr_SP", "sr_YU", "tchinese", "zh_TW", #endif +#ifdef MACOSX + "es-419", "es_XL", // Mappings as done by old Apple JRS code + "sr-Latn", "sr_CS", + "tk", "tk-Cyrl", + "tt-Latn", "tt-Cyrl", + "uz", "uz_UZ", + "uz-Arab", "uz_UZ", + "uz-Latn", "uz_UZ", + "zh-Hans", "zh_CN", + "zh-Hant", "zh_TW", +#endif "", "", };