1 /* 2 * Copyright (c) 2009, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.util.zip; 27 28 import java.nio.ByteBuffer; 29 import java.nio.CharBuffer; 30 import java.nio.charset.Charset; 31 import java.nio.charset.CharsetDecoder; 32 import java.nio.charset.CharsetEncoder; 33 import java.nio.charset.CharacterCodingException; 34 import java.nio.charset.CodingErrorAction; 35 36 /** 37 * Utility class for zipfile name and comment decoding and encoding 38 */ 39 40 class ZipCoder { 41 42 private static final jdk.internal.misc.JavaLangAccess JLA = 43 jdk.internal.misc.SharedSecrets.getJavaLangAccess(); 44 45 static final class UTF8 extends ZipCoder { 46 47 UTF8() { super(java.nio.charset.StandardCharsets.UTF_8); } 48 49 @Override 50 boolean isUTF8() { 51 return true; 52 } 53 54 @Override 55 String toString(byte[] ba, int off, int length) { 56 return JLA.newStringUTF8NoRepl(ba, off, length); 57 } 58 59 @Override 60 byte[] getBytes(String s) { 61 return JLA.getBytesUTF8NoRepl(s); 62 } 63 } 64 65 // UTF_8.ArrayEn/Decoder is stateless, so make it singleton. 66 private static final ZipCoder utf8 = new UTF8(); 67 68 public static ZipCoder get(Charset charset) { 69 if (charset == java.nio.charset.StandardCharsets.UTF_8) 70 return utf8; 71 return new ZipCoder(charset); 72 } 73 74 String toString(byte[] ba, int off, int length) { 75 try { 76 return decoder().decode(ByteBuffer.wrap(ba, off, length)).toString(); 77 } catch (CharacterCodingException x) { 78 throw new IllegalArgumentException(x); 79 } 80 } 81 82 String toString(byte[] ba, int length) { 83 return toString(ba, 0, length); 84 } 85 86 String toString(byte[] ba) { 87 return toString(ba, 0, ba.length); 88 } 89 90 byte[] getBytes(String s) { 91 try { 92 ByteBuffer bb = encoder().encode(CharBuffer.wrap(s)); 93 int pos = bb.position(); 94 int limit = bb.limit(); 95 if (bb.hasArray() && pos == 0 && limit == bb.capacity()) { 96 return bb.array(); 97 } 98 byte[] bytes = new byte[bb.limit() - bb.position()]; 99 bb.get(bytes); 100 return bytes; 101 } catch (CharacterCodingException x) { 102 throw new IllegalArgumentException(x); 103 } 104 } 105 106 static byte[] getBytesUTF8(String s) { 107 return JLA.getBytesUTF8NoRepl(s); 108 } 109 110 static String toStringUTF8(byte[] ba, int len) { 111 return JLA.newStringUTF8NoRepl(ba, 0, len); 112 } 113 114 static String toStringUTF8(byte[] ba, int off, int len) { 115 return JLA.newStringUTF8NoRepl(ba, off, len); 116 } 117 118 boolean isUTF8() { 119 return false; 120 } 121 122 private final Charset cs; 123 private CharsetDecoder dec; 124 private CharsetEncoder enc; 125 126 private ZipCoder(Charset cs) { 127 this.cs = cs; 128 } 129 130 protected CharsetDecoder decoder() { 131 final CharsetDecoder dec = this.dec; 132 return (dec != null) ? dec : 133 (this.dec = cs.newDecoder() 134 .onMalformedInput(CodingErrorAction.REPORT) 135 .onUnmappableCharacter(CodingErrorAction.REPORT)); 136 } 137 138 protected CharsetEncoder encoder() { 139 final CharsetEncoder enc = this.enc; 140 return (enc != null) ? enc : 141 (this.enc = cs.newEncoder() 142 .onMalformedInput(CodingErrorAction.REPORT) 143 .onUnmappableCharacter(CodingErrorAction.REPORT)); 144 } 145 }