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) {
  1432. if (recursionDepth != 0 ||
  1433. currentObject != null ||
  1434. currentClassDesc != null)
  1435. throw new StreamCorruptedException("Illegal stream state for reset");
  1436. /* Reset the stream, and repeat the peek at the next code
  1437. */
  1438. resetStream();
  1439. currCode = 0;
  1440. }
  1441. }
  1442. return currCode;
  1443. }
  1444. /*
  1445. * Return the next control code in the stream.
  1446. * peekCode gets the next code. readCode just consumes it.
  1447. */
  1448. private byte readCode()
  1449. throws IOException, StreamCorruptedException
  1450. {
  1451. byte tc = peekCode();
  1452. currCode = 0;
  1453. return tc;
  1454. }
  1455. /*
  1456. * Put back the specified code to be peeked at next time.
  1457. */
  1458. private void pushbackCode(byte code) {
  1459. currCode = code;
  1460. }
  1461. /* -----------------------------------------------------*/
  1462. /*
  1463. * Implement the InputStream methods. The stream has
  1464. * two modes used internally to ObjectInputStream. When
  1465. * in BlockData mode, all reads are only from datablocks
  1466. * as original written. End of data (-1) is returned
  1467. * if something other than a datablock is next in the stream.
  1468. * When not in BlockData mode (false), reads pass directly
  1469. * through to the underlying stream.
  1470. * The BlockData mode is used to encapsulate data written
  1471. * by class specific writeObject methods that is intended
  1472. * only to be read by corresponding readObject method of the
  1473. * same class. The blocking of data allows it to be skipped
  1474. * if necessary.
  1475. *
  1476. * The setBlockData method is used to switch buffering
  1477. * on and off. When switching between on and off
  1478. * there must be no data pending to be read. This is
  1479. * an internal consistency check that will throw an exception.
  1480. *
  1481. */
  1482. private InputStream in;
  1483. /*
  1484. * Count of bytes available from blockData, if zero, call refill
  1485. * to look for more. If -1 always return eof (-1)
  1486. */
  1487. private int count;
  1488. private boolean blockDataMode;
  1489. private byte[] buf; // byte array of buffered data
  1490. private int bufpos; // current position in buf
  1491. private int bufsize; // number of valid bytes in buf
  1492. /*
  1493. * Set the blockdata buffering mode.
  1494. * If it is being set to false after being true there must
  1495. * be no pending data. If count > 0 a corrupted exception is thrown.
  1496. */
  1497. private boolean setBlockData(boolean mode) throws IOException {
  1498. if (blockDataMode == mode)
  1499. return mode;
  1500. if (blockDataMode && count > 0)
  1501. throw new StreamCorruptedException("Unread data");
  1502. count = mode ? 0 : -1; // set count to allow reading or not
  1503. bufpos = 0; // clear read buffer
  1504. bufsize = 0;
  1505. blockDataMode = mode;
  1506. return !mode;
  1507. }
  1508. /**
  1509. * Reads a byte of data. This method will block if no input is
  1510. * available.
  1511. *
  1512. * @return the byte read, or -1 if the end of the
  1513. * stream is reached.
  1514. * @exception IOException If an I/O error has occurred.
  1515. */
  1516. public int read() throws IOException {
  1517. if (blockDataMode) {
  1518. while (count == 0) // read block data header(s)
  1519. refill();
  1520. if (count < 0)
  1521. return -1;
  1522. try { // attempt to read next byte
  1523. int pos = bufferData(1);
  1524. return buf[pos] & 0xFF;
  1525. } catch (EOFException e) {
  1526. return -1;
  1527. }
  1528. } else { // not block data, read directly
  1529. return in.read();
  1530. }
  1531. }
  1532. /*
  1533. * Expect the next thing in the stream is a datablock, If its a
  1534. * datablock, extract the count of bytes to allow. If data is not
  1535. * available set the count to zero. On error or EOF, set count to -1.
  1536. */
  1537. private void refill() throws IOException {
  1538. count = -1; /* No more data to read, EOF */
  1539. byte code;
  1540. try {
  1541. code = peekCode();
  1542. } catch (EOFException e) {
  1543. return;
  1544. }
  1545. if (code == TC_BLOCKDATA) {
  1546. code = readCode(); /* Consume the code */
  1547. int c = in.read();
  1548. if (c < 0)
  1549. throw new StreamCorruptedException("EOF expecting count");
  1550. count = c & 0xff;
  1551. } else if (code == TC_BLOCKDATALONG) {
  1552. code = readCode();
  1553. int b3 = in.read();
  1554. int b2 = in.read();
  1555. int b1 = in.read();
  1556. int b0 = in.read();
  1557. if ((b3 | b2 | b1 | b0) < 0)
  1558. throw new StreamCorruptedException("EOF expecting count");
  1559. int c = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
  1560. /*
  1561. * The 32 bit integer size in the long block data format is
  1562. * signed (unlike like the normal block data format), and
  1563. * negative values are invalid.
  1564. */
  1565. if (c < 0)
  1566. throw new StreamCorruptedException("Negative block data size");
  1567. count = c;
  1568. }
  1569. }
  1570. /*
  1571. * Buffer the given number of bytes in buf[], mark the bytes as read, and
  1572. * return the index in buf[] of the first byte of the sequence. When in
  1573. * block data mode, this method may eagerly buffer more than the specified
  1574. * number of bytes (however, the caller cannot assume that any index into
  1575. * buf[] past the return value + (len - 1) is valid).
  1576. */
  1577. int bufferData(int len) throws IOException {
  1578. ensureBufferCapacity(len);
  1579. if (blockDataMode) {
  1580. if (len > count) // sanity check
  1581. throw new InternalError("attempt to read past block end");
  1582. int bufavail = bufsize - bufpos;
  1583. if (len > bufavail) { // must refill buffer
  1584. // shift unread contents to beginning of buffer
  1585. if (bufpos > 0) {
  1586. System.arraycopy(buf, bufpos, buf, 0, bufavail);
  1587. bufpos = 0;
  1588. bufsize = bufavail;
  1589. }
  1590. // buffer remainder of data block
  1591. ensureBufferCapacity(count);
  1592. readFullyInternal(buf, bufsize, count - bufsize);
  1593. bufsize = count;
  1594. }
  1595. // mark bytes as read, return starting index into buffer
  1596. int pos = bufpos;
  1597. bufpos += len;
  1598. count -= len;
  1599. return pos;
  1600. } else { // not block data mode, read directly
  1601. readFullyInternal(buf, 0, len);
  1602. return 0;
  1603. }
  1604. }
  1605. /*
  1606. * Ensures that read buffer is large enough to hold the given number of
  1607. * bytes.
  1608. */
  1609. private void ensureBufferCapacity(int size) {
  1610. if (buf.length < size) {
  1611. byte[] newbuf = new byte[size];
  1612. if (bufsize > 0)
  1613. System.arraycopy(buf, 0, newbuf, 0, bufsize);
  1614. buf = newbuf;
  1615. }
  1616. }
  1617. /*
  1618. * The same as readFully, except that it reads from the underlying input
  1619. * stream, instead of the ObjectInputStream. Since this method is unaware
  1620. * of block data boundaries, it should only be called when not in block data
  1621. * mode, or when the block data header is known not to occur within the
  1622. * requested span of bytes.
  1623. */
  1624. private void readFullyInternal(byte[] b, int off, int len)
  1625. throws IOException
  1626. {
  1627. int n = 0;
  1628. while (n < len) {
  1629. int c = in.read(b, off + n, len - n);
  1630. if (c < 0)
  1631. throw new EOFException();
  1632. n += c;
  1633. }
  1634. }
  1635. /**
  1636. * Reads into an array of bytes. This method will
  1637. * block until some input is available. Consider
  1638. * using java.io.DataInputStream.readFully to read exactly
  1639. * 'length' bytes.
  1640. *
  1641. * @param b the buffer into which the data is read
  1642. * @param off the start offset of the data
  1643. * @param len the maximum number of bytes read
  1644. * @return the actual number of bytes read, -1 is
  1645. * returned when the end of the stream is reached.
  1646. * @exception IOException If an I/O error has occurred.
  1647. * @see java.io.DataInputStream#readFully(byte[],int,int)
  1648. */
  1649. public int read(byte[] b, int off, int len) throws IOException {
  1650. if (b == null) {
  1651. throw new NullPointerException();
  1652. } else if ((off < 0) || (len < 0) ||
  1653. ((off + len) > b.length) || ((off + len) < 0))
  1654. {
  1655. throw new IndexOutOfBoundsException();
  1656. } else if (len == 0) {
  1657. return 0;
  1658. }
  1659. if (blockDataMode) {
  1660. while (count == 0) // read block data header(s)
  1661. refill();
  1662. if (count < 0)
  1663. return -1;
  1664. len = Math.min(len, count); // don't read beyond end of block
  1665. int nread = 0;
  1666. int bufavail = bufsize - bufpos;
  1667. if (bufavail > 0) { // copy already buffered data
  1668. nread = Math.min(len, bufavail);
  1669. System.arraycopy(buf, bufpos, b, off, nread);
  1670. bufpos += nread;
  1671. }
  1672. if (len > nread) // read remaining data from stream
  1673. nread += in.read(b, off + nread, len - nread);
  1674. count -= nread;
  1675. return nread;
  1676. } else { // not block data, read from stream
  1677. return in.read(b, off, len);
  1678. }
  1679. }
  1680. /**
  1681. * Returns the number of bytes that can be read without blocking.
  1682. *
  1683. * @return the number of available bytes.
  1684. * @throws IOException if there are I/O errors while reading from the
  1685. * underlying <code>InputStream</code>
  1686. */
  1687. public int available() throws IOException {
  1688. /*
  1689. * If in blockdataMode returns the number of bytes in the
  1690. * current block. If that is zero, it will try to read
  1691. * another blockdata from the stream if any data is available from the
  1692. * underlying stream..
  1693. * If not in blockdata mode it returns zero.
  1694. */
  1695. if (blockDataMode) {
  1696. if (count == 0 && in.available() > 0)
  1697. refill();
  1698. if (count >= 0) {
  1699. return count;
  1700. } else
  1701. return 0; /* EOF is no bytes available */
  1702. } else {
  1703. return 0; /* Not blockdata, no bytes available */
  1704. }
  1705. }
  1706. /**
  1707. * Closes the input stream. Must be called
  1708. * to release any resources associated with
  1709. * the stream.
  1710. *
  1711. * @exception IOException If an I/O error has occurred.
  1712. */
  1713. public void close() throws IOException {
  1714. in.close();
  1715. }
  1716. /* -----------------------------------------------------*/
  1717. /*
  1718. * Provide the methods to implement DataInput. Depending on the current
  1719. * buffer and block size, they either read the values directly from an
  1720. * internal buffer, or delegate to an instance of DataInputStream.
  1721. */
  1722. private DataInputStream dis;
  1723. /**
  1724. * Reads in a boolean.
  1725. * @return the boolean read.
  1726. * @exception EOFException If end of file is reached.
  1727. * @exception IOException If other I/O error has occurred.
  1728. */
  1729. public boolean readBoolean() throws IOException {
  1730. int c = read();
  1731. if (c < 0)
  1732. throw new EOFException();
  1733. return (c != 0);
  1734. }
  1735. /**
  1736. * Reads an 8 bit byte.
  1737. * @return the 8 bit byte read.
  1738. * @exception EOFException If end of file is reached.
  1739. * @exception IOException If other I/O error has occurred.
  1740. */
  1741. public byte readByte() throws IOException {
  1742. int c = read();
  1743. if (c < 0)
  1744. throw new EOFException();
  1745. return (byte) c;
  1746. }
  1747. /**
  1748. * Reads an unsigned 8 bit byte.
  1749. *
  1750. * @return the 8 bit byte read.
  1751. * @exception EOFException If end of file is reached.
  1752. * @exception IOException If other I/O error has occurred.
  1753. */
  1754. public int readUnsignedByte() throws IOException {
  1755. int c = read();
  1756. if (c < 0)
  1757. throw new EOFException();
  1758. return c;
  1759. }
  1760. /**
  1761. * Reads a 16 bit short.
  1762. *
  1763. * @return the 16 bit short read.
  1764. * @exception EOFException If end of file is reached.
  1765. * @exception IOException If other I/O error has occurred.
  1766. */
  1767. public short readShort() throws IOException {
  1768. if (blockDataMode && count < 2)
  1769. return dis.readShort();
  1770. int pos = bufferData(2);
  1771. return (short) (((buf[pos + 0] & 0xFF) << 8) +
  1772. ((buf[pos + 1] & 0xFF) << 0));
  1773. }
  1774. /**
  1775. * Reads an unsigned 16 bit short.
  1776. *
  1777. * @return the 16 bit short read.
  1778. * @exception EOFException If end of file is reached.
  1779. * @exception IOException If other I/O error has occurred.
  1780. */
  1781. public int readUnsignedShort() throws IOException {
  1782. if (blockDataMode && count < 2)
  1783. return dis.readUnsignedShort();
  1784. int pos = bufferData(2);
  1785. return ((buf[pos + 0] & 0xFF) << 8) +
  1786. ((buf[pos + 1] & 0xFF) << 0);
  1787. }
  1788. /**
  1789. * Reads a 16 bit char.
  1790. *
  1791. * @return the 16 bit char read.
  1792. * @exception EOFException If end of file is reached.
  1793. * @exception IOException If other I/O error has occurred.
  1794. */
  1795. public char readChar() throws IOException {
  1796. if (blockDataMode && count < 2)
  1797. return dis.readChar();
  1798. int pos = bufferData(2);
  1799. return (char) (((buf[pos + 0] & 0xFF) << 8) +
  1800. ((buf[pos + 1] & 0xFF) << 0));
  1801. }
  1802. /**
  1803. * Reads a 32 bit int.
  1804. *
  1805. * @return the 32 bit integer read.
  1806. * @exception EOFException If end of file is reached.
  1807. * @exception IOException If other I/O error has occurred.
  1808. */
  1809. public int readInt() throws IOException {
  1810. if (blockDataMode && count < 4)
  1811. return dis.readInt();
  1812. int pos = bufferData(4);
  1813. return ((buf[pos + 0] & 0xFF) << 24) +
  1814. ((buf[pos + 1] & 0xFF) << 16) +
  1815. ((buf[pos + 2] & 0xFF) << 8) +
  1816. ((buf[pos + 3] & 0xFF) << 0);
  1817. }
  1818. /**
  1819. * Reads a 64 bit long.
  1820. *
  1821. * @return the read 64 bit long.
  1822. * @exception EOFException If end of file is reached.
  1823. * @exception IOException If other I/O error has occurred.
  1824. */
  1825. public long readLong() throws IOException {
  1826. if (blockDataMode && count < 8)
  1827. return dis.readLong();
  1828. int pos = bufferData(8);
  1829. return ((buf[pos + 0] & 0xFFL) << 56) +
  1830. ((buf[pos + 1] & 0xFFL) << 48) +
  1831. ((buf[pos + 2] & 0xFFL) << 40) +
  1832. ((buf[pos + 3] & 0xFFL) << 32) +
  1833. ((buf[pos + 4] & 0xFFL) << 24) +
  1834. ((buf[pos + 5] & 0xFFL) << 16) +
  1835. ((buf[pos + 6] & 0xFFL) << 8) +
  1836. ((buf[pos + 7] & 0xFFL) << 0);
  1837. }
  1838. /**
  1839. * Reads a 32 bit float.
  1840. *
  1841. * @return the 32 bit float read.
  1842. * @exception EOFException If end of file is reached.
  1843. * @exception IOException If other I/O error has occurred.
  1844. */
  1845. public float readFloat() throws IOException {
  1846. if (blockDataMode && count < 4)
  1847. return dis.readFloat();
  1848. int pos = bufferData(4);
  1849. return Float.intBitsToFloat(((buf[pos + 0] & 0xFF) << 24) +
  1850. ((buf[pos + 1] & 0xFF) << 16) +
  1851. ((buf[pos + 2] & 0xFF) << 8) +
  1852. ((buf[pos + 3] & 0xFF) << 0));
  1853. }
  1854. /**
  1855. * Reads a 64 bit double.
  1856. *
  1857. * @return the 64 bit double read.
  1858. * @exception EOFException If end of file is reached.
  1859. * @exception IOException If other I/O error has occurred.
  1860. */
  1861. public double readDouble() throws IOException {
  1862. if (blockDataMode && count < 8)
  1863. return dis.readDouble();
  1864. int pos = bufferData(8);
  1865. return Double.longBitsToDouble(((buf[pos + 0] & 0xFFL) << 56) +
  1866. ((buf[pos + 1] & 0xFFL) << 48) +
  1867. ((buf[pos + 2] & 0xFFL) << 40) +
  1868. ((buf[pos + 3] & 0xFFL) << 32) +
  1869. ((buf[pos + 4] & 0xFFL) << 24) +
  1870. ((buf[pos + 5] & 0xFFL) << 16) +
  1871. ((buf[pos + 6] & 0xFFL) << 8) +
  1872. ((buf[pos + 7] & 0xFFL) << 0));
  1873. }
  1874. /**
  1875. * Reads bytes, blocking until all bytes are read.
  1876. *
  1877. * @param data the buffer into which the data is read
  1878. * @exception EOFException If end of file is reached.
  1879. * @exception IOException If other I/O error has occurred.
  1880. */
  1881. public void readFully(byte[] data) throws IOException {
  1882. dis.readFully(data);
  1883. }
  1884. /**
  1885. * Reads bytes, blocking until all bytes are read.
  1886. *
  1887. * @param data the buffer into which the data is read
  1888. * @param offset the start offset of the data
  1889. * @param size the maximum number of bytes to read
  1890. * @exception EOFException If end of file is reached.
  1891. * @exception IOException If other I/O error has occurred.
  1892. */
  1893. public void readFully(byte[] data, int offset, int size) throws IOException {
  1894. if (size < 0)
  1895. throw new IndexOutOfBoundsException();
  1896. dis.readFully(data, offset, size);
  1897. }
  1898. /**
  1899. * Skips bytes, block until all bytes are skipped.
  1900. *
  1901. * @param len the number of bytes to be skipped
  1902. * @return the actual number of bytes skipped.
  1903. * @exception EOFException If end of file is reached.
  1904. * @exception IOException If other I/O error has occurred.
  1905. */
  1906. public int skipBytes(int len) throws IOException {
  1907. return dis.skipBytes(len);
  1908. }
  1909. /**
  1910. * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
  1911. *
  1912. * @return a String copy of the line.
  1913. * @throws IOException if there are I/O errors while reading from the
  1914. * underlying <code>InputStream</code>
  1915. * @deprecated This method does not properly convert bytes to characters.
  1916. * see DataInputStream for the details and alternatives.
  1917. */
  1918. public String readLine() throws IOException {
  1919. return dis.readLine();
  1920. }
  1921. /**
  1922. * Reads a UTF format String.
  1923. *
  1924. * @return the String.
  1925. * @throws IOException if there are I/O errors while reading from the
  1926. * underlying <code>InputStream</code>
  1927. */
  1928. public String readUTF() throws IOException {
  1929. return readUTFBody(readUnsignedShort());
  1930. }
  1931. /**
  1932. * Reads the body of a UTF string with the given length.
  1933. */
  1934. private String readUTFBody(long utflen) throws IOException {
  1935. final int PADLEN = 2;
  1936. long remaining = utflen; // bytes left to read
  1937. int didx = 0; // current index into data buffer
  1938. int dlen = 0; // number of valid bytes in data buffer
  1939. int cidx = 0; // current index into cdata
  1940. int clen = cdata.length; // length of char buffer
  1941. if ((utflen > clen) && (clen < CDATA_MAX_LEN)) {
  1942. cdata = new char[(int) Math.min(utflen, CDATA_MAX_LEN)];
  1943. clen = cdata.length;
  1944. }
  1945. // sbuf.length() == 0, since cleared after each read
  1946. while (remaining > 0) {
  1947. int c, c2, c3;
  1948. // move any leftover bytes from previous loop to start of buffer
  1949. int gap = dlen - didx;
  1950. if (gap > 0)
  1951. System.arraycopy(data, didx, data, 0, gap);
  1952. // read in as many bytes as will fit
  1953. int nread = (int) Math.min(remaining, data.length - gap);
  1954. dis.readFully(data, gap, nread);
  1955. dlen = gap + nread;
  1956. remaining -= nread;
  1957. didx = 0;
  1958. try {
  1959. /* don't initiate a conversion with less than 3 bytes at end of
  1960. * buffer, unless there are no more refills left.
  1961. */
  1962. int dlimit = (remaining > 0) ? (dlen - PADLEN) : dlen;
  1963. while (didx < dlimit) {
  1964. if (cidx >= clen) { // flush cdata
  1965. sbuf.append(cdata);
  1966. cidx = 0;
  1967. }
  1968. c = (int) data[didx++] & 0xFF;
  1969. switch (c >> 4) {
  1970. case 0:
  1971. case 1:
  1972. case 2:
  1973. case 3:
  1974. case 4:
  1975. case 5:
  1976. case 6:
  1977. case 7:
  1978. // 1 byte format: 0xxxxxxx
  1979. cdata[cidx++] = (char) c;
  1980. break;
  1981. case 12:
  1982. case 13:
  1983. // 2 byte format: 110xxxxx 10xxxxxx
  1984. c2 = (int) data[didx++];
  1985. if ((c2 & 0xC0) != 0x80)
  1986. throw new UTFDataFormatException();
  1987. cdata[cidx++] =
  1988. (char) (((c & 0x1F) << 6) | (c2 & 0x3F));
  1989. break;
  1990. case 14:
  1991. // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
  1992. c2 = (int) data[didx++];
  1993. c3 = (int) data[didx++];
  1994. if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
  1995. throw new UTFDataFormatException();
  1996. cdata[cidx++] = (char) (((c & 0x0F) << 12) |
  1997. ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
  1998. break;
  1999. default:
  2000. // 10xx xxxx, 1111 xxxx
  2001. throw new UTFDataFormatException();
  2002. }
  2003. }
  2004. } catch (IndexOutOfBoundsException e) {
  2005. throw new UTFDataFormatException();
  2006. }
  2007. }
  2008. if (cidx > 0)
  2009. sbuf.append(cdata, 0, cidx);
  2010. String s = sbuf.toString();
  2011. sbuf.setLength(0);
  2012. return s;
  2013. }
  2014. /*
  2015. * Invoke the readObject method if present
  2016. */
  2017. private boolean invokeObjectReader(Object obj)
  2018. throws InvalidClassException, StreamCorruptedException,
  2019. ClassNotFoundException, IOException
  2020. {
  2021. if (currentClassDesc.readObjectMethod == null)
  2022. return false;
  2023. try {
  2024. currentClassDesc.readObjectMethod.invoke(obj, readObjectArglist);
  2025. return true;
  2026. } catch (InvocationTargetException e) {
  2027. Throwable t = e.getTargetException();
  2028. if (t instanceof ClassNotFoundException)
  2029. throw (ClassNotFoundException)t;
  2030. else if (t instanceof IOException)
  2031. throw (IOException)t;
  2032. else if (t instanceof RuntimeException)
  2033. throw (RuntimeException) t;
  2034. else if (t instanceof Error)
  2035. throw (Error) t;
  2036. else
  2037. throw new Error("interal error");
  2038. } catch (IllegalAccessException e) {
  2039. return false;
  2040. }
  2041. }
  2042. /*
  2043. * Read the fields of the specified class from the input stream and set
  2044. * the values of the fields in the specified object. If the specified
  2045. * object is null, just consume the fields without setting any values. If
  2046. * any ObjectStreamField does not have a reflected Field, don't try to set
  2047. * that field in the object.
  2048. */
  2049. private void inputClassFields(Object o, Class cl,
  2050. ObjectStreamField[] fields)
  2051. throws InvalidClassException, StreamCorruptedException,
  2052. ClassNotFoundException, IOException
  2053. {
  2054. /*
  2055. * Read and dispatch primitive data fields from the input
  2056. * stream.
  2057. */
  2058. if (currentClassDesc.numPrimBytes > 0) {
  2059. if (data.length < currentClassDesc.numPrimBytes)
  2060. data = new byte[currentClassDesc.numPrimBytes];
  2061. readFully(data, 0, currentClassDesc.numPrimBytes);
  2062. if (o != null)
  2063. setPrimitiveFieldValues(o, currentClassDesc.primFieldIDs,
  2064. currentClassDesc.primFieldTypecodes, data);
  2065. }
  2066. /* Read and set object fields from the input stream. */
  2067. int numPrimFields = fields.length - currentClassDesc.numObjFields;
  2068. for (int i = 0; i < currentClassDesc.numObjFields; i++) {
  2069. Field field = fields[numPrimFields + i].getField();
  2070. boolean requireLocalClass = (field != null);
  2071. Object val = readObject(requireLocalClass);
  2072. if ((o == null) || (field == null))
  2073. continue;
  2074. try {
  2075. setObjectFieldValue(o, currentClassDesc.objFieldIDs[i],
  2076. currentClassDesc.objFieldTypes[i], val);
  2077. } catch (ClassCastException e) {
  2078. // fill in error message
  2079. throw new ClassCastException("Assigning instance of class " +
  2080. val.getClass().getName() + " to field " +
  2081. cl.getName() + '#' + field.getName());
  2082. } catch (Exception e) {
  2083. throw new InvalidClassException(cl.getName(),
  2084. "Invalid field " + field.getName());
  2085. }
  2086. }
  2087. }
  2088. /*
  2089. * Sets the values of the primitive fields of object obj. fieldIDs is an
  2090. * array of field IDs (the primFieldsID field of the appropriate
  2091. * ObjectStreamClass) identifying which fields to set. typecodes is an
  2092. * array of characters designating the primitive type of each field (e.g.,
  2093. * 'C' for char, 'Z' for boolean, etc.) data is the byte buffer from which
  2094. * the primitive field values are read, in the order of their field IDs.
  2095. *
  2096. * For efficiency, this method does not check all of its arguments for
  2097. * safety. Specifically, it assumes that obj's type is compatible with the
  2098. * given field IDs, and that the data array is long enough to contain all of
  2099. * the byte values that will be read out of it.
  2100. */
  2101. private static native void setPrimitiveFieldValues(Object obj,
  2102. long[] fieldIDs, char[] typecodes, byte[] data);
  2103. /*
  2104. * Sets the value of an object field of object obj. fieldID is the field ID
  2105. * identifying which field to set (obtained from the objFieldsID array field
  2106. * of the appropriate ObjectStreamClass). type is the field type; it is
  2107. * provided so that the native method can ensure that the passed value val
  2108. * is assignable to the field.
  2109. *
  2110. * For efficiency, this method does not check all of its arguments for
  2111. * safety. Specifically, it assumes that obj's type is compatible with the
  2112. * given field IDs, and that type is indeed the class type of the field
  2113. * designated by fieldID.
  2114. */
  2115. private static native void setObjectFieldValue(Object obj, long fieldID,
  2116. Class type, Object val);
  2117. /*************************************************************/
  2118. /**
  2119. * Provide access to the persistent fields read from the input stream.
  2120. */
  2121. abstract public static class GetField {
  2122. /**
  2123. * Get the ObjectStreamClass that describes the fields in the stream.
  2124. *
  2125. * @return the descriptor class that describes the serializable fields
  2126. */
  2127. abstract public ObjectStreamClass getObjectStreamClass();
  2128. /**
  2129. * Return true if the named field is defaulted and has no value
  2130. * in this stream.
  2131. *
  2132. * @param name the name of the field
  2133. * @return true, if and only if the named field is defaulted
  2134. * @throws IOException if there are I/O errors while reading from
  2135. * the underlying <code>InputStream</code>
  2136. * @throws IllegalArgumentException if <code>name</code> does not
  2137. * correspond to a serializable field
  2138. */
  2139. abstract public boolean defaulted(String name)
  2140. throws IOException, IllegalArgumentException;
  2141. /**
  2142. * Get the value of the named boolean field from the persistent field.
  2143. *
  2144. * @param name the name of the field
  2145. * @param defvalue the default value to use if <code>name</code>
  2146. * does not have a value
  2147. * @return the value of the named <code>boolean</code> field
  2148. * @throws IOException if there are I/O errors while reading from
  2149. * the underlying <code>InputStream</code>
  2150. * @throws IllegalArgumentException if type of <code>name</code> is
  2151. * not serializable or if the field type is incorrect
  2152. */
  2153. abstract public boolean get(String name, boolean defvalue)
  2154. throws IOException, IllegalArgumentException;
  2155. /**
  2156. * Get the value of the named char field from the persistent fields.
  2157. *
  2158. * @param name the name of the field
  2159. * @param defvalue the default value to use if <code>name</code>
  2160. * does not have a value
  2161. * @return the value of the named <code>char</code> field
  2162. * @throws IOException if there are I/O errors while reading from
  2163. * the underlying <code>InputStream</code>
  2164. * @throws IllegalArgumentException if type of <code>name</code> is
  2165. * not serializable or if the field type is incorrect
  2166. */
  2167. abstract public char get(String name, char defvalue)
  2168. throws IOException, IllegalArgumentException;
  2169. /**
  2170. * Get the value of the named byte field from the persistent fields.
  2171. *
  2172. * @param name the name of the field
  2173. * @param defvalue the default value to use if <code>name</code>
  2174. * does not have a value
  2175. * @return the value of the named <code>byte</code> field
  2176. * @throws IOException if there are I/O errors while reading from
  2177. * the underlying <code>InputStream</code>
  2178. * @throws IllegalArgumentException if type of <code>name</code> is
  2179. * not serializable or if the field type is incorrect
  2180. */
  2181. abstract public byte get(String name, byte defvalue)
  2182. throws IOException, IllegalArgumentException;
  2183. /**
  2184. * Get the value of the named short field from the persistent fields.
  2185. *
  2186. * @param name the name of the field
  2187. * @param defvalue the default value to use if <code>name</code>
  2188. * does not have a value
  2189. * @return the value of the named <code>short</code> field
  2190. * @throws IOException if there are I/O errors while reading from
  2191. * the underlying <code>InputStream</code>
  2192. * @throws IllegalArgumentException if type of <code>name</code> is
  2193. * not serializable or if the field type is incorrect
  2194. */
  2195. abstract public short get(String name, short defvalue)
  2196. throws IOException, IllegalArgumentException;
  2197. /**
  2198. * Get the value of the named int field from the persistent fields.
  2199. *
  2200. * @param name the name of the field
  2201. * @param defvalue the default value to use if <code>name</code>
  2202. * does not have a value
  2203. * @return the value of the named <code>int</code> field
  2204. * @throws IOException if there are I/O errors while reading from
  2205. * the underlying <code>InputStream</code>
  2206. * @throws IllegalArgumentException if type of <code>name</code> is
  2207. * not serializable or if the field type is incorrect
  2208. */
  2209. abstract public int get(String name, int defvalue)
  2210. throws IOException, IllegalArgumentException;
  2211. /**
  2212. * Get the value of the named long field from the persistent fields.
  2213. *
  2214. * @param name the name of the field
  2215. * @param defvalue the default value to use if <code>name</code>
  2216. * does not have a value
  2217. * @return the value of the named <code>long</code> field
  2218. * @throws IOException if there are I/O errors while reading from
  2219. * the underlying <code>InputStream</code>
  2220. * @throws IllegalArgumentException if type of <code>name</code> is
  2221. * not serializable or if the field type is incorrect
  2222. */
  2223. abstract public long get(String name, long defvalue)
  2224. throws IOException, IllegalArgumentException;
  2225. /**
  2226. * Get the value of the named float field from the persistent fields.
  2227. *
  2228. * @param name the name of the field
  2229. * @param defvalue the default value to use if <code>name</code>
  2230. * does not have a value
  2231. * @return the value of the named <code>float</code> field
  2232. * @throws IOException if there are I/O errors while reading from
  2233. * the underlying <code>InputStream</code>
  2234. * @throws IllegalArgumentException if type of <code>name</code> is
  2235. * not serializable or if the field type is incorrect
  2236. */
  2237. abstract public float get(String name, float defvalue)
  2238. throws IOException, IllegalArgumentException;
  2239. /**
  2240. * Get the value of the named double field from the persistent field.
  2241. *
  2242. * @param name the name of the field
  2243. * @param defvalue the default value to use if <code>name</code>
  2244. * does not have a value
  2245. * @return the value of the named <code>double</code> field
  2246. * @throws IOException if there are I/O errors while reading from
  2247. * the underlying <code>InputStream</code>
  2248. * @throws IllegalArgumentException if type of <code>name</code> is
  2249. * not serializable or if the field type is incorrect
  2250. */
  2251. abstract public double get(String name, double defvalue)
  2252. throws IOException, IllegalArgumentException;
  2253. /**
  2254. * Get the value of the named Object field from the persistent field.
  2255. *
  2256. * @param name the name of the field
  2257. * @param defvalue the default value to use if <code>name</code>
  2258. * does not have a value
  2259. * @return the value of the named <code>Object</code> field
  2260. * @throws IOException if there are I/O errors while reading from
  2261. * the underlying <code>InputStream</code>
  2262. * @throws IllegalArgumentException if type of <code>name</code> is
  2263. * not serializable or if the field type is incorrect
  2264. */
  2265. abstract public Object get(String name, Object defvalue)
  2266. throws IOException, IllegalArgumentException;
  2267. }
  2268. /* Internal Implementation of GetField. */
  2269. static final class GetFieldImpl extends GetField {
  2270. /**
  2271. * Get the ObjectStreamClass that describes the fields in the
  2272. * stream.
  2273. *
  2274. * @return the descriptor class that describes the serializable
  2275. * fields
  2276. */
  2277. public ObjectStreamClass getObjectStreamClass() {
  2278. return desc;
  2279. }
  2280. /**
  2281. * Return true if the named field is defaulted and has no value
  2282. * in this stream.
  2283. *
  2284. * @param name the name of the field
  2285. * @return true, if and only if the named field is defaulted
  2286. * @throws IOException if there are I/O errors while reading from
  2287. * the underlying <code>InputStream</code>
  2288. * @throws IllegalArgumentException if <code>name</code> does not
  2289. * correspond to a serializable field
  2290. */
  2291. public boolean defaulted(String name)
  2292. throws IOException, IllegalArgumentException
  2293. {
  2294. ObjectStreamField field = checkField(name, null);
  2295. return (field == null);
  2296. }
  2297. /**
  2298. * Get the value of the named boolean field from the persistent
  2299. * field.
  2300. *
  2301. * @param name the name of the field
  2302. * @param defvalue the default value to use if <code>name</code>
  2303. * does not have a value
  2304. * @return the value of the named <code>boolean</code> field
  2305. * @throws IOException if there are I/O errors while reading from
  2306. * the underlying <code>InputStream</code>
  2307. * @throws IllegalArgumentException if type of <code>name</code> is
  2308. * not serializable or if the field type is incorrect
  2309. */
  2310. public boolean get(String name, boolean defvalue)
  2311. throws IOException, IllegalArgumentException
  2312. {
  2313. ObjectStreamField field = checkField(name, Boolean.TYPE);
  2314. if (field == null)
  2315. return defvalue;
  2316. return (boolean)(data[field.getOffset()] != 0);
  2317. }
  2318. /**
  2319. * Get the value of the named char field from the persistent fields.
  2320. *
  2321. * @param name the name of the field
  2322. * @param defvalue the default value to use if <code>name</code>
  2323. * does not have a value
  2324. * @return the value of the named <code>char</code> field
  2325. * @throws IOException if there are I/O errors while reading from
  2326. * the underlying <code>InputStream</code>
  2327. * @throws IllegalArgumentException if type of <code>name</code> is
  2328. * not serializable or if the field type is incorrect
  2329. */
  2330. public char get(String name, char defvalue)
  2331. throws IOException, IllegalArgumentException
  2332. {
  2333. ObjectStreamField field = checkField(name, Character.TYPE);
  2334. if (field == null)
  2335. return defvalue;
  2336. int loffset = field.getOffset();
  2337. return (char)(((data[loffset] & 0xff) << 8) +
  2338. ((data[loffset+1] & 0xff)));
  2339. }
  2340. /**
  2341. * Get the value of the named byte field from the persistent fields.
  2342. *
  2343. * @param name the name of the field
  2344. * @param defvalue the default value to use if <code>name</code>
  2345. * does not have a value
  2346. * @return the value of the named <code>byte</code> field
  2347. * @throws IOException if there are I/O errors while reading from
  2348. * the underlying <code>InputStream</code>
  2349. * @throws IllegalArgumentException if type of <code>name</code> is
  2350. * not serializable or if the field type is incorrect
  2351. */
  2352. public byte get(String name, byte defvalue)
  2353. throws IOException, IllegalArgumentException
  2354. {
  2355. ObjectStreamField field = checkField(name, Byte.TYPE);
  2356. if (field == null)
  2357. return defvalue;
  2358. return data[field.getOffset()];
  2359. }
  2360. /** Get the value of the named short field from the persistent
  2361. * fields.
  2362. *
  2363. * @param name the name of the field
  2364. * @param defvalue the default value to use if <code>name</code>
  2365. * does not have a value
  2366. * @return the value of the named <code>short</code> field
  2367. * @throws IOException if there are I/O errors while reading from
  2368. * the underlying <code>InputStream</code>
  2369. * @throws IllegalArgumentException if type of <code>name</code> is
  2370. * not serializable or if the field type is incorrect
  2371. */
  2372. public short get(String name, short defvalue)
  2373. throws IOException, IllegalArgumentException
  2374. {
  2375. ObjectStreamField field = checkField(name, Short.TYPE);
  2376. if (field == null)
  2377. return defvalue;
  2378. int loffset = field.getOffset();
  2379. return (short)(((data[loffset] & 0xff) << 8) +
  2380. ((data[loffset+1] & 0xff)));
  2381. }
  2382. /**
  2383. * Get the value of the named int field from the persistent fields.
  2384. *
  2385. * @param name the name of the field
  2386. * @param defvalue the default value to use if <code>name</code>
  2387. * does not have a value
  2388. * @return the value of the named <code>int</code> field
  2389. * @throws IOException if there are I/O errors while reading from
  2390. * the underlying <code>InputStream</code>
  2391. * @throws IllegalArgumentException if type of <code>name</code> is
  2392. * not serializable or if the field type is incorrect
  2393. */
  2394. public int get(String name, int defvalue)
  2395. throws IOException, IllegalArgumentException
  2396. {
  2397. ObjectStreamField field = checkField(name, Integer.TYPE);
  2398. if (field == null)
  2399. return defvalue;
  2400. int loffset = field.getOffset();
  2401. return (((data[loffset] & 0xff) << 24) +
  2402. ((data[loffset+1] & 0xff) << 16) +
  2403. ((data[loffset+2] & 0xff) << 8) +
  2404. ((data[loffset+3] & 0xff)));
  2405. }
  2406. /**
  2407. * Get the value of the named long field from the persistent fields.
  2408. *
  2409. * @param name the name of the field
  2410. * @param defvalue the default value to use if <code>name</code>
  2411. * does not have a value
  2412. * @return the value of the named <code>long</code> field
  2413. * @throws IOException if there are I/O errors while reading from
  2414. * the underlying <code>InputStream</code>
  2415. * @throws IllegalArgumentException if type of <code>name</code> is
  2416. * not serializable or if the field type is incorrect
  2417. */
  2418. public long get(String name, long defvalue)
  2419. throws IOException, IllegalArgumentException
  2420. {
  2421. ObjectStreamField field = checkField(name, Long.TYPE);
  2422. if (field == null)
  2423. return defvalue;
  2424. int loffset = field.getOffset();
  2425. int upper = (((data[loffset] & 0xff) << 24) +
  2426. ((data[loffset+1] & 0xff) << 16) +
  2427. ((data[loffset+2] & 0xff) << 8) +
  2428. ((data[loffset+3] & 0xff)));
  2429. int lower = (((data[loffset+4] & 0xff) << 24) +
  2430. ((data[loffset+5] & 0xff) << 16) +
  2431. ((data[loffset+6] & 0xff) << 8) +
  2432. ((data[loffset+7] & 0xff)));
  2433. long v = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  2434. return v;
  2435. }
  2436. /**
  2437. * Get the value of the named float field from the persistent
  2438. * fields.
  2439. *
  2440. * @param name the name of the field
  2441. * @param defvalue the default value to use if <code>name</code>
  2442. * does not have a value
  2443. * @return the value of the named <code>float</code> field
  2444. * @throws IOException if there are I/O errors while reading from
  2445. * the underlying <code>InputStream</code>
  2446. * @throws IllegalArgumentException if type of <code>name</code> is
  2447. * not serializable or if the field type is incorrect
  2448. */
  2449. public float get(String name, float defvalue)
  2450. throws IOException, IllegalArgumentException
  2451. {
  2452. ObjectStreamField field = checkField(name, Float.TYPE);
  2453. if (field == null)
  2454. return defvalue;
  2455. int loffset = field.getOffset();
  2456. int v = (((data[loffset] & 0xff) << 24) +
  2457. ((data[loffset+1] & 0xff) << 16) +
  2458. ((data[loffset+2] & 0xff) << 8) +
  2459. ((data[loffset+3] & 0xff)));
  2460. return Float.intBitsToFloat(v);
  2461. }
  2462. /**
  2463. * Get the value of the named double field from the persistent
  2464. * field.
  2465. *
  2466. * @param name the name of the field
  2467. * @param defvalue the default value to use if <code>name</code>
  2468. * does not have a value
  2469. * @return the value of the named <code>double</code> field
  2470. * @throws IOException if there are I/O errors while reading from
  2471. * the underlying <code>InputStream</code>
  2472. * @throws IllegalArgumentException if type of <code>name</code> is
  2473. * not serializable or if the field type is incorrect
  2474. */
  2475. public double get(String name, double defvalue)
  2476. throws IOException, IllegalArgumentException
  2477. {
  2478. ObjectStreamField field = checkField(name, Double.TYPE);
  2479. if (field == null)
  2480. return defvalue;
  2481. int loffset = field.getOffset();
  2482. int upper = (((data[loffset] & 0xff) << 24) +
  2483. ((data[loffset+1] & 0xff) << 16) +
  2484. ((data[loffset+2] & 0xff) << 8) +
  2485. ((data[loffset+3] & 0xff)));
  2486. int lower = (((data[loffset+4] & 0xff) << 24) +
  2487. ((data[loffset+5] & 0xff) << 16) +
  2488. ((data[loffset+6] & 0xff) << 8) +
  2489. ((data[loffset+7] & 0xff)));
  2490. long v = ((long)upper << 32) + ((long)lower & 0xFFFFFFFFL);
  2491. return Double.longBitsToDouble(v);
  2492. }
  2493. /**
  2494. * Get the value of the named Object field from the persistent
  2495. * field.
  2496. *
  2497. * @param name the name of the field
  2498. * @param defvalue the default value to use if <code>name</code>
  2499. * does not have a value
  2500. * @return the value of the named <code>Object</code> field
  2501. * @throws IOException if there are I/O errors while reading from
  2502. * the underlying <code>InputStream</code>
  2503. * @throws IllegalArgumentException if type of <code>name</code> is
  2504. * not serializable or if the field type is incorrect
  2505. */
  2506. public Object get(String name, Object defvalue)
  2507. throws IOException, IllegalArgumentException
  2508. {
  2509. ObjectStreamField field = checkField(name, Object.class);
  2510. if (field == null)
  2511. return defvalue;
  2512. return objects[field.getOffset()];
  2513. }
  2514. /*
  2515. * Retrieve the named field.
  2516. * If the field is known in the current descriptor return it.
  2517. * If not, find the descriptor for the class that is being
  2518. * read into and check the name. If the name is not
  2519. * valid in the class throw a IllegalArgumentException.
  2520. * otherwise return null.
  2521. */
  2522. private ObjectStreamField checkField(String name, Class type)
  2523. throws IllegalArgumentException
  2524. {
  2525. ObjectStreamField field = (type == null) ?
  2526. desc.getField(name) : desc.getField(name, type);
  2527. if (field != null) {
  2528. /*
  2529. * Check the type of the field in the stream.
  2530. * If correct return the field.
  2531. */
  2532. if (type != null && type != field.getType())
  2533. throw new IllegalArgumentException("field type incorrect");
  2534. return field;
  2535. } else {
  2536. /* Check the name in the local classes descriptor.
  2537. * If found it's a valid persistent field an
  2538. * should be defaulted.
  2539. * If not the caller shouldn't be using that name.
  2540. */
  2541. ObjectStreamClass localdesc =
  2542. desc.localClassDescriptor();
  2543. if (localdesc == null)
  2544. throw new IllegalArgumentException("No local class descriptor");
  2545. ObjectStreamField localfield = (type == null)
  2546. ? localdesc.getField(name) :
  2547. localdesc.getField(name, type);
  2548. if (localfield == null)
  2549. throw new IllegalArgumentException("no such field");
  2550. if (type != null && type != localfield.getType() &&
  2551. (type.isPrimitive() || localfield.getType().isPrimitive()))
  2552. throw new IllegalArgumentException("field type incorrect");
  2553. return null;
  2554. }
  2555. }
  2556. /**
  2557. * Read the data and fields from the specified stream.
  2558. */
  2559. void read(ObjectInputStream in)
  2560. throws IOException, ClassNotFoundException
  2561. {
  2562. if (data != null)
  2563. in.readFully(data, 0, data.length);
  2564. if (objects != null) {
  2565. for (int i = 0; i < objects.length; i++) {
  2566. /* don't require local class when reading object from stream.*/
  2567. objects[i] = in.readObject(false);
  2568. }
  2569. }
  2570. }
  2571. /**
  2572. * Create a GetField object for the a Class.
  2573. * Allocate the arrays for primitives and objects.
  2574. */
  2575. GetFieldImpl(ObjectStreamClass descriptor){
  2576. desc = descriptor;
  2577. if (desc.numPrimBytes > 0)
  2578. data = new byte[desc.numPrimBytes];
  2579. if (desc.numObjFields > 0)
  2580. objects = new Object[desc.numObjFields];
  2581. }
  2582. /*
  2583. * The byte array that contains the bytes for the primitive fields.
  2584. * The Object array that contains the objects for the object fields.
  2585. */
  2586. private byte[] data;
  2587. private Object[] objects;
  2588. private ObjectStreamClass desc;
  2589. }
  2590. /* Remember the first exception that stopped this stream. */
  2591. private IOException abortIOException = null;
  2592. private ClassNotFoundException abortClassNotFoundException = null;
  2593. /* Allocate a new object for the specified class
  2594. * Native since newInstance may not be able to find a zero arg constructor.
  2595. */
  2596. private static native Object allocateNewObject(Class aclass, Class initclass)
  2597. throws InstantiationException, IllegalAccessException;
  2598. /* Allocate a new array for the specified class
  2599. * Native since the type of the array needs to be set to the class
  2600. */
  2601. private static native Object allocateNewArray(Class aclass, int length);
  2602. /* The object is the current object and class is the the current
  2603. * subclass of the object being read. Nesting information is kept
  2604. * on the stack.
  2605. */
  2606. private Object currentObject;
  2607. private ObjectStreamClass currentClassDesc;
  2608. private Class currentClass;
  2609. private Object currentGetFields;
  2610. /* Buffer used for temporarily storing data for primitive fields, primitive
  2611. * arrays, and UTF strings.
  2612. */
  2613. private byte[] data = new byte[1024];
  2614. /* Buffer used for temporarily storing decoded fragments of UTF strings. */
  2615. private char[] cdata = new char[50];
  2616. private static final int CDATA_MAX_LEN = 1000;
  2617. /* String buffer used for constructing strings. */
  2618. private StringBuffer sbuf = new StringBuffer();
  2619. /* Arrays used to keep track of classes and ObjectStreamClasses
  2620. * as they are being merged; used in inputObject.
  2621. * spClass is the stack pointer for both. */
  2622. ObjectStreamClass[] classdesc;
  2623. Class[] classes;
  2624. int spClass;
  2625. /* During deserialization the objects in the stream are represented by
  2626. * handles (ints), they need to be mapped to the objects.
  2627. * The vector is indexed by the offset between baseWireHandle and the
  2628. * wire handle in the stream.
  2629. */
  2630. private ArrayList wireHandle2Object;
  2631. private int nextWireOffset;
  2632. /* List of validation callback objects
  2633. * The list is created as needed, and ValidationCallback objects added
  2634. * for each call to registerObject. The list is maintained in
  2635. * order of highest (first) priority to lowest
  2636. */
  2637. private ArrayList callbacks;
  2638. /* Recursion level, starts at zero and is incremented for each entry
  2639. * to readObject. Decremented before exit.
  2640. */
  2641. private int recursionDepth;
  2642. /* Last code Peek'ed, if any */
  2643. private byte currCode;
  2644. /*
  2645. * Flag set to true to allow resolveObject to be called.
  2646. * Set by enableResolveObject.
  2647. */
  2648. boolean enableResolve;
  2649. /* if true, override readObject implementation with readObjectOverride.
  2650. */
  2651. private boolean enableSubclassImplementation;
  2652. private Object[] readObjectArglist = {this};
  2653. };
  2654. // Internal class to hold the Callback object and priority
  2655. class ValidationCallback {
  2656. ValidationCallback(ObjectInputValidation cb, int prio) {
  2657. callback = cb;
  2658. priority = prio;
  2659. }
  2660. int priority; // priority of this callback
  2661. ObjectInputValidation callback; // object to be called back
  2662. }