8232860: Error formatting integer values with MessageFormat.format() using HOST provider
authornaoto
Tue, 12 Nov 2019 14:05:18 -0800
changeset 59043 1a79b4bfc85a
parent 59042 8910b995a2ee
child 59044 8c9d0451433b
8232860: Error formatting integer values with MessageFormat.format() using HOST provider Reviewed-by: rriggs
src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
src/java.base/share/classes/sun/util/locale/provider/HostLocaleProviderAdapter.java
src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c
test/jdk/java/util/Locale/LocaleProviders.java
test/jdk/java/util/Locale/LocaleProvidersRun.java
--- a/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Nov 12 13:49:40 2019 -0800
+++ b/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Nov 12 14:05:18 2019 -0800
@@ -429,8 +429,9 @@
 
             @Override
             public NumberFormat getIntegerInstance(Locale locale) {
-                return new DecimalFormat(getNumberPattern(NF_INTEGER, locale),
+                DecimalFormat format = new DecimalFormat(getNumberPattern(NF_INTEGER, locale),
                     DecimalFormatSymbols.getInstance(locale));
+                return HostLocaleProviderAdapter.makeIntegerFormatter(format);
             }
 
             @Override
--- a/src/java.base/share/classes/sun/util/locale/provider/HostLocaleProviderAdapter.java	Tue Nov 12 13:49:40 2019 -0800
+++ b/src/java.base/share/classes/sun/util/locale/provider/HostLocaleProviderAdapter.java	Tue Nov 12 14:05:18 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.text.DecimalFormat;
 import java.util.spi.LocaleServiceProvider;
 
 /**
@@ -60,4 +61,19 @@
         }
         return null;
     }
+
+    /**
+     * Utility to make the decimal format specific to integer, called
+     * by the platform dependent adapter implementations.
+     *
+     * @param df A DecimalFormat object
+     * @return The same DecimalFormat object in the argument, modified
+     *          to allow integer formatting/parsing only.
+     */
+    static DecimalFormat makeIntegerFormatter(DecimalFormat df) {
+        df.setMaximumFractionDigits(0);
+        df.setDecimalSeparatorAlwaysShown(false);
+        df.setParseIntegerOnly(true);
+        return df;
+    }
 }
--- a/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Nov 12 13:49:40 2019 -0800
+++ b/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Nov 12 14:05:18 2019 -0800
@@ -258,8 +258,9 @@
             @Override
             public NumberFormat getIntegerInstance(Locale locale) {
                 AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
-                return new DecimalFormat(patterns.get(NF_INTEGER),
+                DecimalFormat format = new DecimalFormat(patterns.get(NF_INTEGER),
                     DecimalFormatSymbols.getInstance(locale));
+                return HostLocaleProviderAdapter.makeIntegerFormatter(format);
             }
 
             @Override
--- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c	Tue Nov 12 13:49:40 2019 -0800
+++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c	Tue Nov 12 14:05:18 2019 -0800
@@ -910,7 +910,7 @@
     if (digits > 0) {
         int i;
         for(i = digits;  i > 0; i--) {
-            fractionPattern[i] = L'0';
+            fractionPattern[i] = L'#';
         }
         fractionPattern[0] = L'.';
         fractionPattern[digits+1] = L'\0';
--- a/test/jdk/java/util/Locale/LocaleProviders.java	Tue Nov 12 13:49:40 2019 -0800
+++ b/test/jdk/java/util/Locale/LocaleProviders.java	Tue Nov 12 14:05:18 2019 -0800
@@ -24,6 +24,7 @@
 import java.text.spi.*;
 import java.util.*;
 import java.util.spi.*;
+import java.util.stream.IntStream;
 import sun.util.locale.provider.LocaleProviderAdapter;
 
 public class LocaleProviders {
@@ -87,6 +88,10 @@
                 bug8232871Test();
                 break;
 
+            case "bug8232860Test":
+                bug8232860Test();
+                break;
+
             default:
                 throw new RuntimeException("Test method '"+methodName+"' not found.");
         }
@@ -327,4 +332,42 @@
                 "native calendar is not JapaneseCalendar: " + calType);
         }
     }
+
+    static void bug8232860Test() {
+        var inputList = List.of(123, 123.4);
+        var nfExpectedList = List.of("123", "123.4");
+        var ifExpectedList = List.of("123", "123");
+
+        var type = LocaleProviderAdapter.getAdapter(CalendarNameProvider.class, Locale.US)
+                                        .getAdapterType();
+        if (type == LocaleProviderAdapter.Type.HOST && (IS_WINDOWS || IS_MAC)) {
+            final var numf = NumberFormat.getNumberInstance(Locale.US);
+            final var intf = NumberFormat.getIntegerInstance(Locale.US);
+
+            IntStream.range(0, inputList.size())
+                .forEach(i -> {
+                    var input = inputList.get(i);
+                    var nfExpected = nfExpectedList.get(i);
+                    var result = numf.format(input);
+                    if (!result.equals(nfExpected)) {
+                        throw new RuntimeException("Incorrect number format. " +
+                            "input: " + input + ", expected: " +
+                            nfExpected + ", result: " + result);
+                    }
+
+                    var ifExpected = ifExpectedList.get(i);
+                    result = intf.format(input);
+                    if (!result.equals(ifExpected)) {
+                        throw new RuntimeException("Incorrect integer format. " +
+                            "input: " + input + ", expected: " +
+                            ifExpected + ", result: " + result);
+                    }
+                });
+            System.out.println("bug8232860Test succeeded.");
+        } else {
+            System.out.println("Test ignored. Either :-\n" +
+                "OS is neither macOS/Windows, or\n" +
+                "provider is not HOST: " + type);
+        }
+    }
 }
--- a/test/jdk/java/util/Locale/LocaleProvidersRun.java	Tue Nov 12 13:49:40 2019 -0800
+++ b/test/jdk/java/util/Locale/LocaleProvidersRun.java	Tue Nov 12 14:05:18 2019 -0800
@@ -25,7 +25,7 @@
  * @test
  * @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577
  *      8010666 8013086 8013233 8013903 8015960 8028771 8054482 8062006
- *      8150432 8215913 8220227 8228465 8232871
+ *      8150432 8215913 8220227 8228465 8232871 8232860
  * @summary tests for "java.locale.providers" system property
  * @library /test/lib
  * @build LocaleProviders
@@ -159,6 +159,9 @@
 
         //testing 8232871 fix. (macOS only)
         testRun("HOST", "bug8232871Test", "", "", "");
+
+        //testing 8232860 fix. (macOS/Windows only)
+        testRun("HOST", "bug8232860Test", "", "", "");
     }
 
     private static void testRun(String prefList, String methodName,