1. /*
  2. * @(#)ObjectInputStream.java 1.79 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.io;
  8. import java.util.ArrayList;
  9. import java.util.Stack;
  10. import java.util.Hashtable;
  11. import java.lang.Math;
  12. import java.lang.reflect.InvocationTargetException;
  13. /**
  14. * An ObjectInputStream deserializes primitive data and objects previously
  15. * written using an ObjectOutputStream.
  16. *
  17. * ObjectOutputStream and ObjectInputStream can provide an application
  18. * with persistent storage for graphs of objects when used with a
  19. * FileOutputStream and FileInputStream respectively.
  20. * ObjectInputStream is used to recover those objects previously
  21. * serialized. Other uses include passing objects between hosts using
  22. * a socket stream or for marshaling and unmarshaling arguments and
  23. * parameters in a remote communication system.<p>
  24. *
  25. * ObjectInputStream ensures that the types of all objects in the
  26. * graph created from the stream match the classes present in the
  27. * Java Virtual Machine. Classes are loaded as required using the
  28. * standard mechanisms. <p>
  29. *
  30. * Only objects that support the java.io.Serializable or
  31. * java.io.Externalizable interface can be read from streams.
  32. *
  33. * The method <STRONG>readObject</STRONG> is used to read an object
  34. * from the stream. Java's safe casting should be used to get the
  35. * desired type. In Java, strings and arrays are objects and are
  36. * treated as objects during serialization. When read they need to be
  37. * cast to the expected type.<p>
  38. *
  39. * Primitive data types can be read from the stream using the appropriate
  40. * method on DataInput. <p>
  41. *
  42. * The default deserialization mechanism for objects restores the
  43. * contents of each field to the value and type it had when it was written.
  44. * Fields declared as transient or static are ignored by the
  45. * deserialization process. References to other objects cause those
  46. * objects to be read from the stream as necessary. Graphs of objects
  47. * are restored correctly using a reference sharing mechanism. New
  48. * objects are always allocated when deserializing, which prevents
  49. * existing objects from being overwritten. <p>
  50. *
  51. * Reading an object is analogous to running the constructors of a new
  52. * object. Memory is allocated for the object and initialized to zero
  53. * (NULL). No-arg constructors are invoked for the non-serializable
  54. * classes and then the fields of the serializable classes are
  55. * restored from the stream starting with the serializable class closest to
  56. * java.lang.object and finishing with the object's most specifiec
  57. * class. <p>
  58. *
  59. * For example to read from a stream as written by the example in
  60. * ObjectOutputStream: <br>
  61. *
  62. * <PRE>
  63. * FileInputStream istream = new FileInputStream("t.tmp");
  64. * ObjectInputStream p = new ObjectInputStream(istream);
  65. *
  66. * int i = p.readInt();
  67. * String today = (String)p.readObject();
  68. * Date date = (Date)p.readObject();
  69. *
  70. * istream.close();
  71. * </PRE>
  72. *
  73. * Classes control how they are serialized by implementing either the
  74. * java.io.Serializable or java.io.Externalizable interfaces.<P>
  75. *
  76. * Implementing the Serializable interface allows object serialization
  77. * to save and restore the entire state of the object and it allows
  78. * classes to evolve between the time the stream is written and the time it is
  79. * read. It automatically traverses references between objects,
  80. * saving and restoring entire graphs.
  81. *
  82. * Serializable classes that require special handling during the
  83. * serialization and deserialization process should implement both
  84. * of these methods:<p>
  85. *
  86. * <PRE>
  87. * private void writeObject(java.io.ObjectOutputStream stream)
  88. * throws IOException;
  89. * private void readObject(java.io.ObjectInputStream stream)
  90. * throws IOException, ClassNotFoundException;
  91. * </PRE><p>
  92. *
  93. * The readObject method is responsible for reading and restoring the
  94. * state of the object for its particular class using data written to
  95. * the stream by the corresponding writeObject method. The method
  96. * does not need to concern itself with the state belonging to its
  97. * superclasses or subclasses. State is restored by reading data from
  98. * the ObjectInputStream for the individual fields and making
  99. * assignments to the appropriate fields of the object. Reading
  100. * primitive data types is supported by DataInput. <p>
  101. *
  102. * Serialization does not read or assign values to the fields of any
  103. * object that does not implement the java.io.Serializable interface.
  104. * Subclasses of Objects that are not serializable can be
  105. * serializable. In this case the non-serializable class must have a
  106. * no-arg constructor to allow its fields to be initialized. In this
  107. * case it is the responsibility of the subclass to save and restore
  108. * the state of the non-serializable class. It is frequently the case that
  109. * the fields of that class are accessible (public, package, or
  110. * protected) or that there are get and set methods that can be used
  111. * to restore the state. <p>
  112. *
  113. * Any exception that occurs while deserializing an object will be
  114. * caught by the ObjectInputStream and abort the reading process. <p>
  115. *
  116. * Implementing the Externalizable interface allows the object to
  117. * assume complete control over the contents and format of the object's
  118. * serialized form. The methods of the Externalizable interface,
  119. * writeExternal and readExternal, are called to save and restore the
  120. * objects state. When implemented by a class they can write and read
  121. * their own state using all of the methods of ObjectOutput and
  122. * ObjectInput. It is the responsibility of the objects to handle any
  123. * versioning that occurs.
  124. *
  125. * @author Roger Riggs
  126. * @version 1.79, 11/29/01
  127. * @see java.io.DataInput
  128. * @see java.io.ObjectOutputStream
  129. * @see java.io.Serializable
  130. * @see <a href="http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/input.doc.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  131. * @since JDK1.1
  132. */
  133. public class ObjectInputStream extends InputStream
  134. implements ObjectInput, ObjectStreamConstants
  135. {
  136. /**
  137. * Create an ObjectInputStream that reads from the specified InputStream.
  138. * The stream header containing the magic number and version number
  139. * are read from the stream and verified. This method will block
  140. * until the corresponding ObjectOutputStream has written and flushed the header.
  141. * @exception StreamCorruptedException The version or magic number are incorrect.
  142. * @exception IOException An exception occurred in the underlying stream.
  143. */
  144. public ObjectInputStream(InputStream in)
  145. throws IOException, StreamCorruptedException
  146. {
  147. enableSubclassImplementation = false;
  148. /*
  149. * Save the input stream to read bytes from
  150. * Create a DataInputStream used to read primitive types.
  151. * Setup the DataInputStream to read from this ObjectInputStream
  152. */
  153. this.in = in;
  154. dis = new DataInputStream(this);
  155. readStreamHeader();
  156. resetStream();
  157. }
  158. /**
  159. * Provide a way for subclasses that are completely reimplementing
  160. * ObjectInputStream to not have to allocate private data just used by
  161. * this implementation of ObjectInputStream.
  162. *
  163. * <p>If there is a security manager installed, this method first calls the
  164. * security manager's <code>checkPermission</code> method with the
  165. * <code>SerializablePermission("enableSubclassImplementation")</code>
  166. * permission to ensure it's ok to enable subclassing.
  167. *
  168. * @exception IOException Thrown if not called by a subclass.
  169. * @throws SecurityException
  170. * if a security manager exists and its
  171. * <code>checkPermission</code> method denies
  172. * enabling subclassing.
  173. *
  174. * @see SecurityManager#checkPermission
  175. * @see java.security.SerializablePermission
  176. */
  177. protected ObjectInputStream() throws IOException, SecurityException {
  178. SecurityManager sm = System.getSecurityManager();
  179. if (sm != null) sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  180. enableSubclassImplementation = true;
  181. }
  182. /**
  183. * Read an object from the ObjectInputStream.
  184. * The class of the object, the signature of the class, and the values
  185. * of the non-transient and non-static fields of the class and all
  186. * of its supertypes are read. Default deserializing for a class can be
  187. * overriden using the writeObject and readObject methods.
  188. * Objects referenced by this object are read transitively so
  189. * that a complete equivalent graph of objects is reconstructed by
  190. * readObject. <p>
  191. *
  192. * The root object is completly restored when all of its fields
  193. * and the objects it references are completely restored. At this
  194. * point the object validation callbacks are executed in order
  195. * based on their registered priorities. The callbacks are
  196. * registered by objects (in the readObject special methods)
  197. * as they are individually restored.
  198. *
  199. * Exceptions are thrown for problems with the InputStream and for classes
  200. * that should not be deserialized. All exceptions are fatal to the
  201. * InputStream and leave it in an indeterminate state; it is up to the
  202. * caller to ignore or recover the stream state.
  203. * @exception java.lang.ClassNotFoundException Class of a serialized object
  204. * cannot be found.
  205. * @exception InvalidClassException Something is wrong with a class used by
  206. * serialization.
  207. * @exception StreamCorruptedException Control information in the
  208. * stream is inconsistent.
  209. * @exception OptionalDataException Primitive data was found in the
  210. * stream instead of objects.
  211. * @exception IOException Any of the usual Input/Output related exceptions.
  212. */
  213. public final Object readObject()
  214. throws OptionalDataException, ClassNotFoundException, IOException {
  215. if (enableSubclassImplementation)
  216. return readObjectOverride();
  217. else {
  218. /* require local Class for object by default. */
  219. return readObject(true);
  220. }
  221. }
  222. /**
  223. * This method is called by trusted subclasses of ObjectOutputStream
  224. * that constructed ObjectOutputStream using the
  225. * protected no-arg constructor. The subclass is expected to provide
  226. * an override method with the modifier "final".
  227. *
  228. * @return the Object read from the stream.
  229. *
  230. * @see #ObjectInputStream()
  231. * @see #readObject()
  232. * @since JDK 1.2
  233. */
  234. protected Object readObjectOverride()
  235. throws OptionalDataException, ClassNotFoundException, IOException
  236. {
  237. return null;
  238. }
  239. /*
  240. * Private implementation of Read an object from the ObjectInputStream.
  241. *
  242. * @param requireLocalClass If false, do not throw ClassNotFoundException
  243. * when local class does not exist.
  244. *
  245. * @since JDK1.2
  246. */
  247. private final Object readObject(boolean requireLocalClass)
  248. throws OptionalDataException, ClassNotFoundException, IOException
  249. {
  250. /* If the stream is in blockData mode and there's any data
  251. * left throw an exception to report how much there is.
  252. */
  253. if (blockDataMode) {
  254. /* Can't use member method available() since it depends on the unreliable
  255. * method InputStream.available().
  256. */
  257. if (count == 0)
  258. refill();
  259. if (count > 0)
  260. throw new OptionalDataException(count);
  261. }
  262. /*
  263. * Look ahead now to absorb any pending reset's.
  264. * Before changing the state.
  265. */
  266. peekCode();
  267. /* Save the current state and get ready to read an object. */
  268. Object prevObject = currentObject;
  269. ObjectStreamClass prevClass = currentClassDesc;
  270. boolean prevBlockDataMode = setBlockData(false);
  271. recursionDepth++; // Entering
  272. Object obj = null;
  273. /*
  274. * Check for reset, handle it before reading an object.
  275. */
  276. byte rcode;
  277. rcode = readCode();
  278. try {
  279. /*
  280. * Dispatch on the next code in the stream.
  281. */
  282. int wireoffset = -1;
  283. switch (rcode) {
  284. case TC_NULL:
  285. obj = null;
  286. break;
  287. case TC_REFERENCE:
  288. /* This is a reference to a pre-existing object */
  289. wireoffset = readInt() - baseWireHandle;
  290. try {
  291. obj = wireHandle2Object.get(wireoffset);
  292. } catch (ArrayIndexOutOfBoundsException e) {
  293. throw new StreamCorruptedException("Reference to object never serialized.");
  294. }
  295. break;
  296. case TC_STRING:
  297. {
  298. obj = readUTF();
  299. Object localObj = obj;
  300. wireoffset = assignWireOffset(obj);
  301. /* Allow subclasses to replace the object */
  302. if (enableResolve) {
  303. obj = resolveObject(obj);
  304. }
  305. if (obj != localObj)
  306. wireHandle2Object.set(wireoffset, obj);
  307. }
  308. break;
  309. case TC_CLASS:
  310. ObjectStreamClass v =
  311. (ObjectStreamClass)readObject(requireLocalClass);
  312. if (v == null) {
  313. /*
  314. * No class descriptor in stream or class not serializable
  315. */
  316. throw new StreamCorruptedException("Class not in stream");
  317. }
  318. obj = v.forClass();
  319. if (obj == null && requireLocalClass) {
  320. throw new ClassNotFoundException(v.getName());
  321. }
  322. assignWireOffset(obj);
  323. break;
  324. case TC_CLASSDESC:
  325. obj = inputClassDescriptor();
  326. break;
  327. case TC_ARRAY:
  328. wireoffset = inputArray(requireLocalClass);
  329. obj = currentObject;
  330. /* Allow subclasses to replace the object */
  331. if (enableResolve) {
  332. obj = resolveObject(obj);
  333. }
  334. if (obj != currentObject)
  335. wireHandle2Object.set(wireoffset, obj);
  336. break;
  337. case TC_OBJECT:
  338. wireoffset = inputObject(requireLocalClass);
  339. obj = currentObject;
  340. /* Allow the object to resolve itself. */
  341. if (currentObject != null &&
  342. currentClassDesc != null &&
  343. currentClassDesc.isResolvable()) {
  344. obj =
  345. ObjectStreamClass.invokeMethod(currentClassDesc.readResolveMethod,
  346. obj, null);
  347. }
  348. /* Allow subclasses to replace the object */
  349. if (enableResolve) {
  350. obj = resolveObject(obj);
  351. }
  352. if (obj != currentObject)
  353. wireHandle2Object.set(wireoffset, obj);
  354. break;
  355. case TC_ENDBLOCKDATA:
  356. if (!prevBlockDataMode)
  357. throw new StreamCorruptedException("Unexpected end of block data");
  358. pushbackCode(TC_ENDBLOCKDATA);
  359. count = -1; /* Flag EOF */
  360. throw new OptionalDataException(true);
  361. case TC_BLOCKDATA:
  362. case TC_BLOCKDATALONG:
  363. if (rcode == TC_BLOCKDATALONG) { /* long block: 32 bit size */
  364. int b3 = in.read();
  365. int b2 = in.read();
  366. int b1 = in.read();
  367. int b0 = in.read();
  368. if ((b3 | b2 | b1 | b0) < 0)
  369. throw new StreamCorruptedException("EOF expecting count");
  370. count = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  371. if (count < 0)
  372. throw new StreamCorruptedException("Negative block data size");
  373. } else { /* normal block: 8 bit size */
  374. count = in.read();
  375. if (count < 0)
  376. throw new StreamCorruptedException("EOF expecting count");
  377. }
  378. if (!prevBlockDataMode)
  379. throw new StreamCorruptedException("Unexpected blockdata");
  380. throw new OptionalDataException(count);
  381. case TC_EXCEPTION:
  382. /* An exception happened during writing, reset the
  383. * stream, read the exception, reset the stream and
  384. * throw a writeAbortedException with the exception
  385. * that was read.
  386. */
  387. resetStream();
  388. IOException ee = (IOException)readObject();
  389. resetStream();
  390. throw new WriteAbortedException("Writing aborted by exception", ee);
  391. default:
  392. throw new StreamCorruptedException("Unknown code in readObject " + rcode);
  393. }
  394. } catch (OptionalDataException optdata) {
  395. /* OptionalDataExceptions won't terminate everything.
  396. * so just rethrow it.
  397. */
  398. throw optdata;
  399. } catch(IOException ee) {
  400. if (abortIOException == null && abortClassNotFoundException == null)
  401. abortIOException = ee;
  402. } catch(ClassNotFoundException ee) {
  403. if (abortIOException == null && abortClassNotFoundException == null)
  404. abortClassNotFoundException = ee;
  405. } finally {
  406. recursionDepth --;
  407. currentObject = prevObject;
  408. currentClassDesc = prevClass;
  409. currentClass = currentClassDesc != null ?
  410. currentClassDesc.forClass() : null;
  411. setBlockData(prevBlockDataMode);
  412. }
  413. /* Check for thrown exceptions and re-throw them, clearing them if
  414. * this is the last recursive call .
  415. */
  416. IOException exIOE = abortIOException;
  417. if (recursionDepth == 0)
  418. abortIOException = null;
  419. if (exIOE != null)
  420. throw exIOE;
  421. ClassNotFoundException exCNF = abortClassNotFoundException;
  422. if (recursionDepth == 0)
  423. abortClassNotFoundException = null;
  424. if (exCNF != null) {
  425. throw exCNF;
  426. }
  427. // Check if this is the last nested read, if so
  428. // Call the validations
  429. if (recursionDepth == 0) {
  430. doValidations();
  431. }
  432. return obj;
  433. }
  434. /**
  435. * Read the non-static and non-transient fields of the current class
  436. * from this stream. This may only be called from the readObject method
  437. * of the class being deserialized. It will throw the NotActiveException
  438. * if it is called otherwise.
  439. *
  440. * @exception java.lang.ClassNotFoundException if the class of a serialized
  441. * object could not be found.
  442. * @exception IOException if an I/O error occurs.
  443. * @exception NotActiveException if the stream is not currently reading
  444. * objects.
  445. */
  446. public void defaultReadObject()
  447. throws IOException, ClassNotFoundException, NotActiveException
  448. {
  449. if (currentObject == null || currentClassDesc == null)
  450. throw new NotActiveException("defaultReadObject");
  451. ObjectStreamField[] fields =
  452. currentClassDesc.getFieldsNoCopy();
  453. if (fields.length > 0) {
  454. boolean prevmode = setBlockData(false);
  455. inputClassFields(currentObject, currentClass, fields);
  456. setBlockData(prevmode);
  457. }
  458. }
  459. /**
  460. * Reads the persistent fields from the stream and makes them
  461. * available by name.
  462. *
  463. * @exception java.lang.ClassNotFoundException if the class of a serialized
  464. * object could not be found.
  465. * @exception IOException if an I/O error occurs.
  466. * @exception NotActiveException if the stream is not currently reading
  467. * objects.
  468. * @since JDK 1.2
  469. */
  470. public ObjectInputStream.GetField readFields()
  471. throws IOException, ClassNotFoundException, NotActiveException
  472. {
  473. if (currentObject == null || currentClassDesc == null)
  474. throw new NotActiveException("defaultReadObject");
  475. // TBD: Interlock w/ defaultReadObject
  476. GetFieldImpl curr = new GetFieldImpl(currentClassDesc);
  477. currentGetFields = curr;
  478. boolean prevmode = setBlockData(false);
  479. curr.read(this);
  480. setBlockData(prevmode);
  481. return curr;
  482. }
  483. /**
  484. * Register an object to be validated before the graph is
  485. * returned. While similar to resolveObject these validations are
  486. * called after the entire graph has been reconstituted.
  487. * Typically, a readObject method will register the object with
  488. * the stream so that when all of the objects are restored a final
  489. * set of validations can be performed.
  490. * @param obj the object to receive the validation callback.
  491. * @param prio controls the order of callbacks;zero is a good default.
  492. * Use higher numbers to be called back earlier, lower numbers for later
  493. * callbacks. Within a priority, callbacks are processed in no
  494. * particular order.
  495. *
  496. * @exception NotActiveException The stream is not currently reading
  497. * objects so it is invalid to register a callback.
  498. * @exception InvalidObjectException The validation object is null.
  499. */
  500. public synchronized void registerValidation(ObjectInputValidation obj,
  501. int prio)
  502. throws NotActiveException, InvalidObjectException
  503. {
  504. if (recursionDepth == 0) {
  505. throw new NotActiveException("readObject not Active");
  506. }
  507. if (obj == null) {
  508. throw new InvalidObjectException("Null is not a valid callback object");
  509. }
  510. ValidationCallback cb = new ValidationCallback(obj, prio);
  511. if (callbacks == null) {
  512. callbacks = new ArrayList();
  513. }
  514. // insert at the end if the priority is less than or equal to
  515. // the last element.
  516. if (callbacks.isEmpty() ||
  517. ((ValidationCallback)(callbacks.get(callbacks.size()-1))).priority >= prio) {
  518. callbacks.add(cb);
  519. return;
  520. }
  521. // search for the element with priority that is <= to the new
  522. // priority, insert before it.
  523. int size = callbacks.size();
  524. for (int i = 0; i < size; i++) {
  525. ValidationCallback curr = (ValidationCallback)callbacks.get(i);
  526. if (curr.priority <= prio) {
  527. callbacks.add(i, cb);
  528. break;
  529. }
  530. }
  531. }
  532. /*
  533. * If any validations are pending, do them and cleanup the validation vector
  534. * if an exception is raised, it is passed on to abort the deserialization.
  535. */
  536. private void doValidations() throws InvalidObjectException {
  537. if (callbacks == null)
  538. return;
  539. int size = callbacks.size();
  540. for (int i = 0; i < size; i++) {
  541. ValidationCallback curr = (ValidationCallback)callbacks.get(i);
  542. curr.callback.validateObject();
  543. }
  544. callbacks.clear();
  545. }
  546. /**
  547. * Load the local class equivalent of the specified stream class description.
  548. *
  549. * Subclasses may implement this method to allow classes to be
  550. * fetched from an alternate source.
  551. *
  552. * The corresponding method in ObjectOutputStream is
  553. * annotateClass. This method will be invoked only once for each
  554. * unique class in the stream. This method can be implemented by
  555. * subclasses to use an alternate loading mechanism but must
  556. * return a Class object. Once returned, the serialVersionUID of the
  557. * class is compared to the serialVersionUID of the serialized class.
  558. * If there is a mismatch, the deserialization fails and an exception
  559. * is raised. <p>
  560. *
  561. * By default the class name is resolved relative to the class
  562. * that called readObject. <p>
  563. *
  564. * @exception ClassNotFoundException If class of
  565. * a serialized object cannot be found.
  566. */
  567. protected Class resolveClass(ObjectStreamClass v)
  568. throws IOException, ClassNotFoundException
  569. {
  570. /* Resolve by looking up the stack for a non-zero class
  571. * loader. If not found use the system class loader.
  572. */
  573. return loadClass0(null, v.getName());
  574. }
  575. /* Resolve a class name relative to the specified class. If the
  576. * class is null find the first available class loader up the
  577. * stack. This will resolve classes relative to the caller of
  578. * ObjectInputStream instead of the itself. Classes must be
  579. * loaded/resolved relative to the application.
  580. */
  581. private native Class loadClass0(Class cl, String classname)
  582. throws ClassNotFoundException;
  583. /**
  584. * This method will allow trusted subclasses of ObjectInputStream
  585. * to substitute one object for another during
  586. * deserialization. Replacing objects is disabled until
  587. * enableResolveObject is called. The enableResolveObject method
  588. * checks that the stream requesting to resolve object can be
  589. * trusted. Every reference to serializable objects is passed to
  590. * resolveObject. To insure that the private state of objects is
  591. * not unintentionally exposed only trusted streams may use
  592. * resolveObject. <p>
  593. *
  594. * This method is called after an object has been read but before it is
  595. * returned from readObject. The default resolveObject method
  596. * just returns the new object. <p>
  597. *
  598. * When a subclass is replacing objects it must insure that the
  599. * substituted object is compatible with every field where the
  600. * reference will be stored. Objects whose type is not a subclass
  601. * of the type of the field or array element abort the
  602. * serialization by raising an exception and the object is not be
  603. * stored. <p>
  604. *
  605. * This method is called only once when each object is first encountered.
  606. * All subsequent references to the object will be redirected to the
  607. * new object. <P>
  608. *
  609. * @exception IOException Any of the usual Input/Output exceptions.
  610. */
  611. protected Object resolveObject(Object obj)
  612. throws IOException
  613. {
  614. return obj;
  615. }
  616. /**
  617. * Enable the stream to allow objects read from the stream to be replaced.
  618. *
  619. * When enabled, the resolveObject method is called for every object
  620. * being deserialized.
  621. *
  622. * If <i>enable</i> is true, and there is a security manager installed,
  623. * this method first calls the
  624. * security manager's <code>checkPermission</code> method with the
  625. * <code>SerializablePermission("enableSubstitution")</code>
  626. * permission to ensure it's ok to
  627. * enable the stream to allow objects read from the stream to be replaced.
  628. *
  629. * @throws SecurityException
  630. * if a security manager exists and its
  631. * <code>checkPermission</code> method denies
  632. * enabling the stream to allow objects read from the stream to be replaced.
  633. *
  634. * @see SecurityManager#checkPermission
  635. * @see java.security.SerializablePermission
  636. */
  637. protected boolean enableResolveObject(boolean enable)
  638. throws SecurityException
  639. {
  640. boolean previous = enableResolve;
  641. if (enable) {
  642. SecurityManager sm = System.getSecurityManager();
  643. if (sm != null) sm.checkPermission(SUBSTITUTION_PERMISSION);
  644. enableResolve = true;
  645. } else {
  646. enableResolve = false;
  647. }
  648. return previous;
  649. }
  650. /**
  651. * The readStreamHeader method is provided to allow subclasses to
  652. * read and verify their own stream headers. It reads and
  653. * verifies the magic number and version number.
  654. */
  655. protected void readStreamHeader()
  656. throws IOException, StreamCorruptedException
  657. {
  658. short incoming_magic = 0;
  659. short incoming_version = 0;
  660. try {
  661. incoming_magic = readShort();
  662. incoming_version = readShort();
  663. } catch (EOFException e) {
  664. throw new StreamCorruptedException("Caught EOFException " +
  665. "while reading the stream header");
  666. }
  667. if (incoming_magic != STREAM_MAGIC)
  668. throw new StreamCorruptedException("InputStream does not contain a serialized object");
  669. if (incoming_version != STREAM_VERSION)
  670. throw new StreamCorruptedException("Version Mismatch, Expected " +
  671. STREAM_VERSION + " and got " +
  672. incoming_version);
  673. }
  674. /*
  675. * Read a ObjectStreamClass from the stream, it may recursively
  676. * create other ObjectStreamClasses for the classes it references.
  677. */
  678. private ObjectStreamClass inputClassDescriptor()
  679. throws IOException, InvalidClassException, ClassNotFoundException
  680. {
  681. /* Read the class name and hash */
  682. Class aclass;
  683. String classname = readUTF();
  684. long hash = readLong();
  685. /* Read a new class version descriptor from the stream */
  686. ObjectStreamClass v = new ObjectStreamClass(classname, hash);
  687. /* Assign the wire handle for this ObjectStreamClass and read it */
  688. int wireoffset = assignWireOffset(v);
  689. v.read(this);
  690. /* Switch to BlockDataMode and call resolveClass.
  691. * It may raise ClassNotFoundException.
  692. * Consume any extra data or objects left by resolve class and
  693. * read the endOfBlockData. Then switch out of BlockDataMode.
  694. */
  695. boolean prevMode = setBlockData(true);
  696. try {
  697. aclass = resolveClass((ObjectStreamClass)v);
  698. } catch (ClassNotFoundException e) {
  699. /* if the most derived class, this exception will be thrown at a later time. */
  700. aclass = null;
  701. } catch (NoClassDefFoundError e) {
  702. /* This exception was thrown when looking for an array of class,
  703. * and class could not be found.
  704. */
  705. aclass = null;
  706. }
  707. SkipToEndOfBlockData();
  708. prevMode = setBlockData(prevMode);
  709. /* Verify that the class returned is "compatible" with
  710. * the class description. i.e. the name and hash match.
  711. * Set the class this ObjectStreamClass will use to create
  712. * instances.
  713. */
  714. v.setClass(aclass);
  715. /* Get the superdescriptor of this one and it set it.
  716. */
  717. ObjectStreamClass superdesc = (ObjectStreamClass)readObject();
  718. v.setSuperclass(superdesc);
  719. return v;
  720. }
  721. /* Private routine to read in an array. Called from inputObject
  722. * after the typecode has been read from the stream.
  723. */
  724. private int inputArray(boolean requireLocalClass)
  725. throws IOException, ClassNotFoundException
  726. {
  727. /* May raise ClassNotFoundException */
  728. ObjectStreamClass v = (ObjectStreamClass)readObject();
  729. Class arrayclass = v.forClass();
  730. if (arrayclass == null && requireLocalClass)
  731. throw new ClassNotFoundException(v.getName());
  732. /* This can't be done with new because only the top level array
  733. * is needed and the type must be set properly.
  734. * the lower level arrays will be created when they are read.
  735. */
  736. int length = readInt();
  737. currentObject = (arrayclass == null) ?
  738. null : allocateNewArray(arrayclass, length);
  739. int wireoffset = assignWireOffset(currentObject);
  740. /* Read in the values from the array,
  741. * It dispatches using the type and read using the read* methods.
  742. */
  743. int i;
  744. if (arrayclass != null
  745. && arrayclass.getComponentType().isPrimitive()) {
  746. Class type = arrayclass.getComponentType();
  747. /* Arrays of primitive types read data in blocks and
  748. * decode the data types from the buffer.
  749. */
  750. if (buffer == null)
  751. buffer = new byte[1024];
  752. int offset = buffer.length;
  753. int buflen = buffer.length;
  754. if (type == Boolean.TYPE) {
  755. boolean[] array = (boolean[])currentObject;
  756. for (i = 0; i < length; i++) {
  757. if (offset >= buflen) {
  758. int readlen = Math.min(length-i, buflen);
  759. readFully(buffer, 0, readlen);
  760. offset = 0;
  761. }
  762. array[i] = (buffer[offset] != 0);
  763. offset += 1;
  764. }
  765. } else if (type == Byte.TYPE) {
  766. byte[] array = (byte[])currentObject;
  767. int ai = 0;
  768. while (ai < length) {
  769. int readlen = Math.min(length-ai, buflen);
  770. readFully(buffer, 0, readlen);
  771. System.arraycopy(buffer, 0, array, ai, readlen);
  772. ai += readlen;
  773. }
  774. } else if (type == Short.TYPE) {
  775. short[] array = (short[])currentObject;
  776. for (i = 0; i < length; i++) {
  777. if (offset > buflen - 2) {
  778. int readlen = Math.min((length-i)*2, buflen);
  779. readFully(buffer, 0, readlen);
  780. offset = 0;
  781. }
  782. array[i] = (short)(((buffer[offset] & 0xff) << 8) +
  783. ((buffer[offset+1] & 0xff) << 0));
  784. offset += 2;
  785. }
  786. } else if (type == Integer.TYPE) {
  787. int[] array = (int[])currentObject;
  788. for (i = 0; i < length; i++) {
  789. if (offset > buflen - 4) {
  790. int readlen = Math.min((length-i)*4, buflen);
  791. readFully(buffer, 0, readlen);
  792. offset = 0;
  793. }
  794. array[i] = (((buffer[offset] & 0xff) << 24) +
  795. ((buffer[offset+1] & 0xff) << 16) +
  796. ((buffer[offset+2] & 0xff) << 8) +
  797. ((buffer[offset+3] & 0xff) << 0));
  798. offset += 4;
  799. }
  800. } else if (type == Long.TYPE) {
  801. long[] array = (long[])currentObject;
  802. for (i = 0; i < length; i++) {
  803. if (offset > buflen - 8) {
  804. int readlen = Math.min((length-i)*8, buflen);
  805. readFully(buffer, 0, readlen);
  806. offset = 0;
  807. }
  808. int upper = (((buffer[offset] & 0xff) << 24) +
  809. ((buffer[offset+1] & 0xff) << 16) +
  810. ((buffer[offset+2] & 0xff) << 8) +
  811. ((buffer[offset+3] & 0xff) << 0));
  812. int lower = (((buffer[offset+4] & 0xff) << 24) +
  813. ((buffer[offset+5] & 0xff) << 16) +
  814. ((buffer[offset+6] & 0xff) << 8) +
  815. ((buffer[offset+7] & 0xff) << 0));
  816. array[i] = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  817. offset += 8;
  818. }
  819. } else if (type == Float.TYPE) {
  820. float[] array = (float[])currentObject;
  821. for (i = 0; i < length; i++) {
  822. if (offset > buflen - 4) {
  823. int readlen = Math.min((length-i)*4, buflen);
  824. readFully(buffer, 0, readlen);
  825. offset = 0;
  826. }
  827. int value = (((buffer[offset] & 0xff) << 24) +
  828. ((buffer[offset+1] & 0xff) << 16) +
  829. ((buffer[offset+2] & 0xff) << 8) +
  830. ((buffer[offset+3] & 0xff) << 0));
  831. offset += 4;
  832. array[i] = Float.intBitsToFloat(value);
  833. }
  834. } else if (type == Double.TYPE) {
  835. double[] array = (double[])currentObject;
  836. for (i = 0; i < length; i++) {
  837. if (offset > buflen - 8) {
  838. int readlen = Math.min((length-i)*8, buflen);
  839. readFully(buffer, 0, readlen);
  840. offset = 0;
  841. }
  842. int upper = (((buffer[offset] & 0xff) << 24) +
  843. ((buffer[offset+1] & 0xff) << 16) +
  844. ((buffer[offset+2] & 0xff) << 8) +
  845. ((buffer[offset+3] & 0xff) << 0));
  846. int lower = (((buffer[offset+4] & 0xff) << 24) +
  847. ((buffer[offset+5] & 0xff) << 16) +
  848. ((buffer[offset+6] & 0xff) << 8) +
  849. ((buffer[offset+7] & 0xff) << 0));
  850. offset += 8;
  851. array[i] = Double.longBitsToDouble((((long)upper) << 32) +
  852. (lower & 0xFFFFFFFFL));
  853. }
  854. } else if (type == Character.TYPE) {
  855. char[] array = (char[])currentObject;
  856. for (i = 0; i < length; i++) {
  857. if (offset > buflen - 2) {
  858. int readlen = Math.min((length-i)*2, buflen);
  859. readFully(buffer, 0, readlen);
  860. offset = 0;
  861. }
  862. array[i] = (char)(((buffer[offset] & 0xff) << 8) +
  863. ((buffer[offset+1] & 0xff) << 0));
  864. offset += 2;
  865. }
  866. } else {
  867. throw new InvalidClassException(arrayclass.getName());
  868. }
  869. } else { // Is array of objects
  870. Object[] array = (Object[])currentObject;
  871. boolean requiresLocalClass = (arrayclass != null);
  872. for (i = 0; i < length; i++) {
  873. Object obj = readObject(requiresLocalClass);
  874. if (array != null)
  875. array[i] = obj;
  876. }
  877. }
  878. return wireoffset;
  879. }
  880. /*
  881. * Read an instance of a class from the stream
  882. * The new object typecode has already been read and used to dispatch to here.
  883. * The ObjectStreamClass for the class is read and the class
  884. * of the object retrieved from it.
  885. * A new object is created of the specified class and
  886. * each serializable class is processed using either
  887. * the default serialization methods or class defined special methods
  888. * if they have been defined.
  889. * The handle for the object is returned, the object itself is in currentObject.
  890. */
  891. private int inputObject(boolean requireLocalClass)
  892. throws IOException, ClassNotFoundException
  893. {
  894. int handle = -1;
  895. /*
  896. * Get the descriptor and then class of the incoming object.
  897. */
  898. currentClassDesc = (ObjectStreamClass)readObject();
  899. currentClass = currentClassDesc.forClass();
  900. if (currentClass == null && requireLocalClass)
  901. throw new ClassNotFoundException(currentClassDesc.getName());
  902. if (requireLocalClass)
  903. currentClassDesc.verifyInstanceDeserialization();
  904. /* If Externalizable,
  905. * Create an instance and tell it to read its data.
  906. * else,
  907. * Handle it as a serializable class.
  908. */
  909. if (currentClassDesc.isExternalizable()) {
  910. try {
  911. currentObject = (currentClass == null) ?
  912. null : allocateNewObject(currentClass, currentClass);
  913. handle = assignWireOffset(currentObject);
  914. boolean prevmode = blockDataMode;
  915. try {
  916. if (currentClassDesc.hasExternalizableBlockDataMode()) {
  917. prevmode = setBlockData(true);
  918. }
  919. if (currentObject != null) {
  920. Externalizable ext = (Externalizable)currentObject;
  921. ext.readExternal(this);
  922. }
  923. } finally {
  924. if (currentClassDesc.hasExternalizableBlockDataMode()) {
  925. SkipToEndOfBlockData();
  926. setBlockData(prevmode);
  927. }
  928. }
  929. } catch (NoSuchMethodError e) {
  930. throw new InvalidClassException(currentClass.getName(),
  931. e.getMessage());
  932. } catch (IllegalAccessException e) {
  933. throw new InvalidClassException(currentClass.getName(),
  934. "IllegalAccessException");
  935. } catch (InstantiationException e) {
  936. throw new InvalidClassException(currentClass.getName(),
  937. "InstantiationException");
  938. }
  939. } else {
  940. /* Count number of classes and descriptors we might have
  941. * to work on.
  942. */
  943. ObjectStreamClass currdesc = currentClassDesc;
  944. Class currclass = currentClass;
  945. int spBase = spClass; // current top of stack
  946. /* The object's classes should be processed from supertype to subtype
  947. * Push all the clases of the current object onto a stack.
  948. * Note that only the serializable classes are represented
  949. * in the descriptor list.
  950. *
  951. * Handle versioning where one or more supertypes of
  952. * have been inserted or removed. The stack will
  953. * contain pairs of descriptors and the corresponding
  954. * class. If the object has a class that did not occur in
  955. * the original the descriptor will be null. If the
  956. * original object had a descriptor for a class not
  957. * present in the local hierarchy of the object the class will be
  958. * null.
  959. *
  960. */
  961. /*
  962. * This is your basic diff pattern, made simpler
  963. * because reordering is not allowed.
  964. */
  965. for (currdesc = currentClassDesc, currclass = currentClass;
  966. currdesc != null;
  967. currdesc = currdesc.getSuperclass()) {
  968. /*
  969. * Search the classes to see if the class of this
  970. * descriptor appears further up the hierarchy. Until
  971. * it's found assume its an inserted class. If it's
  972. * not found, its the descriptor's class that has been
  973. * removed.
  974. */
  975. Class cc = currdesc.forClass();
  976. Class cl;
  977. for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  978. if (cc == cl) {
  979. // found a superclass that matches this descriptor
  980. break;
  981. } else {
  982. /* Ignore a class that doesn't match. No
  983. * action is needed since it is already
  984. * initialized.
  985. */
  986. }
  987. }
  988. /* Test if there is room for this new entry.
  989. * If not, double the size of the arrays and copy the contents.
  990. */
  991. spClass++;
  992. if (spClass >= classes.length) {
  993. int newlen = classes.length * 2;
  994. Class[] newclasses = new Class[newlen];
  995. ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  996. System.arraycopy(classes, 0,
  997. newclasses, 0,
  998. classes.length);
  999. System.arraycopy(classdesc, 0,
  1000. newclassdesc, 0,
  1001. classes.length);
  1002. classes = newclasses;
  1003. classdesc = newclassdesc;
  1004. }
  1005. if (cl == null) {
  1006. /* Class not found corresponding to this descriptor.
  1007. * Pop off all the extra classes pushed.
  1008. * Push the descriptor and a null class.
  1009. */
  1010. classdesc[spClass] = currdesc;
  1011. classes[spClass] = null;
  1012. } else {
  1013. /* Current class descriptor matches current class.
  1014. * Some classes may have been inserted.
  1015. * Record the match and advance the class, continue
  1016. * with the next descriptor.
  1017. */
  1018. classdesc[spClass] = currdesc;
  1019. classes[spClass] = cl;
  1020. currclass = cl.getSuperclass();
  1021. }
  1022. }
  1023. /* Allocate a new object. The object is only constructed
  1024. * above the highest serializable class and is set to
  1025. * default values for all more specialized classes.
  1026. * Remember the next wirehandle goes with the new object
  1027. */
  1028. try {
  1029. currentObject = (currentClass == null) ?
  1030. null : allocateNewObject(currentClass, currclass);
  1031. } catch (NoSuchMethodError e) {
  1032. throw new InvalidClassException(currclass.getName(),
  1033. e.getMessage());
  1034. } catch (IllegalAccessException e) {
  1035. throw new InvalidClassException(currclass.getName(),
  1036. "IllegalAccessException");
  1037. } catch (InstantiationException e) {
  1038. throw new InvalidClassException(currclass.getName(),
  1039. "InstantiationException");
  1040. }
  1041. handle = assignWireOffset(currentObject);
  1042. /*
  1043. * For all the pushed descriptors and classes.
  1044. * If there is a descriptor but no class, skip the
  1045. * data for that class.
  1046. * If there is a class but no descriptor, just advance,
  1047. * The classes fields have already been initialized to default
  1048. * values.
  1049. * Otherwise, there is both a descriptor and class,
  1050. * if the class has its own writeObject and readObject methods
  1051. * set blockData = true; and call the readObject method
  1052. * else
  1053. * invoke the defaultReadObject method
  1054. * if the stream was written by class specific methods
  1055. * skip any remaining data a objects until TC_ENDBLOCKDATA
  1056. * Avoid setting BlockData=true unless necessary becase it flushes
  1057. * the buffer.
  1058. */
  1059. try {
  1060. for (spClass = spClass; spClass > spBase; spClass--) {
  1061. /*
  1062. * Set current descriptor and corresponding class
  1063. */
  1064. currentClassDesc = classdesc[spClass];
  1065. currentClass = classes[spClass];
  1066. if (classes[spClass] != null) {
  1067. /* Read the data from the stream described by the
  1068. * descriptor and store into the matching class.
  1069. */
  1070. setBlockData(true); /* any reads are from datablocks */
  1071. ObjectStreamClass localDesc = currentClassDesc.localClassDescriptor();
  1072. if (!invokeObjectReader(currentObject)) {
  1073. defaultReadObject();
  1074. }
  1075. } else {
  1076. /* No local class for this descriptor,
  1077. * Skip over the data for this class.
  1078. * like defaultReadObject with a null currentObject.
  1079. * The code will read the values but discard them.
  1080. */
  1081. ObjectStreamField[] fields =
  1082. currentClassDesc.getFieldsNoCopy();
  1083. if (fields.length > 0) {
  1084. boolean prevmode = setBlockData(false);
  1085. inputClassFields(null, currentClass, fields);
  1086. setBlockData(prevmode);
  1087. }
  1088. }
  1089. /*
  1090. * If the source class (stream) had a write object method
  1091. * it may have written more data and will have written the
  1092. * TC_ENDBLOCKDATA. Skip anything up to that and read it.
  1093. */
  1094. if (currentClassDesc.hasWriteObject()) {
  1095. SkipToEndOfBlockData();
  1096. }
  1097. setBlockData(false);
  1098. }
  1099. } finally {
  1100. // Make sure we exit at the same stack level as when we started.
  1101. spClass = spBase;
  1102. }
  1103. }
  1104. return handle;
  1105. }
  1106. /*
  1107. * Skip any unread block data and objects up to the next
  1108. * TC_ENDBLOCKDATA. Anybody can do this because readObject
  1109. * handles the details of reporting if there is data left.
  1110. * Try reading objects. If it throws optional data
  1111. * skip over it and try again.
  1112. */
  1113. private void SkipToEndOfBlockData()
  1114. throws IOException, ClassNotFoundException
  1115. {
  1116. while (peekCode() != TC_ENDBLOCKDATA) {
  1117. try {
  1118. /* do not require a local Class equivalent of object being read.*/
  1119. Object ignore = readObject(false);
  1120. } catch (OptionalDataException data) {
  1121. if (data.length > 0)
  1122. skip(data.length);
  1123. }
  1124. }
  1125. readCode(); /* Consume TC_ENDBLOCKDATA */
  1126. }
  1127. /*
  1128. * Reset the stream to be just like it was after the constructor.
  1129. */
  1130. private void resetStream() throws IOException {
  1131. if (wireHandle2Object == null)
  1132. wireHandle2Object = new ArrayList();
  1133. else
  1134. wireHandle2Object.clear();
  1135. nextWireOffset = 0;
  1136. if (classes == null)
  1137. classes = new Class[20];
  1138. else {
  1139. for (int i = 0; i < classes.length; i++)
  1140. classes[i] = null;
  1141. }
  1142. if (classdesc == null)
  1143. classdesc = new ObjectStreamClass[20];
  1144. else {
  1145. for (int i = 0; i < classdesc.length; i++)
  1146. classdesc[i] = null;
  1147. }
  1148. spClass = 0;
  1149. setBlockData(true); // Re-enable buffering
  1150. if (callbacks != null)
  1151. callbacks.clear(); // discard any pending callbacks
  1152. }
  1153. /* Allocate a handle for an object.
  1154. * The list is indexed by the wireHandleOffset
  1155. * and contains the object.
  1156. */
  1157. private int assignWireOffset(Object obj)
  1158. throws IOException
  1159. {
  1160. wireHandle2Object.add(obj);
  1161. if (++nextWireOffset != wireHandle2Object.size())
  1162. throw new StreamCorruptedException(
  1163. "Elements not assigned in order");
  1164. return nextWireOffset-1;
  1165. }
  1166. /*
  1167. * Peek at the next control code in the stream.
  1168. * If the code has not been peeked at yet, read it from the stream.
  1169. */
  1170. private byte peekCode() throws IOException, StreamCorruptedException{
  1171. while (currCode == 0) {
  1172. int newcode = in.read(); // Read byte from the underlying stream
  1173. if (newcode < 0)
  1174. throw new EOFException("Expecting code");
  1175. currCode = (byte)newcode;
  1176. if (currCode < TC_BASE || currCode > TC_MAX)
  1177. throw new StreamCorruptedException("Type code out of range, is " + currCode);
  1178. /*
  1179. * Handle reset as a hidden code and reset the stream.
  1180. */
  1181. if (currCode == TC_RESET) {
  1182. if (recursionDepth != 0 ||
  1183. currentObject != null ||
  1184. currentClassDesc != null)
  1185. throw new StreamCorruptedException("Illegal stream state for reset");
  1186. /* Reset the stream, and repeat the peek at the next code
  1187. */
  1188. resetStream();
  1189. currCode = 0;
  1190. }
  1191. }
  1192. return currCode;
  1193. }
  1194. /*
  1195. * Return the next control code in the stream.
  1196. * peekCode gets the next code. readCode just consumes it.
  1197. */
  1198. private byte readCode()
  1199. throws IOException, StreamCorruptedException
  1200. {
  1201. byte tc = peekCode();
  1202. currCode = 0;
  1203. return tc;
  1204. }
  1205. /*
  1206. * Put back the specified code to be peeked at next time.
  1207. */
  1208. private void pushbackCode(byte code) {
  1209. currCode = code;
  1210. }
  1211. /* -----------------------------------------------------*/
  1212. /*
  1213. * Implement the InputStream methods. The stream has
  1214. * two modes used internally to ObjectInputStream. When
  1215. * in BlockData mode, all reads are only from datablocks
  1216. * as original written. End of data (-1) is returned
  1217. * if something other than a datablock is next in the stream.
  1218. * When not in BlockData mode (false), reads pass directly
  1219. * through to the underlying stream.
  1220. * The BlockData mode is used to encapsulate data written
  1221. * by class specific writeObject methods that is intended
  1222. * only to be read by corresponding readObject method of the
  1223. * same class. The blocking of data allows it to be skipped
  1224. * if necessary.
  1225. *
  1226. * The setBlockData method is used to switch buffering
  1227. * on and off. When switching between on and off
  1228. * there must be no data pending to be read. This is
  1229. * an internal consistency check that will throw an exception.
  1230. *
  1231. */
  1232. private InputStream in;
  1233. /*
  1234. * Count of bytes available from blockData, if zero, call refill
  1235. * to look for more. If -1 always return eof (-1)
  1236. */
  1237. private int count;
  1238. private boolean blockDataMode;
  1239. private byte[] buffer; // buffer for reading array data
  1240. /*
  1241. * Set the blockdata buffering mode.
  1242. * If it is being set to false after being true there must
  1243. * be no pending data. If count > 0 a corrupted exception is thrown.
  1244. */
  1245. private boolean setBlockData(boolean mode) throws IOException {
  1246. if (blockDataMode == mode)
  1247. return mode;
  1248. if (blockDataMode && count > 0)
  1249. throw new StreamCorruptedException("Unread data");
  1250. /* Set count to allow reading or not */
  1251. count = mode ? 0 : -1;
  1252. blockDataMode = mode;
  1253. return !mode;
  1254. }
  1255. /**
  1256. * Reads a byte of data. This method will block if no input is
  1257. * available.
  1258. * @return the byte read, or -1 if the end of the
  1259. * stream is reached.
  1260. * @exception IOException If an I/O error has occurred.
  1261. */
  1262. public int read() throws IOException {
  1263. int data;
  1264. if (blockDataMode) {
  1265. while (count == 0)
  1266. refill();
  1267. if (count < 0)
  1268. return -1; /* EOF */
  1269. data = in.read();
  1270. if (data >= 0)
  1271. count--;
  1272. } else {
  1273. data = in.read(); /* read directly from input stream */
  1274. }
  1275. return data;
  1276. }
  1277. /*
  1278. * Expect the next thing in the stream is a datablock, If its a
  1279. * datablock, extract the count of bytes to allow. If data is not
  1280. * available set the count to zero. On error or EOF, set count to -1.
  1281. */
  1282. private void refill() throws IOException {
  1283. count = -1; /* No more data to read, EOF */
  1284. byte code;
  1285. try {
  1286. code = peekCode();
  1287. } catch (EOFException e) {
  1288. return;
  1289. }
  1290. if (code == TC_BLOCKDATA) {
  1291. code = readCode(); /* Consume the code */
  1292. int c = in.read();
  1293. if (c < 0)
  1294. throw new StreamCorruptedException("EOF expecting count");
  1295. count = c & 0xff;
  1296. } else if (code == TC_BLOCKDATALONG) {
  1297. code = readCode();
  1298. int b3 = in.read();
  1299. int b2 = in.read();
  1300. int b1 = in.read();
  1301. int b0 = in.read();
  1302. if ((b3 | b2 | b1 | b0) < 0)
  1303. throw new StreamCorruptedException("EOF expecting count");
  1304. int c = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  1305. /*
  1306. * The 32 bit integer size in the long block data format is
  1307. * signed (unlike like the normal block data format), and
  1308. * negative values are invalid.
  1309. */
  1310. if (c < 0)
  1311. throw new StreamCorruptedException("Negative block data size");
  1312. count = c;
  1313. }
  1314. }
  1315. /**
  1316. * Reads into an array of bytes. This method will
  1317. * block until some input is available. Consider
  1318. * using java.io.DataInputStream.readFully to read exactly
  1319. * 'length' bytes.
  1320. * @param b the buffer into which the data is read
  1321. * @param off the start offset of the data
  1322. * @param len the maximum number of bytes read
  1323. * @return the actual number of bytes read, -1 is
  1324. * returned when the end of the stream is reached.
  1325. * @exception IOException If an I/O error has occurred.
  1326. * @see java.io.DataInputStream#readFully(byte[],int,int)
  1327. */
  1328. public int read(byte[] b, int off, int len) throws IOException {
  1329. int v;
  1330. int i;
  1331. if (b == null) {
  1332. throw new NullPointerException();
  1333. } else if ((off < 0) || (off > b.length) || (len < 0) ||
  1334. ((off + len) > b.length) || ((off + len) < 0)) {
  1335. throw new IndexOutOfBoundsException();
  1336. } else if (len == 0) {
  1337. return 0;
  1338. }
  1339. if (blockDataMode) {
  1340. while (count == 0)
  1341. refill();
  1342. if (count < 0)
  1343. return -1;
  1344. int l = Math.min(len, count);
  1345. i = in.read(b, off, l);
  1346. if (i > 0)
  1347. count -= i;
  1348. return i; /* return number of bytes read */
  1349. } else {
  1350. /* read directly from input stream */
  1351. return in.read(b, off, len);
  1352. }
  1353. }
  1354. /**
  1355. * Returns the number of bytes that can be read without blocking.
  1356. * @return the number of available bytes.
  1357. */
  1358. public int available() throws IOException {
  1359. /*
  1360. * If in blockdataMode returns the number of bytes in the
  1361. * current block. If that is zero, it will try to read
  1362. * another blockdata from the stream if any data is available from the
  1363. * underlying stream..
  1364. * If not in blockdata mode it returns zero.
  1365. */
  1366. if (blockDataMode) {
  1367. if (count == 0 && in.available() > 0)
  1368. refill();
  1369. if (count >= 0) {
  1370. return count;
  1371. } else
  1372. return 0; /* EOF is no bytes available */
  1373. } else {
  1374. return 0; /* Not blockdata, no bytes available */
  1375. }
  1376. }
  1377. /**
  1378. * Closes the input stream. Must be called
  1379. * to release any resources associated with
  1380. * the stream.
  1381. * @exception IOException If an I/O error has occurred.
  1382. */
  1383. public void close() throws IOException {
  1384. in.close();
  1385. }
  1386. /* -----------------------------------------------------*/
  1387. /*
  1388. * Provide the methods to implement DataInput.
  1389. * They delegate to an Instance of DataInputStream that
  1390. * reads its input from the ObjectInputStream.
  1391. * This allows this stream to manage the blocked data the data
  1392. * as necessary.
  1393. */
  1394. private DataInputStream dis;
  1395. /**
  1396. * Reads in a boolean.
  1397. * @return the boolean read.
  1398. * @exception EOFException If end of file is reached.
  1399. * @exception IOException If other I/O error has occurred.
  1400. */
  1401. public boolean readBoolean() throws IOException {
  1402. return dis.readBoolean();
  1403. }
  1404. /**
  1405. * Reads an 8 bit byte.
  1406. * @return the 8 bit byte read.
  1407. * @exception EOFException If end of file is reached.
  1408. * @exception IOException If other I/O error has occurred.
  1409. */
  1410. public byte readByte() throws IOException {
  1411. return dis.readByte();
  1412. }
  1413. /**
  1414. * Reads an unsigned 8 bit byte.
  1415. * @return the 8 bit byte read.
  1416. * @exception EOFException If end of file is reached.
  1417. * @exception IOException If other I/O error has occurred.
  1418. */
  1419. public int readUnsignedByte() throws IOException {
  1420. return dis.readUnsignedByte();
  1421. }
  1422. /**
  1423. * Reads a 16 bit short.
  1424. * @return the 16 bit short read.
  1425. * @exception EOFException If end of file is reached.
  1426. * @exception IOException If other I/O error has occurred.
  1427. */
  1428. public short readShort() throws IOException {
  1429. return dis.readShort();
  1430. }
  1431. /**
  1432. * Reads an unsigned 16 bit short.
  1433. * @return the 16 bit short read.
  1434. * @exception EOFException If end of file is reached.
  1435. * @exception IOException If other I/O error has occurred.
  1436. */
  1437. public int readUnsignedShort() throws IOException {
  1438. return dis.readUnsignedShort();
  1439. }
  1440. /**
  1441. * Reads a 16 bit char.
  1442. * @return the 16 bit char read.
  1443. * @exception EOFException If end of file is reached.
  1444. * @exception IOException If other I/O error has occurred.
  1445. */
  1446. public char readChar() throws IOException {
  1447. return dis.readChar();
  1448. }
  1449. /**
  1450. * Reads a 32 bit int.
  1451. * @return the 32 bit integer read.
  1452. * @exception EOFException If end of file is reached.
  1453. * @exception IOException If other I/O error has occurred.
  1454. */
  1455. public int readInt() throws IOException {
  1456. return dis.readInt();
  1457. }
  1458. /**
  1459. * Reads a 64 bit long.
  1460. * @return the read 64 bit long.
  1461. * @exception EOFException If end of file is reached.
  1462. * @exception IOException If other I/O error has occurred.
  1463. */
  1464. public long readLong() throws IOException {
  1465. return dis.readLong();
  1466. }
  1467. /**
  1468. * Reads a 32 bit float.
  1469. * @return the 32 bit float read.
  1470. * @exception EOFException If end of file is reached.
  1471. * @exception IOException If other I/O error has occurred.
  1472. */
  1473. public float readFloat() throws IOException {
  1474. return dis.readFloat();
  1475. }
  1476. /**
  1477. * Reads a 64 bit double.
  1478. * @return the 64 bit double read.
  1479. * @exception EOFException If end of file is reached.
  1480. * @exception IOException If other I/O error has occurred.
  1481. */
  1482. public double readDouble() throws IOException {
  1483. return dis.readDouble();
  1484. }
  1485. /**
  1486. * Reads bytes, blocking until all bytes are read.
  1487. * @param b the buffer into which the data is read
  1488. * @exception EOFException If end of file is reached.
  1489. * @exception IOException If other I/O error has occurred.
  1490. */
  1491. public void readFully(byte[] data) throws IOException {
  1492. dis.readFully(data);
  1493. }
  1494. /**
  1495. * Reads bytes, blocking until all bytes are read.
  1496. * @param b the buffer into which the data is read
  1497. * @param off the start offset of the data
  1498. * @param len the maximum number of bytes to read
  1499. * @exception EOFException If end of file is reached.
  1500. * @exception IOException If other I/O error has occurred.
  1501. */
  1502. public void readFully(byte[] data, int offset, int size) throws IOException {
  1503. if (size < 0)
  1504. throw new IndexOutOfBoundsException();
  1505. dis.readFully(data, offset, size);
  1506. }
  1507. /**
  1508. * Skips bytes, block until all bytes are skipped.
  1509. * @param n the number of bytes to be skipped
  1510. * @return the actual number of bytes skipped.
  1511. * @exception EOFException If end of file is reached.
  1512. * @exception IOException If other I/O error has occurred.
  1513. */
  1514. public int skipBytes(int len) throws IOException {
  1515. return dis.skipBytes(len);
  1516. }
  1517. /**
  1518. * Reads in a line that has been terminated by a \n, \r,
  1519. * \r\n or EOF.
  1520. * @return a String copy of the line.
  1521. * @deprecated This method does not properly convert bytes to characters.
  1522. * see DataInputStream for the details and alternatives.
  1523. */
  1524. public String readLine() throws IOException {
  1525. return dis.readLine();
  1526. }
  1527. /**
  1528. * Reads a UTF format String.
  1529. * @return the String.
  1530. */
  1531. public String readUTF() throws IOException {
  1532. return dis.readUTF();
  1533. }
  1534. /*
  1535. * Invoke the readObject method if present
  1536. */
  1537. private boolean invokeObjectReader(Object obj)
  1538. throws InvalidClassException, StreamCorruptedException,
  1539. ClassNotFoundException, IOException
  1540. {
  1541. if (currentClassDesc.readObjectMethod == null)
  1542. return false;
  1543. try {
  1544. currentClassDesc.readObjectMethod.invoke(obj, readObjectArglist);
  1545. return true;
  1546. } catch (InvocationTargetException e) {
  1547. Throwable t = e.getTargetException();
  1548. if (t instanceof ClassNotFoundException)
  1549. throw (ClassNotFoundException)t;
  1550. else if (t instanceof IOException)
  1551. throw (IOException)t;
  1552. else if (t instanceof RuntimeException)
  1553. throw (RuntimeException) t;
  1554. else if (t instanceof Error)
  1555. throw (Error) t;
  1556. else
  1557. throw new Error("interal error");
  1558. } catch (IllegalAccessException e) {
  1559. return false;
  1560. }
  1561. }
  1562. /*
  1563. * Read the fields of the specified class from the input stream and set
  1564. * the values of the fields in the specified object. If the specified
  1565. * object is null, just consume the fields without setting any values. If
  1566. * any ObjectStreamField does not have a reflected Field, don't try to set
  1567. * that field in the object.
  1568. */
  1569. private void inputClassFields(Object o, Class cl,
  1570. ObjectStreamField[] fields)
  1571. throws InvalidClassException, StreamCorruptedException,
  1572. ClassNotFoundException, IOException
  1573. {
  1574. int primFields = fields.length - currentClassDesc.objFields;
  1575. /*
  1576. * Read and dispatch primitive data fields from the input
  1577. * stream.
  1578. */
  1579. if (currentClassDesc.primBytes > 0) {
  1580. if (data == null) {
  1581. data = new byte[Math.max(currentClassDesc.primBytes,
  1582. INITIAL_BUFFER_SIZE)];
  1583. } else if (data.length < currentClassDesc.primBytes) {
  1584. data = new byte[currentClassDesc.primBytes];
  1585. }
  1586. readFully(data, 0, currentClassDesc.primBytes);
  1587. }
  1588. if (o != null) {
  1589. for (int i = 0; i < primFields; ++i) {
  1590. if (fields[i].getField() == null)
  1591. continue;
  1592. try {
  1593. int lower;
  1594. int upper;
  1595. int loffset = fields[i].getOffset();
  1596. switch (fields[i].getTypeCode()) {
  1597. case 'B':
  1598. byte byteValue = data[loffset];
  1599. fields[i].getField().setByte(o, byteValue);
  1600. break;
  1601. case 'Z':
  1602. boolean booleanValue =
  1603. (boolean)(data[loffset] != 0);
  1604. fields[i].getField().setBoolean(o, booleanValue);
  1605. break;
  1606. case 'C':
  1607. char charValue =
  1608. (char)(((data[loffset] & 0xff) << 8) +
  1609. ((data[loffset+1] & 0xff)));
  1610. fields[i].getField().setChar(o, charValue);
  1611. break;
  1612. case 'S':
  1613. short shortValue =
  1614. (short)(((data[loffset] & 0xff) << 8) +
  1615. ((data[loffset+1] & 0xff)));
  1616. fields[i].getField().setShort(o, shortValue);
  1617. break;
  1618. case 'I':
  1619. int intValue =
  1620. (((data[loffset] & 0xff) << 24) +
  1621. ((data[loffset+1] & 0xff) << 16) +
  1622. ((data[loffset+2] & 0xff) << 8) +
  1623. ((data[loffset+3] & 0xff)));
  1624. fields[i].getField().setInt(o, intValue);
  1625. break;
  1626. case 'J':
  1627. upper = (((data[loffset] & 0xff) << 24) +
  1628. ((data[loffset+1] & 0xff) << 16) +
  1629. ((data[loffset+2] & 0xff) << 8) +
  1630. ((data[loffset+3] & 0xff)));
  1631. lower = (((data[loffset+4] & 0xff) << 24) +
  1632. ((data[loffset+5] & 0xff) << 16) +
  1633. ((data[loffset+6] & 0xff) << 8) +
  1634. ((data[loffset+7] & 0xff)));
  1635. long longValue =
  1636. ((long)upper << 32) + ((long) lower & 0xFFFFFFFFL);
  1637. fields[i].getField().setLong(o, longValue);
  1638. break;
  1639. case 'F' :
  1640. int v = (((data[loffset] & 0xff) << 24) +
  1641. ((data[loffset+1] & 0xff) << 16) +
  1642. ((data[loffset+2] & 0xff) << 8) +
  1643. ((data[loffset+3] & 0xff)));
  1644. float floatValue = Float.intBitsToFloat(v);
  1645. fields[i].getField().setFloat(o, floatValue);
  1646. break;
  1647. case 'D' :
  1648. upper = (((data[loffset] & 0xff) << 24) +
  1649. ((data[loffset+1] & 0xff) << 16) +
  1650. ((data[loffset+2] & 0xff) << 8) +
  1651. ((data[loffset+3] & 0xff)));
  1652. lower = (((data[loffset+4] & 0xff) << 24) +
  1653. ((data[loffset+5] & 0xff) << 16) +
  1654. ((data[loffset+6] & 0xff) << 8) +
  1655. ((data[loffset+7] & 0xff)));
  1656. long vv =
  1657. ((long) upper << 32) + ((long)lower & 0xFFFFFFFFL);
  1658. double doubleValue = Double.longBitsToDouble(vv);
  1659. fields[i].getField().setDouble(o, doubleValue);
  1660. break;
  1661. default:
  1662. // "Impossible"
  1663. throw new InvalidClassException(cl.getName());
  1664. }
  1665. } catch (IllegalAccessException e) {
  1666. throw new InvalidClassException(cl.getName(),
  1667. "IllegalAccessException");
  1668. } catch (IllegalArgumentException e) {
  1669. /* This case should never happen. If the field types
  1670. are not the same, InvalidClassException is raised when
  1671. matching the local class to the serialized ObjectStreamClass. */
  1672. throw new ClassCastException("Assigning instance of class " +
  1673. fields[i].getType().getName() +
  1674. " to field " +
  1675. currentClassDesc.getName() + '#' +
  1676. fields[i].getField().getName());
  1677. }
  1678. }
  1679. }
  1680. /* Read and set object fields from the input stream. */
  1681. if (currentClassDesc.objFields > 0) {
  1682. for (int i = primFields; i < fields.length; i++) {
  1683. boolean requireLocalClass = (fields[i].getField() != null);
  1684. Object objectValue = readObject(requireLocalClass);
  1685. if ((o == null) || (fields[i].getField() == null)) {
  1686. continue;
  1687. }
  1688. try {
  1689. fields[i].getField().set(o, objectValue);
  1690. } catch (IllegalAccessException e) {
  1691. throw new InvalidClassException(cl.getName(),
  1692. "IllegalAccessException");
  1693. } catch (IllegalArgumentException e) {
  1694. throw new ClassCastException("Assigning instance of class " +
  1695. objectValue.getClass().getName() +
  1696. " to field " +
  1697. currentClassDesc.getName() +
  1698. '#' +
  1699. fields[i].getField().getName());
  1700. }
  1701. }
  1702. }
  1703. }
  1704. /*************************************************************/
  1705. /**
  1706. * Provide access to the persistent fields read from the input stream.
  1707. */
  1708. abstract public static class GetField {
  1709. /**
  1710. * Get the ObjectStreamClass that describes the fields in the stream.
  1711. */
  1712. abstract public ObjectStreamClass getObjectStreamClass();
  1713. /**
  1714. * Return true if the named field is defaulted and has no value
  1715. * in this stream.
  1716. */
  1717. abstract public boolean defaulted(String name)
  1718. throws IOException, IllegalArgumentException;
  1719. /**
  1720. * Get the value of the named boolean field from the persistent field.
  1721. */
  1722. abstract public boolean get(String name, boolean defvalue)
  1723. throws IOException, IllegalArgumentException;
  1724. /**
  1725. * Get the value of the named char field from the persistent fields.
  1726. */
  1727. abstract public char get(String name, char defvalue)
  1728. throws IOException, IllegalArgumentException;
  1729. /**
  1730. * Get the value of the named byte field from the persistent fields.
  1731. */
  1732. abstract public byte get(String name, byte defvalue)
  1733. throws IOException, IllegalArgumentException;
  1734. /**
  1735. * Get the value of the named short field from the persistent fields.
  1736. */
  1737. abstract public short get(String name, short defvalue)
  1738. throws IOException, IllegalArgumentException;
  1739. /**
  1740. * Get the value of the named int field from the persistent fields.
  1741. */
  1742. abstract public int get(String name, int defvalue)
  1743. throws IOException, IllegalArgumentException;
  1744. /**
  1745. * Get the value of the named long field from the persistent fields.
  1746. */
  1747. abstract public long get(String name, long defvalue)
  1748. throws IOException, IllegalArgumentException;
  1749. /**
  1750. * Get the value of the named float field from the persistent fields.
  1751. */
  1752. abstract public float get(String name, float defvalue)
  1753. throws IOException, IllegalArgumentException;
  1754. /**
  1755. * Get the value of the named double field from the persistent field.
  1756. */
  1757. abstract public double get(String name, double defvalue)
  1758. throws IOException, IllegalArgumentException;
  1759. /**
  1760. * Get the value of the named Object field from the persistent field.
  1761. */
  1762. abstract public Object get(String name, Object defvalue)
  1763. throws IOException, IllegalArgumentException;
  1764. }
  1765. /* Internal Implementation of GetField. */
  1766. static final class GetFieldImpl extends GetField {
  1767. /**
  1768. * Get the ObjectStreamClass that describes the fields in the stream.
  1769. */
  1770. public ObjectStreamClass getObjectStreamClass() {
  1771. return desc;
  1772. }
  1773. /**
  1774. * Return true if the named field is defaulted and has no value
  1775. * in this stream.
  1776. */
  1777. public boolean defaulted(String name)
  1778. throws IOException, IllegalArgumentException
  1779. {
  1780. ObjectStreamField field = checkField(name, null);
  1781. return (field == null);
  1782. }
  1783. /**
  1784. * Get the value of the named boolean field from the persistent field.
  1785. */
  1786. public boolean get(String name, boolean defvalue)
  1787. throws IOException, IllegalArgumentException
  1788. {
  1789. ObjectStreamField field = checkField(name, Boolean.TYPE);
  1790. if (field == null)
  1791. return defvalue;
  1792. return (boolean)(data[field.getOffset()] != 0);
  1793. }
  1794. /**
  1795. * Get the value of the named char field from the persistent fields.
  1796. */
  1797. public char get(String name, char defvalue)
  1798. throws IOException, IllegalArgumentException
  1799. {
  1800. ObjectStreamField field = checkField(name, Character.TYPE);
  1801. if (field == null)
  1802. return defvalue;
  1803. int loffset = field.getOffset();
  1804. return (char)(((data[loffset] & 0xff) << 8) +
  1805. ((data[loffset+1] & 0xff)));
  1806. }
  1807. /**
  1808. * Get the value of the named byte field from the persistent fields.
  1809. */
  1810. public byte get(String name, byte defvalue)
  1811. throws IOException, IllegalArgumentException
  1812. {
  1813. ObjectStreamField field = checkField(name, Byte.TYPE);
  1814. if (field == null)
  1815. return defvalue;
  1816. return data[field.getOffset()];
  1817. }
  1818. /**
  1819. * Get the value of the named short field from the persistent fields.
  1820. */
  1821. public short get(String name, short defvalue)
  1822. throws IOException, IllegalArgumentException
  1823. {
  1824. ObjectStreamField field = checkField(name, Short.TYPE);
  1825. if (field == null)
  1826. return defvalue;
  1827. int loffset = field.getOffset();
  1828. return (short)(((data[loffset] & 0xff) << 8) +
  1829. ((data[loffset+1] & 0xff)));
  1830. }
  1831. /**
  1832. * Get the value of the named int field from the persistent fields.
  1833. */
  1834. public int get(String name, int defvalue)
  1835. throws IOException, IllegalArgumentException
  1836. {
  1837. ObjectStreamField field = checkField(name, Integer.TYPE);
  1838. if (field == null)
  1839. return defvalue;
  1840. int loffset = field.getOffset();
  1841. return (((data[loffset] & 0xff) << 24) +
  1842. ((data[loffset+1] & 0xff) << 16) +
  1843. ((data[loffset+2] & 0xff) << 8) +
  1844. ((data[loffset+3] & 0xff)));
  1845. }
  1846. /**
  1847. * Get the value of the named long field from the persistent fields.
  1848. */
  1849. public long get(String name, long defvalue)
  1850. throws IOException, IllegalArgumentException
  1851. {
  1852. ObjectStreamField field = checkField(name, Long.TYPE);
  1853. if (field == null)
  1854. return defvalue;
  1855. int loffset = field.getOffset();
  1856. int upper = (((data[loffset] & 0xff) << 24) +
  1857. ((data[loffset+1] & 0xff) << 16) +
  1858. ((data[loffset+2] & 0xff) << 8) +
  1859. ((data[loffset+3] & 0xff)));
  1860. int lower = (((data[loffset+4] & 0xff) << 24) +
  1861. ((data[loffset+5] & 0xff) << 16) +
  1862. ((data[loffset+6] & 0xff) << 8) +
  1863. ((data[loffset+7] & 0xff)));
  1864. long v = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  1865. return v;
  1866. }
  1867. /**
  1868. * Get the value of the named float field from the persistent fields.
  1869. */
  1870. public float get(String name, float defvalue)
  1871. throws IOException, IllegalArgumentException
  1872. {
  1873. ObjectStreamField field = checkField(name, Float.TYPE);
  1874. if (field == null)
  1875. return defvalue;
  1876. int loffset = field.getOffset();
  1877. int v = (((data[loffset] & 0xff) << 24) +
  1878. ((data[loffset+1] & 0xff) << 16) +
  1879. ((data[loffset+2] & 0xff) << 8) +
  1880. ((data[loffset+3] & 0xff)));
  1881. return Float.intBitsToFloat(v);
  1882. }
  1883. /**
  1884. * Get the value of the named double field from the persistent field.
  1885. */
  1886. public double get(String name, double defvalue)
  1887. throws IOException, IllegalArgumentException
  1888. {
  1889. ObjectStreamField field = checkField(name, Double.TYPE);
  1890. if (field == null)
  1891. return defvalue;
  1892. int loffset = field.getOffset();
  1893. int upper = (((data[loffset] & 0xff) << 24) +
  1894. ((data[loffset+1] & 0xff) << 16) +
  1895. ((data[loffset+2] & 0xff) << 8) +
  1896. ((data[loffset+3] & 0xff)));
  1897. int lower = (((data[loffset+4] & 0xff) << 24) +
  1898. ((data[loffset+5] & 0xff) << 16) +
  1899. ((data[loffset+6] & 0xff) << 8) +
  1900. ((data[loffset+7] & 0xff)));
  1901. long v = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  1902. return Double.longBitsToDouble(v);
  1903. }
  1904. /**
  1905. * Get the value of the named Object field from the persistent field.
  1906. */
  1907. public Object get(String name, Object defvalue)
  1908. throws IOException, IllegalArgumentException
  1909. {
  1910. ObjectStreamField field = checkField(name, Object.class);
  1911. if (field == null)
  1912. return defvalue;
  1913. return objects[field.getOffset()];
  1914. }
  1915. /*
  1916. * Retrieve the named field.
  1917. * If the field is known in the current descriptor return it.
  1918. * If not, find the descriptor for the class that is being
  1919. * read into and check the name. If the name is not
  1920. * valid in the class throw a IllegalArgumentException.
  1921. * otherwise return null.
  1922. */
  1923. private ObjectStreamField checkField(String name, Class type)
  1924. throws IllegalArgumentException
  1925. {
  1926. ObjectStreamField field = (type == null) ?
  1927. desc.getField(name) : desc.getField(name, type);
  1928. if (field != null) {
  1929. /*
  1930. * Check the type of the field in the stream.
  1931. * If correct return the field.
  1932. */
  1933. if (type != null && type != field.getType())
  1934. throw new IllegalArgumentException("field type incorrect");
  1935. return field;
  1936. } else {
  1937. /* Check the name in the local classes descriptor.
  1938. * If found it's a valid persistent field an
  1939. * should be defaulted.
  1940. * If not the caller shouldn't be using that name.
  1941. */
  1942. ObjectStreamClass localdesc =
  1943. desc.localClassDescriptor();
  1944. if (localdesc == null)
  1945. throw new IllegalArgumentException("No local class descriptor");
  1946. ObjectStreamField localfield = (type == null)
  1947. ? localdesc.getField(name) :
  1948. localdesc.getField(name, type);
  1949. if (localfield == null)
  1950. throw new IllegalArgumentException("no such field");
  1951. if (type != null && type != localfield.getType() &&
  1952. (type.isPrimitive() || localfield.getType().isPrimitive()))
  1953. throw new IllegalArgumentException("field type incorrect");
  1954. return null;
  1955. }
  1956. }
  1957. /**
  1958. * Read the data and fields from the specified stream.
  1959. */
  1960. void read(ObjectInputStream in)
  1961. throws IOException, ClassNotFoundException
  1962. {
  1963. if (data != null)
  1964. in.readFully(data, 0, data.length);
  1965. if (objects != null) {
  1966. for (int i = 0; i < objects.length; i++) {
  1967. /* don't require local class when reading object from stream.*/
  1968. objects[i] = in.readObject(false);
  1969. }
  1970. }
  1971. }
  1972. /**
  1973. * Create a GetField object for the a Class.
  1974. * Allocate the arrays for primitives and objects.
  1975. */
  1976. GetFieldImpl(ObjectStreamClass descriptor){
  1977. desc = descriptor;
  1978. if (desc.primBytes > 0)
  1979. data = new byte[desc.primBytes];
  1980. if (desc.objFields > 0)
  1981. objects = new Object[desc.objFields];
  1982. }
  1983. /*
  1984. * The byte array that contains the bytes for the primitive fields.
  1985. * The Object array that contains the objects for the object fields.
  1986. */
  1987. private byte[] data;
  1988. private Object[] objects;
  1989. private ObjectStreamClass desc;
  1990. }
  1991. /* Remember the first exception that stopped this stream. */
  1992. private IOException abortIOException = null;
  1993. private ClassNotFoundException abortClassNotFoundException = null;
  1994. /* Allocate a new object for the specified class
  1995. * Native since newInstance may not be able to find a zero arg constructor.
  1996. */
  1997. private static native Object allocateNewObject(Class aclass, Class initclass)
  1998. throws InstantiationException, IllegalAccessException;
  1999. /* Allocate a new array for the specified class
  2000. * Native since the type of the array needs to be set to the class
  2001. */
  2002. private static native Object allocateNewArray(Class aclass, int length);
  2003. /* The object is the current object and class is the the current
  2004. * subclass of the object being read. Nesting information is kept
  2005. * on the stack.
  2006. */
  2007. private Object currentObject;
  2008. private ObjectStreamClass currentClassDesc;
  2009. private Class currentClass;
  2010. private Object currentGetFields;
  2011. /*
  2012. * Primitive data are read from the input stream and stored in
  2013. * this array. The array is allocated prior to first use.
  2014. */
  2015. private static final int INITIAL_BUFFER_SIZE = 64;
  2016. private byte[] data;
  2017. /* Arrays used to keep track of classes and ObjectStreamClasses
  2018. * as they are being merged; used in inputObject.
  2019. * spClass is the stack pointer for both. */
  2020. ObjectStreamClass[] classdesc;
  2021. Class[] classes;
  2022. int spClass;
  2023. /* During deserialization the objects in the stream are represented by
  2024. * handles (ints), they need to be mapped to the objects.
  2025. * The vector is indexed by the offset between baseWireHandle and the
  2026. * wire handle in the stream.
  2027. */
  2028. private ArrayList wireHandle2Object;
  2029. private int nextWireOffset;
  2030. /* List of validation callback objects
  2031. * The list is created as needed, and ValidationCallback objects added
  2032. * for each call to registerObject. The list is maintained in
  2033. * order of highest (first) priority to lowest
  2034. */
  2035. private ArrayList callbacks;
  2036. /* Recursion level, starts at zero and is incremented for each entry
  2037. * to readObject. Decremented before exit.
  2038. */
  2039. private int recursionDepth;
  2040. /* Last code Peek'ed, if any */
  2041. private byte currCode;
  2042. /*
  2043. * Flag set to true to allow resolveObject to be called.
  2044. * Set by enableResolveObject.
  2045. */
  2046. boolean enableResolve;
  2047. /* if true, override readObject implementation with readObjectOverride.
  2048. */
  2049. private boolean enableSubclassImplementation;
  2050. private Object[] readObjectArglist = {this};
  2051. };
  2052. // Internal class to hold the Callback object and priority
  2053. class ValidationCallback {
  2054. ValidationCallback(ObjectInputValidation cb, int prio) {
  2055. callback = cb;
  2056. priority = prio;
  2057. }
  2058. int priority; // priority of this callback
  2059. ObjectInputValidation callback; // object to be called back
  2060. }