Skip to content
Permalink
Browse files

8248695: HostLocaleProviderAdapterImpl provides invalid date-only

Reviewed-by: joehw
  • Loading branch information
Naoto Sato
Naoto Sato committed Jul 14, 2020
1 parent 10e6a6a commit f8f35d30afacc4c581bdd5b749bb978020678917
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@@ -388,6 +388,10 @@ public String getDisplayName(String calendarType, int field,
int value, int style, Locale locale) {
String[] names = getCalendarDisplayStrings(removeExtensions(locale).toLanguageTag(),
getCalendarIDFromLDMLType(calendarType), field, style);
if (field == Calendar.DAY_OF_WEEK) {
// Align value to array index
value--;
}
if (names != null && value >= 0 && value < names.length) {
return names[value];
} else {
@@ -405,7 +409,9 @@ public String getDisplayName(String calendarType, int field,
map = new HashMap<>();
for (int value = 0; value < names.length; value++) {
if (names[value] != null) {
map.put(names[value], value);
map.put(names[value],
// Align array index to field value
field == Calendar.DAY_OF_WEEK ? value + 1 : value);
}
}
map = map.isEmpty() ? null : map;
@@ -549,12 +555,10 @@ public boolean isSupportedLocale(Locale locale) {
@Override
public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
String pattern = new StringBuilder(patterns.get(dateStyle / 2))
.append(" ")
.append(patterns.get(timeStyle / 2 + 2))
.toString();
return toJavaTimeDateTimePattern(calType, pattern);

String datePattern = dateStyle != - 1 ? patterns.get(dateStyle / 2) : "";
String timePattern = timeStyle != - 1 ? patterns.get(timeStyle / 2 + 2) : "";
String delim = dateStyle != -1 && timeStyle != - 1 ? " " : "";
return toJavaTimeDateTimePattern(calType, datePattern + delim + timePattern);
}

private AtomicReferenceArray<String> getDateTimePatterns(Locale locale) {
@@ -699,7 +703,7 @@ private void appendN(char c, int n, StringBuilder sb) {
private static String convertDateTimePattern(String winPattern) {
String ret = winPattern.replaceAll("dddd", "EEEE");
ret = ret.replaceAll("ddd", "EEE");
ret = ret.replaceAll("tt", "aa");
ret = ret.replaceAll("tt", "a");
ret = ret.replaceAll("g", "GG");
return ret;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@@ -34,6 +34,8 @@
// java.util.Calendar constants
#define CALENDAR_FIELD_ERA 0 // Calendar.ERA
#define CALENDAR_FIELD_MONTH 2 // Calendar.MONTH
#define CALENDAR_FIELD_DAY_OF_WEEK 7 // Calendar.DAY_OF_WEEK
#define CALENDAR_FIELD_AM_PM 9 // Calendar.AM_PM
#define CALENDAR_STYLE_SHORT_MASK 0x00000001 // Calendar.SHORT
#define CALENDAR_STYLE_STANDALONE_MASK 0x00008000 // Calendar.STANDALONE

@@ -50,8 +52,7 @@ BOOL initialized = FALSE;
int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen);
int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val);
jint getCalendarID(const jchar *langtag);
void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjectArray jarray,
CALTYPE* pCalTypes, int offset, int length, int style);
void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjectArray jarray, DWORD* pTypes, int offset, int length, int style, BOOL bCal);
WCHAR * getNumberPattern(const jchar * langtag, const jint numberStyle);
void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number);
void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret);
@@ -116,6 +117,15 @@ CALTYPE sWDaysType[] = {
CAL_SABBREVDAYNAME6,
};

#define DOWTYPES (sizeof(wDaysType) / sizeof(CALTYPE))

LCTYPE ampmType [] = {
LOCALE_SAM,
LOCALE_SPM,
};

#define AMPMTYPES (sizeof(ampmType) / sizeof(LCTYPE))

WCHAR * fixes[2][2][3][16] =
{
{ //prefix
@@ -278,35 +288,8 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterIm
*/
JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings
(JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) {
WCHAR buf[BUFLEN];
const jchar *langtag;
jstring tmp_string;

// AM
int got;
langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE);
CHECK_NULL_RETURN(langtag, NULL);
got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN);
if (got) {
tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf));
if (tmp_string != NULL) {
(*env)->SetObjectArrayElement(env, ampms, 0, tmp_string);
}
}

if (!(*env)->ExceptionCheck(env)){
// PM
got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN);
if (got) {
tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf));
if (tmp_string != NULL) {
(*env)->SetObjectArrayElement(env, ampms, 1, tmp_string);
}
}
}

(*env)->ReleaseStringChars(env, jlangtag, langtag);

replaceCalendarArrayElems(env, jlangtag, -1, ampms, ampmType,
0, AMPMTYPES, 0, FALSE);
return ampms;
}

@@ -328,7 +311,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths
(JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) {
replaceCalendarArrayElems(env, jlangtag, -1, months, monthsType,
0, MONTHTYPES, 0);
0, MONTHTYPES, 0, TRUE);
return months;
}

@@ -340,7 +323,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths
(JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) {
replaceCalendarArrayElems(env, jlangtag, -1, smonths, sMonthsType,
0, MONTHTYPES, 0);
0, MONTHTYPES, 0, TRUE);
return smonths;
}

@@ -352,7 +335,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays
(JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) {
replaceCalendarArrayElems(env, jlangtag, -1, wdays, wDaysType,
1, sizeof(wDaysType)/sizeof(CALTYPE), 0);
1, DOWTYPES, 0, TRUE);
return wdays;
}

@@ -364,7 +347,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays
(JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) {
replaceCalendarArrayElems(env, jlangtag, -1, swdays, sWDaysType,
1, sizeof(sWDaysType)/sizeof(CALTYPE), 0);
1, DOWTYPES, 0, TRUE);
return swdays;
}

@@ -689,6 +672,30 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
case CALENDAR_FIELD_ERA:
return getErasImpl(env, jlangtag, calid, style, NULL);

case CALENDAR_FIELD_AM_PM:
ret = (*env)->NewObjectArray(env, AMPMTYPES,
(*env)->FindClass(env, "java/lang/String"), NULL);
if (ret != NULL) {
replaceCalendarArrayElems(env, jlangtag, calid, ret, ampmType,
0, AMPMTYPES, style, FALSE);
}
return ret;

case CALENDAR_FIELD_DAY_OF_WEEK:
ret = (*env)->NewObjectArray(env, DOWTYPES,
(*env)->FindClass(env, "java/lang/String"), NULL);
if (ret != NULL) {
if (style & CALENDAR_STYLE_SHORT_MASK) {
pCalType = sWDaysType;
} else {
pCalType = wDaysType;
}

replaceCalendarArrayElems(env, jlangtag, calid, ret, pCalType,
0, DOWTYPES, style, TRUE);
}
return ret;

case CALENDAR_FIELD_MONTH:
ret = (*env)->NewObjectArray(env, MONTHTYPES,
(*env)->FindClass(env, "java/lang/String"), NULL);
@@ -700,7 +707,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA
}

replaceCalendarArrayElems(env, jlangtag, calid, ret, pCalType,
0, MONTHTYPES, style);
0, MONTHTYPES, style, TRUE);
}
return ret;

@@ -819,7 +826,7 @@ jint getCalendarID(const jchar *langtag) {
return type;
}

void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length, int style) {
void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjectArray jarray, DWORD* pTypes, int offset, int length, int style, BOOL bCal) {
WCHAR name[BUFLEN];
const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE);
jstring tmp_string;
@@ -839,8 +846,9 @@ void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjec
}

for (i = 0; i < length; i++) {
if (getCalendarInfoWrapper(langtag, calid, NULL,
pCalTypes[i] | isGenitive, name, BUFLEN, NULL) != 0) {
if (bCal && getCalendarInfoWrapper(langtag, calid, NULL,
pTypes[i] | isGenitive, name, BUFLEN, NULL) != 0 ||
getLocaleInfoWrapper(langtag, pTypes[i] | isGenitive, name, BUFLEN) != 0) {
tmp_string = (*env)->NewString(env, name, (jsize)wcslen(name));
if (tmp_string != NULL) {
(*env)->SetObjectArrayElement(env, jarray, i + offset, tmp_string);
@@ -22,9 +22,13 @@
*/
import java.text.*;
import java.text.spi.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
import java.util.spi.*;
@@ -102,6 +106,10 @@ public static void main(String[] args) {
bug8245241Test(args[1]);
break;

case "bug8248695Test":
bug8248695Test();
break;

default:
throw new RuntimeException("Test method '"+methodName+"' not found.");
}
@@ -243,24 +251,23 @@ static void bug8013086Test(String lang, String ctry) {
static void bug8013903Test() {
if (IS_WINDOWS) {
Date sampleDate = new Date(0x10000000000L);
String hostResult = "\u5e73\u6210 16.11.03 (Wed) AM 11:53:47";
String jreResult = "\u5e73\u6210 16.11.03 (\u6c34) \u5348\u524d 11:53:47";
String expected = "\u5e73\u6210 16.11.03 (\u6c34) \u5348\u524d 11:53:47";
Locale l = new Locale("ja", "JP", "JP");
SimpleDateFormat sdf = new SimpleDateFormat("GGGG yyyy.MMM.dd '('E')' a hh:mm:ss", l);
sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
String result = sdf.format(sampleDate);
System.out.println(result);
if (LocaleProviderAdapter.getAdapterPreference()
.contains(LocaleProviderAdapter.Type.JRE)) {
if (!jreResult.equals(result)) {
if (!expected.equals(result)) {
throw new RuntimeException("Format failed. result: \"" +
result + "\", expected: \"" + jreResult);
result + "\", expected: \"" + expected);
}
} else {
// Windows display names. Subject to change if Windows changes its format.
if (!hostResult.equals(result)) {
if (!expected.equals(result)) {
throw new RuntimeException("Format failed. result: \"" +
result + "\", expected: \"" + hostResult);
result + "\", expected: \"" + expected);
}
}
}
@@ -404,4 +411,26 @@ public void publish(LogRecord record) {
throw new RuntimeException("Expected log was not emitted. LogRecord: " + lra[0]);
}
}

static void bug8248695Test() {
Locale l = Locale.getDefault(Locale.Category.FORMAT);
LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, l);
LocaleProviderAdapter.Type type = lda.getAdapterType();
if (type == LocaleProviderAdapter.Type.HOST) {
System.out.println("Locale: " + l);
var ld = LocalDate.now();
var zdt = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
var df = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(l);
var tf = DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).withLocale(l);
var dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(l);

// Checks there's no "unsupported temporal field" exception thrown, such as HourOfDay
System.out.println(df.format(ld));
System.out.println(tf.format(zdt));

// Checks there's no "Too many pattern letters: aa" exception thrown, if
// underlying OS provides the "am/pm" pattern.
System.out.println(dtf.format(zdt));
}
}
}
@@ -26,7 +26,7 @@
* @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577
* 8010666 8013086 8013233 8013903 8015960 8028771 8054482 8062006
* 8150432 8215913 8220227 8228465 8232871 8232860 8236495 8245241
* 8246721
* 8246721 8248695
* @summary tests for "java.locale.providers" system property
* @library /test/lib
* @build LocaleProviders
@@ -169,6 +169,9 @@ public static void main(String[] args) throws Throwable {
//double quotes in the string argument.
testRun("FOO", "bug8245241Test",
"Invalid locale provider adapter \"FOO\" ignored.", "", "");

//testing 8248695 fix.
testRun("HOST", "bug8248695Test", "", "", "");
}

private static void testRun(String prefList, String methodName,

0 comments on commit f8f35d3

Please sign in to comment.
You can’t perform that action at this time.