1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 8159420 27 * @summary Checks the proper execution of LanguageRange.parse() and 28 * other LocaleMatcher methods when used in the locales like 29 * Turkish, because the toLowerCase() method is invoked in the 30 * parse() and other LocaleMatcher methods. 31 * e.g. "HI-Deva".toLowerCase() in the Turkish locale returns 32 * "h��-deva", where '��' is the LATIN SMALL LETTER DOTLESS I character 33 * which is not allowed in the language ranges/tags. 34 * @compile -encoding utf-8 Bug8159420.java 35 * @run main Bug8159420 36 */ 37 38import java.util.List; 39import java.util.Locale; 40import java.util.Locale.LanguageRange; 41import java.util.Locale.FilteringMode; 42import java.util.LinkedHashMap; 43import java.util.HashMap; 44import java.util.Iterator; 45import java.util.ArrayList; 46import static java.util.Locale.FilteringMode.EXTENDED_FILTERING; 47import static java.util.Locale.FilteringMode.AUTOSELECT_FILTERING; 48 49public class Bug8159420 { 50 51 static boolean err = false; 52 53 public static void main(String[] args) { 54 55 Locale origLocale = null; 56 try { 57 58 origLocale = Locale.getDefault(); 59 Locale.setDefault(new Locale("tr", "TR")); 60 testParse(); 61 testFilter(EXTENDED_FILTERING); 62 testFilter(AUTOSELECT_FILTERING); 63 testLookup(); 64 testMapEquivalents(); 65 66 if (err) { 67 throw new RuntimeException("[LocaleMatcher method(s) in turkish" 68 + " locale failed]"); 69 } 70 71 } finally { 72 Locale.setDefault(origLocale); 73 } 74 75 } 76 77 /* Before the fix, the testParse() method was throwing 78 * IllegalArgumentException in Turkish Locale 79 */ 80 private static void testParse() { 81 String ranges = "HI-Deva, ja-hIrA-JP, RKI"; 82 try { 83 LanguageRange.parse(ranges); 84 } catch (Exception ex) { 85 System.err.println("[testParse() failed on range string: " 86 + ranges + "] due to "+ex); 87 err = true; 88 } 89 } 90 91 /* Before the fix, the testFilter() method was returning empty list in 92 * Turkish Locale 93 */ 94 private static void testFilter(FilteringMode mode) { 95 96 String ranges = "hi-IN, itc-Ital"; 97 String tags = "hi-IN, itc-Ital"; 98 List<LanguageRange> priorityList = LanguageRange.parse(ranges); 99 List<Locale> tagList = generateLocales(tags); 100 String actualLocales = showLocales(Locale.filter(priorityList, tagList, mode)); 101 String expectedLocales = "hi-IN, itc-Ital"; 102 103 if (!expectedLocales.equals(actualLocales)) { 104 System.err.println("testFilter(" + mode + ") failed on language ranges:" 105 + " [" + ranges + "] and language tags: [" + tags + "]"); 106 err = true; 107 } 108 } 109 110 /* Before the fix, the testLookup() method was returning null in Turkish 111 * Locale 112 */ 113 private static void testLookup() { 114 boolean error = false; 115 String ranges = "hi-IN, itc-Ital"; 116 String tags = "hi-IN, itc-Ital"; 117 List<LanguageRange> priorityList = LanguageRange.parse(ranges); 118 List<Locale> localeList = generateLocales(tags); 119 Locale actualLocale 120 = Locale.lookup(priorityList, localeList); 121 String actualLocaleString = ""; 122 123 if (actualLocale != null) { 124 actualLocaleString = actualLocale.toLanguageTag(); 125 } else { 126 error = true; 127 } 128 129 String expectedLocale = "hi-IN"; 130 131 if (!expectedLocale.equals(actualLocaleString)) { 132 error = true; 133 } 134 135 if (error) { 136 System.err.println("testLookup() failed on language ranges:" 137 + " [" + ranges + "] and language tags: [" + tags + "]"); 138 err = true; 139 } 140 141 } 142 143 /* Before the fix, testMapEquivalents() method was returning only "hi-in" 144 * in Turkish Locale 145 */ 146 private static void testMapEquivalents() { 147 148 String ranges = "HI-IN"; 149 List<LanguageRange> priorityList = LanguageRange.parse(ranges); 150 HashMap<String, List<String>> map = new LinkedHashMap<>(); 151 List<String> equivalentList = new ArrayList<>(); 152 equivalentList.add("HI"); 153 equivalentList.add("HI-Deva"); 154 map.put("HI", equivalentList); 155 156 List<LanguageRange> expected = new ArrayList<>(); 157 expected.add(new LanguageRange("hi-in")); 158 expected.add(new LanguageRange("hi-deva-in")); 159 List<LanguageRange> got 160 = LanguageRange.mapEquivalents(priorityList, map); 161 162 if (!areEqual(expected, got)) { 163 System.err.println("testMapEquivalents() failed"); 164 err = true; 165 } 166 167 } 168 169 private static boolean areEqual(List<LanguageRange> expected, 170 List<LanguageRange> got) { 171 172 boolean error = false; 173 if (expected.equals(got)) { 174 return !error; 175 } 176 177 List<LanguageRange> cloneExpected = new ArrayList<>(expected); 178 cloneExpected.removeAll(got); 179 if (!cloneExpected.isEmpty()) { 180 error = true; 181 System.err.println("Found missing range(s): " + cloneExpected); 182 } 183 184 // not creating the 'got' clone as the list will not be used after this 185 got.removeAll(expected); 186 if (!got.isEmpty()) { 187 error = true; 188 System.err.println("Found extra range(s): " + got); 189 } 190 return !error; 191 } 192 193 private static List<Locale> generateLocales(String tags) { 194 if (tags == null) { 195 return null; 196 } 197 198 List<Locale> localeList = new ArrayList<>(); 199 if (tags.equals("")) { 200 return localeList; 201 } 202 String[] t = tags.split(", "); 203 for (String tag : t) { 204 localeList.add(Locale.forLanguageTag(tag)); 205 } 206 return localeList; 207 } 208 209 private static String showLocales(List<Locale> locales) { 210 StringBuilder sb = new StringBuilder(); 211 212 Iterator<Locale> itr = locales.iterator(); 213 if (itr.hasNext()) { 214 sb.append(itr.next().toLanguageTag()); 215 } 216 while (itr.hasNext()) { 217 sb.append(", "); 218 sb.append(itr.next().toLanguageTag()); 219 } 220 221 return sb.toString().trim(); 222 } 223 224} 225