--- old/src/java.base/share/classes/java/util/Formatter.java 2018-02-22 12:32:20.144570643 +0530 +++ new/src/java.base/share/classes/java/util/Formatter.java 2018-02-22 12:32:19.676570643 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -284,11 +284,11 @@ * {@code 'A'}, and {@code 'T'}) are the same as those for the corresponding * lower-case conversion characters except that the result is converted to * upper case according to the rules of the prevailing {@link java.util.Locale - * Locale}. The result is equivalent to the following invocation of {@link - * String#toUpperCase(Locale)} + * Locale}. If there is no explicit locale specified, either at the + * construction of the instance or as a parameter to its method + * invocation, then the {@link java.util.Locale.Category#FORMAT default locale} + * is used. * - *
- *    out.toUpperCase(Locale.getDefault(Locale.Category.FORMAT)) 
* * * @@ -709,11 +709,10 @@ * {@code 'G'}, {@code 'A'}, and {@code 'T'}) are the same as those for the * corresponding lower-case conversion characters except that the result is * converted to upper case according to the rules of the prevailing {@link - * java.util.Locale Locale}. The result is equivalent to the following - * invocation of {@link String#toUpperCase(Locale)} - * - *
- *    out.toUpperCase(Locale.getDefault(Locale.Category.FORMAT)) 
+ * java.util.Locale Locale}. If there is no explicit locale specified, + * either at the construction of the instance or as a parameter to its method + * invocation, then the {@link java.util.Locale.Category#FORMAT default locale} + * is used. * *

General

* @@ -2897,16 +2896,16 @@ break; case Conversion.CHARACTER: case Conversion.CHARACTER_UPPER: - printCharacter(arg); + printCharacter(arg, l); break; case Conversion.BOOLEAN: - printBoolean(arg); + printBoolean(arg, l); break; case Conversion.STRING: printString(arg, l); break; case Conversion.HASHCODE: - printHashCode(arg); + printHashCode(arg, l); break; case Conversion.LINE_SEPARATOR: a.append(System.lineSeparator()); @@ -2921,7 +2920,7 @@ private void printInteger(Object arg, Locale l) throws IOException { if (arg == null) - print("null"); + print("null", l); else if (arg instanceof Byte) print(((Byte)arg).byteValue(), l); else if (arg instanceof Short) @@ -2938,7 +2937,7 @@ private void printFloat(Object arg, Locale l) throws IOException { if (arg == null) - print("null"); + print("null", l); else if (arg instanceof Float) print(((Float)arg).floatValue(), l); else if (arg instanceof Double) @@ -2951,7 +2950,7 @@ private void printDateTime(Object arg, Locale l) throws IOException { if (arg == null) { - print("null"); + print("null", l); return; } Calendar cal = null; @@ -2982,9 +2981,9 @@ print(cal, c, l); } - private void printCharacter(Object arg) throws IOException { + private void printCharacter(Object arg, Locale l) throws IOException { if (arg == null) { - print("null"); + print("null", l); return; } String s = null; @@ -3011,7 +3010,7 @@ } else { failConversion(c, arg); } - print(s); + print(s, l); } private void printString(Object arg, Locale l) throws IOException { @@ -3024,13 +3023,13 @@ if (f.contains(Flags.ALTERNATE)) failMismatch(Flags.ALTERNATE, 's'); if (arg == null) - print("null"); + print("null", l); else - print(arg.toString()); + print(arg.toString(), l); } } - private void printBoolean(Object arg) throws IOException { + private void printBoolean(Object arg, Locale l) throws IOException { String s; if (arg != null) s = ((arg instanceof Boolean) @@ -3038,24 +3037,29 @@ : Boolean.toString(true)); else s = Boolean.toString(false); - print(s); + print(s, l); } - private void printHashCode(Object arg) throws IOException { + private void printHashCode(Object arg, Locale l) throws IOException { String s = (arg == null ? "null" : Integer.toHexString(arg.hashCode())); - print(s); + print(s, l); } - private void print(String s) throws IOException { + private void print(String s, Locale l) throws IOException { if (precision != -1 && precision < s.length()) s = s.substring(0, precision); if (f.contains(Flags.UPPERCASE)) - s = s.toUpperCase(Locale.getDefault(Locale.Category.FORMAT)); + s = toUpperCaseWithLocale(s, l); appendJustified(a, s); } + private String toUpperCaseWithLocale(String s, Locale l) { + return s.toUpperCase(Objects.requireNonNullElse(l, + Locale.getDefault(Locale.Category.FORMAT))); + } + private Appendable appendJustified(Appendable a, CharSequence cs) throws IOException { if (width == -1) { return a.append(cs); @@ -3276,7 +3280,7 @@ trailingZeros(sb, width - len); } if (f.contains(Flags.UPPERCASE)) - s = s.toUpperCase(Locale.getDefault(Locale.Category.FORMAT)); + s = toUpperCaseWithLocale(s, l); sb.append(s); } @@ -3351,7 +3355,7 @@ trailingZeros(sb, width - len); } if (f.contains(Flags.UPPERCASE)) - s = s.toUpperCase(Locale.getDefault(Locale.Category.FORMAT)); + s = toUpperCaseWithLocale(s, l); sb.append(s); } @@ -3950,7 +3954,7 @@ // justify based on width if (f.contains(Flags.UPPERCASE)) { - appendJustified(a, sb.toString().toUpperCase(Locale.getDefault(Locale.Category.FORMAT))); + appendJustified(a, toUpperCaseWithLocale(sb.toString(), l)); } else { appendJustified(a, sb); } @@ -4132,8 +4136,7 @@ StringBuilder tsb = new StringBuilder(); print(tsb, t, DateTime.AM_PM, l); - sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, - Locale.getDefault(Locale.Category.FORMAT)))); + sb.append(toUpperCaseWithLocale(tsb.toString(), l)); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) @@ -4171,7 +4174,7 @@ print(sb, t, c, l); // justify based on width if (f.contains(Flags.UPPERCASE)) { - appendJustified(a, sb.toString().toUpperCase(Locale.getDefault(Locale.Category.FORMAT))); + appendJustified(a, toUpperCaseWithLocale(sb.toString(), l)); } else { appendJustified(a, sb); } @@ -4373,8 +4376,7 @@ // this may be in wrong place for some locales StringBuilder tsb = new StringBuilder(); print(tsb, t, DateTime.AM_PM, l); - sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, - Locale.getDefault(Locale.Category.FORMAT)))); + sb.append(toUpperCaseWithLocale(tsb.toString(), l)); break; } case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) --- old/test/jdk/java/util/Formatter/FormatLocale.java 2018-02-22 12:32:21.220570643 +0530 +++ new/test/jdk/java/util/Formatter/FormatLocale.java 2018-02-22 12:32:20.764570643 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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,9 +23,12 @@ /** * @test - * @bug 8146156 8159548 + * @bug 8146156 8159548 8060094 * @modules jdk.localedata * @summary test whether uppercasing follows Locale.Category.FORMAT locale. + * Also test whether the uppercasing uses the locale specified to the + * Formatter API. + * * @run main/othervm FormatLocale */ @@ -50,40 +53,80 @@ "%S", "%S", "%TB", - "%G"); + "%G", + "%C"); + static final List src = List.of( "Turkish", "Turkish", LocalDate.of(2016, Month.APRIL, 1), - Float.valueOf(100_000_000)); + Float.valueOf(100_000_000), + 'i'); + + static final List defaultLocale = List.of( + Locale.ENGLISH, + TURKISH, + TURKISH, + Locale.FRANCE, + TURKISH); + static final List formatLocale = List.of( - Locale.ENGLISH, - TURKISH, - TURKISH, - Locale.FRANCE); - static final List expected = List.of( - "TURKISH", - "TURK\u0130SH", - "N\u0130SAN", - "1,00000E+08"); + TURKISH, + Locale.ENGLISH, + Locale.FRANCE, + Locale.ENGLISH, + Locale.ENGLISH); + + static final List expectedWithDefaultLocale = List.of( + "TURKISH", + "TURK\u0130SH", + "N\u0130SAN", + "1,00000E+08", + "\u0130"); + + static final List expectedWithFormatLocale = List.of( + "TURK\u0130SH", + "TURKISH", + "AVRIL", + "1.00000E+08", + "I"); static void formatLocaleTest() { StringBuilder sb = new StringBuilder(); + // checks whether upper casing follows Locale.Category.FORMAT locale IntStream.range(0, src.size()).forEach(i -> { sb.setLength(0); - Locale.setDefault(Locale.Category.FORMAT, formatLocale.get(i)); + Locale.setDefault(Locale.Category.FORMAT, defaultLocale.get(i)); new Formatter(sb).format(conversions.get(i), src.get(i)); - if (!sb.toString().equals(expected.get(i))) { + if (!sb.toString().equals(expectedWithDefaultLocale.get(i))) { throw new RuntimeException( - "Wrong uppercasing with Formatter.format(" + - "\"" + conversions.get(i) + "\"" + - ") in locale " - + formatLocale.get(i) + - ". Expected: " + expected.get(i) + - " Returned: " + sb.toString()); + "Wrong uppercasing with Formatter.format(" + + "\"" + conversions.get(i) + "\"" + + ") in locale " + + defaultLocale.get(i) + + ". Expected: " + expectedWithDefaultLocale.get(i) + + " Returned: " + sb.toString()); } }); + + // checks whether upper casing uses the locale set during creation of + // Formatter instance, instead of the default locale. + IntStream.range(0, src.size()).forEach(i -> { + sb.setLength(0); + Locale.setDefault(Locale.Category.FORMAT, defaultLocale.get(i)); + new Formatter(sb, formatLocale.get(i)).format(conversions.get(i), src.get(i)); + if (!sb.toString().equals(expectedWithFormatLocale.get(i))) { + throw new RuntimeException( + "Wrong uppercasing with Formatter.format(" + + "\"" + conversions.get(i) + "\"" + + ") in locale " + + formatLocale.get(i) + + ". Expected: " + expectedWithFormatLocale.get(i) + + " Returned: " + sb.toString()); + } + }); + } static void nullLocaleTest() {
genConv