1. /*
  2. * @(#)ObjectInputStream.java 1.107 01/02/09
  3. *
  4. * Copyright 1996-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.io;
  11. import java.util.ArrayList;
  12. import java.util.Stack;
  13. import java.util.Hashtable;
  14. import java.lang.Math;
  15. import java.lang.reflect.InvocationTargetException;
  16. import java.lang.reflect.Proxy;
  17. import java.lang.reflect.Field;
  18. /**
  19. * An ObjectInputStream deserializes primitive data and objects previously
  20. * written using an ObjectOutputStream.
  21. *
  22. * ObjectOutputStream and ObjectInputStream can provide an application
  23. * with persistent storage for graphs of objects when used with a
  24. * FileOutputStream and FileInputStream respectively.
  25. * ObjectInputStream is used to recover those objects previously
  26. * serialized. Other uses include passing objects between hosts using
  27. * a socket stream or for marshaling and unmarshaling arguments and
  28. * parameters in a remote communication system.<p>
  29. *
  30. * ObjectInputStream ensures that the types of all objects in the
  31. * graph created from the stream match the classes present in the
  32. * Java Virtual Machine. Classes are loaded as required using the
  33. * standard mechanisms. <p>
  34. *
  35. * Only objects that support the java.io.Serializable or
  36. * java.io.Externalizable interface can be read from streams.
  37. *
  38. * The method <STRONG>readObject</STRONG> is used to read an object
  39. * from the stream. Java's safe casting should be used to get the
  40. * desired type. In Java, strings and arrays are objects and are
  41. * treated as objects during serialization. When read they need to be
  42. * cast to the expected type.<p>
  43. *
  44. * Primitive data types can be read from the stream using the appropriate
  45. * method on DataInput. <p>
  46. *
  47. * The default deserialization mechanism for objects restores the
  48. * contents of each field to the value and type it had when it was written.
  49. * Fields declared as transient or static are ignored by the
  50. * deserialization process. References to other objects cause those
  51. * objects to be read from the stream as necessary. Graphs of objects
  52. * are restored correctly using a reference sharing mechanism. New
  53. * objects are always allocated when deserializing, which prevents
  54. * existing objects from being overwritten. <p>
  55. *
  56. * Reading an object is analogous to running the constructors of a new
  57. * object. Memory is allocated for the object and initialized to zero
  58. * (NULL). No-arg constructors are invoked for the non-serializable
  59. * classes and then the fields of the serializable classes are
  60. * restored from the stream starting with the serializable class closest to
  61. * java.lang.object and finishing with the object's most specifiec
  62. * class. <p>
  63. *
  64. * For example to read from a stream as written by the example in
  65. * ObjectOutputStream: <br>
  66. *
  67. * <PRE>
  68. * FileInputStream istream = new FileInputStream("t.tmp");
  69. * ObjectInputStream p = new ObjectInputStream(istream);
  70. *
  71. * int i = p.readInt();
  72. * String today = (String)p.readObject();
  73. * Date date = (Date)p.readObject();
  74. *
  75. * istream.close();
  76. * </PRE>
  77. *
  78. * Classes control how they are serialized by implementing either the
  79. * java.io.Serializable or java.io.Externalizable interfaces.<P>
  80. *
  81. * Implementing the Serializable interface allows object serialization
  82. * to save and restore the entire state of the object and it allows
  83. * classes to evolve between the time the stream is written and the time it is
  84. * read. It automatically traverses references between objects,
  85. * saving and restoring entire graphs.
  86. *
  87. * Serializable classes that require special handling during the
  88. * serialization and deserialization process should implement both
  89. * of these methods:<p>
  90. *
  91. * <PRE>
  92. * private void writeObject(java.io.ObjectOutputStream stream)
  93. * throws IOException;
  94. * private void readObject(java.io.ObjectInputStream stream)
  95. * throws IOException, ClassNotFoundException;
  96. * </PRE><p>
  97. *
  98. * The readObject method is responsible for reading and restoring the
  99. * state of the object for its particular class using data written to
  100. * the stream by the corresponding writeObject method. The method
  101. * does not need to concern itself with the state belonging to its
  102. * superclasses or subclasses. State is restored by reading data from
  103. * the ObjectInputStream for the individual fields and making
  104. * assignments to the appropriate fields of the object. Reading
  105. * primitive data types is supported by DataInput. <p>
  106. *
  107. * Serialization does not read or assign values to the fields of any
  108. * object that does not implement the java.io.Serializable interface.
  109. * Subclasses of Objects that are not serializable can be
  110. * serializable. In this case the non-serializable class must have a
  111. * no-arg constructor to allow its fields to be initialized. In this
  112. * case it is the responsibility of the subclass to save and restore
  113. * the state of the non-serializable class. It is frequently the case that
  114. * the fields of that class are accessible (public, package, or
  115. * protected) or that there are get and set methods that can be used
  116. * to restore the state. <p>
  117. *
  118. * Any exception that occurs while deserializing an object will be
  119. * caught by the ObjectInputStream and abort the reading process. <p>
  120. *
  121. * Implementing the Externalizable interface allows the object to
  122. * assume complete control over the contents and format of the object's
  123. * serialized form. The methods of the Externalizable interface,
  124. * writeExternal and readExternal, are called to save and restore the
  125. * objects state. When implemented by a class they can write and read
  126. * their own state using all of the methods of ObjectOutput and
  127. * ObjectInput. It is the responsibility of the objects to handle any
  128. * versioning that occurs.
  129. *
  130. * @author Roger Riggs
  131. * @version 1.107, 02/09/01
  132. * @see java.io.DataInput
  133. * @see java.io.ObjectOutputStream
  134. * @see java.io.Serializable
  135. * @see <a href="../../../guide/serialization/spec/input.doc.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  136. * @since JDK1.1
  137. */
  138. public class ObjectInputStream extends InputStream
  139. implements ObjectInput, ObjectStreamConstants
  140. {
  141. /**
  142. * Create an ObjectInputStream that reads from the specified InputStream.
  143. * The stream header containing the magic number and version number
  144. * are read from the stream and verified. This method will block
  145. * until the corresponding ObjectOutputStream has written and flushed the
  146. * header.
  147. *
  148. * @param in the underlying <code>InputStream</code> from which to read
  149. * @exception StreamCorruptedException The version or magic number are
  150. * incorrect.
  151. * @exception IOException An exception occurred in the underlying stream.
  152. */
  153. public ObjectInputStream(InputStream in)
  154. throws IOException, StreamCorruptedException
  155. {
  156. enableSubclassImplementation = false;
  157. /*
  158. * Save the input stream to read bytes from
  159. * Create a DataInputStream used to read primitive types.
  160. * Setup the DataInputStream to read from this ObjectInputStream
  161. */
  162. this.in = in;
  163. buf = new byte[8];
  164. dis = new DataInputStream(this);
  165. readStreamHeader();
  166. resetStream();
  167. }
  168. /**
  169. * Provide a way for subclasses that are completely reimplementing
  170. * ObjectInputStream to not have to allocate private data just used by
  171. * this implementation of ObjectInputStream.
  172. *
  173. * <p>If there is a security manager installed, this method first calls the
  174. * security manager's <code>checkPermission</code> method with the
  175. * <code>SerializablePermission("enableSubclassImplementation")</code>
  176. * permission to ensure it's ok to enable subclassing.
  177. *
  178. * @exception IOException Thrown if not called by a subclass.
  179. * @throws SecurityException
  180. * if a security manager exists and its
  181. * <code>checkPermission</code> method denies
  182. * enabling subclassing.
  183. *
  184. * @see SecurityManager#checkPermission
  185. * @see java.io.SerializablePermission
  186. */
  187. protected ObjectInputStream() throws IOException, SecurityException {
  188. SecurityManager sm = System.getSecurityManager();
  189. if (sm != null) sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  190. enableSubclassImplementation = true;
  191. }
  192. /**
  193. * Read an object from the ObjectInputStream.
  194. * The class of the object, the signature of the class, and the values
  195. * of the non-transient and non-static fields of the class and all
  196. * of its supertypes are read. Default deserializing for a class can be
  197. * overriden using the writeObject and readObject methods.
  198. * Objects referenced by this object are read transitively so
  199. * that a complete equivalent graph of objects is reconstructed by
  200. * readObject. <p>
  201. *
  202. * The root object is completly restored when all of its fields
  203. * and the objects it references are completely restored. At this
  204. * point the object validation callbacks are executed in order
  205. * based on their registered priorities. The callbacks are
  206. * registered by objects (in the readObject special methods)
  207. * as they are individually restored.
  208. *
  209. * Exceptions are thrown for problems with the InputStream and for classes
  210. * that should not be deserialized. All exceptions are fatal to the
  211. * InputStream and leave it in an indeterminate state; it is up to the
  212. * caller to ignore or recover the stream state.
  213. *
  214. * @exception java.lang.ClassNotFoundException Class of a serialized object
  215. * cannot be found.
  216. * @exception InvalidClassException Something is wrong with a class used by
  217. * serialization.
  218. * @exception StreamCorruptedException Control information in the
  219. * stream is inconsistent.
  220. * @exception OptionalDataException Primitive data was found in the
  221. * stream instead of objects.
  222. * @exception IOException Any of the usual Input/Output related exceptions.
  223. */
  224. public final Object readObject()
  225. throws OptionalDataException, ClassNotFoundException, IOException {
  226. if (enableSubclassImplementation)
  227. return readObjectOverride();
  228. else {
  229. /* require local Class for object by default. */
  230. return readObject(true);
  231. }
  232. }
  233. /**
  234. * This method is called by trusted subclasses of ObjectOutputStream
  235. * that constructed ObjectOutputStream using the
  236. * protected no-arg constructor. The subclass is expected to provide
  237. * an override method with the modifier "final".
  238. *
  239. * @return the Object read from the stream.
  240. * @exception java.lang.ClassNotFoundException Class definition of a
  241. * serialized object cannot be found.
  242. * @exception OptionalDataException Primitive data was found in the
  243. * stream instead of objects.
  244. * @exception IOException if I/O errors occurred while reading from the
  245. * underlying stream
  246. *
  247. * @see #ObjectInputStream()
  248. * @see #readObject()
  249. * @since 1.2
  250. */
  251. protected Object readObjectOverride()
  252. throws OptionalDataException, ClassNotFoundException, IOException
  253. {
  254. return null;
  255. }
  256. /*
  257. * Private implementation of Read an object from the ObjectInputStream.
  258. *
  259. * @param requireLocalClass If false, do not throw ClassNotFoundException
  260. * when local class does not exist.
  261. *
  262. * @since 1.2
  263. */
  264. private final Object readObject(boolean requireLocalClass)
  265. throws OptionalDataException, ClassNotFoundException, IOException
  266. {
  267. /* If the stream is in blockData mode and there's any data
  268. * left throw an exception to report how much there is.
  269. */
  270. if (blockDataMode) {
  271. /* Can't use member method available() since it depends on the unreliable
  272. * method InputStream.available().
  273. */
  274. if (count == 0)
  275. refill();
  276. if (count > 0)
  277. throw new OptionalDataException(count);
  278. }
  279. /*
  280. * Look ahead now to absorb any pending reset's.
  281. * Before changing the state.
  282. */
  283. peekCode();
  284. /* Save the current state and get ready to read an object. */
  285. Object prevObject = currentObject;
  286. ObjectStreamClass prevClass = currentClassDesc;
  287. boolean prevBlockDataMode = setBlockData(false);
  288. recursionDepth++; // Entering
  289. Object obj = null;
  290. /*
  291. * Check for reset, handle it before reading an object.
  292. */
  293. byte rcode;
  294. rcode = readCode();
  295. try {
  296. /*
  297. * Dispatch on the next code in the stream.
  298. */
  299. int wireoffset = -1;
  300. switch (rcode) {
  301. case TC_NULL:
  302. obj = null;
  303. break;
  304. case TC_REFERENCE:
  305. /* This is a reference to a pre-existing object */
  306. wireoffset = readInt() - baseWireHandle;
  307. try {
  308. obj = wireHandle2Object.get(wireoffset);
  309. } catch (ArrayIndexOutOfBoundsException e) {
  310. throw new StreamCorruptedException("Reference to object never serialized.");
  311. }
  312. break;
  313. case TC_STRING:
  314. case TC_LONGSTRING:
  315. {
  316. long utflen = (rcode == TC_STRING) ?
  317. readUnsignedShort() : readLong();
  318. obj = readUTFBody(utflen);
  319. Object localObj = obj;
  320. wireoffset = assignWireOffset(obj);
  321. /* Allow subclasses to replace the object */
  322. if (enableResolve) {
  323. obj = resolveObject(obj);
  324. }
  325. if (obj != localObj)
  326. wireHandle2Object.set(wireoffset, obj);
  327. }
  328. break;
  329. case TC_CLASS:
  330. ObjectStreamClass v =
  331. (ObjectStreamClass)readObject(requireLocalClass);
  332. if (v == null) {
  333. /*
  334. * No class descriptor in stream or class not serializable
  335. */
  336. throw new StreamCorruptedException("Class not in stream");
  337. }
  338. obj = v.forClass();
  339. if (obj == null && requireLocalClass) {
  340. throw v.pendingException;
  341. }
  342. assignWireOffset(obj);
  343. break;
  344. case TC_CLASSDESC:
  345. obj = inputClassDescriptor();
  346. break;
  347. case TC_PROXYCLASSDESC:
  348. obj = inputProxyClassDescriptor();
  349. break;
  350. case TC_ARRAY:
  351. wireoffset = inputArray(requireLocalClass);
  352. obj = currentObject;
  353. /* Allow subclasses to replace the object */
  354. if (enableResolve) {
  355. obj = resolveObject(obj);
  356. }
  357. if (obj != currentObject)
  358. wireHandle2Object.set(wireoffset, obj);
  359. break;
  360. case TC_OBJECT:
  361. wireoffset = inputObject(requireLocalClass);
  362. obj = currentObject;
  363. /* Allow the object to resolve itself. */
  364. if (currentObject != null &&
  365. currentClassDesc != null &&
  366. currentClassDesc.isResolvable()) {
  367. obj = ObjectStreamClass.invokeMethod(
  368. currentClassDesc.readResolveMethod, obj, null);
  369. }
  370. /* Allow subclasses to replace the object */
  371. if (enableResolve) {
  372. obj = resolveObject(obj);
  373. }
  374. if (obj != currentObject)
  375. wireHandle2Object.set(wireoffset, obj);
  376. break;
  377. case TC_ENDBLOCKDATA:
  378. if (!prevBlockDataMode)
  379. throw new StreamCorruptedException("Unexpected end of block data");
  380. pushbackCode(TC_ENDBLOCKDATA);
  381. count = -1; /* Flag EOF */
  382. throw new OptionalDataException(true);
  383. case TC_BLOCKDATA:
  384. case TC_BLOCKDATALONG:
  385. if (rcode == TC_BLOCKDATALONG) { /* long block: 32 bit size */
  386. int b3 = in.read();
  387. int b2 = in.read();
  388. int b1 = in.read();
  389. int b0 = in.read();
  390. if ((b3 | b2 | b1 | b0) < 0)
  391. throw new StreamCorruptedException("EOF expecting count");
  392. count = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  393. if (count < 0)
  394. throw new StreamCorruptedException("Negative block data size");
  395. } else { /* normal block: 8 bit size */
  396. count = in.read();
  397. if (count < 0)
  398. throw new StreamCorruptedException("EOF expecting count");
  399. }
  400. if (!prevBlockDataMode)
  401. throw new StreamCorruptedException("Unexpected blockdata");
  402. throw new OptionalDataException(count);
  403. case TC_EXCEPTION:
  404. /* An exception happened during writing, reset the
  405. * stream, read the exception, reset the stream and
  406. * throw a writeAbortedException with the exception
  407. * that was read.
  408. */
  409. resetStream();
  410. IOException ee = (IOException)readObject();
  411. resetStream();
  412. throw new WriteAbortedException("Writing aborted by exception", ee);
  413. default:
  414. throw new StreamCorruptedException("Unknown code in readObject " + rcode);
  415. }
  416. } catch (OptionalDataException optdata) {
  417. /* OptionalDataExceptions won't terminate everything.
  418. * so just rethrow it.
  419. */
  420. throw optdata;
  421. } catch(IOException ee) {
  422. if (abortIOException == null && abortClassNotFoundException == null)
  423. abortIOException = ee;
  424. } catch(ClassNotFoundException ee) {
  425. if (abortIOException == null && abortClassNotFoundException == null)
  426. abortClassNotFoundException = ee;
  427. } finally {
  428. recursionDepth --;
  429. currentObject = prevObject;
  430. currentClassDesc = prevClass;
  431. currentClass = currentClassDesc != null ?
  432. currentClassDesc.forClass() : null;
  433. setBlockData(prevBlockDataMode);
  434. }
  435. /* Check for thrown exceptions and re-throw them, clearing them if
  436. * this is the last recursive call .
  437. */
  438. IOException exIOE = abortIOException;
  439. if (recursionDepth == 0)
  440. abortIOException = null;
  441. if (exIOE != null)
  442. throw exIOE;
  443. ClassNotFoundException exCNF = abortClassNotFoundException;
  444. if (recursionDepth == 0)
  445. abortClassNotFoundException = null;
  446. if (exCNF != null) {
  447. throw exCNF;
  448. }
  449. // Check if this is the last nested read, if so
  450. // Call the validations
  451. if (recursionDepth == 0) {
  452. doValidations();
  453. }
  454. return obj;
  455. }
  456. /**
  457. * Read the non-static and non-transient fields of the current class
  458. * from this stream. This may only be called from the readObject method
  459. * of the class being deserialized. It will throw the NotActiveException
  460. * if it is called otherwise.
  461. *
  462. * @exception java.lang.ClassNotFoundException if the class of a serialized
  463. * object could not be found.
  464. * @exception IOException if an I/O error occurs.
  465. * @exception NotActiveException if the stream is not currently reading
  466. * objects.
  467. */
  468. public void defaultReadObject()
  469. throws IOException, ClassNotFoundException, NotActiveException
  470. {
  471. if (currentObject == null || currentClassDesc == null)
  472. throw new NotActiveException("defaultReadObject");
  473. ObjectStreamField[] fields =
  474. currentClassDesc.getFieldsNoCopy();
  475. if (fields.length > 0) {
  476. boolean prevmode = setBlockData(false);
  477. inputClassFields(currentObject, currentClass, fields);
  478. setBlockData(prevmode);
  479. }
  480. }
  481. /**
  482. * Reads the persistent fields from the stream and makes them
  483. * available by name.
  484. *
  485. * @return the <code>GetField</code> object representing the persistent
  486. * fields of the object being deserialized
  487. * @exception java.lang.ClassNotFoundException if the class of a serialized
  488. * object could not be found.
  489. * @exception IOException if an I/O error occurs.
  490. * @exception NotActiveException if the stream is not currently reading
  491. * objects.
  492. * @since 1.2
  493. */
  494. public ObjectInputStream.GetField readFields()
  495. throws IOException, ClassNotFoundException, NotActiveException
  496. {
  497. if (currentObject == null || currentClassDesc == null)
  498. throw new NotActiveException("defaultReadObject");
  499. // TBD: Interlock w/ defaultReadObject
  500. GetFieldImpl curr = new GetFieldImpl(currentClassDesc);
  501. currentGetFields = curr;
  502. boolean prevmode = setBlockData(false);
  503. curr.read(this);
  504. setBlockData(prevmode);
  505. return curr;
  506. }
  507. /**
  508. * Register an object to be validated before the graph is
  509. * returned. While similar to resolveObject these validations are
  510. * called after the entire graph has been reconstituted.
  511. * Typically, a readObject method will register the object with
  512. * the stream so that when all of the objects are restored a final
  513. * set of validations can be performed.
  514. *
  515. * @param obj the object to receive the validation callback.
  516. * @param prio controls the order of callbacks;zero is a good default.
  517. * Use higher numbers to be called back earlier, lower numbers for later
  518. * callbacks. Within a priority, callbacks are processed in no
  519. * particular order.
  520. *
  521. * @exception NotActiveException The stream is not currently reading
  522. * objects so it is invalid to register a callback.
  523. * @exception InvalidObjectException The validation object is null.
  524. */
  525. public synchronized void registerValidation(ObjectInputValidation obj,
  526. int prio)
  527. throws NotActiveException, InvalidObjectException
  528. {
  529. if (recursionDepth == 0) {
  530. throw new NotActiveException("readObject not Active");
  531. }
  532. if (obj == null) {
  533. throw new InvalidObjectException("Null is not a valid callback object");
  534. }
  535. ValidationCallback cb = new ValidationCallback(obj, prio);
  536. if (callbacks == null) {
  537. callbacks = new ArrayList();
  538. }
  539. // insert at the end if the priority is less than or equal to
  540. // the last element.
  541. if (callbacks.isEmpty() ||
  542. ((ValidationCallback)(callbacks.get(callbacks.size()-1))).priority >= prio) {
  543. callbacks.add(cb);
  544. return;
  545. }
  546. // search for the element with priority that is <= to the new
  547. // priority, insert before it.
  548. int size = callbacks.size();
  549. for (int i = 0; i < size; i++) {
  550. ValidationCallback curr = (ValidationCallback)callbacks.get(i);
  551. if (curr.priority <= prio) {
  552. callbacks.add(i, cb);
  553. break;
  554. }
  555. }
  556. }
  557. /*
  558. * If any validations are pending, do them and cleanup the validation vector
  559. * if an exception is raised, it is passed on to abort the deserialization.
  560. */
  561. private void doValidations() throws InvalidObjectException {
  562. if (callbacks == null)
  563. return;
  564. int size = callbacks.size();
  565. for (int i = 0; i < size; i++) {
  566. ValidationCallback curr = (ValidationCallback)callbacks.get(i);
  567. curr.callback.validateObject();
  568. }
  569. callbacks.clear();
  570. }
  571. /**
  572. * Load the local class equivalent of the specified stream class description.
  573. *
  574. * Subclasses may implement this method to allow classes to be
  575. * fetched from an alternate source.
  576. *
  577. * The corresponding method in ObjectOutputStream is
  578. * annotateClass. This method will be invoked only once for each
  579. * unique class in the stream. This method can be implemented by
  580. * subclasses to use an alternate loading mechanism but must
  581. * return a Class object. Once returned, the serialVersionUID of the
  582. * class is compared to the serialVersionUID of the serialized class.
  583. * If there is a mismatch, the deserialization fails and an exception
  584. * is raised. <p>
  585. *
  586. * By default the class name is resolved relative to the class
  587. * that called readObject. <p>
  588. *
  589. * @param v an instance of class ObjectStreamClass
  590. * @return a Class object corresponding to <code>v</code>
  591. * @exception IOException Any of the usual Input/Output exceptions.
  592. * @exception ClassNotFoundException If class of
  593. * a serialized object cannot be found.
  594. */
  595. protected Class resolveClass(ObjectStreamClass v)
  596. throws IOException, ClassNotFoundException
  597. {
  598. /* Resolve by looking up the stack for a non-zero class
  599. * loader. If not found use the system class loader.
  600. */
  601. ClassLoader loader = latestUserDefinedLoader();
  602. return Class.forName(v.getName(), false, loader);
  603. }
  604. /**
  605. * Returns a proxy class that implements the interfaces named in a
  606. * proxy class descriptor; subclasses may implement this method to
  607. * read custom data from the stream along with the descriptors for
  608. * dynamic proxy classes, allowing them to use an alternate loading
  609. * mechanism for the interfaces and the proxy class.
  610. *
  611. * <p>This method is called exactly once for each unique proxy class
  612. * descriptor in the stream.
  613. *
  614. * <p>The corresponding method in <code>ObjectOutputStream</code> is
  615. * <code>annotateProxyClass</code>. For a given subclass of
  616. * <code>ObjectInputStream</code> that overrides this method, the
  617. * <code>annotateProxyClass</code> method in the corresponding
  618. * subclass of <code>ObjectOutputStream</code> must write any data or
  619. * objects read by this method.
  620. *
  621. * <p>The default implementation of this method in
  622. * <code>ObjectInputStream</code> returns the result of calling
  623. * <code>Proxy.getProxyClass</code> with the list of
  624. * <code>Class</code> objects for the interfaces that are named in
  625. * the <code>interfaces</code> parameter. The <code>Class</code>
  626. * object for each interface name <code>i</code> is the value
  627. * returned by calling
  628. * <pre>
  629. * Class.forName(i, false, loader)
  630. * </pre>
  631. * where <code>loader</code> is that of the first non-null class
  632. * loader up the execution stack, or <code>null</code> if no non-null
  633. * class loaders are on the stack (the same class loader choice used
  634. * by the <code>resolveClass</code> method). This same value of
  635. * <code>loader</code> is also the class loader passed to
  636. * <code>Proxy.getProxyClass</code>. If <code>Proxy.getProxyClass</code>
  637. * throws an <code>IllegalArgumentException</code>,
  638. * <code>resolveProxyClass</code> will throw a
  639. * <code>ClassNotFoundException</code> containing the
  640. * <code>IllegalArgumentException</code>.
  641. *
  642. * @param interfaces the list of interface names that were
  643. * deserialized in the proxy class descriptor
  644. * @return a proxy class for the specified interfaces
  645. * @throws IOException any exception thrown by the underlying
  646. * <code>InputStream</code>
  647. * @throws ClassNotFoundException if the proxy class or any of the
  648. * named interfaces could not be found
  649. * @see ObjectOutputStream#annotateProxyClass(Class)
  650. * @since 1.3
  651. */
  652. protected Class resolveProxyClass(String[] interfaces)
  653. throws IOException, ClassNotFoundException
  654. {
  655. ClassLoader loader = latestUserDefinedLoader();
  656. Class[] classObjs = new Class[interfaces.length];
  657. for (int i = 0; i < interfaces.length; i++) {
  658. classObjs[i] = Class.forName(interfaces[i], false, loader);
  659. }
  660. try {
  661. return Proxy.getProxyClass(loader, classObjs);
  662. } catch (IllegalArgumentException e) {
  663. throw new ClassNotFoundException(null, e);
  664. }
  665. }
  666. /*
  667. * Returns the first non-null class loader up the execution stack, or null
  668. * if only code from the null class loader is on the stack.
  669. */
  670. private static native ClassLoader latestUserDefinedLoader()
  671. throws ClassNotFoundException;
  672. /*
  673. * Simulates the behavior of the old native "loadClass0" method,
  674. * preserved here only for invocation by the following native method
  675. * in the RMI-IIOP implementation:
  676. *
  677. * com.sun.corba.se.internal.util.JDKClassLoader.specialLoadClass
  678. *
  679. * This method should be removed when the above use is cleaned up.
  680. */
  681. private Class loadClass0(Class cl, String classname)
  682. throws ClassNotFoundException
  683. {
  684. ClassLoader loader;
  685. if (cl != null) {
  686. loader = cl.getClassLoader();
  687. } else {
  688. loader = latestUserDefinedLoader();
  689. }
  690. return Class.forName(classname, false, loader);
  691. }
  692. /**
  693. * This method will allow trusted subclasses of ObjectInputStream
  694. * to substitute one object for another during
  695. * deserialization. Replacing objects is disabled until
  696. * enableResolveObject is called. The enableResolveObject method
  697. * checks that the stream requesting to resolve object can be
  698. * trusted. Every reference to serializable objects is passed to
  699. * resolveObject. To insure that the private state of objects is
  700. * not unintentionally exposed only trusted streams may use
  701. * resolveObject. <p>
  702. *
  703. * This method is called after an object has been read but before it is
  704. * returned from readObject. The default resolveObject method
  705. * just returns the same object. <p>
  706. *
  707. * When a subclass is replacing objects it must insure that the
  708. * substituted object is compatible with every field where the
  709. * reference will be stored. Objects whose type is not a subclass
  710. * of the type of the field or array element abort the
  711. * serialization by raising an exception and the object is not be
  712. * stored. <p>
  713. *
  714. * This method is called only once when each object is first encountered.
  715. * All subsequent references to the object will be redirected to the
  716. * new object. <P>
  717. *
  718. * @param obj object to be substituted
  719. * @return the substituted object
  720. * @exception IOException Any of the usual Input/Output exceptions.
  721. */
  722. protected Object resolveObject(Object obj)
  723. throws IOException
  724. {
  725. return obj;
  726. }
  727. /**
  728. * Enable the stream to allow objects read from the stream to be replaced.
  729. *
  730. * When enabled, the resolveObject method is called for every object
  731. * being deserialized.
  732. *
  733. * If <i>enable</i> is true, and there is a security manager installed,
  734. * this method first calls the
  735. * security manager's <code>checkPermission</code> method with the
  736. * <code>SerializablePermission("enableSubstitution")</code>
  737. * permission to ensure it's ok to
  738. * enable the stream to allow objects read from the stream to be replaced.
  739. *
  740. * @param enable true for enabling use of <code>resolveObject</code> for
  741. * every object being deserialized
  742. * @return the previous setting before this method was invoked
  743. * @throws SecurityException
  744. * if a security manager exists and its
  745. * <code>checkPermission</code> method denies
  746. * enabling the stream to allow objects read from the stream to be
  747. * replaced.
  748. *
  749. * @see SecurityManager#checkPermission
  750. * @see java.io.SerializablePermission
  751. */
  752. protected boolean enableResolveObject(boolean enable)
  753. throws SecurityException
  754. {
  755. boolean previous = enableResolve;
  756. if (enable) {
  757. SecurityManager sm = System.getSecurityManager();
  758. if (sm != null) sm.checkPermission(SUBSTITUTION_PERMISSION);
  759. enableResolve = true;
  760. } else {
  761. enableResolve = false;
  762. }
  763. return previous;
  764. }
  765. /**
  766. * The readStreamHeader method is provided to allow subclasses to
  767. * read and verify their own stream headers. It reads and
  768. * verifies the magic number and version number.
  769. *
  770. * @throws IOException if there are I/O errors while reading from the
  771. * underlying <code>InputStream</code>
  772. * @throws StreamCorruptedException if control information in the
  773. * stream is inconsistent
  774. */
  775. protected void readStreamHeader()
  776. throws IOException, StreamCorruptedException
  777. {
  778. short incoming_magic = 0;
  779. short incoming_version = 0;
  780. try {
  781. incoming_magic = readShort();
  782. incoming_version = readShort();
  783. } catch (EOFException e) {
  784. throw new StreamCorruptedException("Caught EOFException " +
  785. "while reading the stream header");
  786. }
  787. if (incoming_magic != STREAM_MAGIC)
  788. throw new StreamCorruptedException("InputStream does not contain a serialized object");
  789. if (incoming_version != STREAM_VERSION)
  790. throw new StreamCorruptedException("Version Mismatch, Expected " +
  791. STREAM_VERSION + " and got " +
  792. incoming_version);
  793. }
  794. /**
  795. * Read a class descriptor from the serialization stream. This method is
  796. * called when the ObjectInputStream expects a class descriptor as the next
  797. * item in the serialization stream. Subclasses of ObjectInputStream may
  798. * override this method to read in class descriptors that have been written
  799. * in non-standard formats (by subclasses of ObjectOutputStream which have
  800. * overridden the <code>writeClassDescriptor</code> method). By default,
  801. * this method reads class descriptors according to the format defined in
  802. * the Object Serialization specification.
  803. * <p>
  804. *
  805. * @return the class descriptor read
  806. * @exception IOException If an I/O error has occurred.
  807. * @exception ClassNotFoundException If the Class of a serialized object
  808. * used in the class descriptor representation cannot be found
  809. * @see
  810. * java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
  811. * @since 1.3
  812. */
  813. protected ObjectStreamClass readClassDescriptor()
  814. throws IOException, ClassNotFoundException
  815. {
  816. String classname = readUTF();
  817. long hash = readLong();
  818. ObjectStreamClass v = new ObjectStreamClass(classname, hash);
  819. v.read(this);
  820. return v;
  821. }
  822. /*
  823. * Read a ObjectStreamClass from the stream, it may recursively
  824. * create other ObjectStreamClasses for the classes it references.
  825. */
  826. private ObjectStreamClass inputClassDescriptor()
  827. throws IOException, InvalidClassException, ClassNotFoundException
  828. {
  829. Class aclass;
  830. /* For backwards compatibility, the wire handle for the incoming class
  831. * descriptor must be assigned _before_ the class descriptor data is
  832. * read in. To get around this, we reserve the next wire handle by
  833. * assigning it to an empty class descriptor, then the class descriptor
  834. * data is read in, and finally we copy the class descriptor data back
  835. * into the empty class descriptor.
  836. */
  837. ObjectStreamClass copydesc = new ObjectStreamClass(null, 0);
  838. int wireoffset = assignWireOffset(copydesc);
  839. /* Read in class descriptor */
  840. ObjectStreamClass desc = readClassDescriptor();
  841. /* copy into empty class descriptor */
  842. copydesc.lightCopy(desc);
  843. /* Switch to BlockDataMode and call resolveClass.
  844. * It may raise ClassNotFoundException.
  845. * Consume any extra data or objects left by resolve class and
  846. * read the endOfBlockData. Then switch out of BlockDataMode.
  847. */
  848. boolean prevMode = setBlockData(true);
  849. try {
  850. aclass = resolveClass(copydesc);
  851. } catch (ClassNotFoundException e) {
  852. /* if the most derived class, this exception will be thrown at a
  853. * later time. */
  854. aclass = null;
  855. /* Fix for 4191941: stash original exception, to throw later. */
  856. copydesc.pendingException = e;
  857. }
  858. skipToEndOfBlockData();
  859. prevMode = setBlockData(prevMode);
  860. /* Verify that the class returned is "compatible" with
  861. * the class description. i.e. the name and hash match.
  862. * Set the class this ObjectStreamClass will use to create
  863. * instances.
  864. */
  865. copydesc.setClass(aclass);
  866. /* Get the superdescriptor of this one and it set it.
  867. */
  868. ObjectStreamClass superdesc = (ObjectStreamClass)readObject();
  869. copydesc.setSuperclass(superdesc);
  870. return copydesc;
  871. }
  872. /**
  873. * Read a proxy class descriptor from the stream, returning the
  874. * equivalent incoming ObjectStreamClass object for the resolved
  875. * proxy class.
  876. */
  877. private ObjectStreamClass inputProxyClassDescriptor()
  878. throws IOException, InvalidClassException, ClassNotFoundException
  879. {
  880. /*
  881. * The wire handle must be assigned for the ObjectStreamClass
  882. * object we will return before reading any other objects from
  883. * the stream that could reference it, so we have to construct
  884. * the ObjectStreamClass first, with no name.
  885. *
  886. * All proxy classes have a serialVersionUID of 0L.
  887. */
  888. ObjectStreamClass v = new ObjectStreamClass("", 0L);
  889. int wireoffset = assignWireOffset(v);
  890. /*
  891. * Read in the names of the proxy interfaces.
  892. */
  893. int numInterfaces = readInt();
  894. String[] interfaces = new String[numInterfaces];
  895. for (int i = 0; i < numInterfaces; i++) {
  896. interfaces[i] = readUTF();
  897. }
  898. /*
  899. * Within block data mode to allow reading custom data, invoke
  900. * resolveProxyClass to get the appropriate Class object for the
  901. * proxy class with the described interfaces.
  902. */
  903. Class cl;
  904. boolean prevMode = setBlockData(true);
  905. try {
  906. cl = resolveProxyClass(interfaces);
  907. } catch (ClassNotFoundException e) {
  908. cl = null;
  909. v.pendingException = e;
  910. }
  911. skipToEndOfBlockData();
  912. prevMode = setBlockData(prevMode);
  913. /*
  914. * Fill in the fields of ObjectStreamClass that are read from the
  915. * stream for non-proxy classes but are implicit for proxy classes.
  916. */
  917. v.initProxyClassDesc(cl);
  918. /*
  919. * Set the local Class object for the descriptor and read and set
  920. * the descriptor for the superclass.
  921. */
  922. v.setClass(cl);
  923. ObjectStreamClass superdesc = (ObjectStreamClass)readObject();
  924. v.setSuperclass(superdesc);
  925. return v;
  926. }
  927. /* Private routine to read in an array. Called from inputObject
  928. * after the typecode has been read from the stream.
  929. */
  930. private int inputArray(boolean requireLocalClass)
  931. throws IOException, ClassNotFoundException
  932. {
  933. /* May raise ClassNotFoundException */
  934. ObjectStreamClass v = (ObjectStreamClass)readObject();
  935. Class arrayclass = v.forClass();
  936. if (arrayclass == null && requireLocalClass)
  937. throw v.pendingException;
  938. /* This can't be done with new because only the top level array
  939. * is needed and the type must be set properly.
  940. * the lower level arrays will be created when they are read.
  941. */
  942. int length = readInt();
  943. currentObject = (arrayclass == null) ?
  944. null : allocateNewArray(arrayclass, length);
  945. int wireoffset = assignWireOffset(currentObject);
  946. /* Read in the values from the array,
  947. * It dispatches using the type and read using the read* methods.
  948. */
  949. int i;
  950. if (arrayclass != null
  951. && arrayclass.getComponentType().isPrimitive()) {
  952. Class type = arrayclass.getComponentType();
  953. /* Arrays of primitive types read data in blocks and
  954. * decode the data types from the buffer.
  955. */
  956. int offset = data.length;
  957. int buflen = data.length;
  958. if (type == Boolean.TYPE) {
  959. boolean[] array = (boolean[])currentObject;
  960. for (i = 0; i < length; i++) {
  961. if (offset >= buflen) {
  962. int readlen = Math.min(length-i, buflen);
  963. readFully(data, 0, readlen);
  964. offset = 0;
  965. }
  966. array[i] = (data[offset] != 0);
  967. offset += 1;
  968. }
  969. } else if (type == Byte.TYPE) {
  970. byte[] array = (byte[])currentObject;
  971. int ai = 0;
  972. while (ai < length) {
  973. int readlen = Math.min(length-ai, buflen);
  974. readFully(data, 0, readlen);
  975. System.arraycopy(data, 0, array, ai, readlen);
  976. ai += readlen;
  977. }
  978. } else if (type == Short.TYPE) {
  979. short[] array = (short[])currentObject;
  980. for (i = 0; i < length; i++) {
  981. if (offset > buflen - 2) {
  982. int readlen = Math.min((length-i)*2, buflen);
  983. readFully(data, 0, readlen);
  984. offset = 0;
  985. }
  986. array[i] = (short)(((data[offset] & 0xff) << 8) +
  987. ((data[offset+1] & 0xff) << 0));
  988. offset += 2;
  989. }
  990. } else if (type == Integer.TYPE) {
  991. int[] array = (int[])currentObject;
  992. for (i = 0; i < length; i++) {
  993. if (offset > buflen - 4) {
  994. int readlen = Math.min((length-i) << 2, buflen);
  995. readFully(data, 0, readlen);
  996. offset = 0;
  997. }
  998. array[i] = (((data[offset] & 0xff) << 24) +
  999. ((data[offset+1] & 0xff) << 16) +
  1000. ((data[offset+2] & 0xff) << 8) +
  1001. ((data[offset+3] & 0xff) << 0));
  1002. offset += 4;
  1003. }
  1004. } else if (type == Long.TYPE) {
  1005. long[] array = (long[])currentObject;
  1006. for (i = 0; i < length; i++) {
  1007. if (offset > buflen - 8) {
  1008. int readlen = Math.min((length - i) << 3, buflen);
  1009. readFully(data, 0, readlen);
  1010. offset = 0;
  1011. }
  1012. int upper = (((data[offset] & 0xff) << 24) +
  1013. ((data[offset+1] & 0xff) << 16) +
  1014. ((data[offset+2] & 0xff) << 8) +
  1015. ((data[offset+3] & 0xff) << 0));
  1016. int lower = (((data[offset+4] & 0xff) << 24) +
  1017. ((data[offset+5] & 0xff) << 16) +
  1018. ((data[offset+6] & 0xff) << 8) +
  1019. ((data[offset+7] & 0xff) << 0));
  1020. array[i] = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  1021. offset += 8;
  1022. }
  1023. } else if (type == Float.TYPE) {
  1024. float[] array = (float[])currentObject;
  1025. for (i = 0; i < length; ) {
  1026. int n = Math.min(length - i, buflen >> 2);
  1027. readFully(data, 0, n << 2);
  1028. bytesToFloats(data, 0, array, i, n);
  1029. i += n;
  1030. }
  1031. } else if (type == Double.TYPE) {
  1032. double[] array = (double[])currentObject;
  1033. for (i = 0; i < length; ) {
  1034. int n = Math.min(length - i, buflen >> 3);
  1035. readFully(data, 0, n << 3);
  1036. bytesToDoubles(data, 0, array, i, n);
  1037. i += n;
  1038. }
  1039. } else if (type == Character.TYPE) {
  1040. char[] array = (char[])currentObject;
  1041. for (i = 0; i < length; i++) {
  1042. if (offset > buflen - 2) {
  1043. int readlen = Math.min((length-i)*2, buflen);
  1044. readFully(data, 0, readlen);
  1045. offset = 0;
  1046. }
  1047. array[i] = (char)(((data[offset] & 0xff) << 8) +
  1048. ((data[offset+1] & 0xff) << 0));
  1049. offset += 2;
  1050. }
  1051. } else {
  1052. throw new InvalidClassException(arrayclass.getName());
  1053. }
  1054. } else { // Is array of objects
  1055. Object[] array = (Object[])currentObject;
  1056. boolean requiresLocalClass = (arrayclass != null);
  1057. for (i = 0; i < length; i++) {
  1058. Object obj = readObject(requiresLocalClass);
  1059. if (array != null)
  1060. array[i] = obj;
  1061. }
  1062. }
  1063. return wireoffset;
  1064. }
  1065. /*
  1066. * Reconstitutes nfloats float values from their byte representations. Byte
  1067. * values are read from array src starting at offset srcpos; the resulting
  1068. * float values are written to array dst starting at dstpos.
  1069. */
  1070. private static native void bytesToFloats(byte[] src, int srcpos,
  1071. float[] dst, int dstpos, int nfloats);
  1072. /*
  1073. * Reconstitutes ndoubles double values from their byte representations.
  1074. * Byte values are read from array src starting at offset srcpos; the
  1075. * resulting double values are written to array dst starting at dstpos.
  1076. */
  1077. private static native void bytesToDoubles(byte[] src, int srcpos,
  1078. double[] dst, int dstpos, int ndoubles);
  1079. /*
  1080. * Read an instance of a class from the stream
  1081. * The new object typecode has already been read and used to dispatch to here.
  1082. * The ObjectStreamClass for the class is read and the class
  1083. * of the object retrieved from it.
  1084. * A new object is created of the specified class and
  1085. * each serializable class is processed using either
  1086. * the default serialization methods or class defined special methods
  1087. * if they have been defined.
  1088. * The handle for the object is returned, the object itself is in currentObject.
  1089. */
  1090. private int inputObject(boolean requireLocalClass)
  1091. throws IOException, ClassNotFoundException
  1092. {
  1093. int handle = -1;
  1094. /*
  1095. * Get the descriptor and then class of the incoming object.
  1096. */
  1097. currentClassDesc = (ObjectStreamClass)readObject();
  1098. currentClass = currentClassDesc.forClass();
  1099. if (currentClass == null && requireLocalClass)
  1100. throw currentClassDesc.pendingException;
  1101. if (requireLocalClass)
  1102. currentClassDesc.verifyInstanceDeserialization();
  1103. /* If Externalizable,
  1104. * Create an instance and tell it to read its data.
  1105. * else,
  1106. * Handle it as a serializable class.
  1107. */
  1108. if (currentClassDesc.isExternalizable()) {
  1109. try {
  1110. currentObject = (currentClass == null) ?
  1111. null : allocateNewObject(currentClass, currentClass);
  1112. handle = assignWireOffset(currentObject);
  1113. boolean prevmode = blockDataMode;
  1114. try {
  1115. if (currentClassDesc.hasExternalizableBlockDataMode()) {
  1116. prevmode = setBlockData(true);
  1117. }
  1118. if (currentObject != null) {
  1119. Externalizable ext = (Externalizable)currentObject;
  1120. ext.readExternal(this);
  1121. }
  1122. } finally {
  1123. if (currentClassDesc.hasExternalizableBlockDataMode()) {
  1124. skipToEndOfBlockData();
  1125. setBlockData(prevmode);
  1126. }
  1127. }
  1128. } catch (NoSuchMethodError e) {
  1129. throw new InvalidClassException(currentClass.getName() +
  1130. "Missing no-arg constructor for class");
  1131. } catch (IllegalAccessException e) {
  1132. throw new InvalidClassException(currentClass.getName(),
  1133. "IllegalAccessException");
  1134. } catch (InstantiationException e) {
  1135. throw new InvalidClassException(currentClass.getName(),
  1136. "InstantiationException");
  1137. }
  1138. } else {
  1139. /* Count number of classes and descriptors we might have
  1140. * to work on.
  1141. */
  1142. ObjectStreamClass currdesc;
  1143. Class currclass;
  1144. int numAncestors;
  1145. int spBase;
  1146. if (currentClassDesc.ancestors == null) {
  1147. currdesc = currentClassDesc;
  1148. currclass = currentClass;
  1149. spBase = spClass; // current top of stack
  1150. /* The object's classes should be processed from supertype to
  1151. * subtype. Push all the classes of the current object onto a
  1152. * stack. Note that only the serializable classes are
  1153. * represented in the descriptor list.
  1154. *
  1155. * Handle versioning where one or more supertypes of have been
  1156. * inserted or removed. The stack will contain pairs of
  1157. * descriptors and the corresponding class. If the object has a
  1158. * class that did not occur in the original the descriptor will
  1159. * be null. If the original object had a descriptor for a class
  1160. * not present in the local hierarchy of the object the class
  1161. * will be null.
  1162. *
  1163. */
  1164. /*
  1165. * This is your basic diff pattern, made simpler
  1166. * because reordering is not allowed.
  1167. */
  1168. for (currdesc = currentClassDesc, currclass = currentClass;
  1169. currdesc != null;
  1170. currdesc = currdesc.superclass) {
  1171. /*
  1172. * Search the classes to see if the class of this
  1173. * descriptor appears further up the hierarchy. Until
  1174. * it's found assume its an inserted class. If it's
  1175. * not found, its the descriptor's class that has been
  1176. * removed.
  1177. */
  1178. Class cc = currdesc.forClass();
  1179. Class cl;
  1180. for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  1181. if (cc == cl) {
  1182. // found a superclass that matches this descriptor
  1183. break;
  1184. } else {
  1185. /* Ignore a class that doesn't match. No
  1186. * action is needed since it is already
  1187. * initialized.
  1188. */
  1189. }
  1190. }
  1191. /* Test if there is room for this new entry. If not, double
  1192. * the size of the arrays and copy the contents.
  1193. */
  1194. if (spClass >= classes.length) {
  1195. growClassStacks();
  1196. }
  1197. if (cl == null) {
  1198. /* Class not found corresponding to this descriptor.
  1199. * Pop off all the extra classes pushed.
  1200. * Push the descriptor and a null class.
  1201. */
  1202. classdesc[spClass] = currdesc;
  1203. classes[spClass] = null;
  1204. } else {
  1205. /* Current class descriptor matches current class.
  1206. * Some classes may have been inserted.
  1207. * Record the match and advance the class, continue
  1208. * with the next descriptor.
  1209. */
  1210. classdesc[spClass] = currdesc;
  1211. classes[spClass] = cl;
  1212. /* Ignoring all the classes between currclass and cl.
  1213. */
  1214. currclass = cl.getSuperclass();
  1215. }
  1216. spClass++;
  1217. }
  1218. /*
  1219. * Find the highest non-serializable object. Note that the
  1220. * class Object is non-serializable.
  1221. */
  1222. if (currclass != null) {
  1223. while (Serializable.class.isAssignableFrom(currclass))
  1224. currclass = currclass.getSuperclass();
  1225. }
  1226. numAncestors = spClass - spBase;
  1227. currentClassDesc.ancestors = new Class[numAncestors + 1];
  1228. for (int i = 0; i < numAncestors; i++)
  1229. currentClassDesc.ancestors[i] = classes[spBase + i];
  1230. currentClassDesc.ancestors[numAncestors] = currclass;
  1231. spClass = spBase;
  1232. }
  1233. numAncestors = currentClassDesc.ancestors.length - 1;
  1234. currclass = currentClassDesc.ancestors[numAncestors];
  1235. /* Allocate a new object. The object is only constructed
  1236. * above the highest serializable class and is set to
  1237. * default values for all more specialized classes.
  1238. * Remember the next wirehandle goes with the new object
  1239. */
  1240. try {
  1241. currentObject = (currentClass == null) ?
  1242. null : allocateNewObject(currentClass, currclass);
  1243. } catch (NoSuchMethodError e) {
  1244. throw new InvalidClassException(currclass.getName() +
  1245. "Missing no-arg constructor for class");
  1246. } catch (IllegalAccessException e) {
  1247. throw new InvalidClassException(currclass.getName(),
  1248. "IllegalAccessException");
  1249. } catch (InstantiationException e) {
  1250. throw new InvalidClassException(currclass.getName(),
  1251. "InstantiationException");
  1252. }
  1253. handle = assignWireOffset(currentObject);
  1254. /*
  1255. * For all the pushed descriptors and classes.
  1256. * If there is a descriptor but no class, skip the
  1257. * data for that class.
  1258. * If there is a class but no descriptor, just advance,
  1259. * The classes fields have already been initialized to default
  1260. * values.
  1261. * Otherwise, there is both a descriptor and class,
  1262. * if the class has its own writeObject and readObject methods
  1263. * set blockData = true; and call the readObject method
  1264. * else
  1265. * invoke the defaultReadObject method
  1266. * if the stream was written by class specific methods
  1267. * skip any remaining data a objects until TC_ENDBLOCKDATA
  1268. * Avoid setting BlockData=true unless necessary becase it flushes
  1269. * the buffer.
  1270. */
  1271. /* Push ancestor class descriptors and their associated local
  1272. * classes onto the stack.
  1273. */
  1274. spBase = spClass;
  1275. for (currdesc = currentClassDesc; currdesc != null;
  1276. currdesc = currdesc.superclass)
  1277. {
  1278. if (spClass >= classes.length) {
  1279. growClassStacks();
  1280. }
  1281. classdesc[spClass] = currdesc;
  1282. classes[spClass] =
  1283. currentClassDesc.ancestors[spClass - spBase];
  1284. spClass++;
  1285. }
  1286. try {
  1287. for (spClass--; spClass >= spBase; spClass--) {
  1288. /*
  1289. * Set current descriptor and corresponding class
  1290. */
  1291. currentClassDesc = classdesc[spClass];
  1292. currentClass = classes[spClass];
  1293. setBlockData(true); /* any reads are from datablocks */
  1294. if (classes[spClass] != null) {
  1295. /* Read the data from the stream described by the
  1296. * descriptor and store into the matching class.
  1297. */
  1298. ObjectStreamClass localDesc =
  1299. currentClassDesc.localClassDescriptor();
  1300. if (!invokeObjectReader(currentObject)) {
  1301. defaultReadObject();
  1302. }
  1303. } else {
  1304. /* No local class for this descriptor,
  1305. * Skip over the data for this class.
  1306. * like defaultReadObject with a null currentObject.
  1307. * The code will read the values but discard them.
  1308. */
  1309. ObjectStreamField[] fields =
  1310. currentClassDesc.getFieldsNoCopy();
  1311. if (fields.length > 0) {
  1312. boolean prevmode = setBlockData(false);
  1313. inputClassFields(null, currentClass, fields);
  1314. setBlockData(prevmode);
  1315. }
  1316. }
  1317. /*
  1318. * If the source class (stream) had a write object method
  1319. * it may have written more data and will have written the
  1320. * TC_ENDBLOCKDATA. Skip anything up to that and read it.
  1321. */
  1322. if (currentClassDesc.hasWriteObject()) {
  1323. skipToEndOfBlockData();
  1324. }
  1325. setBlockData(false);
  1326. }
  1327. } finally {
  1328. // Make sure we exit at the same stack level as when we started.
  1329. spClass = spBase;
  1330. }
  1331. }
  1332. return handle;
  1333. }
  1334. /*
  1335. * Grow the size of the class descriptor and class stacks.
  1336. */
  1337. private void growClassStacks() {
  1338. int newlen = classes.length * 2;
  1339. Class[] newclasses = new Class[newlen];
  1340. ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  1341. System.arraycopy(classes, 0, newclasses, 0, classes.length);
  1342. System.arraycopy(classdesc, 0, newclassdesc, 0, classes.length);
  1343. classes = newclasses;
  1344. classdesc = newclassdesc;
  1345. }
  1346. /*
  1347. * Skip any unread block data and objects up to the next
  1348. * TC_ENDBLOCKDATA. Anybody can do this because readObject
  1349. * handles the details of reporting if there is data left.
  1350. * Try reading objects. If it throws optional data
  1351. * skip over it and try again.
  1352. */
  1353. private void skipToEndOfBlockData()
  1354. throws IOException, ClassNotFoundException
  1355. {
  1356. if (! blockDataMode)
  1357. return;
  1358. for (;;) {
  1359. while (count > 0)
  1360. skip(count);
  1361. switch (peekCode()) {
  1362. case -1: // EOF
  1363. return;
  1364. case TC_BLOCKDATA:
  1365. case TC_BLOCKDATALONG:
  1366. refill(); // read in next block header
  1367. break;
  1368. case TC_ENDBLOCKDATA:
  1369. readCode(); // consume TC_ENDBLOCKDATA
  1370. return;
  1371. default:
  1372. readObject(false); // don't require local class
  1373. break;
  1374. }
  1375. }
  1376. }
  1377. /*
  1378. * Reset the stream to be just like it was after the constructor.
  1379. */
  1380. private void resetStream() throws IOException {
  1381. if (wireHandle2Object == null)
  1382. wireHandle2Object = new ArrayList();
  1383. else
  1384. wireHandle2Object.clear();
  1385. nextWireOffset = 0;
  1386. if (classes == null)
  1387. classes = new Class[20];
  1388. else {
  1389. for (int i = 0; i < classes.length; i++)
  1390. classes[i] = null;
  1391. }
  1392. if (classdesc == null)
  1393. classdesc = new ObjectStreamClass[20];
  1394. else {
  1395. for (int i = 0; i < classdesc.length; i++)
  1396. classdesc[i] = null;
  1397. }
  1398. spClass = 0;
  1399. setBlockData(true); // Re-enable buffering
  1400. if (callbacks != null)
  1401. callbacks.clear(); // discard any pending callbacks
  1402. }
  1403. /* Allocate a handle for an object.
  1404. * The list is indexed by the wireHandleOffset
  1405. * and contains the object.
  1406. */
  1407. private int assignWireOffset(Object obj)
  1408. throws IOException
  1409. {
  1410. wireHandle2Object.add(obj);
  1411. if (++nextWireOffset != wireHandle2Object.size())
  1412. throw new StreamCorruptedException(
  1413. "Elements not assigned in order");
  1414. return nextWireOffset-1;
  1415. }
  1416. /*
  1417. * Peek at the next control code in the stream.
  1418. * If the code has not been peeked at yet, read it from the stream.
  1419. */
  1420. private byte peekCode() throws IOException, StreamCorruptedException{
  1421. while (currCode == 0) {
  1422. int newcode = in.read(); // Read byte from the underlying stream
  1423. if (newcode < 0)
  1424. throw new EOFException("Expecting code");
  1425. currCode = (byte)newcode;
  1426. if (currCode < TC_BASE || currCode > TC_MAX)
  1427. throw new StreamCorruptedException("Type code out of range, is " + currCode);
  1428. /*
  1429. * Handle reset as a hidden code and reset the stream.
  1430. */
  1431. if (currCode == TC_RESET) {