1 7 8 package java.io; 9 10 import java.io.ObjectStreamClass.WeakClassKey ; 11 import java.lang.ref.ReferenceQueue ; 12 import java.lang.reflect.Array ; 13 import java.lang.reflect.Modifier ; 14 import java.lang.reflect.Proxy ; 15 import java.security.AccessController ; 16 import java.security.PrivilegedAction ; 17 import java.util.Arrays ; 18 import java.util.HashMap ; 19 import java.util.concurrent.ConcurrentHashMap ; 20 import java.util.concurrent.ConcurrentMap ; 21 import java.util.concurrent.atomic.AtomicBoolean ; 22 import static java.io.ObjectStreamClass.processQueue ; 23 24 185 public class ObjectInputStream 186 extends InputStream implements ObjectInput , ObjectStreamConstants 187 { 188 189 private static final int NULL_HANDLE = -1; 190 191 192 private static final Object unsharedMarker = new Object (); 193 194 195 private static final HashMap primClasses = new HashMap (8, 1.0F); 196 static { 197 primClasses.put("boolean", boolean.class); 198 primClasses.put("byte", byte.class); 199 primClasses.put("char", char.class); 200 primClasses.put("short", short.class); 201 primClasses.put("int", int.class); 202 primClasses.put("long", long.class); 203 primClasses.put("float", float.class); 204 primClasses.put("double", double.class); 205 primClasses.put("void", void.class); 206 } 207 208 private static class Caches { 209 210 static final ConcurrentMap <WeakClassKey,Boolean > subclassAudits = 211 new ConcurrentHashMap <WeakClassKey,Boolean >(); 212 213 214 static final ReferenceQueue <Class <?>> subclassAuditsQueue = 215 new ReferenceQueue <Class <?>>(); 216 } 217 218 219 private final BlockDataInputStream bin; 220 221 private final ValidationList vlist; 222 223 private int depth; 224 225 private boolean closed; 226 227 228 private final HandleTable handles; 229 230 private int passHandle = NULL_HANDLE; 231 232 private boolean defaultDataEnd = false; 233 234 235 private byte[] primVals; 236 237 238 private final boolean enableOverride; 239 240 private boolean enableResolve; 241 242 247 private CallbackContext curContext; 248 249 271 public ObjectInputStream(InputStream in) throws IOException { 272 verifySubclass(); 273 bin = new BlockDataInputStream(in); 274 handles = new HandleTable(10); 275 vlist = new ValidationList(); 276 enableOverride = false; 277 readStreamHeader(); 278 bin.setBlockDataMode(true); 279 } 280 281 297 protected ObjectInputStream() throws IOException , SecurityException { 298 SecurityManager sm = System.getSecurityManager(); 299 if (sm != null) { 300 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 301 } 302 bin = null; 303 handles = null; 304 vlist = null; 305 enableOverride = true; 306 } 307 308 338 public final Object readObject() 339 throws IOException , ClassNotFoundException 340 { 341 if (enableOverride) { 342 return readObjectOverride(); 343 } 344 345 int outerHandle = passHandle; 347 try { 348 Object obj = readObject0(false); 349 handles.markDependency(outerHandle, passHandle); 350 ClassNotFoundException ex = handles.lookupException(passHandle); 351 if (ex != null) { 352 throw ex; 353 } 354 if (depth == 0) { 355 vlist.doCallbacks(); 356 } 357 return obj; 358 } finally { 359 passHandle = outerHandle; 360 if (closed && depth == 0) { 361 clear(); 362 } 363 } 364 } 365 366 383 protected Object readObjectOverride() 384 throws IOException , ClassNotFoundException 385 { 386 return null; 387 } 388 389 436 public Object readUnshared() throws IOException , ClassNotFoundException { 437 int outerHandle = passHandle; 439 try { 440 Object obj = readObject0(true); 441 handles.markDependency(outerHandle, passHandle); 442 ClassNotFoundException ex = handles.lookupException(passHandle); 443 if (ex != null) { 444 throw ex; 445 } 446 if (depth == 0) { 447 vlist.doCallbacks(); 448 } 449 return obj; 450 } finally { 451 passHandle = outerHandle; 452 if (closed && depth == 0) { 453 clear(); 454 } 455 } 456 } 457 458 470 public void defaultReadObject() 471 throws IOException , ClassNotFoundException 472 { 473 if (curContext == null) { 474 throw new NotActiveException ("not in call to readObject"); 475 } 476 Object curObj = curContext.getObj(); 477 ObjectStreamClass curDesc = curContext.getDesc(); 478 bin.setBlockDataMode(false); 479 defaultReadFields(curObj, curDesc); 480 bin.setBlockDataMode(true); 481 if (!curDesc.hasWriteObjectData()) { 482 487 defaultDataEnd = true; 488 } 489 ClassNotFoundException ex = handles.lookupException(passHandle); 490 if (ex != null) { 491 throw ex; 492 } 493 } 494 495 508 public ObjectInputStream.GetField readFields() 509 throws IOException , ClassNotFoundException 510 { 511 if (curContext == null) { 512 throw new NotActiveException ("not in call to readObject"); 513 } 514 Object curObj = curContext.getObj(); 515 ObjectStreamClass curDesc = curContext.getDesc(); 516 bin.setBlockDataMode(false); 517 GetFieldImpl getField = new GetFieldImpl(curDesc); 518 getField.readFields(); 519 bin.setBlockDataMode(true); 520 if (!curDesc.hasWriteObjectData()) { 521 526 defaultDataEnd = true; 527 } 528 529 return getField; 530 } 531 532 548 public void registerValidation(ObjectInputValidation obj, int prio) 549 throws NotActiveException , InvalidObjectException 550 { 551 if (depth == 0) { 552 throw new NotActiveException ("stream inactive"); 553 } 554 vlist.register(obj, prio); 555 } 556 557 580 protected Class <?> resolveClass(ObjectStreamClass desc) 581 throws IOException , ClassNotFoundException 582 { 583 String name = desc.getName(); 584 try { 585 return Class.forName(name, false, latestUserDefinedLoader()); 586 } catch (ClassNotFoundException ex) { 587 Class cl = (Class ) primClasses.get(name); 588 if (cl != null) { 589 return cl; 590 } else { 591 throw ex; 592 } 593 } 594 } 595 596 647 protected Class <?> resolveProxyClass(String [] interfaces) 648 throws IOException , ClassNotFoundException 649 { 650 ClassLoader latestLoader = latestUserDefinedLoader(); 651 ClassLoader nonPublicLoader = null; 652 boolean hasNonPublicInterface = false; 653 654 Class [] classObjs = new Class [interfaces.length]; 656 for (int i = 0; i < interfaces.length; i++) { 657 Class cl = Class.forName(interfaces[i], false, latestLoader); 658 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) { 659 if (hasNonPublicInterface) { 660 if (nonPublicLoader != cl.getClassLoader()) { 661 throw new IllegalAccessError ( 662 "conflicting non-public interface class loaders"); 663 } 664 } else { 665 nonPublicLoader = cl.getClassLoader(); 666 hasNonPublicInterface = true; 667 } 668 } 669 classObjs[i] = cl; 670 } 671 try { 672 return Proxy.getProxyClass( 673 hasNonPublicInterface ? nonPublicLoader : latestLoader, 674 classObjs); 675 } catch (IllegalArgumentException e) { 676 throw new ClassNotFoundException (null, e); 677 } 678 } 679 680 707 protected Object resolveObject(Object obj) throws IOException { 708 return obj; 709 } 710 711 732 protected boolean enableResolveObject(boolean enable) 733 throws SecurityException 734 { 735 if (enable == enableResolve) { 736 return enable; 737 } 738 if (enable) { 739 SecurityManager sm = System.getSecurityManager(); 740 if (sm != null) { 741 sm.checkPermission(SUBSTITUTION_PERMISSION); 742 } 743 } 744 enableResolve = enable; 745 return !enableResolve; 746 } 747 748 758 protected void readStreamHeader() 759 throws IOException , StreamCorruptedException 760 { 761 if (bin.readShort() != STREAM_MAGIC || 762 bin.readShort() != STREAM_VERSION) 763 { 764 throw new StreamCorruptedException ("invalid stream header"); 765 } 766 } 767 768 785 protected ObjectStreamClass readClassDescriptor() 786 throws IOException , ClassNotFoundException 787 { 788 ObjectStreamClass desc = new ObjectStreamClass (); 789 desc.readNonProxy(this); 790 return desc; 791 } 792 793 799 public int read() throws IOException { 800 return bin.read(); 801 } 802 803 816 public int read(byte[] buf, int off, int len) throws IOException { 817 if (buf == null) { 818 throw new NullPointerException (); 819 } 820 int endoff = off + len; 821 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { 822 throw new IndexOutOfBoundsException (); 823 } 824 return bin.read(buf, off, len, false); 825 } 826 827 834 public int available() throws IOException { 835 return bin.available(); 836 } 837 838 844 public void close() throws IOException { 845 849 closed = true; 850 if (depth == 0) { 851 clear(); 852 } 853 bin.close(); 854 } 855 856 863 public boolean readBoolean() throws IOException { 864 return bin.readBoolean(); 865 } 866 867 874 public byte readByte() throws IOException { 875 return bin.readByte(); 876 } 877 878 885 public int readUnsignedByte() throws IOException { 886 return bin.readUnsignedByte(); 887 } 888 889 896 public char readChar() throws IOException { 897 return bin.readChar(); 898 } 899 900 907 public short readShort() throws IOException { 908 return bin.readShort(); 909 } 910 911 918 public int readUnsignedShort() throws IOException { 919 return bin.readUnsignedShort(); 920 } 921 922 929 public int readInt() throws IOException { 930 return bin.readInt(); 931 } 932 933 940 public long readLong() throws IOException { 941 return bin.readLong(); 942 } 943 944 951 public float readFloat() throws IOException { 952 return bin.readFloat(); 953 } 954 955 962 public double readDouble() throws IOException { 963 return bin.readDouble(); 964 } 965 966 973 public void readFully(byte[] buf) throws IOException { 974 bin.readFully(buf, 0, buf.length, false); 975 } 976 977 986 public void readFully(byte[] buf, int off, int len) throws IOException { 987 int endoff = off + len; 988 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { 989 throw new IndexOutOfBoundsException (); 990 } 991 bin.readFully(buf, off, len, false); 992 } 993 994 1002 public int skipBytes(int len) throws IOException { 1003 return bin.skipBytes(len); 1004 } 1005 1006 1015 @Deprecated 1016 public String readLine() throws IOException { 1017 return bin.readLine(); 1018 } 1019 1020 1031 public String readUTF() throws IOException { 1032 return bin.readUTF(); 1033 } 1034 1035 1038 public static abstract class GetField { 1039 1040 1045 public abstract ObjectStreamClass getObjectStreamClass(); 1046 1047 1058 public abstract boolean defaulted(String name) throws IOException ; 1059 1060 1072 public abstract boolean get(String name, boolean val) 1073 throws IOException ; 1074 1075 1087 public abstract byte get(String name, byte val) throws IOException ; 1088 1089 1101 public abstract char get(String name, char val) throws IOException ; 1102 1103 1115 public abstract short get(String name, short val) throws IOException ; 1116 1117 1129 public abstract int get(String name, int val) throws IOException ; 1130 1131 1143 public abstract long get(String name, long val) throws IOException ; 1144 1145 1157 public abstract float get(String name, float val) throws IOException ; 1158 1159 1171 public abstract double get(String name, double val) throws IOException ; 1172 1173 1185 public abstract Object get(String name, Object val) throws IOException ; 1186 } 1187 1188 1194 private void verifySubclass() { 1195 Class cl = getClass(); 1196 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); 1197 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); 1198 Boolean result = Caches.subclassAudits.get(key); 1199 if (result == null) { 1200 result = Boolean.valueOf(auditSubclass(cl)); 1201 Caches.subclassAudits.putIfAbsent(key, result); 1202 } 1203 if (result.booleanValue()) { 1204 return; 1205 } 1206 SecurityManager sm = System.getSecurityManager(); 1207 if (sm != null) { 1208 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 1209 } 1210 } 1211 1212 1217 private static boolean auditSubclass(final Class subcl) { 1218 Boolean result = (Boolean ) AccessController.doPrivileged( 1219 new PrivilegedAction () { 1220 public Object run() { 1221 for (Class cl = subcl; 1222 cl != ObjectInputStream .class; 1223 cl = cl.getSuperclass()) 1224 { 1225 try { 1226 cl.getDeclaredMethod("readUnshared", new Class [0]); 1227 return Boolean.FALSE; 1228 } catch (NoSuchMethodException ex) { 1229 } 1230 try { 1231 cl.getDeclaredMethod("readFields", new Class [0]); 1232 return Boolean.FALSE; 1233 } catch (NoSuchMethodException ex) { 1234 } 1235 } 1236 return Boolean.TRUE; 1237 } 1238 } 1239 ); 1240 return result.booleanValue(); 1241 } 1242 1243 1246 private void clear() { 1247 handles.clear(); 1248 vlist.clear(); 1249 } 1250 1251 1254 private Object readObject0(boolean unshared) throws IOException { 1255 boolean oldMode = bin.getBlockDataMode(); 1256 if (oldMode) { 1257 int remain = bin.currentBlockRemaining(); 1258 if (remain > 0) { 1259 throw new OptionalDataException (remain); 1260 } else if (defaultDataEnd) { 1261 1267 throw new OptionalDataException (true); 1268 } 1269 bin.setBlockDataMode(false); 1270 } 1271 1272 byte tc; 1273 while ((tc = bin.peekByte()) == TC_RESET) { 1274 bin.readByte(); 1275 handleReset(); 1276 } 1277 1278 depth++; 1279 try { 1280 switch (tc) { 1281 case TC_NULL: 1282 return readNull(); 1283 1284 case TC_REFERENCE: 1285 return readHandle(unshared); 1286 1287 case TC_CLASS: 1288 return readClass(unshared); 1289 1290 case TC_CLASSDESC: 1291 case TC_PROXYCLASSDESC: 1292 return readClassDesc(unshared); 1293 1294 case TC_STRING: 1295 case TC_LONGSTRING: 1296 return checkResolve(readString(unshared)); 1297 1298 case TC_ARRAY: 1299 return checkResolve(readArray(unshared)); 1300 1301 case TC_ENUM: 1302 return checkResolve(readEnum(unshared)); 1303 1304 case TC_OBJECT: 1305 return checkResolve(readOrdinaryObject(unshared)); 1306 1307 case TC_EXCEPTION: 1308 IOException ex = readFatalException(); 1309 throw new WriteAbortedException ("writing aborted", ex); 1310 1311 case TC_BLOCKDATA: 1312 case TC_BLOCKDATALONG: 1313 if (oldMode) { 1314 bin.setBlockDataMode(true); 1315 bin.peek(); throw new OptionalDataException ( 1317 bin.currentBlockRemaining()); 1318 } else { 1319 throw new StreamCorruptedException ( 1320 "unexpected block data"); 1321 } 1322 1323 case TC_ENDBLOCKDATA: 1324 if (oldMode) { 1325 throw new OptionalDataException (true); 1326 } else { 1327 throw new StreamCorruptedException ( 1328 "unexpected end of block data"); 1329 } 1330 1331 default: 1332 throw new StreamCorruptedException (); 1333 } 1334 } finally { 1335 depth--; 1336 bin.setBlockDataMode(oldMode); 1337 } 1338 } 1339 1340 1348 private Object checkResolve(Object obj) throws IOException { 1349 if (!enableResolve || handles.lookupException(passHandle) != null) { 1350 return obj; 1351 } 1352 Object rep = resolveObject(obj); 1353 if (rep != obj) { 1354 handles.setObject(passHandle, rep); 1355 } 1356 return rep; 1357 } 1358 1359 1363 String readTypeString() throws IOException { 1364 int oldHandle = passHandle; 1365 try { 1366 switch (bin.peekByte()) { 1367 case TC_NULL: 1368 return (String ) readNull(); 1369 1370 case TC_REFERENCE: 1371 return (String ) readHandle(false); 1372 1373 case TC_STRING: 1374 case TC_LONGSTRING: 1375 return readString(false); 1376 1377 default: 1378 throw new StreamCorruptedException (); 1379 } 1380 } finally { 1381 passHandle = oldHandle; 1382 } 1383 } 1384 1385 1388 private Object readNull() throws IOException { 1389 if (bin.readByte() != TC_NULL) { 1390 throw new StreamCorruptedException (); 1391 } 1392 passHandle = NULL_HANDLE; 1393 return null; 1394 } 1395 1396 1400 private Object readHandle(boolean unshared) throws IOException { 1401 if (bin.readByte() != TC_REFERENCE) { 1402 throw new StreamCorruptedException (); 1403 } 1404 passHandle = bin.readInt() - baseWireHandle; 1405 if (passHandle < 0 || passHandle >= handles.size()) { 1406 throw new StreamCorruptedException ("illegal handle value"); 1407 } 1408 if (unshared) { 1409 throw new InvalidObjectException ( 1411 "cannot read back reference as unshared"); 1412 } 1413 1414 Object obj = handles.lookupObject(passHandle); 1415 if (obj == unsharedMarker) { 1416 throw new InvalidObjectException ( 1418 "cannot read back reference to unshared object"); 1419 } 1420 return obj; 1421 } 1422 1423 1429 private Class readClass(boolean unshared) throws IOException { 1430 if (bin.readByte() != TC_CLASS) { 1431 throw new StreamCorruptedException (); 1432 } 1433 ObjectStreamClass desc = readClassDesc(false); 1434 Class cl = desc.forClass(); 1435 passHandle = handles.assign(unshared ? unsharedMarker : cl); 1436 1437 ClassNotFoundException resolveEx = desc.getResolveException(); 1438 if (resolveEx != null) { 1439 handles.markException(passHandle, resolveEx); 1440 } 1441 1442 handles.finish(passHandle); 1443 return cl; 1444 } 1445 1446 1452 private ObjectStreamClass readClassDesc(boolean unshared) 1453 throws IOException 1454 { 1455 switch (bin.peekByte()) { 1456 case TC_NULL: 1457 return (ObjectStreamClass ) readNull(); 1458 1459 case TC_REFERENCE: 1460 return (ObjectStreamClass ) readHandle(unshared); 1461 1462 case TC_PROXYCLASSDESC: 1463 return readProxyDesc(unshared); 1464 1465 case TC_CLASSDESC: 1466 return readNonProxyDesc(unshared); 1467 1468 default: 1469 throw new StreamCorruptedException (); 1470 } 1471 } 1472 1473 1479 private ObjectStreamClass readProxyDesc(boolean unshared) 1480 throws IOException 1481 { 1482 if (bin.readByte() != TC_PROXYCLASSDESC) { 1483 throw new StreamCorruptedException (); 1484 } 1485 1486 ObjectStreamClass desc = new ObjectStreamClass (); 1487 int descHandle = handles.assign(unshared ? unsharedMarker : desc); 1488 passHandle = NULL_HANDLE; 1489 1490 int numIfaces = bin.readInt(); 1491 String [] ifaces = new String [numIfaces]; 1492 for (int i = 0; i < numIfaces; i++) { 1493 ifaces[i] = bin.readUTF(); 1494 } 1495 1496 Class cl = null; 1497 ClassNotFoundException resolveEx = null; 1498 bin.setBlockDataMode(true); 1499 try { 1500 if ((cl = resolveProxyClass(ifaces)) == null) { 1501 throw new ClassNotFoundException ("null class"); 1502 } 1503 } catch (ClassNotFoundException ex) { 1504 resolveEx = ex; 1505 } 1506 skipCustomData(); 1507 1508 desc.initProxy(cl, resolveEx, readClassDesc(false)); 1509 1510 handles.finish(descHandle); 1511 passHandle = descHandle; 1512 return desc; 1513 } 1514 1515 1521 private ObjectStreamClass readNonProxyDesc(boolean unshared) 1522 throws IOException 1523 { 1524 if (bin.readByte() != TC_CLASSDESC) { 1525 throw new StreamCorruptedException (); 1526 } 1527 1528 ObjectStreamClass desc = new ObjectStreamClass (); 1529 int descHandle = handles.assign(unshared ? unsharedMarker : desc); 1530 passHandle = NULL_HANDLE; 1531 1532 ObjectStreamClass readDesc = null; 1533 try { 1534 readDesc = readClassDescriptor(); 1535 } catch (ClassNotFoundException ex) { 1536 throw (IOException ) new InvalidClassException ( 1537 "failed to read class descriptor").initCause(ex); 1538 } 1539 1540 Class cl = null; 1541 ClassNotFoundException resolveEx = null; 1542 bin.setBlockDataMode(true); 1543 try { 1544 if ((cl = resolveClass(readDesc)) == null) { 1545 throw new ClassNotFoundException ("null class"); 1546 } 1547 } catch (ClassNotFoundException ex) { 1548 resolveEx = ex; 1549 } 1550 skipCustomData(); 1551 1552 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); 1553 1554 handles.finish(descHandle); 1555 passHandle = descHandle; 1556 return desc; 1557 } 1558 1559 1563 private String readString(boolean unshared) throws IOException { 1564 String str; 1565 switch (bin.readByte()) { 1566 case TC_STRING: 1567 str = bin.readUTF(); 1568 break; 1569 1570 case TC_LONGSTRING: 1571 str = bin.readLongUTF(); 1572 break; 1573 1574 default: 1575 throw new StreamCorruptedException (); 1576 } 1577 passHandle = handles.assign(unshared ? unsharedMarker : str); 1578 handles.finish(passHandle); 1579 return str; 1580 } 1581 1582 1586 private Object readArray(boolean unshared) throws IOException { 1587 if (bin.readByte() != TC_ARRAY) { 1588 throw new StreamCorruptedException (); 1589 } 1590 1591 ObjectStreamClass desc = readClassDesc(false); 1592 int len = bin.readInt(); 1593 1594 Object array = null; 1595 Class cl, ccl = null; 1596 if ((cl = desc.forClass()) != null) { 1597 ccl = cl.getComponentType(); 1598 array = Array.newInstance(ccl, len); 1599 } 1600 1601 int arrayHandle = handles.assign(unshared ? unsharedMarker : array); 1602 ClassNotFoundException resolveEx = desc.getResolveException(); 1603 if (resolveEx != null) { 1604 handles.markException(arrayHandle, resolveEx); 1605 } 1606 1607 if (ccl == null) { 1608 for (int i = 0; i < len; i++) { 1609 readObject0(false); 1610 } 1611 } else if (ccl.isPrimitive()) { 1612 if (ccl == Integer.TYPE) { 1613 bin.readInts((int[]) array, 0, len); 1614 } else if (ccl == Byte.TYPE) { 1615 bin.readFully((byte[]) array, 0, len, true); 1616 } else if (ccl == Long.TYPE) { 1617 bin.readLongs((long[]) array, 0, len); 1618 } else if (ccl == Float.TYPE) { 1619 bin.readFloats((float[]) array, 0, len); 1620 } else if (ccl == Double.TYPE) { 1621 bin.readDoubles((double[]) array, 0, len); 1622 } else if (ccl == Short.TYPE) { 1623 bin.readShorts((short[]) array, 0, len); 1624 } else if (ccl == Character.TYPE) { 1625 bin.readChars((char[]) array, 0, len); 1626 } else if (ccl == Boolean.TYPE) { 1627 bin.readBooleans((boolean[]) array, 0, len); 1628 } else { 1629 throw new InternalError (); 1630 } 1631 } else { 1632 Object [] oa = (Object []) array; 1633 for (int i = 0; i < len; i++) { 1634 oa[i] = readObject0(false); 1635 handles.markDependency(arrayHandle, passHandle); 1636 } 1637 } 1638 1639 handles.finish(arrayHandle); 1640 passHandle = arrayHandle; 1641 return array; 1642 } 1643 1644 1648 private Enum readEnum(boolean unshared) throws IOException { 1649 if (bin.readByte() != TC_ENUM) { 1650 throw new StreamCorruptedException (); 1651 } 1652 1653 ObjectStreamClass desc = readClassDesc(false); 1654 if (!desc.isEnum()) { 1655 throw new InvalidClassException ("non-enum class: " + desc); 1656 } 1657 1658 int enumHandle = handles.assign(unshared ? unsharedMarker : null); 1659 ClassNotFoundException resolveEx = desc.getResolveException(); 1660 if (resolveEx != null) { 1661 handles.markException(enumHandle, resolveEx); 1662 } 1663 1664 String name = readString(false); 1665 Enum en = null; 1666 Class cl = desc.forClass(); 1667 if (cl != null) { 1668 try { 1669 en = Enum.valueOf(cl, name); 1670 } catch (IllegalArgumentException ex) { 1671 throw (IOException ) new InvalidObjectException ( 1672 "enum constant " + name + " does not exist in " + 1673 cl).initCause(ex); 1674 } 1675 if (!unshared) { 1676 handles.setObject(enumHandle, en); 1677 } 1678 } 1679 1680 handles.finish(enumHandle); 1681 passHandle = enumHandle; 1682 return en; 1683 } 1684 1685 1692 private Object readOrdinaryObject(boolean unshared) 1693 throws IOException 1694 { 1695 if (bin.readByte() != TC_OBJECT) { 1696 throw new StreamCorruptedException (); 1697 } 1698 1699 ObjectStreamClass desc = readClassDesc(false); 1700 desc.checkDeserialize(); 1701 1702 Object obj; 1703 try { 1704 obj = desc.isInstantiable() ? desc.newInstance() : null; 1705 } catch (Exception ex) { 1706 throw new InvalidClassException ( 1707 desc.forClass().getName(), "unable to create instance"); 1708 } 1709 1710 passHandle = handles.assign(unshared ? unsharedMarker : obj); 1711 ClassNotFoundException resolveEx = desc.getResolveException(); 1712 if (resolveEx != null) { 1713 handles.markException(passHandle, resolveEx); 1714 } 1715 1716 if (desc.isExternalizable()) { 1717 readExternalData((Externalizable ) obj, desc); 1718 } else { 1719 readSerialData(obj, desc); 1720 } 1721 1722 handles.finish(passHandle); 1723 1724 if (obj != null && 1725 handles.lookupException(passHandle) == null && 1726 desc.hasReadResolveMethod()) 1727 { 1728 Object rep = desc.invokeReadResolve(obj); 1729 if (rep != obj) { 1730 handles.setObject(passHandle, obj = rep); 1731 } 1732 } 1733 1734 return obj; 1735 } 1736 1737 1743 private void readExternalData(Externalizable obj, ObjectStreamClass desc) 1744 throws IOException 1745 { 1746 CallbackContext oldContext = curContext; 1747 curContext = null; 1748 1749 boolean blocked = desc.hasBlockExternalData(); 1750 if (blocked) { 1751 bin.setBlockDataMode(true); 1752 } 1753 if (obj != null) { 1754 try { 1755 obj.readExternal(this); 1756 } catch (ClassNotFoundException ex) { 1757 1763 handles.markException(passHandle, ex); 1764 } 1765 } 1766 if (blocked) { 1767 skipCustomData(); 1768 } 1769 1770 1782 1783 curContext = oldContext; 1784 } 1785 1786 1792 private void readSerialData(Object obj, ObjectStreamClass desc) 1793 throws IOException 1794 { 1795 ObjectStreamClass.ClassDataSlot [] slots = desc.getClassDataLayout(); 1796 for (int i = 0; i < slots.length; i++) { 1797 ObjectStreamClass slotDesc = slots[i].desc; 1798 1799 if (slots[i].hasData) { 1800 if (obj != null && 1801 slotDesc.hasReadObjectMethod() && 1802 handles.lookupException(passHandle) == null) 1803 { 1804 CallbackContext oldContext = curContext; 1805 curContext = new CallbackContext(obj, slotDesc); 1806 1807 bin.setBlockDataMode(true); 1808 try { 1809 slotDesc.invokeReadObject(obj, this); 1810 } catch (ClassNotFoundException ex) { 1811 1818 handles.markException(passHandle, ex); 1819 } finally { 1820 curContext.setUsed(); 1821 } 1822 1823 curContext = oldContext; 1824 1825 1830 defaultDataEnd = false; 1831 } else { 1832 defaultReadFields(obj, slotDesc); 1833 } 1834 if (slotDesc.hasWriteObjectData()) { 1835 skipCustomData(); 1836 } else { 1837 bin.setBlockDataMode(false); 1838 } 1839 } else { 1840 if (obj != null && 1841 slotDesc.hasReadObjectNoDataMethod() && 1842 handles.lookupException(passHandle) == null) 1843 { 1844 slotDesc.invokeReadObjectNoData(obj); 1845 } 1846 } 1847 } 1848 } 1849 1850 1854 private void skipCustomData() throws IOException { 1855 int oldHandle = passHandle; 1856 for (;;) { 1857 if (bin.getBlockDataMode()) { 1858 bin.skipBlockData(); 1859 bin.setBlockDataMode(false); 1860 } 1861 switch (bin.peekByte()) { 1862 case TC_BLOCKDATA: 1863 case TC_BLOCKDATALONG: 1864 bin.setBlockDataMode(true); 1865 break; 1866 1867 case TC_ENDBLOCKDATA: 1868 bin.readByte(); 1869 passHandle = oldHandle; 1870 return; 1871 1872 default: 1873 readObject0(false); 1874 break; 1875 } 1876 } 1877 } 1878 1879 1884 private void defaultReadFields(Object obj, ObjectStreamClass desc) 1885 throws IOException 1886 { 1887 Class cl = desc.forClass(); 1889 if (cl != null && obj != null && !cl.isInstance(obj)) { 1890 throw new ClassCastException (); 1891 } 1892 1893 int primDataSize = desc.getPrimDataSize(); 1894 if (primVals == null || primVals.length < primDataSize) { 1895 primVals = new byte[primDataSize]; 1896 } 1897 bin.readFully(primVals, 0, primDataSize, false); 1898 if (obj != null) { 1899 desc.setPrimFieldValues(obj, primVals); 1900 } 1901 1902 int objHandle = passHandle; 1903 ObjectStreamField [] fields = desc.getFields(false); 1904 Object [] objVals = new Object [desc.getNumObjFields()]; 1905 int numPrimFields = fields.length - objVals.length; 1906 for (int i = 0; i < objVals.length; i++) { 1907 ObjectStreamField f = fields[numPrimFields + i]; 1908 objVals[i] = readObject0(f.isUnshared()); 1909 if (f.getField() != null) { 1910 handles.markDependency(objHandle, passHandle); 1911 } 1912 } 1913 if (obj != null) { 1914 desc.setObjFieldValues(obj, objVals); 1915 } 1916 passHandle = objHandle; 1917 } 1918 1919 1924 private IOException readFatalException() throws IOException { 1925 if (bin.readByte() != TC_EXCEPTION) { 1926 throw new StreamCorruptedException (); 1927 } 1928 clear(); 1929 return (IOException ) readObject0(false); 1930 } 1931 1932 1937 private void handleReset() throws StreamCorruptedException { 1938 if (depth > 0) { 1939 throw new StreamCorruptedException ("unexpected reset"); 1940 } 1941 clear(); 1942 } 1943 1944 1947 private static native void bytesToFloats(byte[] src, int srcpos, 1949 float[] dst, int dstpos, 1950 int nfloats); 1951 1952 1955 private static native void bytesToDoubles(byte[] src, int srcpos, 1957 double[] dst, int dstpos, 1958 int ndoubles); 1959 1960 1971 private static native ClassLoader latestUserDefinedLoader(); 1973 1974 1977 private class GetFieldImpl extends GetField { 1978 1979 1980 private final ObjectStreamClass desc; 1981 1982 private final byte[] primVals; 1983 1984 private final Object [] objVals; 1985 1986 private final int[] objHandles; 1987 1988 1992 GetFieldImpl(ObjectStreamClass desc) { 1993 this.desc = desc; 1994 primVals = new byte[desc.getPrimDataSize()]; 1995 objVals = new Object [desc.getNumObjFields()]; 1996 objHandles = new int[objVals.length]; 1997 } 1998 1999 public ObjectStreamClass getObjectStreamClass() { 2000 return desc; 2001 } 2002 2003 public boolean defaulted(String name) throws IOException { 2004 return (getFieldOffset(name, null) < 0); 2005 } 2006 2007 public boolean get(String name, boolean val) throws IOException { 2008 int off = getFieldOffset(name, Boolean.TYPE); 2009 return (off >= 0) ? Bits.getBoolean(primVals, off) : val; 2010 } 2011 2012 public byte get(String name, byte val) throws IOException { 2013 int off = getFieldOffset(name, Byte.TYPE); 2014 return (off >= 0) ? primVals[off] : val; 2015 } 2016 2017 public char get(String name, char val) throws IOException { 2018 int off = getFieldOffset(name, Character.TYPE); 2019 return (off >= 0) ? Bits.getChar(primVals, off) : val; 2020 } 2021 2022 public short get(String name, short val) throws IOException { 2023 int off = getFieldOffset(name, Short.TYPE); 2024 return (off >= 0) ? Bits.getShort(primVals, off) : val; 2025 } 2026 2027 public int get(String name, int val) throws IOException { 2028 int off = getFieldOffset(name, Integer.TYPE); 2029 return (off >= 0) ? Bits.getInt(primVals, off) : val; 2030 } 2031 2032 public float get(String name, float val) throws IOException { 2033 int off = getFieldOffset(name, Float.TYPE); 2034 return (off >= 0) ? Bits.getFloat(primVals, off) : val; 2035 } 2036 2037 public long get(String name, long val) throws IOException { 2038 int off = getFieldOffset(name, Long.TYPE); 2039 return (off >= 0) ? Bits.getLong(primVals, off) : val; 2040 } 2041 2042 public double get(String name, double val) throws IOException { 2043 int off = getFieldOffset(name, Double.TYPE); 2044 return (off >= 0) ? Bits.getDouble(primVals, off) : val; 2045 } 2046 2047 public Object get(String name, Object val) throws IOException { 2048 int off = getFieldOffset(name, Object .class); 2049 if (off >= 0) { 2050 int objHandle = objHandles[off]; 2051 handles.markDependency(passHandle, objHandle); 2052 return (handles.lookupException(objHandle) == null) ? 2053 objVals[off] : null; 2054 } else { 2055 return val; 2056 } 2057 } 2058 2059 2062 void readFields() throws IOException { 2063 bin.readFully(primVals, 0, primVals.length, false); 2064 2065 int oldHandle = passHandle; 2066 ObjectStreamField [] fields = desc.getFields(false); 2067 int numPrimFields = fields.length - objVals.length; 2068 for (int i = 0; i < objVals.length; i++) { 2069 objVals[i] = 2070 readObject0(fields[numPrimFields + i].isUnshared()); 2071 objHandles[i] = passHandle; 2072 } 2073 passHandle = oldHandle; 2074 } 2075 2076 2085 private int getFieldOffset(String name, Class type) { 2086 ObjectStreamField field = desc.getField(name, type); 2087 if (field != null) { 2088 return field.getOffset(); 2089 } else if (desc.getLocalDesc().getField(name, type) != null) { 2090 return -1; 2091 } else { 2092 throw new IllegalArgumentException ("no such field"); 2093 } 2094 } 2095 } 2096 2097 2101 private static class ValidationList { 2102 2103 private static class Callback { 2104 final ObjectInputValidation obj; 2105 final int priority; 2106 Callback next; 2107 2108 Callback(ObjectInputValidation obj, int priority, Callback next) { 2109 this.obj = obj; 2110 this.priority = priority; 2111 this.next = next; 2112 } 2113 } 2114 2115 2116 private Callback list; 2117 2118 2121 ValidationList() { 2122 } 2123 2124 2128 void register(ObjectInputValidation obj, int priority) 2129 throws InvalidObjectException 2130 { 2131 if (obj == null) { 2132 throw new InvalidObjectException ("null callback"); 2133 } 2134 2135 Callback prev = null, cur = list; 2136 while (cur != null && priority < cur.priority) { 2137 prev = cur; 2138 cur = cur.next; 2139 } 2140 if (prev != null) { 2141 prev.next = new Callback(obj, priority, cur); 2142 } else { 2143 list = new Callback(obj, priority, list); 2144 } 2145 } 2146 2147 2154 void doCallbacks() throws InvalidObjectException { 2155 try { 2156 while (list != null) { 2157 list.obj.validateObject(); 2158 list = list.next; 2159 } 2160 } catch (InvalidObjectException ex) { 2161 list = null; 2162 throw ex; 2163 } 2164 } 2165 2166 2169 public void clear() { 2170 list = null; 2171 } 2172 } 2173 2174 2177 private static class PeekInputStream extends InputStream { 2178 2179 2180 private final InputStream in; 2181 2182 private int peekb = -1; 2183 2184 2187 PeekInputStream(InputStream in) { 2188 this.in = in; 2189 } 2190 2191 2195 int peek() throws IOException { 2196 return (peekb >= 0) ? peekb : (peekb = in.read()); 2197 } 2198 2199 public int read() throws IOException { 2200 if (peekb >= 0) { 2201 int v = peekb; 2202 peekb = -1; 2203 return v; 2204 } else { 2205 return in.read(); 2206 } 2207 } 2208 2209 public int read(byte[] b, int off, int len) throws IOException { 2210 if (len == 0) { 2211 return 0; 2212 } else if (peekb < 0) { 2213 return in.read(b, off, len); 2214 } else { 2215 b[off++] = (byte) peekb; 2216 len--; 2217 peekb = -1; 2218 int n = in.read(b, off, len); 2219 return (n >= 0) ? (n + 1) : 1; 2220 } 2221 } 2222 2223 void readFully(byte[] b, int off, int len) throws IOException { 2224 int n = 0; 2225 while (n < len) { 2226 int count = read(b, off + n, len - n); 2227 if (count < 0) { 2228 throw new EOFException (); 2229 } 2230 n += count; 2231 } 2232 } 2233 2234 public long skip(long n) throws IOException { 2235 if (n <= 0) { 2236 return 0; 2237 } 2238 int skipped = 0; 2239 if (peekb >= 0) { 2240 peekb = -1; 2241 skipped++; 2242 n--; 2243 } 2244 return skipped + skip(n); 2245 } 2246 2247 public int available() throws IOException { 2248 return in.available() + ((peekb >= 0) ? 1 : 0); 2249 } 2250 2251 public void close() throws IOException { 2252 in.close(); 2253 } 2254 } 2255 2256 2264 private class BlockDataInputStream 2265 extends InputStream implements DataInput 2266 { 2267 2268 private static final int MAX_BLOCK_SIZE = 1024; 2269 2270 private static final int MAX_HEADER_SIZE = 5; 2271 2272 private static final int CHAR_BUF_SIZE = 256; 2273 2274 private static final int HEADER_BLOCKED = -2; 2275 2276 2277 private final byte[] buf = new byte[MAX_BLOCK_SIZE]; 2278 2279 private final byte[] hbuf = new byte[MAX_HEADER_SIZE]; 2280 2281 private final char[] cbuf = new char[CHAR_BUF_SIZE]; 2282 2283 2284 private boolean blkmode = false; 2285 2286 2288 private int pos = 0; 2289 2290 private int end = -1; 2291 2292 private int unread = 0; 2293 2294 2295 private final PeekInputStream in; 2296 2297 private final DataInputStream din; 2298 2299 2303 BlockDataInputStream(InputStream in) { 2304 this.in = new PeekInputStream(in); 2305 din = new DataInputStream (this); 2306 } 2307 2308 2315 boolean setBlockDataMode(boolean newmode) throws IOException { 2316 if (blkmode == newmode) { 2317 return blkmode; 2318 } 2319 if (newmode) { 2320 pos = 0; 2321 end = 0; 2322 unread = 0; 2323 } else if (pos < end) { 2324 throw new IllegalStateException ("unread block data"); 2325 } 2326 blkmode = newmode; 2327 return !blkmode; 2328 } 2329 2330 2334 boolean getBlockDataMode() { 2335 return blkmode; 2336 } 2337 2338 2343 void skipBlockData() throws IOException { 2344 if (!blkmode) { 2345 throw new IllegalStateException ("not in block data mode"); 2346 } 2347 while (end >= 0) { 2348 refill(); 2349 } 2350 } 2351 2352 2359 private int readBlockHeader(boolean canBlock) throws IOException { 2360 if (defaultDataEnd) { 2361 2367 return -1; 2368 } 2369 try { 2370 for (;;) { 2371 int avail = canBlock ? Integer.MAX_VALUE : in.available(); 2372 if (avail == 0) { 2373 return HEADER_BLOCKED; 2374 } 2375 2376 int tc = in.peek(); 2377 switch (tc) { 2378 case TC_BLOCKDATA: 2379 if (avail < 2) { 2380 return HEADER_BLOCKED; 2381 } 2382 in.readFully(hbuf, 0, 2); 2383 return hbuf[1] & 0xFF; 2384 2385 case TC_BLOCKDATALONG: 2386 if (avail < 5) { 2387 return HEADER_BLOCKED; 2388 } 2389 in.readFully(hbuf, 0, 5); 2390 int len = Bits.getInt(hbuf, 1); 2391 if (len < 0) { 2392 throw new StreamCorruptedException ( 2393 "illegal block data header length"); 2394 } 2395 return len; 2396 2397 2403 case TC_RESET: 2404 in.read(); 2405 handleReset(); 2406 break; 2407 2408 default: 2409 if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) { 2410 throw new StreamCorruptedException (); 2411 } 2412 return -1; 2413 } 2414 } 2415 } catch (EOFException ex) { 2416 throw new StreamCorruptedException ( 2417 "unexpected EOF while reading block data header"); 2418 } 2419 } 2420 2421 2428 private void refill() throws IOException { 2429 try { 2430 do { 2431 pos = 0; 2432 if (unread > 0) { 2433 int n = 2434 in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE)); 2435 if (n >= 0) { 2436 end = n; 2437 unread -= n; 2438 } else { 2439 throw new StreamCorruptedException ( 2440 "unexpected EOF in middle of data block"); 2441 } 2442 } else { 2443 int n = readBlockHeader(true); 2444 if (n >= 0) { 2445 end = 0; 2446 unread = n; 2447 } else { 2448 end = -1; 2449 unread = 0; 2450 } 2451 } 2452 } while (pos == end); 2453 } catch (IOException ex) { 2454 pos = 0; 2455 end = -1; 2456 unread = 0; 2457 throw ex; 2458 } 2459 } 2460 2461 2466 int currentBlockRemaining() { 2467 if (blkmode) { 2468 return (end >= 0) ? (end - pos) + unread : 0; 2469 } else { 2470 throw new IllegalStateException (); 2471 } 2472 } 2473 2474 2479 int peek() throws IOException { 2480 if (blkmode) { 2481 if (pos == end) { 2482 refill(); 2483 } 2484 return (end >= 0) ? (buf[pos] & 0xFF) : -1; 2485 } else { 2486 return in.peek(); 2487 } 2488 } 2489 2490 2495 byte peekByte() throws IOException { 2496 int val = peek(); 2497 if (val < 0) { 2498 throw new EOFException (); 2499 } 2500 return (byte) val; 2501 } 2502 2503 2504 2505 2511 2512 public int read() throws IOException { 2513 if (blkmode) { 2514 if (pos == end) { 2515 refill(); 2516 } 2517 return (end >= 0) ? (buf[pos++] & 0xFF) : -1; 2518 } else { 2519 return in.read(); 2520 } 2521 } 2522 2523 public int read(byte[] b, int off, int len) throws IOException { 2524 return read(b, off, len, false); 2525 } 2526 2527 public long skip(long len) throws IOException { 2528 long remain = len; 2529 while (remain > 0) { 2530 if (blkmode) { 2531 if (pos == end) { 2532 refill(); 2533 } 2534 if (end < 0) { 2535 break; 2536 } 2537 int nread = (int) Math.min(remain, end - pos); 2538 remain -= nread; 2539 pos += nread; 2540 } else { 2541 int nread = (int) Math.min(remain, MAX_BLOCK_SIZE); 2542 if ((nread = in.read(buf, 0, nread)) < 0) { 2543 break; 2544 } 2545 remain -= nread; 2546 } 2547 } 2548 return len - remain; 2549 } 2550 2551 public int available() throws IOException { 2552 if (blkmode) { 2553 if ((pos == end) && (unread == 0)) { 2554 int n; 2555 while ((n = readBlockHeader(false)) == 0) ; 2556 switch (n) { 2557 case HEADER_BLOCKED: 2558 break; 2559 2560 case -1: 2561 pos = 0; 2562 end = -1; 2563 break; 2564 2565 default: 2566 pos = 0; 2567 end = 0; 2568 unread = n; 2569 break; 2570 } 2571 } 2572 int unreadAvail = (unread > 0) ? 2574 Math.min(in.available(), unread) : 0; 2575 return (end >= 0) ? (end - pos) + unreadAvail : 0; 2576 } else { 2577 return in.available(); 2578 } 2579 } 2580 2581 public void close() throws IOException { 2582 if (blkmode) { 2583 pos = 0; 2584 end = -1; 2585 unread = 0; 2586 } 2587 in.close(); 2588 } 2589 2590 2597 int read(byte[] b, int off, int len, boolean copy) throws IOException { 2598 if (len == 0) { 2599 return 0; 2600 } else if (blkmode) { 2601 if (pos == end) { 2602 refill(); 2603 } 2604 if (end < 0) { 2605 return -1; 2606 } 2607 int nread = Math.min(len, end - pos); 2608 System.arraycopy(buf, pos, b, off, nread); 2609 pos += nread; 2610 return nread; 2611 } else if (copy) { 2612 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE)); 2613 if (nread > 0) { 2614 System.arraycopy(buf, 0, b, off, nread); 2615 } 2616 return nread; 2617 } else { 2618 return in.read(b, off, len); 2619 } 2620 } 2621 2622 2623 2629 2630 public void readFully(byte[] b) throws IOException { 2631 readFully(b, 0, b.length, false); 2632 } 2633 2634 public void readFully(byte[] b, int off, int len) throws IOException { 2635 readFully(b, off, len, false); 2636 } 2637 2638 public void readFully(byte[] b, int off, int len, boolean copy) 2639 throws IOException 2640 { 2641 while (len > 0) { 2642 int n = read(b, off, len, copy); 2643 if (n < 0) { 2644 throw new EOFException (); 2645 } 2646 off += n; 2647 len -= n; 2648 } 2649 } 2650 2651 public int skipBytes(int n) throws IOException { 2652 return din.skipBytes(n); 2653 } 2654 2655 public boolean readBoolean() throws IOException { 2656 int v = read(); 2657 if (v < 0) { 2658 throw new EOFException (); 2659 } 2660 return (v != 0); 2661 } 2662 2663 public byte readByte() throws IOException { 2664 int v = read(); 2665 if (v < 0) { 2666 throw new EOFException (); 2667 } 2668 return (byte) v; 2669 } 2670 2671 public int readUnsignedByte() throws IOException { 2672 int v = read(); 2673 if (v < 0) { 2674 throw new EOFException (); 2675 } 2676 return v; 2677 } 2678 2679 public char readChar() throws IOException { 2680 if (!blkmode) { 2681 pos = 0; 2682 in.readFully(buf, 0, 2); 2683 } else if (end - pos < 2) { 2684 return din.readChar(); 2685 } 2686 char v = Bits.getChar(buf, pos); 2687 pos += 2; 2688 return v; 2689 } 2690 2691 public short readShort() throws IOException { 2692 if (!blkmode) { 2693 pos = 0; 2694 in.readFully(buf, 0, 2); 2695 } else if (end - pos < 2) { 2696 return din.readShort(); 2697 } 2698 short v = Bits.getShort(buf, pos); 2699 pos += 2; 2700 return v; 2701 } 2702 2703 public int readUnsignedShort() throws IOException { 2704 if (!blkmode) { 2705 pos = 0; 2706 in.readFully(buf, 0, 2); 2707 } else if (end - pos < 2) { 2708 return din.readUnsignedShort(); 2709 } 2710 int v = Bits.getShort(buf, pos) & 0xFFFF; 2711 pos += 2; 2712 return v; 2713 } 2714 2715 public int readInt() throws IOException { 2716 if (!blkmode) { 2717 pos = 0; 2718 in.readFully(buf, 0, 4); 2719 } else if (end - pos < 4) { 2720 return din.readInt(); 2721 } 2722 int v = Bits.getInt(buf, pos); 2723 pos += 4; 2724 return v; 2725 } 2726 2727 public float readFloat() throws IOException { 2728 if (!blkmode) { 2729 pos = 0; 2730 in.readFully(buf, 0, 4); 2731 } else if (end - pos < 4) { 2732 return din.readFloat(); 2733 } 2734 float v = Bits.getFloat(buf, pos); 2735 pos += 4; 2736 return v; 2737 } 2738 2739 public long readLong() throws IOException { 2740 if (!blkmode) { 2741 pos = 0; 2742 in.readFully(buf, 0, 8); 2743 } else if (end - pos < 8) { 2744 return din.readLong(); 2745 } 2746 long v = Bits.getLong(buf, pos); 2747 pos += 8; 2748 return v; 2749 } 2750 2751 public double readDouble() throws IOException { 2752 if (!blkmode) { 2753 pos = 0; 2754 in.readFully(buf, 0, 8); 2755 } else if (end - pos < 8) { 2756 return din.readDouble(); 2757 } 2758 double v = Bits.getDouble(buf, pos); 2759 pos += 8; 2760 return v; 2761 } 2762 2763 public String readUTF() throws IOException { 2764 return readUTFBody(readUnsignedShort()); 2765 } 2766 2767 public String readLine() throws IOException { 2768 return din.readLine(); } 2770 2771 2772 2778 2779 void readBooleans(boolean[] v, int off, int len) throws IOException { 2780 int stop, endoff = off + len; 2781 while (off < endoff) { 2782 if (!blkmode) { 2783 int span = Math.min(endoff - off, MAX_BLOCK_SIZE); 2784 in.readFully(buf, 0, span); 2785 stop = off + span; 2786 pos = 0; 2787 } else if (end - pos < 1) { 2788 v[off++] = din.readBoolean(); 2789 continue; 2790 } else { 2791 stop = Math.min(endoff, off + end - pos); 2792 } 2793 2794 while (off < stop) { 2795 v[off++] = Bits.getBoolean(buf, pos++); 2796 } 2797 } 2798 } 2799 2800 void readChars(char[] v, int off, int len) throws IOException { 2801 int stop, endoff = off + len; 2802 while (off < endoff) { 2803 if (!blkmode) { 2804 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1); 2805 in.readFully(buf, 0, span << 1); 2806 stop = off + span; 2807 pos = 0; 2808 } else if (end - pos < 2) { 2809 v[off++] = din.readChar(); 2810 continue; 2811 } else { 2812 stop = Math.min(endoff, off + ((end - pos) >> 1)); 2813 } 2814 2815 while (off < stop) { 2816 v[off++] = Bits.getChar(buf, pos); 2817 pos += 2; 2818 } 2819 } 2820 } 2821 2822 void readShorts(short[] v, int off, int len) throws IOException { 2823 int stop, endoff = off + len; 2824 while (off < endoff) { 2825 if (!blkmode) { 2826 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1); 2827 in.readFully(buf, 0, span << 1); 2828 stop = off + span; 2829 pos = 0; 2830 } else if (end - pos < 2) { 2831 v[off++] = din.readShort(); 2832 continue; 2833 } else { 2834 stop = Math.min(endoff, off + ((end - pos) >> 1)); 2835 } 2836 2837 while (off < stop) { 2838 v[off++] = Bits.getShort(buf, pos); 2839 pos += 2; 2840 } 2841 } 2842 } 2843 2844 void readInts(int[] v, int off, int len) throws IOException { 2845 int stop, endoff = off + len; 2846 while (off < endoff) { 2847 if (!blkmode) { 2848 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2); 2849 in.readFully(buf, 0, span << 2); 2850 stop = off + span; 2851 pos = 0; 2852 } else if (end - pos < 4) { 2853 v[off++] = din.readInt(); 2854 continue; 2855 } else { 2856 stop = Math.min(endoff, off + ((end - pos) >> 2)); 2857 } 2858 2859 while (off < stop) { 2860 v[off++] = Bits.getInt(buf, pos); 2861 pos += 4; 2862 } 2863 } 2864 } 2865 2866 void readFloats(float[] v, int off, int len) throws IOException { 2867 int span, endoff = off + len; 2868 while (off < endoff) { 2869 if (!blkmode) { 2870 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2); 2871 in.readFully(buf, 0, span << 2); 2872 pos = 0; 2873 } else if (end - pos < 4) { 2874 v[off++] = din.readFloat(); 2875 continue; 2876 } else { 2877 span = Math.min(endoff - off, ((end - pos) >> 2)); 2878 } 2879 2880 bytesToFloats(buf, pos, v, off, span); 2881 off += span; 2882 pos += span << 2; 2883 } 2884 } 2885 2886 void readLongs(long[] v, int off, int len) throws IOException { 2887 int stop, endoff = off + len; 2888 while (off < endoff) { 2889 if (!blkmode) { 2890 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3); 2891 in.readFully(buf, 0, span << 3); 2892 stop = off + span; 2893 pos = 0; 2894 } else if (end - pos < 8) { 2895 v[off++] = din.readLong(); 2896 continue; 2897 } else { 2898 stop = Math.min(endoff, off + ((end - pos) >> 3)); 2899 } 2900 2901 while (off < stop) { 2902 v[off++] = Bits.getLong(buf, pos); 2903 pos += 8; 2904 } 2905 } 2906 } 2907 2908 void readDoubles(double[] v, int off, int len) throws IOException { 2909 int span, endoff = off + len; 2910 while (off < endoff) { 2911 if (!blkmode) { 2912 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3); 2913 in.readFully(buf, 0, span << 3); 2914 pos = 0; 2915 } else if (end - pos < 8) { 2916 v[off++] = din.readDouble(); 2917 continue; 2918 } else { 2919 span = Math.min(endoff - off, ((end - pos) >> 3)); 2920 } 2921 2922 bytesToDoubles(buf, pos, v, off, span); 2923 off += span; 2924 pos += span << 3; 2925 } 2926 } 2927 2928 2933 String readLongUTF() throws IOException { 2934 return readUTFBody(readLong()); 2935 } 2936 2937 2942 private String readUTFBody(long utflen) throws IOException { 2943 StringBuffer sbuf = new StringBuffer (); 2944 if (!blkmode) { 2945 end = pos = 0; 2946 } 2947 2948 while (utflen > 0) { 2949 int avail = end - pos; 2950 if (avail >= 3 || (long) avail == utflen) { 2951 utflen -= readUTFSpan(sbuf, utflen); 2952 } else { 2953 if (blkmode) { 2954 utflen -= readUTFChar(sbuf, utflen); 2956 } else { 2957 if (avail > 0) { 2959 System.arraycopy(buf, pos, buf, 0, avail); 2960 } 2961 pos = 0; 2962 end = (int) Math.min(MAX_BLOCK_SIZE, utflen); 2963 in.readFully(buf, avail, end - avail); 2964 } 2965 } 2966 } 2967 2968 return sbuf.toString(); 2969 } 2970 2971 2977 private long readUTFSpan(StringBuffer sbuf, long utflen) 2978 throws IOException 2979 { 2980 int cpos = 0; 2981 int start = pos; 2982 int avail = Math.min(end - pos, CHAR_BUF_SIZE); 2983 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen); 2985 boolean outOfBounds = false; 2986 2987 try { 2988 while (pos < stop) { 2989 int b1, b2, b3; 2990 b1 = buf[pos++] & 0xFF; 2991 switch (b1 >> 4) { 2992 case 0: 2993 case 1: 2994 case 2: 2995 case 3: 2996 case 4: 2997 case 5: 2998 case 6: 2999 case 7: cbuf[cpos++] = (char) b1; 3001 break; 3002 3003 case 12: 3004 case 13: b2 = buf[pos++]; 3006 if ((b2 & 0xC0) != 0x80) { 3007 throw new UTFDataFormatException (); 3008 } 3009 cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) | 3010 ((b2 & 0x3F) << 0)); 3011 break; 3012 3013 case 14: b3 = buf[pos + 1]; 3015 b2 = buf[pos + 0]; 3016 pos += 2; 3017 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) { 3018 throw new UTFDataFormatException (); 3019 } 3020 cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) | 3021 ((b2 & 0x3F) << 6) | 3022 ((b3 & 0x3F) << 0)); 3023 break; 3024 3025 default: throw new UTFDataFormatException (); 3027 } 3028 } 3029 } catch (ArrayIndexOutOfBoundsException ex) { 3030 outOfBounds = true; 3031 } finally { 3032 if (outOfBounds || (pos - start) > utflen) { 3033 3038 pos = start + (int) utflen; 3039 throw new UTFDataFormatException (); 3040 } 3041 } 3042 3043 sbuf.append(cbuf, 0, cpos); 3044 return pos - start; 3045 } 3046 3047 3054 private int readUTFChar(StringBuffer sbuf, long utflen) 3055 throws IOException 3056 { 3057 int b1, b2, b3; 3058 b1 = readByte() & 0xFF; 3059 switch (b1 >> 4) { 3060 case 0: 3061 case 1: 3062 case 2: 3063 case 3: 3064 case 4: 3065 case 5: 3066 case 6: 3067 case 7: sbuf.append((char) b1); 3069 return 1; 3070 3071 case 12: 3072 case 13: if (utflen < 2) { 3074 throw new UTFDataFormatException (); 3075 } 3076 b2 = readByte(); 3077 if ((b2 & 0xC0) != 0x80) { 3078 throw new UTFDataFormatException (); 3079 } 3080 sbuf.append((char) (((b1 & 0x1F) << 6) | 3081 ((b2 & 0x3F) << 0))); 3082 return 2; 3083 3084 case 14: if (utflen < 3) { 3086 if (utflen == 2) { 3087 readByte(); } 3089 throw new UTFDataFormatException (); 3090 } 3091 b2 = readByte(); 3092 b3 = readByte(); 3093 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) { 3094 throw new UTFDataFormatException (); 3095 } 3096 sbuf.append((char) (((b1 & 0x0F) << 12) | 3097 ((b2 & 0x3F) << 6) | 3098 ((b3 & 0x3F) << 0))); 3099 return 3; 3100 3101 default: throw new UTFDataFormatException (); 3103 } 3104 } 3105 } 3106 3107 3135 private static class HandleTable { 3137 3138 3139 private static final byte STATUS_OK = 1; 3140 private static final byte STATUS_UNKNOWN = 2; 3141 private static final byte STATUS_EXCEPTION = 3; 3142 3143 3144 byte[] status; 3145 3146 Object [] entries; 3147 3148 HandleList[] deps; 3149 3150 int lowDep = -1; 3151 3152 int size = 0; 3153 3154 3157 HandleTable(int initialCapacity) { 3158 status = new byte[initialCapacity]; 3159 entries = new Object [initialCapacity]; 3160 deps = new HandleList[initialCapacity]; 3161 } 3162 3163 3169 int assign(Object obj) { 3170 if (size >= entries.length) { 3171 grow(); 3172 } 3173 status[size] = STATUS_UNKNOWN; 3174 entries[size] = obj; 3175 return size++; 3176 } 3177 3178 3184 void markDependency(int dependent, int target) { 3185 if (dependent == NULL_HANDLE || target == NULL_HANDLE) { 3186 return; 3187 } 3188 switch (status[dependent]) { 3189 3190 case STATUS_UNKNOWN: 3191 switch (status[target]) { 3192 case STATUS_OK: 3193 break; 3195 3196 case STATUS_EXCEPTION: 3197 markException(dependent, 3199 (ClassNotFoundException ) entries[target]); 3200 break; 3201 3202 case STATUS_UNKNOWN: 3203 if (deps[target] == null) { 3205 deps[target] = new HandleList(); 3206 } 3207 deps[target].add(dependent); 3208 3209 if (lowDep < 0 || lowDep > target) { 3211 lowDep = target; 3212 } 3213 break; 3214 3215 default: 3216 throw new InternalError (); 3217 } 3218 break; 3219 3220 case STATUS_EXCEPTION: 3221 break; 3222 3223 default: 3224 throw new InternalError (); 3225 } 3226 } 3227 3228 3234 void markException(int handle, ClassNotFoundException ex) { 3235 switch (status[handle]) { 3236 case STATUS_UNKNOWN: 3237 status[handle] = STATUS_EXCEPTION; 3238 entries[handle] = ex; 3239 3240 HandleList dlist = deps[handle]; 3242 if (dlist != null) { 3243 int ndeps = dlist.size(); 3244 for (int i = 0; i < ndeps; i++) { 3245 markException(dlist.get(i), ex); 3246 } 3247 deps[handle] = null; 3248 } 3249 break; 3250 3251 case STATUS_EXCEPTION: 3252 break; 3253 3254 default: 3255 throw new InternalError (); 3256 } 3257 } 3258 3259 3264 void finish(int handle) { 3265 int end; 3266 if (lowDep < 0) { 3267 end = handle + 1; 3269 } else if (lowDep >= handle) { 3270 end = size; 3272 lowDep = -1; 3273 } else { 3274 return; 3276 } 3277 3278 for (int i = handle; i < end; i++) { 3280 switch (status[i]) { 3281 case STATUS_UNKNOWN: 3282 status[i] = STATUS_OK; 3283 deps[i] = null; 3284 break; 3285 3286 case STATUS_OK: 3287 case STATUS_EXCEPTION: 3288 break; 3289 3290 default: 3291 throw new InternalError (); 3292 } 3293 } 3294 } 3295 3296 3302 void setObject(int handle, Object obj) { 3303 switch (status[handle]) { 3304 case STATUS_UNKNOWN: 3305 case STATUS_OK: 3306 entries[handle] = obj; 3307 break; 3308 3309 case STATUS_EXCEPTION: 3310 break; 3311 3312 default: 3313 throw new InternalError (); 3314 } 3315 } 3316 3317 3322 Object lookupObject(int handle) { 3323 return (handle != NULL_HANDLE && 3324 status[handle] != STATUS_EXCEPTION) ? 3325 entries[handle] : null; 3326 } 3327 3328 3333 ClassNotFoundException lookupException(int handle) { 3334 return (handle != NULL_HANDLE && 3335 status[handle] == STATUS_EXCEPTION) ? 3336 (ClassNotFoundException ) entries[handle] : null; 3337 } 3338 3339 3342 void clear() { 3343 Arrays.fill(status, 0, size, (byte) 0); 3344 Arrays.fill(entries, 0, size, null); 3345 Arrays.fill(deps, 0, size, null); 3346 lowDep = -1; 3347 size = 0; 3348 } 3349 3350 3353 int size() { 3354 return size; 3355 } 3356 3357 3360 private void grow() { 3361 int newCapacity = (entries.length << 1) + 1; 3362 3363 byte[] newStatus = new byte[newCapacity]; 3364 Object [] newEntries = new Object [newCapacity]; 3365 HandleList[] newDeps = new HandleList[newCapacity]; 3366 3367 System.arraycopy(status, 0, newStatus, 0, size); 3368 System.arraycopy(entries, 0, newEntries, 0, size); 3369 System.arraycopy(deps, 0, newDeps, 0, size); 3370 3371 status = newStatus; 3372 entries = newEntries; 3373 deps = newDeps; 3374 } 3375 3376 3379 private static class HandleList { 3380 private int[] list = new int[4]; 3381 private int size = 0; 3382 3383 public HandleList() { 3384 } 3385 3386 public void add(int handle) { 3387 if (size >= list.length) { 3388 int[] newList = new int[list.length << 1]; 3389 System.arraycopy(list, 0, newList, 0, list.length); 3390 list = newList; 3391 } 3392 list[size++] = handle; 3393 } 3394 3395 public int get(int index) { 3396 if (index >= size) { 3397 throw new ArrayIndexOutOfBoundsException (); 3398 } 3399 return list[index]; 3400 } 3401 3402 public int size() { 3403 return size; 3404 } 3405 } 3406 } 3407 3408 3416 private static class CallbackContext { 3417 private final Object obj; 3418 private final ObjectStreamClass desc; 3419 private final AtomicBoolean used = new AtomicBoolean (); 3420 3421 public CallbackContext(Object obj, ObjectStreamClass desc) { 3422 this.obj = obj; 3423 this.desc = desc; 3424 } 3425 3426 public Object getObj() throws NotActiveException { 3427 checkAndSetUsed(); 3428 return obj; 3429 } 3430 3431 public ObjectStreamClass getDesc() { 3432 return desc; 3433 } 3434 3435 private void checkAndSetUsed() throws NotActiveException { 3436 if (!used.compareAndSet(false, true)) { 3437 throw new NotActiveException ( 3438 "not in readObject invocation or fields already read"); 3439 } 3440 } 3441 3442 public void setUsed() { 3443 used.set(true); 3444 } 3445 } 3446} 3447 | Popular Tags |