/* * Copyright (c) 2008, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4831163 5053096 5056440 * @summary NIO charset basic verification of JISAutodetect decoder * @author Martin Buchholz */ import java.io.*; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import static java.lang.System.*; public class NIOJISAutoDetectTest { private static int failures = 0; private static void fail(String failureMsg) { System.out.println(failureMsg); failures++; } private static void check(boolean cond, String msg) { if (!cond) { fail("test failed: " + msg); new Exception().printStackTrace(); } } private static String SJISName() throws Exception { return detectingCharset(new byte[] {(byte)0xbb, (byte)0xdd, (byte)0xcf, (byte)0xb2}); } private static String EUCJName() throws Exception { return detectingCharset(new byte[] {(byte)0xa4, (byte)0xd2, (byte)0xa4, (byte)0xe9}); } private static String detectingCharset(byte[] bytes) throws Exception { //---------------------------------------------------------------- // Test special public methods of CharsetDecoder while we're here //---------------------------------------------------------------- CharsetDecoder cd = Charset.forName("JISAutodetect").newDecoder(); check(cd.isAutoDetecting(), "isAutodecting()"); check(! cd.isCharsetDetected(), "isCharsetDetected"); cd.decode(ByteBuffer.wrap(new byte[] {(byte)'A'})); check(! cd.isCharsetDetected(), "isCharsetDetected"); try { cd.detectedCharset(); fail("no IllegalStateException"); } catch (IllegalStateException e) {} cd.decode(ByteBuffer.wrap(bytes)); check(cd.isCharsetDetected(), "isCharsetDetected"); Charset cs = cd.detectedCharset(); check(cs != null, "cs != null"); check(! cs.newDecoder().isAutoDetecting(), "isAutodetecting()"); return cs.name(); } public static void main(String[] argv) throws Exception { //---------------------------------------------------------------- // Used to throw BufferOverflowException //---------------------------------------------------------------- out.println(new String(new byte[] {0x61}, "JISAutoDetect")); //---------------------------------------------------------------- // InputStreamReader(...JISAutoDetect) used to infloop //---------------------------------------------------------------- { byte[] bytes = "ABCD\n".getBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); InputStreamReader isr = new InputStreamReader(bais, "JISAutoDetect"); BufferedReader reader = new BufferedReader(isr); check (reader.readLine().equals("ABCD"), "first read gets text"); // used to return "ABCD" on second and subsequent reads check (reader.readLine() == null, "second read gets null"); } //---------------------------------------------------------------- // Check all Japanese chars for sanity //---------------------------------------------------------------- String SJIS = SJISName(); String EUCJ = EUCJName(); out.printf("SJIS charset is %s%n", SJIS); out.printf("EUCJ charset is %s%n", EUCJ); int cnt2022 = 0; int cnteucj = 0; int cntsjis = 0; int cntBAD = 0; for (char c = '\u0000'; c < '\uffff'; c++) { if (c == '\u001b' || // ESC c == '\u2014') // Em-Dash? continue; String s = new String (new char[] {c}); //---------------------------------------------------------------- // JISAutoDetect can handle all chars that EUC-JP can, // unless there is an ambiguity with SJIS. //---------------------------------------------------------------- byte[] beucj = s.getBytes(EUCJ); String seucj = new String(beucj, EUCJ); if (seucj.equals(s)) { cnteucj++; String sauto = new String(beucj, "JISAutoDetect"); if (! sauto.equals(seucj)) { cntBAD++; String ssjis = new String(beucj, SJIS); if (! sauto.equals(ssjis)) { fail("Autodetection agrees with neither EUC nor SJIS"); } } } else continue; // Optimization //---------------------------------------------------------------- // JISAutoDetect can handle all chars that ISO-2022-JP can. //---------------------------------------------------------------- byte[] b2022 = s.getBytes("ISO-2022-JP"); if (new String(b2022, "ISO-2022-JP").equals(s)) { cnt2022++; check(new String(b2022,"JISAutoDetect").equals(s), "ISO2022 autodetection"); } //---------------------------------------------------------------- // JISAutoDetect can handle almost all chars that SJIS can. //---------------------------------------------------------------- byte[] bsjis = s.getBytes(SJIS); if (new String(bsjis, SJIS).equals(s)) { cntsjis++; check(new String(bsjis,"JISAutoDetect").equals(s), "SJIS autodetection"); } } out.printf("There are %d ISO-2022-JP-encodable characters.%n", cnt2022); out.printf("There are %d SJIS-encodable characters.%n", cntsjis); out.printf("There are %d EUC-JP-encodable characters.%n", cnteucj); out.printf("There are %d characters that are " + "misdetected as SJIS after being EUC-encoded.%n", cntBAD); //---------------------------------------------------------------- // tests for specific byte sequences //---------------------------------------------------------------- test("ISO-2022-JP", new byte[] {'A', 'B', 'C'}); test("EUC-JP", new byte[] {'A', 'B', 'C'}); test("SJIS", new byte[] {'A', 'B', 'C'}); test("SJIS", new byte[] { 'C', 'o', 'p', 'y', 'r', 'i', 'g', 'h', 't', ' ', (byte)0xa9, ' ', '1', '9', '9', '8' }); test("SJIS", new byte[] { (byte)0xbb, (byte)0xdd, (byte)0xcf, (byte)0xb2, (byte)0xb8, (byte)0xdb, (byte)0xbc, (byte)0xbd, (byte)0xc3, (byte)0xd1, (byte)0xbd, (byte)0xde, (byte)0x82, (byte)0xc5, (byte)0x82, (byte)0xb7 }); test("EUC-JP", new byte[] { (byte)0xa4, (byte)0xd2, (byte)0xa4, (byte)0xe9, (byte)0xa4, (byte)0xac, (byte)0xa4, (byte)0xca }); test("SJIS", new byte[] { (byte)0xbb, (byte)0xdd, (byte)0xcf, (byte)0xb2, (byte)0xb8, (byte)0xdb, (byte)0xbc, (byte)0xbd, (byte)0xc3, (byte)0xd1, (byte)0xbd, (byte)0xde}); test("SJIS", new byte[] { (byte)0xbb, (byte)0xdd, (byte)0xcf, (byte)0xb2, (byte)0xb8, (byte)0xdb, (byte)0xbc, (byte)0xbd, (byte)0xc3, (byte)0xd1, (byte)0xbd }); test("SJIS", new byte[] { (byte)0x8f, (byte)0xa1, (byte)0xaa }); test("EUC-JP", new byte[] { (byte)0x8f, (byte)0xc5, (byte)0xe0, (byte)0x20}); test("EUC-JP", new byte[] { (byte)0xbb, (byte)0xdd, (byte)0xcf, (byte)0xb2, (byte)0xb8, (byte)0xdb, (byte)0xbc, (byte)0xbd, (byte)0xc3, (byte)0xd1, (byte)0xbd, (byte)0xde, (byte)0xa4, (byte)0xc7, (byte)0xa4, (byte)0xb9 }); test("ISO-2022-JP", new byte[] { 0x1b, '$', 'B', '#', '4', '$', '5', 0x1b, '(', 'B' }); //---------------------------------------------------------------- // Check handling of ambiguous end-of-input in middle of first char //---------------------------------------------------------------- { CharsetDecoder dc = Charset.forName("x-JISAutoDetect").newDecoder(); ByteBuffer bb = ByteBuffer.allocate(128); CharBuffer cb = CharBuffer.allocate(128); bb.put((byte)'A').put((byte)0x8f); bb.flip(); CoderResult res = dc.decode(bb,cb,false); check(res.isUnderflow(), "isUnderflow"); check(bb.position() == 1, "bb.position()"); check(cb.position() == 1, "cb.position()"); res = dc.decode(bb,cb,false); check(res.isUnderflow(), "isUnderflow"); check(bb.position() == 1, "bb.position()"); check(cb.position() == 1, "cb.position()"); bb.compact(); bb.put((byte)0xa1); bb.flip(); res = dc.decode(bb,cb,true); check(res.isUnderflow(), "isUnderflow"); check(bb.position() == 2, "bb.position()"); check(cb.position() == 2, "cb.position()"); } if (failures > 0) throw new RuntimeException(failures + " tests failed"); } static void checkCoderResult(CoderResult result) { check(result.isUnderflow(), "Unexpected coder result: " + result); } static void test(String expectedCharset, byte[] input) throws Exception { Charset cs = Charset.forName("x-JISAutoDetect"); CharsetDecoder autoDetect = cs.newDecoder(); Charset cs2 = Charset.forName(expectedCharset); CharsetDecoder decoder = cs2.newDecoder(); ByteBuffer bb = ByteBuffer.allocate(128); CharBuffer charOutput = CharBuffer.allocate(128); CharBuffer charExpected = CharBuffer.allocate(128); bb.put(input); bb.flip(); bb.mark(); CoderResult result = autoDetect.decode(bb, charOutput, true); checkCoderResult(result); charOutput.flip(); String actual = charOutput.toString(); bb.reset(); result = decoder.decode(bb, charExpected, true); checkCoderResult(result); charExpected.flip(); String expected = charExpected.toString(); check(actual.equals(expected), String.format("actual=%s expected=%s", actual, expected)); } }