1. /*
  2. * @(#)ObjectInputStream.java 1.146 04/01/13
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. import java.lang.reflect.Array;
  9. import java.lang.reflect.Modifier;
  10. import java.lang.reflect.Proxy;
  11. import java.security.AccessController;
  12. import java.security.PrivilegedAction;
  13. import java.util.Arrays;
  14. import java.util.HashMap;
  15. import sun.misc.SoftCache;
  16. /**
  17. * An ObjectInputStream deserializes primitive data and objects previously
  18. * written using an ObjectOutputStream.
  19. *
  20. * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  21. * persistent storage for graphs of objects when used with a FileOutputStream
  22. * and FileInputStream respectively. ObjectInputStream is used to recover
  23. * those objects previously serialized. Other uses include passing objects
  24. * between hosts using a socket stream or for marshaling and unmarshaling
  25. * arguments and parameters in a remote communication system.
  26. *
  27. * <p>ObjectInputStream ensures that the types of all objects in the graph
  28. * created from the stream match the classes present in the Java Virtual
  29. * Machine. Classes are loaded as required using the standard mechanisms.
  30. *
  31. * <p>Only objects that support the java.io.Serializable or
  32. * java.io.Externalizable interface can be read from streams.
  33. *
  34. * <p>The method <code>readObject</code> is used to read an object from the
  35. * stream. Java's safe casting should be used to get the desired type. In
  36. * Java, strings and arrays are objects and are treated as objects during
  37. * serialization. When read they need to be cast to the expected type.
  38. *
  39. * <p>Primitive data types can be read from the stream using the appropriate
  40. * method on DataInput.
  41. *
  42. * <p>The default deserialization mechanism for objects restores the contents
  43. * of each field to the value and type it had when it was written. Fields
  44. * declared as transient or static are ignored by the deserialization process.
  45. * References to other objects cause those objects to be read from the stream
  46. * as necessary. Graphs of objects are restored correctly using a reference
  47. * sharing mechanism. New objects are always allocated when deserializing,
  48. * which prevents existing objects from being overwritten.
  49. *
  50. * <p>Reading an object is analogous to running the constructors of a new
  51. * object. Memory is allocated for the object and initialized to zero (NULL).
  52. * No-arg constructors are invoked for the non-serializable classes and then
  53. * the fields of the serializable classes are restored from the stream starting
  54. * with the serializable class closest to java.lang.object and finishing with
  55. * the object's most specific class.
  56. *
  57. * <p>For example to read from a stream as written by the example in
  58. * ObjectOutputStream:
  59. * <br>
  60. * <pre>
  61. * FileInputStream fis = new FileInputStream("t.tmp");
  62. * ObjectInputStream ois = new ObjectInputStream(fis);
  63. *
  64. * int i = ois.readInt();
  65. * String today = (String) ois.readObject();
  66. * Date date = (Date) ois.readObject();
  67. *
  68. * ois.close();
  69. * </pre>
  70. *
  71. * <p>Classes control how they are serialized by implementing either the
  72. * java.io.Serializable or java.io.Externalizable interfaces.
  73. *
  74. * <p>Implementing the Serializable interface allows object serialization to
  75. * save and restore the entire state of the object and it allows classes to
  76. * evolve between the time the stream is written and the time it is read. It
  77. * automatically traverses references between objects, saving and restoring
  78. * entire graphs.
  79. *
  80. * <p>Serializable classes that require special handling during the
  81. * serialization and deserialization process should implement the following
  82. * methods:<p>
  83. *
  84. * <pre>
  85. * private void writeObject(java.io.ObjectOutputStream stream)
  86. * throws IOException;
  87. * private void readObject(java.io.ObjectInputStream stream)
  88. * throws IOException, ClassNotFoundException;
  89. * private void readObjectNoData()
  90. * throws ObjectStreamException;
  91. * </pre>
  92. *
  93. * <p>The readObject method is responsible for reading and restoring the state
  94. * of the object for its particular class using data written to the stream by
  95. * the corresponding writeObject method. The method does not need to concern
  96. * itself with the state belonging to its superclasses or subclasses. State is
  97. * restored by reading data from the ObjectInputStream for the individual
  98. * fields and making assignments to the appropriate fields of the object.
  99. * Reading primitive data types is supported by DataInput.
  100. *
  101. * <p>Any attempt to read object data which exceeds the boundaries of the
  102. * custom data written by the corresponding writeObject method will cause an
  103. * OptionalDataException to be thrown with an eof field value of true.
  104. * Non-object reads which exceed the end of the allotted data will reflect the
  105. * end of data in the same way that they would indicate the end of the stream:
  106. * bytewise reads will return -1 as the byte read or number of bytes read, and
  107. * primitive reads will throw EOFExceptions. If there is no corresponding
  108. * writeObject method, then the end of default serialized data marks the end of
  109. * the allotted data.
  110. *
  111. * <p>Primitive and object read calls issued from within a readExternal method
  112. * behave in the same manner--if the stream is already positioned at the end of
  113. * data written by the corresponding writeExternal method, object reads will
  114. * throw OptionalDataExceptions with eof set to true, bytewise reads will
  115. * return -1, and primitive reads will throw EOFExceptions. Note that this
  116. * behavior does not hold for streams written with the old
  117. * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
  118. * end of data written by writeExternal methods is not demarcated, and hence
  119. * cannot be detected.
  120. *
  121. * <p>The readObjectNoData method is responsible for initializing the state of
  122. * the object for its particular class in the event that the serialization
  123. * stream does not list the given class as a superclass of the object being
  124. * deserialized. This may occur in cases where the receiving party uses a
  125. * different version of the deserialized instance's class than the sending
  126. * party, and the receiver's version extends classes that are not extended by
  127. * the sender's version. This may also occur if the serialization stream has
  128. * been tampered; hence, readObjectNoData is useful for initializing
  129. * deserialized objects properly despite a "hostile" or incomplete source
  130. * stream.
  131. *
  132. * <p>Serialization does not read or assign values to the fields of any object
  133. * that does not implement the java.io.Serializable interface. Subclasses of
  134. * Objects that are not serializable can be serializable. In this case the
  135. * non-serializable class must have a no-arg constructor to allow its fields to
  136. * be initialized. In this case it is the responsibility of the subclass to
  137. * save and restore the state of the non-serializable class. It is frequently
  138. * the case that the fields of that class are accessible (public, package, or
  139. * protected) or that there are get and set methods that can be used to restore
  140. * the state.
  141. *
  142. * <p>Any exception that occurs while deserializing an object will be caught by
  143. * the ObjectInputStream and abort the reading process.
  144. *
  145. * <p>Implementing the Externalizable interface allows the object to assume
  146. * complete control over the contents and format of the object's serialized
  147. * form. The methods of the Externalizable interface, writeExternal and
  148. * readExternal, are called to save and restore the objects state. When
  149. * implemented by a class they can write and read their own state using all of
  150. * the methods of ObjectOutput and ObjectInput. It is the responsibility of
  151. * the objects to handle any versioning that occurs.
  152. *
  153. * @author Mike Warres
  154. * @author Roger Riggs
  155. * @version 1.146, 04/01/13
  156. * @see java.io.DataInput
  157. * @see java.io.ObjectOutputStream
  158. * @see java.io.Serializable
  159. * @see <a href="../../../guide/serialization/spec/input.doc.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  160. * @since JDK1.1
  161. */
  162. public class ObjectInputStream
  163. extends InputStream implements ObjectInput, ObjectStreamConstants
  164. {
  165. /** handle value representing null */
  166. private static final int NULL_HANDLE = -1;
  167. /** marker for unshared objects in internal handle table */
  168. private static final Object unsharedMarker = new Object();
  169. /** table mapping primitive type names to corresponding class objects */
  170. private static final HashMap primClasses = new HashMap(8, 1.0F);
  171. static {
  172. primClasses.put("boolean", boolean.class);
  173. primClasses.put("byte", byte.class);
  174. primClasses.put("char", char.class);
  175. primClasses.put("short", short.class);
  176. primClasses.put("int", int.class);
  177. primClasses.put("long", long.class);
  178. primClasses.put("float", float.class);
  179. primClasses.put("double", double.class);
  180. primClasses.put("void", void.class);
  181. }
  182. /** cache of subclass security audit results */
  183. private static final SoftCache subclassAudits = new SoftCache(5);
  184. /** filter stream for handling block data conversion */
  185. private final BlockDataInputStream bin;
  186. /** validation callback list */
  187. private final ValidationList vlist;
  188. /** recursion depth */
  189. private int depth;
  190. /** whether stream is closed */
  191. private boolean closed;
  192. /** wire handle -> obj/exception map */
  193. private final HandleTable handles;
  194. /** scratch field for passing handle values up/down call stack */
  195. private int passHandle = NULL_HANDLE;
  196. /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
  197. private boolean defaultDataEnd = false;
  198. /** buffer for reading primitive field values */
  199. private byte[] primVals;
  200. /** if true, invoke readObjectOverride() instead of readObject() */
  201. private final boolean enableOverride;
  202. /** if true, invoke resolveObject() */
  203. private boolean enableResolve;
  204. // values below valid only during upcalls to readObject()/readExternal()
  205. /** object currently being deserialized */
  206. private Object curObj;
  207. /** descriptor for current class (null if in readExternal()) */
  208. private ObjectStreamClass curDesc;
  209. /** current GetField object */
  210. private GetFieldImpl curGet;
  211. /**
  212. * Creates an ObjectInputStream that reads from the specified InputStream.
  213. * A serialization stream header is read from the stream and verified.
  214. * This constructor will block until the corresponding ObjectOutputStream
  215. * has written and flushed the header.
  216. *
  217. * <p>If a security manager is installed, this constructor will check for
  218. * the "enableSubclassImplementation" SerializablePermission when invoked
  219. * directly or indirectly by the constructor of a subclass which overrides
  220. * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
  221. * methods.
  222. *
  223. * @param in input stream to read from
  224. * @throws StreamCorruptedException if the stream header is incorrect
  225. * @throws IOException if an I/O error occurs while reading stream header
  226. * @throws SecurityException if untrusted subclass illegally overrides
  227. * security-sensitive methods
  228. * @throws NullPointerException if <code>in</code> is <code>null</code>
  229. * @see ObjectInputStream#ObjectInputStream()
  230. * @see ObjectInputStream#readFields()
  231. * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
  232. */
  233. public ObjectInputStream(InputStream in) throws IOException {
  234. verifySubclass();
  235. bin = new BlockDataInputStream(in);
  236. handles = new HandleTable(10);
  237. vlist = new ValidationList();
  238. enableOverride = false;
  239. readStreamHeader();
  240. bin.setBlockDataMode(true);
  241. }
  242. /**
  243. * Provide a way for subclasses that are completely reimplementing
  244. * ObjectInputStream to not have to allocate private data just used by this
  245. * implementation of ObjectInputStream.
  246. *
  247. * <p>If there is a security manager installed, this method first calls the
  248. * security manager's <code>checkPermission</code> method with the
  249. * <code>SerializablePermission("enableSubclassImplementation")</code>
  250. * permission to ensure it's ok to enable subclassing.
  251. *
  252. * @throws SecurityException if a security manager exists and its
  253. * <code>checkPermission</code> method denies enabling
  254. * subclassing.
  255. * @see SecurityManager#checkPermission
  256. * @see java.io.SerializablePermission
  257. */
  258. protected ObjectInputStream() throws IOException, SecurityException {
  259. SecurityManager sm = System.getSecurityManager();
  260. if (sm != null) {
  261. sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  262. }
  263. bin = null;
  264. handles = null;
  265. vlist = null;
  266. enableOverride = true;
  267. }
  268. /**
  269. * Read an object from the ObjectInputStream. The class of the object, the
  270. * signature of the class, and the values of the non-transient and
  271. * non-static fields of the class and all of its supertypes are read.
  272. * Default deserializing for a class can be overriden using the writeObject
  273. * and readObject methods. Objects referenced by this object are read
  274. * transitively so that a complete equivalent graph of objects is
  275. * reconstructed by readObject.
  276. *
  277. * <p>The root object is completly restored when all of its fields and the
  278. * objects it references are completely restored. At this point the object
  279. * validation callbacks are executed in order based on their registered
  280. * priorities. The callbacks are registered by objects (in the readObject
  281. * special methods) as they are individually restored.
  282. *
  283. * <p>Exceptions are thrown for problems with the InputStream and for
  284. * classes that should not be deserialized. All exceptions are fatal to
  285. * the InputStream and leave it in an indeterminate state; it is up to the
  286. * caller to ignore or recover the stream state.
  287. *
  288. * @throws ClassNotFoundException Class of a serialized object cannot be
  289. * found.
  290. * @throws InvalidClassException Something is wrong with a class used by
  291. * serialization.
  292. * @throws StreamCorruptedException Control information in the
  293. * stream is inconsistent.
  294. * @throws OptionalDataException Primitive data was found in the
  295. * stream instead of objects.
  296. * @throws IOException Any of the usual Input/Output related exceptions.
  297. */
  298. public final Object readObject()
  299. throws IOException, ClassNotFoundException
  300. {
  301. if (enableOverride) {
  302. return readObjectOverride();
  303. }
  304. // if nested read, passHandle contains handle of enclosing object
  305. int outerHandle = passHandle;
  306. try {
  307. Object obj = readObject0(false);
  308. handles.markDependency(outerHandle, passHandle);
  309. ClassNotFoundException ex = handles.lookupException(passHandle);
  310. if (ex != null) {
  311. throw ex;
  312. }
  313. if (depth == 0) {
  314. vlist.doCallbacks();
  315. }
  316. return obj;
  317. } finally {
  318. passHandle = outerHandle;
  319. if (closed && depth == 0) {
  320. clear();
  321. }
  322. }
  323. }
  324. /**
  325. * This method is called by trusted subclasses of ObjectOutputStream that
  326. * constructed ObjectOutputStream using the protected no-arg constructor.
  327. * The subclass is expected to provide an override method with the modifier
  328. * "final".
  329. *
  330. * @return the Object read from the stream.
  331. * @throws ClassNotFoundException Class definition of a serialized object
  332. * cannot be found.
  333. * @throws OptionalDataException Primitive data was found in the stream
  334. * instead of objects.
  335. * @throws IOException if I/O errors occurred while reading from the
  336. * underlying stream
  337. * @see #ObjectInputStream()
  338. * @see #readObject()
  339. * @since 1.2
  340. */
  341. protected Object readObjectOverride()
  342. throws IOException, ClassNotFoundException
  343. {
  344. return null;
  345. }
  346. /**
  347. * Reads an "unshared" object from the ObjectInputStream. This method is
  348. * identical to readObject, except that it prevents subsequent calls to
  349. * readObject and readUnshared from returning additional references to the
  350. * deserialized instance obtained via this call. Specifically:
  351. * <ul>
  352. * <li>If readUnshared is called to deserialize a back-reference (the
  353. * stream representation of an object which has been written
  354. * previously to the stream), an ObjectStreamException will be
  355. * thrown.
  356. *
  357. * <li>If readUnshared returns successfully, then any subsequent attempts
  358. * to deserialize back-references to the stream handle deserialized
  359. * by readUnshared will cause an ObjectStreamException to be thrown.
  360. * </ul>
  361. * Deserializing an object via readUnshared invalidates the stream handle
  362. * associated with the returned object. Note that this in itself does not
  363. * always guarantee that the reference returned by readUnshared is unique;
  364. * the deserialized object may define a readResolve method which returns an
  365. * object visible to other parties, or readUnshared may return a Class
  366. * object obtainable elsewhere in the stream or through external means.
  367. *
  368. * <p>However, for objects which are not instances of java.lang.Class and
  369. * do not define readResolve methods, readUnshared guarantees that the
  370. * returned object reference is unique and cannot be obtained a second time
  371. * from the ObjectInputStream that created it, even if the underlying data
  372. * stream has been manipulated. This guarantee applies only to the
  373. * base-level object returned by readUnshared, and not to any transitively
  374. * referenced sub-objects in the returned object graph.
  375. *
  376. * <p>ObjectInputStream subclasses which override this method can only be
  377. * constructed in security contexts possessing the
  378. * "enableSubclassImplementation" SerializablePermission; any attempt to
  379. * instantiate such a subclass without this permission will cause a
  380. * SecurityException to be thrown.
  381. *
  382. * @return reference to deserialized object
  383. * @throws ClassNotFoundException if class of an object to deserialize
  384. * cannot be found
  385. * @throws StreamCorruptedException if control information in the stream
  386. * is inconsistent
  387. * @throws ObjectStreamException if object to deserialize has already
  388. * appeared in stream
  389. * @throws OptionalDataException if primitive data is next in stream
  390. * @throws IOException if an I/O error occurs during deserialization
  391. */
  392. public Object readUnshared() throws IOException, ClassNotFoundException {
  393. // if nested read, passHandle contains handle of enclosing object
  394. int outerHandle = passHandle;
  395. try {
  396. Object obj = readObject0(true);
  397. handles.markDependency(outerHandle, passHandle);
  398. ClassNotFoundException ex = handles.lookupException(passHandle);
  399. if (ex != null) {
  400. throw ex;
  401. }
  402. if (depth == 0) {
  403. vlist.doCallbacks();
  404. }
  405. return obj;
  406. } finally {
  407. passHandle = outerHandle;
  408. if (closed && depth == 0) {
  409. clear();
  410. }
  411. }
  412. }
  413. /**
  414. * Read the non-static and non-transient fields of the current class from
  415. * this stream. This may only be called from the readObject method of the
  416. * class being deserialized. It will throw the NotActiveException if it is
  417. * called otherwise.
  418. *
  419. * @throws ClassNotFoundException if the class of a serialized object
  420. * could not be found.
  421. * @throws IOException if an I/O error occurs.
  422. * @throws NotActiveException if the stream is not currently reading
  423. * objects.
  424. */
  425. public void defaultReadObject()
  426. throws IOException, ClassNotFoundException
  427. {
  428. if (curObj == null || curDesc == null) {
  429. throw new NotActiveException("not in call to readObject");
  430. }
  431. bin.setBlockDataMode(false);
  432. defaultReadFields(curObj, curDesc);
  433. bin.setBlockDataMode(true);
  434. if (!curDesc.hasWriteObjectData()) {
  435. /*
  436. * Fix for 4360508: since stream does not contain terminating
  437. * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  438. * knows to simulate end-of-custom-data behavior.
  439. */
  440. defaultDataEnd = true;
  441. }
  442. ClassNotFoundException ex = handles.lookupException(passHandle);
  443. if (ex != null) {
  444. throw ex;
  445. }
  446. }
  447. /**
  448. * Reads the persistent fields from the stream and makes them available by
  449. * name.
  450. *
  451. * @return the <code>GetField</code> object representing the persistent
  452. * fields of the object being deserialized
  453. * @throws ClassNotFoundException if the class of a serialized object
  454. * could not be found.
  455. * @throws IOException if an I/O error occurs.
  456. * @throws NotActiveException if the stream is not currently reading
  457. * objects.
  458. * @since 1.2
  459. */
  460. public ObjectInputStream.GetField readFields()
  461. throws IOException, ClassNotFoundException
  462. {
  463. if (curGet == null) {
  464. if (curObj == null || curDesc == null) {
  465. throw new NotActiveException("not in call to readObject");
  466. }
  467. curGet = new GetFieldImpl(curDesc);
  468. }
  469. bin.setBlockDataMode(false);
  470. curGet.readFields();
  471. bin.setBlockDataMode(true);
  472. if (!curDesc.hasWriteObjectData()) {
  473. /*
  474. * Fix for 4360508: since stream does not contain terminating
  475. * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  476. * knows to simulate end-of-custom-data behavior.
  477. */
  478. defaultDataEnd = true;
  479. }
  480. return curGet;
  481. }
  482. /**
  483. * Register an object to be validated before the graph is returned. While
  484. * similar to resolveObject these validations are called after the entire
  485. * graph has been reconstituted. Typically, a readObject method will
  486. * register the object with the stream so that when all of the objects are
  487. * restored a final set of validations can be performed.
  488. *
  489. * @param obj the object to receive the validation callback.
  490. * @param prio controls the order of callbacks;zero is a good default.
  491. * Use higher numbers to be called back earlier, lower numbers for
  492. * later callbacks. Within a priority, callbacks are processed in
  493. * no particular order.
  494. * @throws NotActiveException The stream is not currently reading objects
  495. * so it is invalid to register a callback.
  496. * @throws InvalidObjectException The validation object is null.
  497. */
  498. public void registerValidation(ObjectInputValidation obj, int prio)
  499. throws NotActiveException, InvalidObjectException
  500. {
  501. if (depth == 0) {
  502. throw new NotActiveException("stream inactive");
  503. }
  504. vlist.register(obj, prio);
  505. }
  506. /**
  507. * Load the local class equivalent of the specified stream class
  508. * description. Subclasses may implement this method to allow classes to
  509. * be fetched from an alternate source.
  510. *
  511. * <p>The corresponding method in <code>ObjectOutputStream</code> is
  512. * <code>annotateClass</code>. This method will be invoked only once for
  513. * each unique class in the stream. This method can be implemented by
  514. * subclasses to use an alternate loading mechanism but must return a
  515. * <code>Class</code> object. Once returned, the serialVersionUID of the
  516. * class is compared to the serialVersionUID of the serialized class. If
  517. * there is a mismatch, the deserialization fails and an exception is
  518. * raised.
  519. *
  520. * <p>By default the class name is resolved relative to the class that
  521. * called <code>readObject</code>.
  522. *
  523. * @param desc an instance of class <code>ObjectStreamClass</code>
  524. * @return a <code>Class</code> object corresponding to <code>desc</code>
  525. * @throws IOException any of the usual input/output exceptions
  526. * @throws ClassNotFoundException if class of a serialized object cannot
  527. * be found
  528. */
  529. protected Class resolveClass(ObjectStreamClass desc)
  530. throws IOException, ClassNotFoundException
  531. {
  532. String name = desc.getName();
  533. try {
  534. return Class.forName(name, false, latestUserDefinedLoader());
  535. } catch (ClassNotFoundException ex) {
  536. Class cl = (Class) primClasses.get(name);
  537. if (cl != null) {
  538. return cl;
  539. } else {
  540. throw ex;
  541. }
  542. }
  543. }
  544. /**
  545. * Returns a proxy class that implements the interfaces named in a proxy
  546. * class descriptor; subclasses may implement this method to read custom
  547. * data from the stream along with the descriptors for dynamic proxy
  548. * classes, allowing them to use an alternate loading mechanism for the
  549. * interfaces and the proxy class.
  550. *
  551. * <p>This method is called exactly once for each unique proxy class
  552. * descriptor in the stream.
  553. *
  554. * <p>The corresponding method in <code>ObjectOutputStream</code> is
  555. * <code>annotateProxyClass</code>. For a given subclass of
  556. * <code>ObjectInputStream</code> that overrides this method, the
  557. * <code>annotateProxyClass</code> method in the corresponding subclass of
  558. * <code>ObjectOutputStream</code> must write any data or objects read by
  559. * this method.
  560. *
  561. * <p>The default implementation of this method in
  562. * <code>ObjectInputStream</code> returns the result of calling
  563. * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
  564. * objects for the interfaces that are named in the <code>interfaces</code>
  565. * parameter. The <code>Class</code> object for each interface name
  566. * <code>i</code> is the value returned by calling
  567. * <pre>
  568. * Class.forName(i, false, loader)
  569. * </pre>
  570. * where <code>loader</code> is that of the first non-<code>null</code>
  571. * class loader up the execution stack, or <code>null</code> if no
  572. * non-<code>null</code> class loaders are on the stack (the same class
  573. * loader choice used by the <code>resolveClass</code> method). Unless any
  574. * of the resolved interfaces are non-public, this same value of
  575. * <code>loader</code> is also the class loader passed to
  576. * <code>Proxy.getProxyClass</code> if non-public interfaces are present,
  577. * their class loader is passed instead (if more than one non-public
  578. * interface class loader is encountered, an
  579. * <code>IllegalAccessError</code> is thrown).
  580. * If <code>Proxy.getProxyClass</code> throws an
  581. * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
  582. * will throw a <code>ClassNotFoundException</code> containing the
  583. * <code>IllegalArgumentException</code>.
  584. *
  585. * @param interfaces the list of interface names that were
  586. * deserialized in the proxy class descriptor
  587. * @return a proxy class for the specified interfaces
  588. * @throws IOException any exception thrown by the underlying
  589. * <code>InputStream</code>
  590. * @throws ClassNotFoundException if the proxy class or any of the
  591. * named interfaces could not be found
  592. * @see ObjectOutputStream#annotateProxyClass(Class)
  593. * @since 1.3
  594. */
  595. protected Class resolveProxyClass(String[] interfaces)
  596. throws IOException, ClassNotFoundException
  597. {
  598. ClassLoader latestLoader = latestUserDefinedLoader();
  599. ClassLoader nonPublicLoader = null;
  600. boolean hasNonPublicInterface = false;
  601. // define proxy in class loader of non-public interface(s), if any
  602. Class[] classObjs = new Class[interfaces.length];
  603. for (int i = 0; i < interfaces.length; i++) {
  604. Class cl = Class.forName(interfaces[i], false, latestLoader);
  605. if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
  606. if (hasNonPublicInterface) {
  607. if (nonPublicLoader != cl.getClassLoader()) {
  608. throw new IllegalAccessError(
  609. "conflicting non-public interface class loaders");
  610. }
  611. } else {
  612. nonPublicLoader = cl.getClassLoader();
  613. hasNonPublicInterface = true;
  614. }
  615. }
  616. classObjs[i] = cl;
  617. }
  618. try {
  619. return Proxy.getProxyClass(
  620. hasNonPublicInterface ? nonPublicLoader : latestLoader,
  621. classObjs);
  622. } catch (IllegalArgumentException e) {
  623. throw new ClassNotFoundException(null, e);
  624. }
  625. }
  626. /**
  627. * This method will allow trusted subclasses of ObjectInputStream to
  628. * substitute one object for another during deserialization. Replacing
  629. * objects is disabled until enableResolveObject is called. The
  630. * enableResolveObject method checks that the stream requesting to resolve
  631. * object can be trusted. Every reference to serializable objects is passed
  632. * to resolveObject. To insure that the private state of objects is not
  633. * unintentionally exposed only trusted streams may use resolveObject.
  634. *
  635. * <p>This method is called after an object has been read but before it is
  636. * returned from readObject. The default resolveObject method just returns
  637. * the same object.
  638. *
  639. * <p>When a subclass is replacing objects it must insure that the
  640. * substituted object is compatible with every field where the reference
  641. * will be stored. Objects whose type is not a subclass of the type of the
  642. * field or array element abort the serialization by raising an exception
  643. * and the object is not be stored.
  644. *
  645. * <p>This method is called only once when each object is first
  646. * encountered. All subsequent references to the object will be redirected
  647. * to the new object.
  648. *
  649. * @param obj object to be substituted
  650. * @return the substituted object
  651. * @throws IOException Any of the usual Input/Output exceptions.
  652. */
  653. protected Object resolveObject(Object obj) throws IOException {
  654. return obj;
  655. }
  656. /**
  657. * Enable the stream to allow objects read from the stream to be replaced.
  658. * When enabled, the resolveObject method is called for every object being
  659. * deserialized.
  660. *
  661. * <p>If <i>enable</i> is true, and there is a security manager installed,
  662. * this method first calls the security manager's
  663. * <code>checkPermission</code> method with the
  664. * <code>SerializablePermission("enableSubstitution")</code> permission to
  665. * ensure it's ok to enable the stream to allow objects read from the
  666. * stream to be replaced.
  667. *
  668. * @param enable true for enabling use of <code>resolveObject</code> for
  669. * every object being deserialized
  670. * @return the previous setting before this method was invoked
  671. * @throws SecurityException if a security manager exists and its
  672. * <code>checkPermission</code> method denies enabling the stream
  673. * to allow objects read from the stream to be replaced.
  674. * @see SecurityManager#checkPermission
  675. * @see java.io.SerializablePermission
  676. */
  677. protected boolean enableResolveObject(boolean enable)
  678. throws SecurityException
  679. {
  680. if (enable == enableResolve) {
  681. return enable;
  682. }
  683. if (enable) {
  684. SecurityManager sm = System.getSecurityManager();
  685. if (sm != null) {
  686. sm.checkPermission(SUBSTITUTION_PERMISSION);
  687. }
  688. }
  689. enableResolve = enable;
  690. return !enableResolve;
  691. }
  692. /**
  693. * The readStreamHeader method is provided to allow subclasses to read and
  694. * verify their own stream headers. It reads and verifies the magic number
  695. * and version number.
  696. *
  697. * @throws IOException if there are I/O errors while reading from the
  698. * underlying <code>InputStream</code>
  699. * @throws StreamCorruptedException if control information in the stream
  700. * is inconsistent
  701. */
  702. protected void readStreamHeader()
  703. throws IOException, StreamCorruptedException
  704. {
  705. if (bin.readShort() != STREAM_MAGIC ||
  706. bin.readShort() != STREAM_VERSION)
  707. {
  708. throw new StreamCorruptedException("invalid stream header");
  709. }
  710. }
  711. /**
  712. * Read a class descriptor from the serialization stream. This method is
  713. * called when the ObjectInputStream expects a class descriptor as the next
  714. * item in the serialization stream. Subclasses of ObjectInputStream may
  715. * override this method to read in class descriptors that have been written
  716. * in non-standard formats (by subclasses of ObjectOutputStream which have
  717. * overridden the <code>writeClassDescriptor</code> method). By default,
  718. * this method reads class descriptors according to the format defined in
  719. * the Object Serialization specification.
  720. *
  721. * @return the class descriptor read
  722. * @throws IOException If an I/O error has occurred.
  723. * @throws ClassNotFoundException If the Class of a serialized object used
  724. * in the class descriptor representation cannot be found
  725. * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
  726. * @since 1.3
  727. */
  728. protected ObjectStreamClass readClassDescriptor()
  729. throws IOException, ClassNotFoundException
  730. {
  731. ObjectStreamClass desc = new ObjectStreamClass();
  732. desc.readNonProxy(this);
  733. return desc;
  734. }
  735. /**
  736. * Reads a byte of data. This method will block if no input is available.
  737. *
  738. * @return the byte read, or -1 if the end of the stream is reached.
  739. * @throws IOException If an I/O error has occurred.
  740. */
  741. public int read() throws IOException {
  742. return bin.read();
  743. }
  744. /**
  745. * Reads into an array of bytes. This method will block until some input
  746. * is available. Consider using java.io.DataInputStream.readFully to read
  747. * exactly 'length' bytes.
  748. *
  749. * @param buf the buffer into which the data is read
  750. * @param off the start offset of the data
  751. * @param len the maximum number of bytes read
  752. * @return the actual number of bytes read, -1 is returned when the end of
  753. * the stream is reached.
  754. * @throws IOException If an I/O error has occurred.
  755. * @see java.io.DataInputStream#readFully(byte[],int,int)
  756. */
  757. public int read(byte[] buf, int off, int len) throws IOException {
  758. int endoff = off + len;
  759. if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  760. throw new IndexOutOfBoundsException();
  761. }
  762. return bin.read(buf, off, len, false);
  763. }
  764. /**
  765. * Returns the number of bytes that can be read without blocking.
  766. *
  767. * @return the number of available bytes.
  768. * @throws IOException if there are I/O errors while reading from the
  769. * underlying <code>InputStream</code>
  770. */
  771. public int available() throws IOException {
  772. return bin.available();
  773. }
  774. /**
  775. * Closes the input stream. Must be called to release any resources
  776. * associated with the stream.
  777. *
  778. * @throws IOException If an I/O error has occurred.
  779. */
  780. public void close() throws IOException {
  781. /*
  782. * Even if stream already closed, propagate redundant close to
  783. * underlying stream to stay consistent with previous implementations.
  784. */
  785. closed = true;
  786. if (depth == 0) {
  787. clear();
  788. }
  789. bin.close();
  790. }
  791. /**
  792. * Reads in a boolean.
  793. *
  794. * @return the boolean read.
  795. * @throws EOFException If end of file is reached.
  796. * @throws IOException If other I/O error has occurred.
  797. */
  798. public boolean readBoolean() throws IOException {
  799. return bin.readBoolean();
  800. }
  801. /**
  802. * Reads an 8 bit byte.
  803. *
  804. * @return the 8 bit byte read.
  805. * @throws EOFException If end of file is reached.
  806. * @throws IOException If other I/O error has occurred.
  807. */
  808. public byte readByte() throws IOException {
  809. return bin.readByte();
  810. }
  811. /**
  812. * Reads an unsigned 8 bit byte.
  813. *
  814. * @return the 8 bit byte read.
  815. * @throws EOFException If end of file is reached.
  816. * @throws IOException If other I/O error has occurred.
  817. */
  818. public int readUnsignedByte() throws IOException {
  819. return bin.readUnsignedByte();
  820. }
  821. /**
  822. * Reads a 16 bit char.
  823. *
  824. * @return the 16 bit char read.
  825. * @throws EOFException If end of file is reached.
  826. * @throws IOException If other I/O error has occurred.
  827. */
  828. public char readChar() throws IOException {
  829. return bin.readChar();
  830. }
  831. /**
  832. * Reads a 16 bit short.
  833. *
  834. * @return the 16 bit short read.
  835. * @throws EOFException If end of file is reached.
  836. * @throws IOException If other I/O error has occurred.
  837. */
  838. public short readShort() throws IOException {
  839. return bin.readShort();
  840. }
  841. /**
  842. * Reads an unsigned 16 bit short.
  843. *
  844. * @return the 16 bit short read.
  845. * @throws EOFException If end of file is reached.
  846. * @throws IOException If other I/O error has occurred.
  847. */
  848. public int readUnsignedShort() throws IOException {
  849. return bin.readUnsignedShort();
  850. }
  851. /**
  852. * Reads a 32 bit int.
  853. *
  854. * @return the 32 bit integer read.
  855. * @throws EOFException If end of file is reached.
  856. * @throws IOException If other I/O error has occurred.
  857. */
  858. public int readInt() throws IOException {
  859. return bin.readInt();
  860. }
  861. /**
  862. * Reads a 64 bit long.
  863. *
  864. * @return the read 64 bit long.
  865. * @throws EOFException If end of file is reached.
  866. * @throws IOException If other I/O error has occurred.
  867. */
  868. public long readLong() throws IOException {
  869. return bin.readLong();
  870. }
  871. /**
  872. * Reads a 32 bit float.
  873. *
  874. * @return the 32 bit float read.
  875. * @throws EOFException If end of file is reached.
  876. * @throws IOException If other I/O error has occurred.
  877. */
  878. public float readFloat() throws IOException {
  879. return bin.readFloat();
  880. }
  881. /**
  882. * Reads a 64 bit double.
  883. *
  884. * @return the 64 bit double read.
  885. * @throws EOFException If end of file is reached.
  886. * @throws IOException If other I/O error has occurred.
  887. */
  888. public double readDouble() throws IOException {
  889. return bin.readDouble();
  890. }
  891. /**
  892. * Reads bytes, blocking until all bytes are read.
  893. *
  894. * @param buf the buffer into which the data is read
  895. * @throws EOFException If end of file is reached.
  896. * @throws IOException If other I/O error has occurred.
  897. */
  898. public void readFully(byte[] buf) throws IOException {
  899. bin.readFully(buf, 0, buf.length, false);
  900. }
  901. /**
  902. * Reads bytes, blocking until all bytes are read.
  903. *
  904. * @param buf the buffer into which the data is read
  905. * @param off the start offset of the data
  906. * @param len the maximum number of bytes to read
  907. * @throws EOFException If end of file is reached.
  908. * @throws IOException If other I/O error has occurred.
  909. */
  910. public void readFully(byte[] buf, int off, int len) throws IOException {
  911. int endoff = off + len;
  912. if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  913. throw new IndexOutOfBoundsException();
  914. }
  915. bin.readFully(buf, off, len, false);
  916. }
  917. /**
  918. * Skips bytes, block until all bytes are skipped.
  919. *
  920. * @param len the number of bytes to be skipped
  921. * @return the actual number of bytes skipped.
  922. * @throws EOFException If end of file is reached.
  923. * @throws IOException If other I/O error has occurred.
  924. */
  925. public int skipBytes(int len) throws IOException {
  926. return bin.skipBytes(len);
  927. }
  928. /**
  929. * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
  930. *
  931. * @return a String copy of the line.
  932. * @throws IOException if there are I/O errors while reading from the
  933. * underlying <code>InputStream</code>
  934. * @deprecated This method does not properly convert bytes to characters.
  935. * see DataInputStream for the details and alternatives.
  936. */
  937. public String readLine() throws IOException {
  938. return bin.readLine();
  939. }
  940. /**
  941. * Reads a UTF format String.
  942. *
  943. * @return the String.
  944. * @throws IOException if there are I/O errors while reading from the
  945. * underlying <code>InputStream</code>
  946. * @throws UTFDataFormatException if read bytes do not represent a valid
  947. * UTF-8 encoding of a string
  948. */
  949. public String readUTF() throws IOException {
  950. return bin.readUTF();
  951. }
  952. /**
  953. * Provide access to the persistent fields read from the input stream.
  954. */
  955. public static abstract class GetField {
  956. /**
  957. * Get the ObjectStreamClass that describes the fields in the stream.
  958. *
  959. * @return the descriptor class that describes the serializable fields
  960. */
  961. public abstract ObjectStreamClass getObjectStreamClass();
  962. /**
  963. * Return true if the named field is defaulted and has no value in this
  964. * stream.
  965. *
  966. * @param name the name of the field
  967. * @return true, if and only if the named field is defaulted
  968. * @throws IOException if there are I/O errors while reading from
  969. * the underlying <code>InputStream</code>
  970. * @throws IllegalArgumentException if <code>name</code> does not
  971. * correspond to a serializable field
  972. */
  973. public abstract boolean defaulted(String name) throws IOException;
  974. /**
  975. * Get the value of the named boolean field from the persistent field.
  976. *
  977. * @param name the name of the field
  978. * @param val the default value to use if <code>name</code> does not
  979. * have a value
  980. * @return the value of the named <code>boolean</code> field
  981. * @throws IOException if there are I/O errors while reading from the
  982. * underlying <code>InputStream</code>
  983. * @throws IllegalArgumentException if type of <code>name</code> is
  984. * not serializable or if the field type is incorrect
  985. */
  986. public abstract boolean get(String name, boolean val)
  987. throws IOException;
  988. /**
  989. * Get the value of the named byte field from the persistent field.
  990. *
  991. * @param name the name of the field
  992. * @param val the default value to use if <code>name</code> does not
  993. * have a value
  994. * @return the value of the named <code>byte</code> field
  995. * @throws IOException if there are I/O errors while reading from the
  996. * underlying <code>InputStream</code>
  997. * @throws IllegalArgumentException if type of <code>name</code> is
  998. * not serializable or if the field type is incorrect
  999. */
  1000. public abstract byte get(String name, byte val) throws IOException;
  1001. /**
  1002. * Get the value of the named char field from the persistent field.
  1003. *
  1004. * @param name the name of the field
  1005. * @param val the default value to use if <code>name</code> does not
  1006. * have a value
  1007. * @return the value of the named <code>char</code> field
  1008. * @throws IOException if there are I/O errors while reading from the
  1009. * underlying <code>InputStream</code>
  1010. * @throws IllegalArgumentException if type of <code>name</code> is
  1011. * not serializable or if the field type is incorrect
  1012. */
  1013. public abstract char get(String name, char val) throws IOException;
  1014. /**
  1015. * Get the value of the named short field from the persistent field.
  1016. *
  1017. * @param name the name of the field
  1018. * @param val the default value to use if <code>name</code> does not
  1019. * have a value
  1020. * @return the value of the named <code>short</code> field
  1021. * @throws IOException if there are I/O errors while reading from the
  1022. * underlying <code>InputStream</code>
  1023. * @throws IllegalArgumentException if type of <code>name</code> is
  1024. * not serializable or if the field type is incorrect
  1025. */
  1026. public abstract short get(String name, short val) throws IOException;
  1027. /**
  1028. * Get the value of the named int field from the persistent field.
  1029. *
  1030. * @param name the name of the field
  1031. * @param val the default value to use if <code>name</code> does not
  1032. * have a value
  1033. * @return the value of the named <code>int</code> field
  1034. * @throws IOException if there are I/O errors while reading from the
  1035. * underlying <code>InputStream</code>
  1036. * @throws IllegalArgumentException if type of <code>name</code> is
  1037. * not serializable or if the field type is incorrect
  1038. */
  1039. public abstract int get(String name, int val) throws IOException;
  1040. /**
  1041. * Get the value of the named long field from the persistent field.
  1042. *
  1043. * @param name the name of the field
  1044. * @param val the default value to use if <code>name</code> does not
  1045. * have a value
  1046. * @return the value of the named <code>long</code> field
  1047. * @throws IOException if there are I/O errors while reading from the
  1048. * underlying <code>InputStream</code>
  1049. * @throws IllegalArgumentException if type of <code>name</code> is
  1050. * not serializable or if the field type is incorrect
  1051. */
  1052. public abstract long get(String name, long val) throws IOException;
  1053. /**
  1054. * Get the value of the named float field from the persistent field.
  1055. *
  1056. * @param name the name of the field
  1057. * @param val the default value to use if <code>name</code> does not
  1058. * have a value
  1059. * @return the value of the named <code>float</code> field
  1060. * @throws IOException if there are I/O errors while reading from the
  1061. * underlying <code>InputStream</code>
  1062. * @throws IllegalArgumentException if type of <code>name</code> is
  1063. * not serializable or if the field type is incorrect
  1064. */
  1065. public abstract float get(String name, float val) throws IOException;
  1066. /**
  1067. * Get the value of the named double field from the persistent field.
  1068. *
  1069. * @param name the name of the field
  1070. * @param val the default value to use if <code>name</code> does not
  1071. * have a value
  1072. * @return the value of the named <code>double</code> field
  1073. * @throws IOException if there are I/O errors while reading from the
  1074. * underlying <code>InputStream</code>
  1075. * @throws IllegalArgumentException if type of <code>name</code> is
  1076. * not serializable or if the field type is incorrect
  1077. */
  1078. public abstract double get(String name, double val) throws IOException;
  1079. /**
  1080. * Get the value of the named Object field from the persistent field.
  1081. *
  1082. * @param name the name of the field
  1083. * @param val the default value to use if <code>name</code> does not
  1084. * have a value
  1085. * @return the value of the named <code>Object</code> field
  1086. * @throws IOException if there are I/O errors while reading from the
  1087. * underlying <code>InputStream</code>
  1088. * @throws IllegalArgumentException if type of <code>name</code> is
  1089. * not serializable or if the field type is incorrect
  1090. */
  1091. public abstract Object get(String name, Object val) throws IOException;
  1092. }
  1093. /**
  1094. * Verifies that this (possibly subclass) instance can be constructed
  1095. * without violating security constraints: the subclass must not override
  1096. * security-sensitive non-final methods, or else the
  1097. * "enableSubclassImplementation" SerializablePermission is checked.
  1098. */
  1099. private void verifySubclass() {
  1100. Class cl = getClass();
  1101. synchronized (subclassAudits) {
  1102. Boolean result = (Boolean) subclassAudits.get(cl);
  1103. if (result == null) {
  1104. /*
  1105. * Note: only new Boolean instances (i.e., not Boolean.TRUE or
  1106. * Boolean.FALSE) must be used as cache values, otherwise cache
  1107. * entry will pin associated class.
  1108. */
  1109. result = new Boolean(auditSubclass(cl));
  1110. subclassAudits.put(cl, result);
  1111. }
  1112. if (result.booleanValue()) {
  1113. return;
  1114. }
  1115. }
  1116. SecurityManager sm = System.getSecurityManager();
  1117. if (sm != null) {
  1118. sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  1119. }
  1120. }
  1121. /**
  1122. * Performs reflective checks on given subclass to verify that it doesn't
  1123. * override security-sensitive non-final methods. Returns true if subclass
  1124. * is "safe", false otherwise.
  1125. */
  1126. private static boolean auditSubclass(final Class subcl) {
  1127. Boolean result = (Boolean) AccessController.doPrivileged(
  1128. new PrivilegedAction() {
  1129. public Object run() {
  1130. for (Class cl = subcl;
  1131. cl != ObjectInputStream.class;
  1132. cl = cl.getSuperclass())
  1133. {
  1134. try {
  1135. cl.getDeclaredMethod("readUnshared", new Class[0]);
  1136. return Boolean.FALSE;
  1137. } catch (NoSuchMethodException ex) {
  1138. }
  1139. try {
  1140. cl.getDeclaredMethod("readFields", new Class[0]);
  1141. return Boolean.FALSE;
  1142. } catch (NoSuchMethodException ex) {
  1143. }
  1144. }
  1145. return Boolean.TRUE;
  1146. }
  1147. }
  1148. );
  1149. return result.booleanValue();
  1150. }
  1151. /**
  1152. * Clears internal data structures.
  1153. */
  1154. private void clear() {
  1155. handles.clear();
  1156. vlist.clear();
  1157. }
  1158. /**
  1159. * Underlying readObject implementation.
  1160. */
  1161. private Object readObject0(boolean unshared) throws IOException {
  1162. boolean oldMode = bin.getBlockDataMode();
  1163. if (oldMode) {
  1164. int remain = bin.currentBlockRemaining();
  1165. if (remain > 0) {
  1166. throw new OptionalDataException(remain);
  1167. } else if (defaultDataEnd) {
  1168. /*
  1169. * Fix for 4360508: stream is currently at the end of a field
  1170. * value block written via default serialization; since there
  1171. * is no terminating TC_ENDBLOCKDATA tag, simulate
  1172. * end-of-custom-data behavior explicitly.
  1173. */
  1174. throw new OptionalDataException(true);
  1175. }
  1176. bin.setBlockDataMode(false);
  1177. }
  1178. byte tc;
  1179. while ((tc = bin.peekByte()) == TC_RESET) {
  1180. bin.readByte();
  1181. handleReset();
  1182. }
  1183. depth++;
  1184. try {
  1185. switch (tc) {
  1186. case TC_NULL:
  1187. return readNull();
  1188. case TC_REFERENCE:
  1189. return readHandle(unshared);
  1190. case TC_CLASS:
  1191. return readClass(unshared);
  1192. case TC_CLASSDESC:
  1193. case TC_PROXYCLASSDESC:
  1194. return readClassDesc(unshared);
  1195. case TC_STRING:
  1196. case TC_LONGSTRING:
  1197. return checkResolve(readString(unshared));
  1198. case TC_ARRAY:
  1199. return checkResolve(readArray(unshared));
  1200. case TC_OBJECT:
  1201. return checkResolve(readOrdinaryObject(unshared));
  1202. case TC_EXCEPTION:
  1203. IOException ex = readFatalException();
  1204. throw new WriteAbortedException("writing aborted", ex);
  1205. case TC_BLOCKDATA:
  1206. case TC_BLOCKDATALONG:
  1207. if (oldMode) {
  1208. bin.setBlockDataMode(true);
  1209. bin.peek(); // force header read
  1210. throw new OptionalDataException(
  1211. bin.currentBlockRemaining());
  1212. } else {
  1213. throw new StreamCorruptedException(
  1214. "unexpected block data");
  1215. }
  1216. case TC_ENDBLOCKDATA:
  1217. if (oldMode) {
  1218. throw new OptionalDataException(true);
  1219. } else {
  1220. throw new StreamCorruptedException(
  1221. "unexpected end of block data");
  1222. }
  1223. default:
  1224. throw new StreamCorruptedException();
  1225. }
  1226. } finally {
  1227. depth--;
  1228. bin.setBlockDataMode(oldMode);
  1229. }
  1230. }
  1231. /**
  1232. * If resolveObject has been enabled and given object does not have an
  1233. * exception associated with it, calls resolveObject to determine
  1234. * replacement for object, and updates handle table accordingly. Returns
  1235. * replacement object, or echoes provided object if no replacement
  1236. * occurred. Expects that passHandle is set to given object's handle prior
  1237. * to calling this method.
  1238. */
  1239. private Object checkResolve(Object obj) throws IOException {
  1240. if (!enableResolve || handles.lookupException(passHandle) != null) {
  1241. return obj;
  1242. }
  1243. Object rep = resolveObject(obj);
  1244. if (rep != obj) {
  1245. handles.setObject(passHandle, rep);
  1246. }
  1247. return rep;
  1248. }
  1249. /**
  1250. * Reads string without allowing it to be replaced in stream. Called from
  1251. * within ObjectStreamClass.read().
  1252. */
  1253. String readTypeString() throws IOException {
  1254. int oldHandle = passHandle;
  1255. try {
  1256. switch (bin.peekByte()) {
  1257. case TC_NULL:
  1258. return (String) readNull();
  1259. case TC_REFERENCE:
  1260. return (String) readHandle(false);
  1261. case TC_STRING:
  1262. case TC_LONGSTRING:
  1263. return readString(false);
  1264. default:
  1265. throw new StreamCorruptedException();
  1266. }
  1267. } finally {
  1268. passHandle = oldHandle;
  1269. }
  1270. }
  1271. /**
  1272. * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
  1273. */
  1274. private Object readNull() throws IOException {
  1275. if (bin.readByte() != TC_NULL) {
  1276. throw new StreamCorruptedException();
  1277. }
  1278. passHandle = NULL_HANDLE;
  1279. return null;
  1280. }
  1281. /**
  1282. * Reads in object handle, sets passHandle to the read handle, and returns
  1283. * object associated with the handle.
  1284. */
  1285. private Object readHandle(boolean unshared) throws IOException {
  1286. if (bin.readByte() != TC_REFERENCE) {
  1287. throw new StreamCorruptedException();
  1288. }
  1289. passHandle = bin.readInt() - baseWireHandle;
  1290. if (passHandle < 0 || passHandle >= handles.size()) {
  1291. throw new StreamCorruptedException("illegal handle value");
  1292. }
  1293. if (unshared) {
  1294. // REMIND: what type of exception to throw here?
  1295. throw new InvalidObjectException(
  1296. "cannot read back reference as unshared");
  1297. }
  1298. Object obj = handles.lookupObject(passHandle);
  1299. if (obj == unsharedMarker) {
  1300. // REMIND: what type of exception to throw here?
  1301. throw new InvalidObjectException(
  1302. "cannot read back reference to unshared object");
  1303. }
  1304. return obj;
  1305. }
  1306. /**
  1307. * Reads in and returns class object. Sets passHandle to class object's
  1308. * assigned handle. Returns null if class is unresolvable (in which case a
  1309. * ClassNotFoundException will be associated with the class' handle in the
  1310. * handle table).
  1311. */
  1312. private Class readClass(boolean unshared) throws IOException {
  1313. if (bin.readByte() != TC_CLASS) {
  1314. throw new StreamCorruptedException();
  1315. }
  1316. ObjectStreamClass desc = readClassDesc(false);
  1317. Class cl = desc.forClass();
  1318. passHandle = handles.assign(unshared ? unsharedMarker : cl);
  1319. ClassNotFoundException resolveEx = desc.getResolveException();
  1320. if (resolveEx != null) {
  1321. handles.markException(passHandle, resolveEx);
  1322. }
  1323. handles.finish(passHandle);
  1324. return cl;
  1325. }
  1326. /**
  1327. * Reads in and returns (possibly null) class descriptor. Sets passHandle
  1328. * to class descriptor's assigned handle. If class descriptor cannot be
  1329. * resolved to a class in the local VM, a ClassNotFoundException is
  1330. * associated with the class descriptor's handle.
  1331. */
  1332. private ObjectStreamClass readClassDesc(boolean unshared)
  1333. throws IOException
  1334. {
  1335. switch (bin.peekByte()) {
  1336. case TC_NULL:
  1337. return (ObjectStreamClass) readNull();
  1338. case TC_REFERENCE:
  1339. return (ObjectStreamClass) readHandle(unshared);
  1340. case TC_PROXYCLASSDESC:
  1341. return readProxyDesc(unshared);
  1342. case TC_CLASSDESC:
  1343. return readNonProxyDesc(unshared);
  1344. default:
  1345. throw new StreamCorruptedException();
  1346. }
  1347. }
  1348. /**