22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.io.ObjectStreamClass.WeakClassKey;
29 import java.lang.ref.ReferenceQueue;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Modifier;
32 import java.lang.reflect.Proxy;
33 import java.security.AccessControlContext;
34 import java.security.AccessController;
35 import java.security.PrivilegedAction;
36 import java.security.PrivilegedActionException;
37 import java.security.PrivilegedExceptionAction;
38 import java.util.Arrays;
39 import java.util.HashMap;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.ConcurrentMap;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import static java.io.ObjectStreamClass.processQueue;
44 import sun.reflect.misc.ReflectUtil;
45
46 /**
47 * An ObjectInputStream deserializes primitive data and objects previously
48 * written using an ObjectOutputStream.
49 *
50 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
51 * persistent storage for graphs of objects when used with a FileOutputStream
52 * and FileInputStream respectively. ObjectInputStream is used to recover
53 * those objects previously serialized. Other uses include passing objects
54 * between hosts using a socket stream or for marshaling and unmarshaling
55 * arguments and parameters in a remote communication system.
56 *
57 * <p>ObjectInputStream ensures that the types of all objects in the graph
58 * created from the stream match the classes present in the Java Virtual
59 * Machine. Classes are loaded as required using the standard mechanisms.
60 *
61 * <p>Only objects that support the java.io.Serializable or
62 * java.io.Externalizable interface can be read from streams.
517 /**
518 * Reads the persistent fields from the stream and makes them available by
519 * name.
520 *
521 * @return the <code>GetField</code> object representing the persistent
522 * fields of the object being deserialized
523 * @throws ClassNotFoundException if the class of a serialized object
524 * could not be found.
525 * @throws IOException if an I/O error occurs.
526 * @throws NotActiveException if the stream is not currently reading
527 * objects.
528 * @since 1.2
529 */
530 public ObjectInputStream.GetField readFields()
531 throws IOException, ClassNotFoundException
532 {
533 SerialCallbackContext ctx = curContext;
534 if (ctx == null) {
535 throw new NotActiveException("not in call to readObject");
536 }
537 Object curObj = ctx.getObj();
538 ObjectStreamClass curDesc = ctx.getDesc();
539 bin.setBlockDataMode(false);
540 GetFieldImpl getField = new GetFieldImpl(curDesc);
541 getField.readFields();
542 bin.setBlockDataMode(true);
543 if (!curDesc.hasWriteObjectData()) {
544 /*
545 * Fix for 4360508: since stream does not contain terminating
546 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
547 * knows to simulate end-of-custom-data behavior.
548 */
549 defaultDataEnd = true;
550 }
551
552 return getField;
553 }
554
555 /**
556 * Register an object to be validated before the graph is returned. While
557 * similar to resolveObject these validations are called after the entire
1580 return desc;
1581 }
1582
1583 /**
1584 * Reads in and returns class descriptor for a class that is not a dynamic
1585 * proxy class. Sets passHandle to class descriptor's assigned handle. If
1586 * class descriptor cannot be resolved to a class in the local VM, a
1587 * ClassNotFoundException is associated with the descriptor's handle.
1588 */
1589 private ObjectStreamClass readNonProxyDesc(boolean unshared)
1590 throws IOException
1591 {
1592 if (bin.readByte() != TC_CLASSDESC) {
1593 throw new InternalError();
1594 }
1595
1596 ObjectStreamClass desc = new ObjectStreamClass();
1597 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1598 passHandle = NULL_HANDLE;
1599
1600 ObjectStreamClass readDesc = null;
1601 try {
1602 readDesc = readClassDescriptor();
1603 } catch (ClassNotFoundException ex) {
1604 throw (IOException) new InvalidClassException(
1605 "failed to read class descriptor").initCause(ex);
1606 }
1607
1608 Class<?> cl = null;
1609 ClassNotFoundException resolveEx = null;
1610 bin.setBlockDataMode(true);
1611 final boolean checksRequired = isCustomSubclass();
1612 try {
1613 if ((cl = resolveClass(readDesc)) == null) {
1614 resolveEx = new ClassNotFoundException("null class");
1615 } else if (checksRequired) {
1616 ReflectUtil.checkPackageAccess(cl);
1617 }
1618 } catch (ClassNotFoundException ex) {
1619 resolveEx = ex;
1620 }
1959 readObject0(false);
1960 break;
1961 }
1962 }
1963 }
1964
1965 /**
1966 * Reads in values of serializable fields declared by given class
1967 * descriptor. If obj is non-null, sets field values in obj. Expects that
1968 * passHandle is set to obj's handle before this method is called.
1969 */
1970 private void defaultReadFields(Object obj, ObjectStreamClass desc)
1971 throws IOException
1972 {
1973 Class<?> cl = desc.forClass();
1974 if (cl != null && obj != null && !cl.isInstance(obj)) {
1975 throw new ClassCastException();
1976 }
1977
1978 int primDataSize = desc.getPrimDataSize();
1979 if (primVals == null || primVals.length < primDataSize) {
1980 primVals = new byte[primDataSize];
1981 }
1982 bin.readFully(primVals, 0, primDataSize, false);
1983 if (obj != null) {
1984 desc.setPrimFieldValues(obj, primVals);
1985 }
1986
1987 int objHandle = passHandle;
1988 ObjectStreamField[] fields = desc.getFields(false);
1989 Object[] objVals = new Object[desc.getNumObjFields()];
1990 int numPrimFields = fields.length - objVals.length;
1991 for (int i = 0; i < objVals.length; i++) {
1992 ObjectStreamField f = fields[numPrimFields + i];
1993 objVals[i] = readObject0(f.isUnshared());
1994 if (f.getField() != null) {
1995 handles.markDependency(objHandle, passHandle);
1996 }
1997 }
1998 if (obj != null) {
1999 desc.setObjFieldValues(obj, objVals);
2000 }
2001 passHandle = objHandle;
2002 }
2003
2004 /**
2005 * Reads in and returns IOException that caused serialization to abort.
2006 * All stream state is discarded prior to reading in fatal exception. Sets
2007 * passHandle to fatal exception's handle.
2008 */
2009 private IOException readFatalException() throws IOException {
2010 if (bin.readByte() != TC_EXCEPTION) {
2011 throw new InternalError();
2012 }
2013 clear();
2014 return (IOException) readObject0(false);
2015 }
2016
2017 /**
2018 * If recursion depth is 0, clears internal data structures; otherwise,
2019 * throws a StreamCorruptedException. This method is called when a
2020 * TC_RESET typecode is encountered.
2021 */
2022 private void handleReset() throws StreamCorruptedException {
2360 * for details). Buffering depends on block data mode: when in default
2361 * mode, no data is buffered in advance; when in block data mode, all data
2362 * for the current data block is read in at once (and buffered).
2363 */
2364 private class BlockDataInputStream
2365 extends InputStream implements DataInput
2366 {
2367 /** maximum data block length */
2368 private static final int MAX_BLOCK_SIZE = 1024;
2369 /** maximum data block header length */
2370 private static final int MAX_HEADER_SIZE = 5;
2371 /** (tunable) length of char buffer (for reading strings) */
2372 private static final int CHAR_BUF_SIZE = 256;
2373 /** readBlockHeader() return value indicating header read may block */
2374 private static final int HEADER_BLOCKED = -2;
2375
2376 /** buffer for reading general/block data */
2377 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2378 /** buffer for reading block data headers */
2379 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2380 /** char buffer for fast string reads */
2381 private final char[] cbuf = new char[CHAR_BUF_SIZE];
2382
2383 /** block data mode */
2384 private boolean blkmode = false;
2385
2386 // block data state fields; values meaningful only when blkmode true
2387 /** current offset into buf */
2388 private int pos = 0;
2389 /** end offset of valid data in buf, or -1 if no more block data */
2390 private int end = -1;
2391 /** number of bytes in current block yet to be read from stream */
2392 private int unread = 0;
2393
2394 /** underlying stream (wrapped in peekable filter stream) */
2395 private final PeekInputStream in;
2396 /** loopback stream (for data reads that span data blocks) */
2397 private final DataInputStream din;
2398
2399 /**
2400 * Creates new BlockDataInputStream on top of given underlying stream.
2401 * Block data mode is turned off by default.
3027 off += span;
3028 pos += span << 3;
3029 }
3030 }
3031
3032 /**
3033 * Reads in string written in "long" UTF format. "Long" UTF format is
3034 * identical to standard UTF, except that it uses an 8 byte header
3035 * (instead of the standard 2 bytes) to convey the UTF encoding length.
3036 */
3037 String readLongUTF() throws IOException {
3038 return readUTFBody(readLong());
3039 }
3040
3041 /**
3042 * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3043 * or 8-byte length header) of a UTF encoding, which occupies the next
3044 * utflen bytes.
3045 */
3046 private String readUTFBody(long utflen) throws IOException {
3047 StringBuilder sbuf = new StringBuilder();
3048 if (!blkmode) {
3049 end = pos = 0;
3050 }
3051
3052 while (utflen > 0) {
3053 int avail = end - pos;
3054 if (avail >= 3 || (long) avail == utflen) {
3055 utflen -= readUTFSpan(sbuf, utflen);
3056 } else {
3057 if (blkmode) {
3058 // near block boundary, read one byte at a time
3059 utflen -= readUTFChar(sbuf, utflen);
3060 } else {
3061 // shift and refill buffer manually
3062 if (avail > 0) {
3063 System.arraycopy(buf, pos, buf, 0, avail);
3064 }
3065 pos = 0;
3066 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3067 in.readFully(buf, avail, end - avail);
3068 }
3069 }
3070 }
3071
3072 return sbuf.toString();
3073 }
3074
3075 /**
3076 * Reads span of UTF-encoded characters out of internal buffer
3077 * (starting at offset pos and ending at or before offset end),
3078 * consuming no more than utflen bytes. Appends read characters to
3079 * sbuf. Returns the number of bytes consumed.
3080 */
3081 private long readUTFSpan(StringBuilder sbuf, long utflen)
3082 throws IOException
3083 {
3084 int cpos = 0;
3085 int start = pos;
3086 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3087 // stop short of last char unless all of utf bytes in buffer
3088 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3089 boolean outOfBounds = false;
3090
3091 try {
3092 while (pos < stop) {
3093 int b1, b2, b3;
3094 b1 = buf[pos++] & 0xFF;
3095 switch (b1 >> 4) {
3096 case 0:
3097 case 1:
3098 case 2:
3099 case 3:
3100 case 4:
3101 case 5:
3133 } catch (ArrayIndexOutOfBoundsException ex) {
3134 outOfBounds = true;
3135 } finally {
3136 if (outOfBounds || (pos - start) > utflen) {
3137 /*
3138 * Fix for 4450867: if a malformed utf char causes the
3139 * conversion loop to scan past the expected end of the utf
3140 * string, only consume the expected number of utf bytes.
3141 */
3142 pos = start + (int) utflen;
3143 throw new UTFDataFormatException();
3144 }
3145 }
3146
3147 sbuf.append(cbuf, 0, cpos);
3148 return pos - start;
3149 }
3150
3151 /**
3152 * Reads in single UTF-encoded character one byte at a time, appends
3153 * the character to sbuf, and returns the number of bytes consumed.
3154 * This method is used when reading in UTF strings written in block
3155 * data mode to handle UTF-encoded characters which (potentially)
3156 * straddle block-data boundaries.
3157 */
3158 private int readUTFChar(StringBuilder sbuf, long utflen)
3159 throws IOException
3160 {
3161 int b1, b2, b3;
3162 b1 = readByte() & 0xFF;
3163 switch (b1 >> 4) {
3164 case 0:
3165 case 1:
3166 case 2:
3167 case 3:
3168 case 4:
3169 case 5:
3170 case 6:
3171 case 7: // 1 byte format: 0xxxxxxx
3172 sbuf.append((char) b1);
3173 return 1;
3174
3175 case 12:
3176 case 13: // 2 byte format: 110xxxxx 10xxxxxx
3177 if (utflen < 2) {
3178 throw new UTFDataFormatException();
|
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.io.ObjectStreamClass.WeakClassKey;
29 import java.lang.ref.ReferenceQueue;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Modifier;
32 import java.lang.reflect.Proxy;
33 import java.security.AccessControlContext;
34 import java.security.AccessController;
35 import java.security.PrivilegedAction;
36 import java.security.PrivilegedActionException;
37 import java.security.PrivilegedExceptionAction;
38 import java.util.Arrays;
39 import java.util.HashMap;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.ConcurrentMap;
42 import static java.io.ObjectStreamClass.processQueue;
43 import sun.reflect.misc.ReflectUtil;
44
45 /**
46 * An ObjectInputStream deserializes primitive data and objects previously
47 * written using an ObjectOutputStream.
48 *
49 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
50 * persistent storage for graphs of objects when used with a FileOutputStream
51 * and FileInputStream respectively. ObjectInputStream is used to recover
52 * those objects previously serialized. Other uses include passing objects
53 * between hosts using a socket stream or for marshaling and unmarshaling
54 * arguments and parameters in a remote communication system.
55 *
56 * <p>ObjectInputStream ensures that the types of all objects in the graph
57 * created from the stream match the classes present in the Java Virtual
58 * Machine. Classes are loaded as required using the standard mechanisms.
59 *
60 * <p>Only objects that support the java.io.Serializable or
61 * java.io.Externalizable interface can be read from streams.
516 /**
517 * Reads the persistent fields from the stream and makes them available by
518 * name.
519 *
520 * @return the <code>GetField</code> object representing the persistent
521 * fields of the object being deserialized
522 * @throws ClassNotFoundException if the class of a serialized object
523 * could not be found.
524 * @throws IOException if an I/O error occurs.
525 * @throws NotActiveException if the stream is not currently reading
526 * objects.
527 * @since 1.2
528 */
529 public ObjectInputStream.GetField readFields()
530 throws IOException, ClassNotFoundException
531 {
532 SerialCallbackContext ctx = curContext;
533 if (ctx == null) {
534 throw new NotActiveException("not in call to readObject");
535 }
536 ctx.checkAndSetUsed();
537 ObjectStreamClass curDesc = ctx.getDesc();
538 bin.setBlockDataMode(false);
539 GetFieldImpl getField = new GetFieldImpl(curDesc);
540 getField.readFields();
541 bin.setBlockDataMode(true);
542 if (!curDesc.hasWriteObjectData()) {
543 /*
544 * Fix for 4360508: since stream does not contain terminating
545 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
546 * knows to simulate end-of-custom-data behavior.
547 */
548 defaultDataEnd = true;
549 }
550
551 return getField;
552 }
553
554 /**
555 * Register an object to be validated before the graph is returned. While
556 * similar to resolveObject these validations are called after the entire
1579 return desc;
1580 }
1581
1582 /**
1583 * Reads in and returns class descriptor for a class that is not a dynamic
1584 * proxy class. Sets passHandle to class descriptor's assigned handle. If
1585 * class descriptor cannot be resolved to a class in the local VM, a
1586 * ClassNotFoundException is associated with the descriptor's handle.
1587 */
1588 private ObjectStreamClass readNonProxyDesc(boolean unshared)
1589 throws IOException
1590 {
1591 if (bin.readByte() != TC_CLASSDESC) {
1592 throw new InternalError();
1593 }
1594
1595 ObjectStreamClass desc = new ObjectStreamClass();
1596 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1597 passHandle = NULL_HANDLE;
1598
1599 ObjectStreamClass readDesc;
1600 try {
1601 readDesc = readClassDescriptor();
1602 } catch (ClassNotFoundException ex) {
1603 throw (IOException) new InvalidClassException(
1604 "failed to read class descriptor").initCause(ex);
1605 }
1606
1607 Class<?> cl = null;
1608 ClassNotFoundException resolveEx = null;
1609 bin.setBlockDataMode(true);
1610 final boolean checksRequired = isCustomSubclass();
1611 try {
1612 if ((cl = resolveClass(readDesc)) == null) {
1613 resolveEx = new ClassNotFoundException("null class");
1614 } else if (checksRequired) {
1615 ReflectUtil.checkPackageAccess(cl);
1616 }
1617 } catch (ClassNotFoundException ex) {
1618 resolveEx = ex;
1619 }
1958 readObject0(false);
1959 break;
1960 }
1961 }
1962 }
1963
1964 /**
1965 * Reads in values of serializable fields declared by given class
1966 * descriptor. If obj is non-null, sets field values in obj. Expects that
1967 * passHandle is set to obj's handle before this method is called.
1968 */
1969 private void defaultReadFields(Object obj, ObjectStreamClass desc)
1970 throws IOException
1971 {
1972 Class<?> cl = desc.forClass();
1973 if (cl != null && obj != null && !cl.isInstance(obj)) {
1974 throw new ClassCastException();
1975 }
1976
1977 int primDataSize = desc.getPrimDataSize();
1978 if (primDataSize > 0) {
1979 if (primVals == null || primVals.length < primDataSize) {
1980 primVals = new byte[primDataSize];
1981 }
1982 bin.readFully(primVals, 0, primDataSize, false);
1983 if (obj != null) {
1984 desc.setPrimFieldValues(obj, primVals);
1985 }
1986 }
1987
1988 int numObjFields = desc.getNumObjFields();
1989 if (numObjFields > 0) {
1990 int objHandle = passHandle;
1991 ObjectStreamField[] fields = desc.getFields(false);
1992 Object[] objVals = new Object[numObjFields];
1993 int numPrimFields = fields.length - objVals.length;
1994 for (int i = 0; i < objVals.length; i++) {
1995 ObjectStreamField f = fields[numPrimFields + i];
1996 objVals[i] = readObject0(f.isUnshared());
1997 if (f.getField() != null) {
1998 handles.markDependency(objHandle, passHandle);
1999 }
2000 }
2001 if (obj != null) {
2002 desc.setObjFieldValues(obj, objVals);
2003 }
2004 passHandle = objHandle;
2005 }
2006 }
2007
2008 /**
2009 * Reads in and returns IOException that caused serialization to abort.
2010 * All stream state is discarded prior to reading in fatal exception. Sets
2011 * passHandle to fatal exception's handle.
2012 */
2013 private IOException readFatalException() throws IOException {
2014 if (bin.readByte() != TC_EXCEPTION) {
2015 throw new InternalError();
2016 }
2017 clear();
2018 return (IOException) readObject0(false);
2019 }
2020
2021 /**
2022 * If recursion depth is 0, clears internal data structures; otherwise,
2023 * throws a StreamCorruptedException. This method is called when a
2024 * TC_RESET typecode is encountered.
2025 */
2026 private void handleReset() throws StreamCorruptedException {
2364 * for details). Buffering depends on block data mode: when in default
2365 * mode, no data is buffered in advance; when in block data mode, all data
2366 * for the current data block is read in at once (and buffered).
2367 */
2368 private class BlockDataInputStream
2369 extends InputStream implements DataInput
2370 {
2371 /** maximum data block length */
2372 private static final int MAX_BLOCK_SIZE = 1024;
2373 /** maximum data block header length */
2374 private static final int MAX_HEADER_SIZE = 5;
2375 /** (tunable) length of char buffer (for reading strings) */
2376 private static final int CHAR_BUF_SIZE = 256;
2377 /** readBlockHeader() return value indicating header read may block */
2378 private static final int HEADER_BLOCKED = -2;
2379
2380 /** buffer for reading general/block data */
2381 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2382 /** buffer for reading block data headers */
2383 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2384 /** char buffer for fast string reads - used by {@link #readUTFSpan(long)} */
2385 private final char[] cbuf = new char[CHAR_BUF_SIZE];
2386 /** shared string builder for less object allocations - used by
2387 * {@link #readUTFBody(long)}, {@link #readUTFChar(long)} and
2388 * {@link #readUTFSpan(long)} */
2389 private final StringBuilder sbuf = new StringBuilder(CHAR_BUF_SIZE);
2390
2391 /** block data mode */
2392 private boolean blkmode = false;
2393
2394 // block data state fields; values meaningful only when blkmode true
2395 /** current offset into buf */
2396 private int pos = 0;
2397 /** end offset of valid data in buf, or -1 if no more block data */
2398 private int end = -1;
2399 /** number of bytes in current block yet to be read from stream */
2400 private int unread = 0;
2401
2402 /** underlying stream (wrapped in peekable filter stream) */
2403 private final PeekInputStream in;
2404 /** loopback stream (for data reads that span data blocks) */
2405 private final DataInputStream din;
2406
2407 /**
2408 * Creates new BlockDataInputStream on top of given underlying stream.
2409 * Block data mode is turned off by default.
3035 off += span;
3036 pos += span << 3;
3037 }
3038 }
3039
3040 /**
3041 * Reads in string written in "long" UTF format. "Long" UTF format is
3042 * identical to standard UTF, except that it uses an 8 byte header
3043 * (instead of the standard 2 bytes) to convey the UTF encoding length.
3044 */
3045 String readLongUTF() throws IOException {
3046 return readUTFBody(readLong());
3047 }
3048
3049 /**
3050 * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3051 * or 8-byte length header) of a UTF encoding, which occupies the next
3052 * utflen bytes.
3053 */
3054 private String readUTFBody(long utflen) throws IOException {
3055 if (!blkmode) {
3056 end = pos = 0;
3057 }
3058
3059 sbuf.setLength(0);
3060 while (utflen > 0) {
3061 int avail = end - pos;
3062 if (avail >= 3 || (long) avail == utflen) {
3063 utflen -= readUTFSpan(utflen);
3064 } else {
3065 if (blkmode) {
3066 // near block boundary, read one byte at a time
3067 utflen -= readUTFChar(utflen);
3068 } else {
3069 // shift and refill buffer manually
3070 if (avail > 0) {
3071 System.arraycopy(buf, pos, buf, 0, avail);
3072 }
3073 pos = 0;
3074 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3075 in.readFully(buf, avail, end - avail);
3076 }
3077 }
3078 }
3079
3080 return sbuf.toString();
3081 }
3082
3083 /**
3084 * Reads span of UTF-encoded characters out of internal buffer
3085 * (starting at offset pos and ending at or before offset end),
3086 * consuming no more than utflen bytes. Appends read characters to
3087 * {@link #sbuf}. Returns the number of bytes consumed.
3088 */
3089 private long readUTFSpan(long utflen)
3090 throws IOException
3091 {
3092 int cpos = 0;
3093 int start = pos;
3094 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3095 // stop short of last char unless all of utf bytes in buffer
3096 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3097 boolean outOfBounds = false;
3098
3099 try {
3100 while (pos < stop) {
3101 int b1, b2, b3;
3102 b1 = buf[pos++] & 0xFF;
3103 switch (b1 >> 4) {
3104 case 0:
3105 case 1:
3106 case 2:
3107 case 3:
3108 case 4:
3109 case 5:
3141 } catch (ArrayIndexOutOfBoundsException ex) {
3142 outOfBounds = true;
3143 } finally {
3144 if (outOfBounds || (pos - start) > utflen) {
3145 /*
3146 * Fix for 4450867: if a malformed utf char causes the
3147 * conversion loop to scan past the expected end of the utf
3148 * string, only consume the expected number of utf bytes.
3149 */
3150 pos = start + (int) utflen;
3151 throw new UTFDataFormatException();
3152 }
3153 }
3154
3155 sbuf.append(cbuf, 0, cpos);
3156 return pos - start;
3157 }
3158
3159 /**
3160 * Reads in single UTF-encoded character one byte at a time, appends
3161 * the character to {@link #sbuf}, and returns the number of bytes consumed.
3162 * This method is used when reading in UTF strings written in block
3163 * data mode to handle UTF-encoded characters which (potentially)
3164 * straddle block-data boundaries.
3165 */
3166 private int readUTFChar(long utflen)
3167 throws IOException
3168 {
3169 int b1, b2, b3;
3170 b1 = readByte() & 0xFF;
3171 switch (b1 >> 4) {
3172 case 0:
3173 case 1:
3174 case 2:
3175 case 3:
3176 case 4:
3177 case 5:
3178 case 6:
3179 case 7: // 1 byte format: 0xxxxxxx
3180 sbuf.append((char) b1);
3181 return 1;
3182
3183 case 12:
3184 case 13: // 2 byte format: 110xxxxx 10xxxxxx
3185 if (utflen < 2) {
3186 throw new UTFDataFormatException();
|