src/java.base/share/classes/java/lang/StringCoding.java
Print this page
@@ -213,25 +213,69 @@
CharsetDecoder cd = cs.newDecoder();
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
if (len == 0)
return ca;
- boolean isTrusted = false;
- if (System.getSecurityManager() != null) {
- if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
+
+ boolean isTrusted = isTrusted(cs);
+ if (!isTrusted) {
ba = Arrays.copyOfRange(ba, off, off + len);
off = 0;
}
- }
- cd.onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE)
- .reset();
+
+ setupDecoder(cd);
+
if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+ return performDecode(cs, isTrusted, ca, cd, bb);
+ }
+ }
+
+ static char[] decode(Charset cs, ByteBuffer bb) {
+ // See comment at top of decode(Charset,byte[],int,int)
+ CharsetDecoder cd = cs.newDecoder();
+ int len = bb.remaining();
+ int en = scale(len, cd.maxCharsPerByte());
+ char[] ca = new char[en];
+ if (len == 0)
+ return ca;
+
+ boolean isTrusted = isTrusted(cs);
+ if (!isTrusted) {
+ // setup the bytebuffer for copying
+
+ // copy the bytebuffer
+ ByteBuffer originalByteBuffer = bb;
+ bb = ByteBuffer.allocateDirect(len)
+ .put(originalByteBuffer);
+ bb.position(0);
+ }
+
+ setupDecoder(cd);
+
+ return performDecode(cs, isTrusted, ca, cd, bb);
+ }
+
+ private static boolean isTrusted(Charset cs) {
+ return System.getSecurityManager() != null
+ // null classloader means the class is on the boot classpath
+ && cs.getClass().getClassLoader0() == null;
+ }
+
+ private static void setupDecoder(CharsetDecoder cd) {
+ cd.onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset();
+ }
+
+ static char[] performDecode(
+ Charset cs, boolean isTrusted, char[] ca,
+ CharsetDecoder cd, ByteBuffer bb) {
+
CharBuffer cb = CharBuffer.wrap(ca);
try {
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
cr.throwException();
@@ -243,11 +287,10 @@
// so this shouldn't happen
throw new Error(x);
}
return safeTrim(ca, cb.position(), cs, isTrusted);
}
- }
static char[] decode(byte[] ba, int off, int len) {
String csn = Charset.defaultCharset().name();
try {
// use charset name decode() variant which provides caching.
@@ -348,20 +391,16 @@
CharsetEncoder ce = cs.newEncoder();
int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en];
if (len == 0)
return ba;
- boolean isTrusted = false;
- if (System.getSecurityManager() != null) {
- if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
+ boolean isTrusted = isTrusted(cs);
+ if (!isTrusted) {
ca = Arrays.copyOfRange(ca, off, off + len);
off = 0;
}
- }
- ce.onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE)
- .reset();
+ setupEncoder(ce);
if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ByteBuffer bb = ByteBuffer.wrap(ba);
@@ -378,10 +417,38 @@
}
return safeTrim(ba, bb.position(), cs, isTrusted);
}
}
+ static int encode(Charset cs, char[] ca, int off, int len, byte[] destBuffer, int destOffset) {
+ ByteBuffer bb = ByteBuffer.wrap(destBuffer, destOffset, destBuffer.length - destOffset);
+ return encode(cs, ca, off, len, bb);
+ }
+
+ static int encode(Charset cs, char[] ca, int off, int len, ByteBuffer destBuffer) {
+ CharsetEncoder ce = cs.newEncoder();
+ final int originalPosition = destBuffer.position();
+ CharBuffer cb = CharBuffer.wrap(ca, off, len);
+ try {
+ CoderResult cr = ce.encode(cb, destBuffer, true);
+ if (!cr.isUnderflow())
+ cr.throwException();
+ cr = ce.flush(destBuffer);
+ if (!cr.isUnderflow())
+ cr.throwException();
+ } catch (CharacterCodingException x) {
+ throw new Error(x);
+ }
+ return destBuffer.position() - originalPosition;
+ }
+
+ private static void setupEncoder(CharsetEncoder encoder) {
+ encoder.onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset();
+ }
+
static byte[] encode(char[] ca, int off, int len) {
String csn = Charset.defaultCharset().name();
try {
// use charset name encode() variant which provides caching.
return encode(csn, ca, off, len);