8248695: HostLocaleProviderAdapterImpl provides invalid date-only

Reviewed-by: joehw
diff --git a/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
index c6df88d..8699a14 100644
--- a/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
+++ b/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
@@ -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 @@
                 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 @@
                     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 @@
             @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 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;
     }
diff --git a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c
index 2f297ed..e678d51 100644
--- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c
+++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c
@@ -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 @@
 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 @@
     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 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_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_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_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_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 @@
     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 @@
             }
 
             replaceCalendarArrayElems(env, jlangtag, calid, ret, pCalType,
-                          0, MONTHTYPES, style);
+                          0, MONTHTYPES, style, TRUE);
         }
         return ret;
 
@@ -819,7 +826,7 @@
     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 @@
         }
 
         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);
diff --git a/test/jdk/java/util/Locale/LocaleProviders.java b/test/jdk/java/util/Locale/LocaleProviders.java
index 0cd972a..9d90b07 100644
--- a/test/jdk/java/util/Locale/LocaleProviders.java
+++ b/test/jdk/java/util/Locale/LocaleProviders.java
@@ -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 @@
                 bug8245241Test(args[1]);
                 break;
 
+            case "bug8248695Test":
+                bug8248695Test();
+                break;
+
             default:
                 throw new RuntimeException("Test method '"+methodName+"' not found.");
         }
@@ -243,8 +251,7 @@
     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"));
@@ -252,15 +259,15 @@
             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 @@
             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));
+        }
+    }
 }
diff --git a/test/jdk/java/util/Locale/LocaleProvidersRun.java b/test/jdk/java/util/Locale/LocaleProvidersRun.java
index ac99914..e6b4135 100644
--- a/test/jdk/java/util/Locale/LocaleProvidersRun.java
+++ b/test/jdk/java/util/Locale/LocaleProvidersRun.java
@@ -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 @@
         //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,