1/* 2 * Copyright (c) 2015, 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 * @test 25 * @bug 8027607 26 * @summary Test UTF-8 based properties files can be loaded successfully, 27 * @run main CodePointTest 28 * @run main/othervm -Djava.util.PropertyResourceBundle.encoding=ISO-8859-1 CodePointTest 29 * @run main/othervm -Djava.util.PropertyResourceBundle.encoding=UTF-8 CodePointTest 30 */ 31 32import java.io.*; 33import java.nio.charset.*; 34import java.nio.file.*; 35import java.util.*; 36import static java.util.ResourceBundle.Control; 37import java.util.stream.*; 38 39/* 40 * Dumps every legal characters in ISO-8859-1/UTF-8 into 41 * a <CharSet>.properties file. Each entry has a form of 42 * "keyXXXX=c", where "XXXX" is a code point (variable length) 43 * and "c" is the character encoded in the passed character set. 44 * Then, load it with ResourceBundle.Control.newBundle() and compare both 45 * contents. This confirms the following two functions: 46 * - For UTF-8.properties, UTF-8 code points are loaded correctly 47 * - For ISO-8859-1.properties, UTF-8->ISO-8859-1 fallback works 48 * 49 * Does the same test with "java.util.PropertyResourceBundle.encoding" 50 * to "ISO-8859-1", and confirms only UTF-8 properties loading fails. 51 */ 52public class CodePointTest { 53 static final Charset[] props = {StandardCharsets.ISO_8859_1, 54 StandardCharsets.UTF_8, 55 StandardCharsets.US_ASCII}; 56 static final String encoding = 57 System.getProperty("java.util.PropertyResourceBundle.encoding", ""); 58 59 public static void main(String[] args) { 60 for (Charset cs : props) { 61 try { 62 checkProps(cs, 63 cs == StandardCharsets.UTF_8 && 64 encoding.equals("ISO-8859-1")); 65 66 if (cs == StandardCharsets.ISO_8859_1 && 67 encoding.equals("UTF-8")) { 68 // should not happen 69 throw new RuntimeException("Reading ISO-8859-1 properties in "+ 70 "strict UTF-8 encoding should throw an exception"); 71 } 72 } catch (IOException e) { 73 if ((e instanceof MalformedInputException || 74 e instanceof UnmappableCharacterException) && 75 cs == StandardCharsets.ISO_8859_1 && 76 encoding.equals("UTF-8")) { 77 // Expected exception is correctly detected. 78 } else { 79 throw new RuntimeException(e); 80 } 81 } 82 } 83 } 84 85 static void checkProps(Charset cs, boolean shouldFail) throws IOException { 86 int start = Character.MIN_CODE_POINT; 87 int end= 0; 88 89 switch (cs.name()) { 90 case "ISO-8859-1": 91 end = 0xff; 92 break; 93 case "UTF-8": 94 end = Character.MAX_CODE_POINT; 95 break; 96 case "US-ASCII": 97 end = 0x7f; 98 break; 99 default: 100 assert false; 101 } 102 103 Properties p = new Properties(); 104 String outputName = cs.name() + ".properties"; 105 106 // Forget previous test artifacts 107 ResourceBundle.clearCache(); 108 109 IntStream.range(start, end+1).forEach(c -> 110 { 111 if (Character.isDefined(c) && 112 (Character.isSupplementaryCodePoint(c) || 113 !Character.isSurrogate((char)c))) { 114 p.setProperty("key"+Integer.toHexString(c), 115 Character.isSupplementaryCodePoint(c) ? 116 String.valueOf(Character.toChars(c)) : 117 Character.toString((char)c)); 118 } 119 } 120 ); 121 122 try (BufferedWriter bw = Files.newBufferedWriter( 123 FileSystems.getDefault().getPath(System.getProperty("test.classes", "."), 124 outputName), cs)) { 125 p.store(bw, null); 126 } catch (IOException ex) { 127 throw new RuntimeException(ex); 128 } 129 130 // try loading it 131 Control c = Control.getControl(Control.FORMAT_PROPERTIES); 132 ResourceBundle rb; 133 try { 134 rb = c.newBundle(cs.name(), Locale.ROOT, "java.properties", 135 CodePointTest.class.getClassLoader(), false); 136 } catch (IllegalAccessException | 137 InstantiationException ex) { 138 throw new RuntimeException(ex); 139 } 140 Properties result = new Properties(); 141 rb.keySet().stream().forEach((key) -> { 142 result.setProperty(key, rb.getString(key)); 143 }); 144 145 if (!p.equals(result) && !shouldFail) { 146 System.out.println("Charset: "+cs); 147 rb.keySet().stream().sorted().forEach((key) -> { 148 if (!p.getProperty(key).equals(result.getProperty(key))) { 149 System.out.println(key+": file: "+p.getProperty(key)+", RB: "+result.getProperty(key)); 150 } 151 }); 152 throw new RuntimeException("not equal!"); 153 } 154 } 155} 156