1. /*
  2. * @(#)IIOPInputStream.java 1.48 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.internal.io;
  16. import java.io.InputStream;
  17. import java.io.IOException;
  18. import java.io.StreamCorruptedException;
  19. import java.io.ObjectInputValidation;
  20. import java.io.NotActiveException;
  21. import java.io.InvalidObjectException;
  22. import java.io.InvalidClassException;
  23. import java.io.DataInputStream;
  24. import java.io.OptionalDataException;
  25. import java.io.WriteAbortedException;
  26. import java.io.Externalizable;
  27. import java.io.EOFException;
  28. import java.lang.reflect.InvocationTargetException;
  29. import java.util.Vector;
  30. import java.util.Stack;
  31. import java.util.Hashtable;
  32. import java.util.Enumeration;
  33. import com.sun.corba.se.internal.io.ObjectStreamClass;
  34. import com.sun.corba.se.internal.util.Utility;
  35. import com.sun.corba.se.internal.util.MinorCodes;
  36. import com.sun.corba.se.internal.util.Utility;
  37. import org.omg.CORBA.ValueMember;
  38. import org.omg.CORBA.TCKind;
  39. import org.omg.CORBA.ORB; //d11638
  40. import org.omg.CORBA.CompletionStatus;
  41. import org.omg.CORBA.portable.IndirectionException;
  42. import org.omg.CORBA.MARSHAL;
  43. import org.omg.CORBA.TypeCode;
  44. import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
  45. import com.sun.org.omg.SendingContext.CodeBase; // d11638
  46. import javax.rmi.PortableRemoteObject;
  47. import javax.rmi.CORBA.Util;
  48. import javax.rmi.CORBA.ValueHandler;
  49. import java.util.*;
  50. /**
  51. * IIOPInputStream is used by the ValueHandlerImpl to handle Java serialization
  52. * input semantics.
  53. *
  54. * @author Stephen Lewallen
  55. * @since JDK1.1.6
  56. */
  57. public class IIOPInputStream
  58. extends com.sun.corba.se.internal.io.InputStreamHook
  59. {
  60. // Necessary to pass the appropriate fields into the
  61. // defaultReadObjectDelegate method (which takes no
  62. // parameters since it's called from
  63. // java.io.ObjectInpuStream defaultReadObject()
  64. // which we can't change).
  65. //
  66. // This is only used in the case where the fields had
  67. // to be obtained remotely because of a serializable
  68. // version difference. Set in inputObjectUsingFVD.
  69. // Part of serialization evolution fixes for Ladybird,
  70. // bug 4365188.
  71. private ValueMember defaultReadObjectFVDMembers[] = null;
  72. private org.omg.CORBA_2_3.portable.InputStream orbStream;
  73. private CodeBase cbSender; //d11638
  74. private ValueHandlerImpl vhandler; //d4365188
  75. private Object currentObject = null;
  76. private ObjectStreamClass currentClassDesc = null;
  77. private Class currentClass = null;
  78. private int recursionDepth = 0;
  79. private int simpleReadDepth = 0;
  80. // The ActiveRecursionManager replaces the old RecursionManager which
  81. // used to record how many recursions were made, and resolve them after
  82. // an object was completely deserialized.
  83. //
  84. // That created problems (as in bug 4414154) because when custom
  85. // unmarshaling in readObject, there can be recursive references
  86. // to one of the objects currently being unmarshaled, and the
  87. // passive recursion system failed.
  88. ActiveRecursionManager activeRecursionMgr = new ActiveRecursionManager();
  89. private IOException abortIOException = null;
  90. /* Remember the first exception that stopped this stream. */
  91. private ClassNotFoundException abortClassNotFoundException = null;
  92. /* Vector of validation callback objects
  93. * The vector is created as needed. The vector is maintained in
  94. * order of highest (first) priority to lowest
  95. */
  96. private Vector callbacks;
  97. // Serialization machinery fields
  98. /* Arrays used to keep track of classes and ObjectStreamClasses
  99. * as they are being merged; used in inputObject.
  100. * spClass is the stack pointer for both. */
  101. ObjectStreamClass[] classdesc;
  102. Class[] classes;
  103. int spClass;
  104. private static final String kEmptyStr = "";
  105. // TCKind TypeCodes used in FVD inputClassFields
  106. //public static final TypeCode kRemoteTypeCode = new TypeCodeImpl(TCKind._tk_objref);
  107. //public static final TypeCode kValueTypeCode = new TypeCodeImpl(TCKind._tk_value);
  108. //d11638 removed TypeCodeImpl dependency
  109. public static final TypeCode kRemoteTypeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
  110. public static final TypeCode kValueTypeCode = ORB.init().get_primitive_tc(TCKind.tk_value);
  111. // TESTING CODE - useFVDOnly should be made final before FCS in order to
  112. // optimize out the check.
  113. private static final boolean useFVDOnly = false;
  114. public static void setTestFVDFlag(boolean val){
  115. // useFVDOnly = val;
  116. }
  117. /**
  118. * Dummy constructor; passes upper stream a dummy stream;
  119. **/
  120. public IIOPInputStream()
  121. throws java.io.IOException {
  122. super();
  123. resetStream();
  124. }
  125. public final void setOrbStream(org.omg.CORBA_2_3.portable.InputStream os) {
  126. orbStream = os;
  127. }
  128. public final org.omg.CORBA_2_3.portable.InputStream getOrbStream() {
  129. return orbStream;
  130. }
  131. //d11638 added setSender and getSender
  132. public final void setSender(CodeBase cb) {
  133. cbSender = cb;
  134. }
  135. public final CodeBase getSender() {
  136. return cbSender;
  137. }
  138. // 4365188 this is added to enable backward compatability w/ wrong
  139. // rep-ids
  140. public final void setValueHandler(ValueHandler vh) {
  141. vhandler = (com.sun.corba.se.internal.io.ValueHandlerImpl) vh;
  142. }
  143. public final ValueHandler getValueHandler() {
  144. return (javax.rmi.CORBA.ValueHandler) vhandler;
  145. }
  146. public final void increaseRecursionDepth(){
  147. recursionDepth++;
  148. }
  149. public final int decreaseRecursionDepth(){
  150. return --recursionDepth;
  151. }
  152. /**
  153. * Override the actions of the final method "readObject()"
  154. * in ObjectInputStream.
  155. * @since JDK1.1.6
  156. *
  157. * Read an object from the ObjectInputStream.
  158. * The class of the object, the signature of the class, and the values
  159. * of the non-transient and non-static fields of the class and all
  160. * of its supertypes are read. Default deserializing for a class can be
  161. * overriden using the writeObject and readObject methods.
  162. * Objects referenced by this object are read transitively so
  163. * that a complete equivalent graph of objects is reconstructed by readObject. <p>
  164. *
  165. * The root object is completly restored when all of its fields
  166. * and the objects it references are completely restored. At this
  167. * point the object validation callbacks are executed in order
  168. * based on their registered priorities. The callbacks are
  169. * registered by objects (in the readObject special methods)
  170. * as they are individually restored.
  171. *
  172. * Exceptions are thrown for problems with the InputStream and for classes
  173. * that should not be deserialized. All exceptions are fatal to the
  174. * InputStream and leave it in an indeterminate state; it is up to the caller
  175. * to ignore or recover the stream state.
  176. * @exception java.lang.ClassNotFoundException Class of a serialized object
  177. * cannot be found.
  178. * @exception InvalidClassException Something is wrong with a class used by
  179. * serialization.
  180. * @exception StreamCorruptedException Control information in the
  181. * stream is inconsistent.
  182. * @exception OptionalDataException Primitive data was found in the
  183. * stream instead of objects.
  184. * @exception IOException Any of the usual Input/Output related exceptions.
  185. * @since JDK1.1
  186. */
  187. public final Object readObjectDelegate() throws IOException
  188. {
  189. try
  190. {
  191. return orbStream.read_abstract_interface();
  192. }
  193. catch(IndirectionException cdrie)
  194. {
  195. // The CDR stream had never seen the given offset before,
  196. // so check the recursion manager (it will throw an
  197. // IOException if it doesn't have a reference, either).
  198. return activeRecursionMgr.getObject(cdrie.offset);
  199. }
  200. }
  201. final Object simpleReadObject(Class clz,
  202. String repositoryID,
  203. com.sun.org.omg.SendingContext.CodeBase sender,
  204. int offset)
  205. /* throws OptionalDataException, ClassNotFoundException, IOException */
  206. {
  207. /* Save the current state and get ready to read an object. */
  208. Object prevObject = currentObject;
  209. ObjectStreamClass prevClass = currentClassDesc;
  210. simpleReadDepth++; // Entering
  211. Object obj = null;
  212. /*
  213. * Check for reset, handle it before reading an object.
  214. */
  215. try {
  216. // d4365188: backward compatability
  217. if (vhandler.useFullValueDescription(clz, repositoryID)) {
  218. obj = inputObjectUsingFVD(clz, repositoryID, sender, offset);
  219. } else {
  220. obj = inputObject(clz, repositoryID, sender, offset);
  221. }
  222. obj = currentClassDesc.readResolve(obj);
  223. }
  224. catch(ClassNotFoundException cnfe)
  225. {
  226. throwExceptionType(ClassNotFoundException.class, cnfe.getMessage());
  227. return null;
  228. }
  229. catch(IOException ioe)
  230. {
  231. // System.out.println("CLZ = " + clz + "; " + ioe.toString());
  232. throwExceptionType(IOException.class, ioe.getMessage());
  233. return null;
  234. }
  235. finally {
  236. simpleReadDepth --;
  237. currentObject = prevObject;
  238. currentClassDesc = prevClass;
  239. }
  240. /* Check for thrown exceptions and re-throw them, clearing them if
  241. * this is the last recursive call .
  242. */
  243. IOException exIOE = abortIOException;
  244. if (simpleReadDepth == 0)
  245. abortIOException = null;
  246. if (exIOE != null){
  247. throwExceptionType(IOException.class, exIOE.getMessage());
  248. return null;
  249. }
  250. ClassNotFoundException exCNF = abortClassNotFoundException;
  251. if (simpleReadDepth == 0)
  252. abortClassNotFoundException = null;
  253. if (exCNF != null) {
  254. throwExceptionType(ClassNotFoundException.class, exCNF.getMessage());
  255. return null;
  256. }
  257. return obj;
  258. }
  259. public final void simpleSkipObject(String repositoryID,
  260. com.sun.org.omg.SendingContext.CodeBase sender)
  261. /* throws OptionalDataException, ClassNotFoundException, IOException */
  262. {
  263. /* Save the current state and get ready to read an object. */
  264. Object prevObject = currentObject;
  265. ObjectStreamClass prevClass = currentClassDesc;
  266. simpleReadDepth++; // Entering
  267. Object obj = null;
  268. /*
  269. * Check for reset, handle it before reading an object.
  270. */
  271. try {
  272. skipObjectUsingFVD(repositoryID, sender);
  273. }
  274. catch(ClassNotFoundException cnfe)
  275. {
  276. throwExceptionType(ClassNotFoundException.class, cnfe.getMessage());
  277. return;
  278. }
  279. catch(IOException ioe)
  280. {
  281. throwExceptionType(IOException.class, ioe.getMessage());
  282. return;
  283. }
  284. finally {
  285. simpleReadDepth --;
  286. currentObject = prevObject;
  287. currentClassDesc = prevClass;
  288. }
  289. /* Check for thrown exceptions and re-throw them, clearing them if
  290. * this is the last recursive call .
  291. */
  292. IOException exIOE = abortIOException;
  293. if (simpleReadDepth == 0)
  294. abortIOException = null;
  295. if (exIOE != null){
  296. throwExceptionType(IOException.class, exIOE.getMessage());
  297. return;
  298. }
  299. ClassNotFoundException exCNF = abortClassNotFoundException;
  300. if (simpleReadDepth == 0)
  301. abortClassNotFoundException = null;
  302. if (exCNF != null) {
  303. throwExceptionType(ClassNotFoundException.class, exCNF.getMessage());
  304. return;
  305. }
  306. return;
  307. }
  308. /////////////////
  309. /**
  310. * This method is called by trusted subclasses of ObjectOutputStream
  311. * that constructed ObjectOutputStream using the
  312. * protected no-arg constructor. The subclass is expected to provide
  313. * an override method with the modifier "final".
  314. *
  315. * @return the Object read from the stream.
  316. *
  317. * @see #ObjectInputStream()
  318. * @see #readObject
  319. * @since JDK 1.2
  320. */
  321. protected final Object readObjectOverride()
  322. throws OptionalDataException, ClassNotFoundException, IOException
  323. {
  324. return readObjectDelegate();
  325. }
  326. /**
  327. * Override the actions of the final method "defaultReadObject()"
  328. * in ObjectInputStream.
  329. * @since JDK1.1.6
  330. *
  331. * Read the non-static and non-transient fields of the current class
  332. * from this stream. This may only be called from the readObject method
  333. * of the class being deserialized. It will throw the NotActiveException
  334. * if it is called otherwise.
  335. *
  336. * @exception java.lang.ClassNotFoundException if the class of a serialized
  337. * object could not be found.
  338. * @exception IOException if an I/O error occurs.
  339. * @exception NotActiveException if the stream is not currently reading
  340. * objects.
  341. * @since JDK1.1
  342. */
  343. public final void defaultReadObjectDelegate()
  344. /* throws IOException, ClassNotFoundException, NotActiveException */
  345. {
  346. try {
  347. if (currentObject == null || currentClassDesc == null)
  348. throw new NotActiveException("defaultReadObjectDelegate");
  349. // The array will be null unless fields were retrieved
  350. // remotely because of a serializable version difference.
  351. // Bug fix for 4365188. See the definition of
  352. // defaultReadObjectFVDMembers for more information.
  353. if (defaultReadObjectFVDMembers != null &&
  354. defaultReadObjectFVDMembers.length > 0) {
  355. // WARNING: Be very careful! What if some of
  356. // these fields actually have to do this, too?
  357. // This works because the defaultReadObjectFVDMembers
  358. // reference is passed to inputClassFields, but
  359. // there is no guarantee that
  360. // defaultReadObjectFVDMembers will point to the
  361. // same array after calling inputClassFields.
  362. // Use the remote fields to unmarshal.
  363. inputClassFields(currentObject,
  364. currentClass,
  365. currentClassDesc,
  366. defaultReadObjectFVDMembers,
  367. cbSender);
  368. } else {
  369. // Use the local fields to unmarshal.
  370. ObjectStreamField[] fields =
  371. currentClassDesc.getFieldsNoCopy();
  372. if (fields.length > 0) {
  373. inputClassFields(currentObject, currentClass, fields, cbSender); //d11638
  374. }
  375. }
  376. }
  377. catch(NotActiveException nae)
  378. {
  379. throwExceptionType(java.io.NotActiveException.class, nae.getMessage());
  380. }
  381. catch(IOException ioe)
  382. {
  383. throwExceptionType(java.io.IOException.class, ioe.getMessage());
  384. }
  385. catch(ClassNotFoundException cnfe)
  386. {
  387. throwExceptionType(java.lang.ClassNotFoundException.class, cnfe.getMessage());
  388. }
  389. }
  390. /**
  391. * Override the actions of the final method "enableResolveObject()"
  392. * in ObjectInputStream.
  393. * @since JDK1.1.6
  394. *
  395. * Enable the stream to allow objects read from the stream to be replaced.
  396. * If the stream is a trusted class it is allowed to enable replacment.
  397. * Trusted classes are those classes with a classLoader equals null. <p>
  398. *
  399. * When enabled the resolveObject method is called for every object
  400. * being deserialized.
  401. *
  402. * @exception SecurityException The classloader of this stream object is non-null.
  403. * @since JDK1.1
  404. */
  405. public final boolean enableResolveObjectDelegate(boolean enable)
  406. /* throws SecurityException */
  407. {
  408. return false;
  409. }
  410. // The following three methods allow the implementing orbStream
  411. // to provide mark/reset behavior as defined in java.io.InputStream.
  412. public final void mark(int readAheadLimit) {
  413. orbStream.mark(readAheadLimit);
  414. }
  415. public final boolean markSupported() {
  416. return orbStream.markSupported();
  417. }
  418. public final void reset() throws IOException {
  419. try {
  420. orbStream.reset();
  421. } catch (Error e) {
  422. throw new IOException(e.getMessage());
  423. }
  424. }
  425. public final int available() throws IOException{
  426. return 0; // unreliable
  427. }
  428. public final void close() throws IOException{
  429. // no op
  430. }
  431. public final int read() throws IOException{
  432. try{
  433. return (orbStream.read_octet() << 0) & 0x000000FF;
  434. }
  435. catch(Error e)
  436. {
  437. throw new IOException(e.getMessage());
  438. }
  439. }
  440. public final int read(byte data[], int offset, int length) throws IOException{
  441. try{
  442. orbStream.read_octet_array(data, offset, length);
  443. return length;
  444. }
  445. catch(Error e)
  446. {
  447. throw new IOException(e.getMessage());
  448. }
  449. }
  450. public final boolean readBoolean() throws IOException{
  451. try{
  452. return orbStream.read_boolean();
  453. }
  454. catch(Error e)
  455. {
  456. throw new IOException(e.getMessage());
  457. }
  458. }
  459. public final byte readByte() throws IOException{
  460. try{
  461. return orbStream.read_octet();
  462. }
  463. catch(Error e)
  464. {
  465. throw new IOException(e.getMessage());
  466. }
  467. }
  468. public final char readChar() throws IOException{
  469. try{
  470. return orbStream.read_wchar();
  471. }
  472. catch(Error e)
  473. {
  474. throw new IOException(e.getMessage());
  475. }
  476. }
  477. public final double readDouble() throws IOException{
  478. try{
  479. return orbStream.read_double();
  480. }
  481. catch(Error e)
  482. {
  483. throw new IOException(e.getMessage());
  484. }
  485. }
  486. public final float readFloat() throws IOException{
  487. try{
  488. return orbStream.read_float();
  489. }
  490. catch(Error e)
  491. {
  492. throw new IOException(e.getMessage());
  493. }
  494. }
  495. public final void readFully(byte data[]) throws IOException{
  496. // d11623 : implement readFully, required for serializing some core classes
  497. readFully(data, 0, data.length);
  498. }
  499. public final void readFully(byte data[], int offset, int size) throws IOException{
  500. // d11623 : implement readFully, required for serializing some core classes
  501. try{
  502. orbStream.read_octet_array(data, offset, size);
  503. }
  504. catch(Error e)
  505. {
  506. throw new IOException(e.getMessage());
  507. }
  508. }
  509. public final int readInt() throws IOException{
  510. try{
  511. return orbStream.read_long();
  512. }
  513. catch(Error e)
  514. {
  515. throw new IOException(e.getMessage());
  516. }
  517. }
  518. public final String readLine() throws IOException{
  519. throw new IOException("Method readLine not supported");
  520. }
  521. public final long readLong() throws IOException{
  522. try{
  523. return orbStream.read_longlong();
  524. }
  525. catch(Error e)
  526. {
  527. throw new IOException(e.getMessage());
  528. }
  529. }
  530. public final short readShort() throws IOException{
  531. try{
  532. return orbStream.read_short();
  533. }
  534. catch(Error e)
  535. {
  536. throw new IOException(e.getMessage());
  537. }
  538. }
  539. protected final void readStreamHeader() throws IOException, StreamCorruptedException{
  540. // no op
  541. }
  542. public final int readUnsignedByte() throws IOException{
  543. try{
  544. return (orbStream.read_octet() << 0) & 0x000000FF;
  545. }
  546. catch(Error e)
  547. {
  548. throw new IOException(e.getMessage());
  549. }
  550. }
  551. public final int readUnsignedShort() throws IOException{
  552. try{
  553. return (orbStream.read_ushort() << 0) & 0x0000FFFF;
  554. }
  555. catch(Error e)
  556. {
  557. throw new IOException(e.getMessage());
  558. }
  559. }
  560. /**
  561. * Helper method for correcting the Kestrel bug 4367783 (dealing
  562. * with larger than 8-bit chars). The old behavior is preserved
  563. * in orbutil.IIOPInputStream_1_3 in order to interoperate with
  564. * our legacy ORBs.
  565. */
  566. protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream)
  567. {
  568. return stream.read_wstring();
  569. }
  570. public final String readUTF() throws IOException{
  571. try{
  572. return internalReadUTF(orbStream);
  573. }
  574. catch(Error e)
  575. {
  576. throw new IOException(e.getMessage());
  577. }
  578. }
  579. public final synchronized void registerValidation(ObjectInputValidation obj,
  580. int prio)
  581. throws NotActiveException, InvalidObjectException{
  582. throw new Error("Method registerValidation not supported");
  583. }
  584. protected final Class resolveClass(ObjectStreamClass v)
  585. throws IOException, ClassNotFoundException{
  586. throw new IOException("Method resolveClass not supported");
  587. }
  588. protected final Object resolveObject(Object obj) throws IOException{
  589. throw new IOException("Method resolveObject not supported");
  590. }
  591. public final int skipBytes(int len) throws IOException{
  592. try{
  593. byte buf[] = new byte[len];
  594. orbStream.read_octet_array(buf, 0, len);
  595. return len;
  596. }
  597. catch(Error e)
  598. {
  599. throw new IOException(e.getMessage());
  600. }
  601. }
  602. private Object inputObject(Class clz,
  603. String repositoryID,
  604. com.sun.org.omg.SendingContext.CodeBase sender,
  605. int offset)
  606. throws IOException, ClassNotFoundException
  607. {
  608. /*
  609. * Get the descriptor and then class of the incoming object.
  610. */
  611. currentClassDesc = ObjectStreamClass.lookup(clz);
  612. currentClass = currentClassDesc.forClass();
  613. //currentClassDesc.setClass(currentClass);
  614. if (currentClass == null)
  615. throw new ClassNotFoundException(currentClassDesc.getName());
  616. try {
  617. /* If Externalizable,
  618. * Create an instance and tell it to read its data.
  619. * else,
  620. * Handle it as a serializable class.
  621. */
  622. if (currentClassDesc.isExternalizable()) {
  623. try {
  624. currentObject = (currentClass == null) ?
  625. null : allocateNewObject(currentClass, currentClass);
  626. if (currentObject != null) {
  627. // Store this object and its beginning position
  628. // since there might be indirections to it while
  629. // it's been unmarshalled.
  630. activeRecursionMgr.addObject(offset, currentObject);
  631. // Read format version
  632. readByte();
  633. Externalizable ext = (Externalizable)currentObject;
  634. ext.readExternal(this);
  635. }
  636. }
  637. catch (NoSuchMethodError e) {
  638. throw new InvalidClassException(currentClass.getName(),
  639. "NoSuchMethodError accessing no-arg constructor");
  640. }
  641. catch (IllegalAccessException e) {
  642. throw new InvalidClassException(currentClass.getName(),
  643. "IllegalAccessException");
  644. }
  645. catch (InstantiationException e) {
  646. throw new InvalidClassException(currentClass.getName(),
  647. "InstantiationException");
  648. }
  649. } // end : if (currentClassDesc.isExternalizable())
  650. else {
  651. /* Count number of classes and descriptors we might have
  652. * to work on.
  653. */
  654. ObjectStreamClass currdesc = currentClassDesc;
  655. Class currclass = currentClass;
  656. int spBase = spClass; // current top of stack
  657. /* The object's classes should be processed from supertype to subtype
  658. * Push all the clases of the current object onto a stack.
  659. * Note that only the serializable classes are represented
  660. * in the descriptor list.
  661. *
  662. * Handle versioning where one or more supertypes of
  663. * have been inserted or removed. The stack will
  664. * contain pairs of descriptors and the corresponding
  665. * class. If the object has a class that did not occur in
  666. * the original the descriptor will be null. If the
  667. * original object had a descriptor for a class not
  668. * present in the local hierarchy of the object the class will be
  669. * null.
  670. *
  671. */
  672. /*
  673. * This is your basic diff pattern, made simpler
  674. * because reordering is not allowed.
  675. */
  676. // sun.4296963 ibm.11861
  677. // d11861 we should stop when we find the highest serializable class
  678. // We need this so that when we allocate the new object below, we
  679. // can call the constructor of the non-serializable superclass.
  680. // Note that in the JRMP variant of this code the
  681. // ObjectStreamClass.lookup() method handles this, but we've put
  682. // this fix here rather than change lookup because the new behaviour
  683. // is needed in other cases.
  684. for (currdesc = currentClassDesc, currclass = currentClass;
  685. currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
  686. currdesc = currdesc.getSuperclass()) {
  687. /*
  688. * Search the classes to see if the class of this
  689. * descriptor appears further up the hierarchy. Until
  690. * it's found assume its an inserted class. If it's
  691. * not found, its the descriptor's class that has been
  692. * removed.
  693. */
  694. Class cc = currdesc.forClass();
  695. Class cl;
  696. for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  697. if (cc == cl) {
  698. // found a superclass that matches this descriptor
  699. break;
  700. } else {
  701. /* Ignore a class that doesn't match. No
  702. * action is needed since it is already
  703. * initialized.
  704. */
  705. }
  706. } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  707. /* Test if there is room for this new entry.
  708. * If not, double the size of the arrays and copy the contents.
  709. */
  710. spClass++;
  711. if (spClass >= classes.length) {
  712. int newlen = classes.length * 2;
  713. Class[] newclasses = new Class[newlen];
  714. ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  715. System.arraycopy(classes, 0,
  716. newclasses, 0,
  717. classes.length);
  718. System.arraycopy(classdesc, 0,
  719. newclassdesc, 0,
  720. classes.length);
  721. classes = newclasses;
  722. classdesc = newclassdesc;
  723. }
  724. if (cl == null) {
  725. /* Class not found corresponding to this descriptor.
  726. * Pop off all the extra classes pushed.
  727. * Push the descriptor and a null class.
  728. */
  729. classdesc[spClass] = currdesc;
  730. classes[spClass] = null;
  731. } else {
  732. /* Current class descriptor matches current class.
  733. * Some classes may have been inserted.
  734. * Record the match and advance the class, continue
  735. * with the next descriptor.
  736. */
  737. classdesc[spClass] = currdesc;
  738. classes[spClass] = cl;
  739. currclass = cl.getSuperclass();
  740. }
  741. } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  742. /* Allocate a new object. The object is only constructed
  743. * above the highest serializable class and is set to
  744. * default values for all more specialized classes.
  745. */
  746. try {
  747. currentObject = (currentClass == null) ?
  748. null : allocateNewObject(currentClass, currclass);
  749. // Store this object and its beginning position
  750. // since there might be indirections to it while
  751. // it's been unmarshalled.
  752. activeRecursionMgr.addObject(offset, currentObject);
  753. } catch (NoSuchMethodError e) {
  754. throw new InvalidClassException(currclass.getName(),
  755. "NoSuchMethodError accessing no-arg constructor");
  756. } catch (IllegalAccessException e) {
  757. throw new InvalidClassException(currclass.getName(),
  758. "IllegalAccessException");
  759. } catch (InstantiationException e) {
  760. throw new InvalidClassException("UNKNOWN",//currclass.getName(),
  761. "InstantiationException");
  762. }
  763. /*
  764. * For all the pushed descriptors and classes.
  765. * if the class has its own writeObject and readObject methods
  766. * call the readObject method
  767. * else
  768. * invoke the defaultReadObject method
  769. */
  770. try {
  771. for (spClass = spClass; spClass > spBase; spClass--) {
  772. /*
  773. * Set current descriptor and corresponding class
  774. */
  775. currentClassDesc = classdesc[spClass];
  776. currentClass = classes[spClass];
  777. if (classes[spClass] != null) {
  778. /* Read the data from the stream described by the
  779. * descriptor and store into the matching class.
  780. */
  781. // Changed since invokeObjectReader no longer does this.
  782. if (currentClassDesc.hasWriteObject()) {
  783. // Read format version
  784. readByte();
  785. // Read defaultWriteObject indicator
  786. readBoolean();
  787. }
  788. if (!invokeObjectReader(currentClassDesc, currentObject, currentClass)) {
  789. ObjectStreamField[] fields =
  790. currentClassDesc.getFieldsNoCopy();
  791. if (fields.length > 0) {
  792. inputClassFields(currentObject, currentClass, fields, sender);
  793. }
  794. }
  795. } else {
  796. // _REVISIT_ : Can we ever get here?
  797. /* No local class for this descriptor,
  798. * Skip over the data for this class.
  799. * like defaultReadObject with a null currentObject.
  800. * The code will read the values but discard them.
  801. */
  802. ObjectStreamField[] fields =
  803. currentClassDesc.getFieldsNoCopy();
  804. if (fields.length > 0) {
  805. inputClassFields(null, currentClass, fields, sender);
  806. }
  807. }
  808. }
  809. } finally {
  810. // Make sure we exit at the same stack level as when we started.
  811. spClass = spBase;
  812. }
  813. }
  814. } finally {
  815. // We've completed deserializing this object. Any
  816. // future indirections will be handled correctly at the
  817. // CDR level. The ActiveRecursionManager only deals with
  818. // objects currently being deserialized.
  819. activeRecursionMgr.removeObject(offset);
  820. }
  821. return currentObject;
  822. }
  823. // This retrieves a vector of FVD's for the hierarchy of serializable classes stemming from
  824. // repositoryID. It is assumed that the sender will not provide base_value id's for non-serializable
  825. // classes!
  826. private Vector getOrderedDescriptions(String repositoryID,
  827. com.sun.org.omg.SendingContext.CodeBase sender) {
  828. Vector descs = new Vector();
  829. FullValueDescription aFVD = sender.meta(repositoryID);
  830. while (aFVD != null) {
  831. descs.insertElementAt(aFVD, 0);
  832. if ((aFVD.base_value != null) && !kEmptyStr.equals(aFVD.base_value)) {
  833. aFVD = sender.meta(aFVD.base_value);
  834. }
  835. else return descs;
  836. }
  837. return descs;
  838. }
  839. /**
  840. * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  841. * read in the data. This method is capable of throwing out data not applicable to client's fields.
  842. * This method handles instances where the reader has a class not sent by the sender, the sender sent
  843. * a class not present on the reader, and/or the reader's class does not match the sender's class.
  844. *
  845. * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  846. * indicates custom marsahling than the local type is used to read the data off the wire. However,
  847. * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
  848. * a form of custom marshaling.
  849. *
  850. */
  851. private Object inputObjectUsingFVD(Class clz,
  852. String repositoryID,
  853. com.sun.org.omg.SendingContext.CodeBase sender,
  854. int offset)
  855. throws IOException, ClassNotFoundException
  856. {
  857. int spBase = spClass; // current top of stack
  858. try{
  859. /*
  860. * Get the descriptor and then class of the incoming object.
  861. */
  862. ObjectStreamClass currdesc = currentClassDesc = ObjectStreamClass.lookup(clz);
  863. Class currclass = currentClass = clz;
  864. /* If Externalizable,
  865. * Create an instance and tell it to read its data.
  866. * else,
  867. * Handle it as a serializable class.
  868. */
  869. if (currentClassDesc.isExternalizable()) {
  870. try {
  871. currentObject = (currentClass == null) ?
  872. null : allocateNewObject(currentClass, currentClass);
  873. if (currentObject != null) {
  874. // Store this object and its beginning position
  875. // since there might be indirections to it while
  876. // it's been unmarshalled.
  877. activeRecursionMgr.addObject(offset, currentObject);
  878. // Read format version
  879. readByte();
  880. Externalizable ext = (Externalizable)currentObject;
  881. ext.readExternal(this);
  882. }
  883. }
  884. catch (NoSuchMethodError e) {
  885. throw new InvalidClassException(currentClass.getName(),
  886. "NoSuchMethodError accessing no-arg constructor");
  887. }
  888. catch (IllegalAccessException e) {
  889. throw new InvalidClassException(currentClass.getName(),
  890. "IllegalAccessException");
  891. }
  892. catch (InstantiationException e) {
  893. throw new InvalidClassException(currentClass.getName(),
  894. "InstantiationException");
  895. }
  896. } // end : if (currentClassDesc.isExternalizable())
  897. else {
  898. /*
  899. * This is your basic diff pattern, made simpler
  900. * because reordering is not allowed.
  901. */
  902. for (currdesc = currentClassDesc, currclass = currentClass;
  903. currdesc != null && currdesc.isSerializable(); /*sun.4296963 ibm.11861*/
  904. currdesc = currdesc.getSuperclass()) {
  905. /*
  906. * Search the classes to see if the class of this
  907. * descriptor appears further up the hierarchy. Until
  908. * it's found assume its an inserted class. If it's
  909. * not found, its the descriptor's class that has been
  910. * removed.
  911. */
  912. Class cc = currdesc.forClass();
  913. Class cl;
  914. for (cl = currclass; cl != null; cl = cl.getSuperclass()) {
  915. if (cc == cl) {
  916. // found a superclass that matches this descriptor
  917. break;
  918. } else {
  919. /* Ignore a class that doesn't match. No
  920. * action is needed since it is already
  921. * initialized.
  922. */
  923. }
  924. } // end : for (cl = currclass; cl != null; cl = cl.getSuperclass())
  925. /* Test if there is room for this new entry.
  926. * If not, double the size of the arrays and copy the contents.
  927. */
  928. spClass++;
  929. if (spClass >= classes.length) {
  930. int newlen = classes.length * 2;
  931. Class[] newclasses = new Class[newlen];
  932. ObjectStreamClass[] newclassdesc = new ObjectStreamClass[newlen];
  933. System.arraycopy(classes, 0,
  934. newclasses, 0,
  935. classes.length);
  936. System.arraycopy(classdesc, 0,
  937. newclassdesc, 0,
  938. classes.length);
  939. classes = newclasses;
  940. classdesc = newclassdesc;
  941. }
  942. if (cl == null) {
  943. /* Class not found corresponding to this descriptor.
  944. * Pop off all the extra classes pushed.
  945. * Push the descriptor and a null class.
  946. */
  947. classdesc[spClass] = currdesc;
  948. classes[spClass] = null;
  949. } else {
  950. /* Current class descriptor matches current class.
  951. * Some classes may have been inserted.
  952. * Record the match and advance the class, continue
  953. * with the next descriptor.
  954. */
  955. classdesc[spClass] = currdesc;
  956. classes[spClass] = cl;
  957. currclass = cl.getSuperclass();
  958. }
  959. } // end : for (currdesc = currentClassDesc, currclass = currentClass;
  960. /* Allocate a new object.
  961. */
  962. try {
  963. currentObject = (currentClass == null) ?
  964. null : allocateNewObject(currentClass, currclass);
  965. // Store this object and its beginning position
  966. // since there might be indirections to it while
  967. // it's been unmarshalled.
  968. activeRecursionMgr.addObject(offset, currentObject);
  969. } catch (NoSuchMethodError e) {
  970. throw new InvalidClassException(currclass.getName(),
  971. "NoSuchMethodError accessing no-arg constructor");
  972. } catch (IllegalAccessException e) {
  973. throw new InvalidClassException(currclass.getName(),
  974. "IllegalAccessException");
  975. } catch (InstantiationException e) {
  976. throw new InvalidClassException(currclass.getName(),
  977. "InstantiationException");
  978. }
  979. Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  980. while((fvdsList.hasMoreElements()) && (spClass > spBase)) {
  981. FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  982. // d4365188: backward compatability
  983. String repIDForFVD = vhandler.getClassName(fvd.id);
  984. String repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  985. while ((spClass > spBase) &&
  986. (!repIDForFVD.equals(repIDForClass))) {
  987. int pos = findNextClass(repIDForFVD, classes, spClass, spBase);
  988. if (pos != -1){
  989. spClass = pos;
  990. currclass = currentClass = classes[spClass];
  991. repIDForClass = vhandler.getClassName(vhandler.getRMIRepositoryID(currentClass));
  992. }
  993. else { // Read and throw away one level of the fvdslist
  994. if (fvd.is_custom) {
  995. // Is this actually an error? REVISIT
  996. throw new IOException("Remote superclass is custom marshalled: "
  997. + fvd.id);
  998. } else {
  999. inputClassFields(null, currentClass, null, fvd.members, sender);
  1000. }
  1001. if (fvdsList.hasMoreElements()){
  1002. fvd = (FullValueDescription)fvdsList.nextElement();
  1003. repIDForFVD = vhandler.getClassName(fvd.id);
  1004. }
  1005. else return currentObject;
  1006. }
  1007. }
  1008. currdesc = currentClassDesc = ObjectStreamClass.lookup(currentClass);
  1009. if (!repIDForClass.equals("java.lang.Object")) {
  1010. // If the sender used custom marshaling, then it should have put
  1011. // these two bytes on the wire. Currently, we don't do anything
  1012. // with these, but that has to change at some point.
  1013. if (fvd.is_custom) {
  1014. // Read format version
  1015. readByte();
  1016. // Read defaultWriteObject indicator
  1017. readBoolean();
  1018. }
  1019. // Always use readObject if it exists, and fall back to default
  1020. // unmarshaling if it doesn't.
  1021. boolean usedReadObject = false;
  1022. try {
  1023. // See the definition of defaultReadObjectFVDMembers
  1024. // for more information. This concerns making sure
  1025. // we use the remote FVD's members in defaultReadObject.
  1026. defaultReadObjectFVDMembers = fvd.members;
  1027. usedReadObject = invokeObjectReader(currentClassDesc,
  1028. currentObject,
  1029. currentClass);
  1030. } finally {
  1031. defaultReadObjectFVDMembers = null;
  1032. }
  1033. if (!usedReadObject)
  1034. inputClassFields(currentObject, currentClass, currdesc, fvd.members, sender);
  1035. currclass = currentClass = classes[--spClass];
  1036. } else {
  1037. // The remaining hierarchy of the local class does not match the sender's FVD.
  1038. // So, use remaining FVDs to read data off wire. If any remaining FVDs indicate
  1039. // custom marshaling, throw MARSHAL error.
  1040. inputClassFields(null, currentClass, null, fvd.members, sender);
  1041. while (fvdsList.hasMoreElements()){
  1042. fvd = (FullValueDescription)fvdsList.nextElement();
  1043. if (fvd.is_custom)
  1044. throw new IOException("Sender's custom marshaling class does not match local class: " + fvd.id);
  1045. else inputClassFields(null, currentClass, null, fvd.members, sender);
  1046. }
  1047. }
  1048. } // end : while(fvdsList.hasMoreElements())
  1049. while (fvdsList.hasMoreElements()){
  1050. FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1051. if (fvd.is_custom)
  1052. throw new IOException("Sender's custom marshaling class does not match local class: " + fvd.id);
  1053. else throwAwayData(fvd.members, sender);
  1054. }
  1055. }
  1056. return currentObject;
  1057. }
  1058. finally {
  1059. // Make sure we exit at the same stack level as when we started.
  1060. spClass = spBase;
  1061. // We've completed deserializing this object. Any
  1062. // future indirections will be handled correctly at the
  1063. // CDR level. The ActiveRecursionManager only deals with
  1064. // objects currently being deserialized.
  1065. activeRecursionMgr.removeObject(offset);
  1066. }
  1067. }
  1068. /**
  1069. * This input method uses FullValueDescriptions retrieved from the sender's runtime to
  1070. * read in the data. This method is capable of throwing out data not applicable to client's fields.
  1071. *
  1072. * NOTE : If the local description indicates custom marshaling and the remote type's FVD also
  1073. * indicates custom marsahling than the local type is used to read the data off the wire. However,
  1074. * if either says custom while the other does not, a MARSHAL error is thrown. Externalizable is
  1075. * a form of custom marshaling.
  1076. *
  1077. */
  1078. private Object skipObjectUsingFVD(String repositoryID,
  1079. com.sun.org.omg.SendingContext.CodeBase sender)
  1080. throws IOException, ClassNotFoundException
  1081. {
  1082. Enumeration fvdsList = getOrderedDescriptions(repositoryID, sender).elements();
  1083. while(fvdsList.hasMoreElements()) {
  1084. FullValueDescription fvd = (FullValueDescription)fvdsList.nextElement();
  1085. String repIDForFVD = vhandler.getClassName(fvd.id);
  1086. if (!repIDForFVD.equals("java.lang.Object")) {
  1087. if (fvd.is_custom) {
  1088. throw new IOException("Can't skip sender's custom marshaled class: "
  1089. + fvd.id);
  1090. }
  1091. else {
  1092. // Use default marshaling
  1093. inputClassFields(null, null, null, fvd.members, sender);
  1094. }
  1095. }
  1096. } // end : while(fvdsList.hasMoreElements())
  1097. return null;
  1098. }
  1099. ///////////////////
  1100. private int findNextClass(String classname, Class classes[], int _spClass, int _spBase){
  1101. for (int i = _spClass; i > _spBase; i--){
  1102. if (classname.equals(classes[i].getName())) {
  1103. return i;
  1104. }
  1105. }
  1106. return -1;
  1107. }
  1108. /*
  1109. * Invoke the readObject method if present. Assumes that in the case of custom
  1110. * marshaling, the format version and defaultWriteObject indicator were already
  1111. * removed.
  1112. */
  1113. private boolean invokeObjectReader(ObjectStreamClass osc, Object obj, Class aclass)
  1114. throws InvalidClassException, StreamCorruptedException,
  1115. ClassNotFoundException, IOException
  1116. {
  1117. if (osc.readObjectMethod == null) {
  1118. return false;
  1119. }
  1120. try {
  1121. readObject(obj, aclass, this);
  1122. return true;
  1123. } catch (InvocationTargetException e) {
  1124. Throwable t = e.getTargetException();
  1125. if (t instanceof ClassNotFoundException)
  1126. throw (ClassNotFoundException)t;
  1127. else if (t instanceof IOException)
  1128. throw (IOException)t;
  1129. else if (t instanceof RuntimeException)
  1130. throw (RuntimeException) t;
  1131. else if (t instanceof Error)
  1132. throw (Error) t;
  1133. else
  1134. throw new Error("interal error");
  1135. } catch (IllegalAccessException e) {
  1136. return false;
  1137. }
  1138. }
  1139. /*
  1140. * Reset the stream to be just like it was after the constructor.
  1141. */
  1142. private void resetStream() throws IOException {
  1143. if (classes == null)
  1144. classes = new Class[20];
  1145. else {
  1146. for (int i = 0; i < classes.length; i++)
  1147. classes[i] = null;
  1148. }
  1149. if (classdesc == null)
  1150. classdesc = new ObjectStreamClass[20];
  1151. else {
  1152. for (int i = 0; i < classdesc.length; i++)
  1153. classdesc[i] = null;
  1154. }
  1155. spClass = 0;
  1156. if (callbacks != null)
  1157. callbacks.setSize(0); // discard any pending callbacks
  1158. }
  1159. /**
  1160. * Factored out of inputClassFields This reads a primitive value and sets it
  1161. * (with a native call) in the field of o described by the ObjectStreamField
  1162. * field.
  1163. */
  1164. private void inputPrimitiveField(Object o, Class cl, ObjectStreamField field)
  1165. throws InvalidClassException, IOException {
  1166. try {
  1167. switch (field.getTypeCode()) {
  1168. case 'B':
  1169. byte byteValue = orbStream.read_octet();
  1170. setByteFieldOpt(o, field.getFieldID(cl), byteValue);
  1171. break;
  1172. case 'Z':
  1173. boolean booleanValue = orbStream.read_boolean();
  1174. setBooleanFieldOpt(o, field.getFieldID(cl), booleanValue);
  1175. break;
  1176. case 'C':
  1177. char charValue = orbStream.read_wchar();
  1178. setCharFieldOpt(o, field.getFieldID(cl), charValue);
  1179. break;
  1180. case 'S':
  1181. short shortValue = orbStream.read_short();
  1182. setShortFieldOpt(o, field.getFieldID(cl), shortValue);
  1183. break;
  1184. case 'I':
  1185. int intValue = orbStream.read_long();
  1186. setIntFieldOpt(o, field.getFieldID(cl), intValue);
  1187. break;
  1188. case 'J':
  1189. long longValue = orbStream.read_longlong();
  1190. setLongFieldOpt(o, field.getFieldID(cl), longValue);
  1191. break;
  1192. case 'F' :
  1193. float floatValue = orbStream.read_float();
  1194. setFloatFieldOpt(o, field.getFieldID(cl), floatValue);
  1195. break;
  1196. case 'D' :
  1197. double doubleValue = orbStream.read_double();
  1198. setDoubleFieldOpt(o, field.getFieldID(cl), doubleValue);
  1199. break;
  1200. default:
  1201. throw new InvalidClassException(cl.getName());
  1202. }
  1203. } catch (IllegalArgumentException e) {
  1204. /* This case should never happen. If the field types
  1205. are not the same, InvalidClassException is raised when
  1206. matching the local class to the serialized ObjectStreamClass. */
  1207. throw new ClassCastException("Assigning instance of class " +
  1208. field.getType().getName() +
  1209. " to field " +
  1210. currentClassDesc.getName() + '#' +
  1211. field.getField().getName());
  1212. }
  1213. }
  1214. private Object inputObjectField(org.omg.CORBA.ValueMember field,
  1215. com.sun.org.omg.SendingContext.CodeBase sender)
  1216. throws IndirectionException, ClassNotFoundException, IOException,
  1217. StreamCorruptedException {
  1218. Object objectValue = null;
  1219. Class type = null;
  1220. String id = field.id;
  1221. try {
  1222. type = vhandler.getClassFromType(id);
  1223. } catch(ClassNotFoundException cnfe) {
  1224. // Make sure type = null
  1225. type = null;
  1226. }
  1227. String signature = null;
  1228. if (type != null)
  1229. signature = ValueUtility.getSignature(field);
  1230. if (signature != null && (signature.equals("Ljava/lang/Object;") ||
  1231. signature.equals("Ljava/io/Serializable;") ||
  1232. signature.equals("Ljava/io/Externalizable;"))) {
  1233. objectValue = javax.rmi.CORBA.Util.readAny(orbStream);
  1234. } else {
  1235. // Decide what method call to make based on the type. If
  1236. // it is a type for which we need to load a stub, convert
  1237. // the type to the correct stub type.
  1238. //
  1239. // NOTE : Since FullValueDescription does not allow us
  1240. // to ask whether something is an interface we do not
  1241. // have the ability to optimize this check.
  1242. int callType = ValueHandlerImpl.kValueType;
  1243. if (!vhandler.isSequence(id)) {
  1244. if (field.type.kind().value() == kRemoteTypeCode.kind().value()) {
  1245. // RMI Object reference...
  1246. callType = ValueHandlerImpl.kRemoteType;
  1247. } else {
  1248. // REVISIT. If we don't have the local class,
  1249. // we should probably verify that it's an RMI type,
  1250. // query the remote FVD, and use is_abstract.
  1251. // Our FVD seems to get NullPointerExceptions for any
  1252. // non-RMI types.
  1253. // This uses the local class in the same way as
  1254. // inputObjectField(ObjectStreamField) does. REVISIT
  1255. // inputObjectField(ObjectStreamField)'s loadStubClass
  1256. // logic. Assumption is that the given type cannot
  1257. // evolve to become a CORBA abstract interface or
  1258. // a RMI abstract interface.
  1259. if (type != null && type.isInterface() &&
  1260. (vhandler.isAbstractBase(type) ||
  1261. ObjectStreamClassCorbaExt.isAbstractInterface(type))) {
  1262. callType = ValueHandlerImpl.kAbstractType;
  1263. }
  1264. }
  1265. }
  1266. // Now that we have used the FVD of the field to determine the proper course
  1267. // of action, it is ok to use the type (Class) from this point forward since
  1268. // the rep. id for this read will also follow on the wire.
  1269. switch (callType) {
  1270. case ValueHandlerImpl.kRemoteType:
  1271. if (type != null)
  1272. objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1273. else
  1274. objectValue = orbStream.read_Object();
  1275. break;
  1276. case ValueHandlerImpl.kAbstractType:
  1277. if (type != null)
  1278. objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1279. else
  1280. objectValue = orbStream.read_abstract_interface();
  1281. break;
  1282. case ValueHandlerImpl.kValueType:
  1283. if (type != null)
  1284. objectValue = orbStream.read_value(type);
  1285. else
  1286. objectValue = orbStream.read_value();
  1287. break;
  1288. default:
  1289. throw new StreamCorruptedException("Unknown callType: " + callType);
  1290. }
  1291. }
  1292. return objectValue;
  1293. }
  1294. /**
  1295. * Factored out of inputClassFields and reused in
  1296. * inputCurrentClassFieldsForReadFields.
  1297. *
  1298. * Reads the field (which of an Object type as opposed to a primitive)
  1299. * described by ObjectStreamField field and returns it.
  1300. */
  1301. private Object inputObjectField(ObjectStreamField field)
  1302. throws InvalidClassException, StreamCorruptedException,
  1303. ClassNotFoundException, IndirectionException, IOException {
  1304. if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
  1305. return javax.rmi.CORBA.Util.readAny(orbStream);
  1306. }
  1307. Object objectValue = null;
  1308. // fields have an API to provide the actual class
  1309. // corresponding to the data type
  1310. // Class type = osc.forClass();
  1311. Class type = field.getType();
  1312. // Decide what method call to make based on the type. If
  1313. // it is a type for which we need to load a stub, convert
  1314. // the type to the correct stub type.
  1315. int callType = ValueHandlerImpl.kValueType;
  1316. boolean narrow = false;
  1317. if (type.isInterface()) {
  1318. boolean loadStubClass = false;
  1319. if (java.rmi.Remote.class.isAssignableFrom(type)) {
  1320. // RMI Object reference...
  1321. callType = ValueHandlerImpl.kRemoteType;
  1322. } else if (org.omg.CORBA.Object.class.isAssignableFrom(type)){
  1323. // IDL Object reference...
  1324. callType = ValueHandlerImpl.kRemoteType;
  1325. loadStubClass = true;
  1326. } else if (vhandler.isAbstractBase(type)) {
  1327. // IDL Abstract Object reference...
  1328. callType = ValueHandlerImpl.kAbstractType;
  1329. loadStubClass = true;
  1330. } else if (ObjectStreamClassCorbaExt.isAbstractInterface(type)) {
  1331. // RMI Abstract Object reference...
  1332. callType = ValueHandlerImpl.kAbstractType;
  1333. }
  1334. if (loadStubClass) {
  1335. try {
  1336. String codebase = Util.getCodebase(type);
  1337. String repID = vhandler.createForAnyType(type);
  1338. type = Utility.loadStubClass(repID, codebase, type); //d11638
  1339. } catch (ClassNotFoundException e) {
  1340. narrow = true;
  1341. }
  1342. } else {
  1343. narrow = true;
  1344. }
  1345. }
  1346. switch (callType) {
  1347. case ValueHandlerImpl.kRemoteType:
  1348. if (!narrow)
  1349. objectValue = (Object)orbStream.read_Object(type);
  1350. else
  1351. objectValue = Utility.readObjectAndNarrow(orbStream, type);
  1352. break;
  1353. case ValueHandlerImpl.kAbstractType:
  1354. if (!narrow)
  1355. objectValue = (Object)orbStream.read_abstract_interface(type);
  1356. else
  1357. objectValue = Utility.readAbstractAndNarrow(orbStream, type);
  1358. break;
  1359. case ValueHandlerImpl.kValueType:
  1360. objectValue = (Object)orbStream.read_value(type);
  1361. break;
  1362. default:
  1363. throw new StreamCorruptedException("Unknown callType: " + callType);
  1364. }
  1365. return objectValue;
  1366. }
  1367. private final boolean mustUseRemoteValueMembers() {
  1368. return defaultReadObjectFVDMembers != null;
  1369. }
  1370. void readFields(java.util.Map fieldToValueMap)
  1371. throws InvalidClassException, StreamCorruptedException,
  1372. ClassNotFoundException, IOException {
  1373. if (mustUseRemoteValueMembers()) {
  1374. inputRemoteMembersForReadFields(fieldToValueMap);
  1375. } else
  1376. inputCurrentClassFieldsForReadFields(fieldToValueMap);
  1377. }
  1378. private final void inputRemoteMembersForReadFields(java.util.Map fieldToValueMap)
  1379. throws InvalidClassException, StreamCorruptedException,
  1380. ClassNotFoundException, IOException {
  1381. // Must have this local variable since defaultReadObjectFVDMembers
  1382. // may get mangled by recursion.
  1383. ValueMember fields[] = defaultReadObjectFVDMembers;
  1384. try {
  1385. for (int i = 0; i < fields.length; i++) {
  1386. switch (fields[i].type.kind().value()) {
  1387. case TCKind._tk_octet:
  1388. byte byteValue = orbStream.read_octet();
  1389. fieldToValueMap.put(fields[i].name, new Byte(byteValue));
  1390. break;
  1391. case TCKind._tk_boolean:
  1392. boolean booleanValue = orbStream.read_boolean();
  1393. fieldToValueMap.put(fields[i].name, new Boolean(booleanValue));
  1394. break;
  1395. case TCKind._tk_char:
  1396. // Backwards compatibility. Older Sun ORBs sent
  1397. // _tk_char even though they read and wrote wchars
  1398. // correctly.
  1399. //
  1400. // Fall through to the _tk_wchar case.
  1401. case TCKind._tk_wchar:
  1402. char charValue = orbStream.read_wchar();
  1403. fieldToValueMap.put(fields[i].name, new Character(charValue));
  1404. break;
  1405. case TCKind._tk_short:
  1406. short shortValue = orbStream.read_short();
  1407. fieldToValueMap.put(fields[i].name, new Short(shortValue));
  1408. break;
  1409. case TCKind._tk_long:
  1410. int intValue = orbStream.read_long();
  1411. fieldToValueMap.put(fields[i].name, new Integer(intValue));
  1412. break;
  1413. case TCKind._tk_longlong:
  1414. long longValue = orbStream.read_longlong();
  1415. fieldToValueMap.put(fields[i].name, new Long(longValue));
  1416. break;
  1417. case TCKind._tk_float:
  1418. float floatValue = orbStream.read_float();
  1419. fieldToValueMap.put(fields[i].name, new Float(floatValue));
  1420. break;
  1421. case TCKind._tk_double:
  1422. double doubleValue = orbStream.read_double();
  1423. fieldToValueMap.put(fields[i].name, new Double(doubleValue));
  1424. break;
  1425. case TCKind._tk_value:
  1426. case TCKind._tk_objref:
  1427. case TCKind._tk_value_box:
  1428. Object objectValue = null;
  1429. try {
  1430. objectValue = inputObjectField(fields[i],
  1431. cbSender);
  1432. } catch (IndirectionException cdrie) {
  1433. // The CDR stream had never seen the given offset before,
  1434. // so check the recursion manager (it will throw an
  1435. // IOException if it doesn't have a reference, either).
  1436. objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1437. }
  1438. fieldToValueMap.put(fields[i].name, objectValue);
  1439. break;
  1440. default:
  1441. throw new StreamCorruptedException("Unknown kind: "
  1442. + fields[i].type.kind().value());
  1443. }
  1444. }
  1445. } catch (Throwable t) {
  1446. throw new StreamCorruptedException(t.getMessage());
  1447. }
  1448. }
  1449. /**
  1450. * Called from InputStreamHook.
  1451. *
  1452. * Reads the fields of the current class (could be the ones
  1453. * queried from the remote FVD) and puts them in
  1454. * the given Map, name to value. Wraps primitives in the
  1455. * corresponding java.lang Objects.
  1456. */
  1457. private final void inputCurrentClassFieldsForReadFields(java.util.Map fieldToValueMap)
  1458. throws InvalidClassException, StreamCorruptedException,
  1459. ClassNotFoundException, IOException {
  1460. ObjectStreamField[] fields = currentClassDesc.getFieldsNoCopy();
  1461. int primFields = fields.length - currentClassDesc.objFields;
  1462. // Handle the primitives first
  1463. for (int i = 0; i < primFields; ++i) {
  1464. switch (fields[i].getTypeCode()) {
  1465. case 'B':
  1466. byte byteValue = orbStream.read_octet();
  1467. fieldToValueMap.put(fields[i].getName(),
  1468. new Byte(byteValue));
  1469. break;
  1470. case 'Z':
  1471. boolean booleanValue = orbStream.read_boolean();
  1472. fieldToValueMap.put(fields[i].getName(),
  1473. new Boolean(booleanValue));
  1474. break;
  1475. case 'C':
  1476. char charValue = orbStream.read_wchar();
  1477. fieldToValueMap.put(fields[i].getName(),
  1478. new Character(charValue));
  1479. break;
  1480. case 'S':
  1481. short shortValue = orbStream.read_short();
  1482. fieldToValueMap.put(fields[i].getName(),
  1483. new Short(shortValue));
  1484. break;
  1485. case 'I':
  1486. int intValue = orbStream.read_long();
  1487. fieldToValueMap.put(fields[i].getName(),
  1488. new Integer(intValue));
  1489. break;
  1490. case 'J':
  1491. long longValue = orbStream.read_longlong();
  1492. fieldToValueMap.put(fields[i].getName(),
  1493. new Long(longValue));
  1494. break;
  1495. case 'F' :
  1496. float floatValue = orbStream.read_float();
  1497. fieldToValueMap.put(fields[i].getName(),
  1498. new Float(floatValue));
  1499. break;
  1500. case 'D' :
  1501. double doubleValue = orbStream.read_double();
  1502. fieldToValueMap.put(fields[i].getName(),
  1503. new Double(doubleValue));
  1504. break;
  1505. default:
  1506. throw new InvalidClassException(currentClassDesc.getName());
  1507. }
  1508. }
  1509. /* Read and set object fields from the input stream. */
  1510. if (currentClassDesc.objFields > 0) {
  1511. for (int i = primFields; i < fields.length; i++) {
  1512. Object objectValue = null;
  1513. try {
  1514. objectValue = inputObjectField(fields[i]);
  1515. } catch(IndirectionException cdrie) {
  1516. // The CDR stream had never seen the given offset before,
  1517. // so check the recursion manager (it will throw an
  1518. // IOException if it doesn't have a reference, either).
  1519. objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1520. }
  1521. fieldToValueMap.put(fields[i].getName(), objectValue);
  1522. }
  1523. }
  1524. }
  1525. /*
  1526. * Read the fields of the specified class from the input stream and set
  1527. * the values of the fields in the specified object. If the specified
  1528. * object is null, just consume the fields without setting any values. If
  1529. * any ObjectStreamField does not have a reflected Field, don't try to set
  1530. * that field in the object.
  1531. *
  1532. * REVISIT -- This code doesn't do what the comment says to when
  1533. * getField() is null!
  1534. */
  1535. private void inputClassFields(Object o, Class cl,
  1536. ObjectStreamField[] fields,
  1537. com.sun.org.omg.SendingContext.CodeBase sender)
  1538. throws InvalidClassException, StreamCorruptedException,
  1539. ClassNotFoundException, IOException
  1540. {
  1541. int primFields = fields.length - currentClassDesc.objFields;
  1542. if (o != null) {
  1543. for (int i = 0; i < primFields; ++i) {
  1544. if (fields[i].getField() == null)
  1545. continue;
  1546. inputPrimitiveField(o, cl, fields[i]);
  1547. }
  1548. }
  1549. /* Read and set object fields from the input stream. */
  1550. if (currentClassDesc.objFields > 0) {
  1551. for (int i = primFields; i < fields.length; i++) {
  1552. Object objectValue = null;
  1553. try {
  1554. objectValue = inputObjectField(fields[i]);
  1555. } catch(IndirectionException cdrie) {
  1556. // The CDR stream had never seen the given offset before,
  1557. // so check the recursion manager (it will throw an
  1558. // IOException if it doesn't have a reference, either).
  1559. objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1560. }
  1561. if ((o == null) || (fields[i].getField() == null)) {
  1562. continue;
  1563. }
  1564. try {
  1565. setObjectFieldOpt(o, fields[i].getFieldID(cl), objectValue);
  1566. } catch (IllegalArgumentException e) {
  1567. throw new ClassCastException("Assigning instance of class " +
  1568. objectValue.getClass().getName() +
  1569. " to field " +
  1570. currentClassDesc.getName() +
  1571. '#' +
  1572. fields[i].getField().getName());
  1573. }
  1574. } // end : for loop
  1575. }
  1576. }
  1577. /*
  1578. * Read the fields of the specified class from the input stream and set
  1579. * the values of the fields in the specified object. If the specified
  1580. * object is null, just consume the fields without setting any values. If
  1581. * any ObjectStreamField does not have a reflected Field, don't try to set
  1582. * that field in the object.
  1583. */
  1584. private void inputClassFields(Object o, Class cl,
  1585. ObjectStreamClass osc,
  1586. ValueMember[] fields,
  1587. com.sun.org.omg.SendingContext.CodeBase sender)
  1588. throws InvalidClassException, StreamCorruptedException,
  1589. ClassNotFoundException, IOException
  1590. {
  1591. try{
  1592. for (int i = 0; i < fields.length; ++i) {
  1593. try {
  1594. switch (fields[i].type.kind().value()) {
  1595. case TCKind._tk_octet:
  1596. byte byteValue = orbStream.read_octet();
  1597. if ((o != null) && osc.hasField(fields[i]))
  1598. setByteField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), byteValue);
  1599. break;
  1600. case TCKind._tk_boolean:
  1601. boolean booleanValue = orbStream.read_boolean();
  1602. if ((o != null) && osc.hasField(fields[i]))
  1603. setBooleanField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), booleanValue);
  1604. break;
  1605. case TCKind._tk_char:
  1606. // Backwards compatibility. Older Sun ORBs sent
  1607. // _tk_char even though they read and wrote wchars
  1608. // correctly.
  1609. //
  1610. // Fall through to the _tk_wchar case.
  1611. case TCKind._tk_wchar:
  1612. char charValue = orbStream.read_wchar();
  1613. if ((o != null) && osc.hasField(fields[i]))
  1614. setCharField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), charValue);
  1615. break;
  1616. case TCKind._tk_short:
  1617. short shortValue = orbStream.read_short();
  1618. if ((o != null) && osc.hasField(fields[i]))
  1619. setShortField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), shortValue);
  1620. break;
  1621. case TCKind._tk_long:
  1622. int intValue = orbStream.read_long();
  1623. if ((o != null) && osc.hasField(fields[i]))
  1624. setIntField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), intValue);
  1625. break;
  1626. case TCKind._tk_longlong:
  1627. long longValue = orbStream.read_longlong();
  1628. if ((o != null) && osc.hasField(fields[i]))
  1629. setLongField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), longValue);
  1630. break;
  1631. case TCKind._tk_float:
  1632. float floatValue = orbStream.read_float();
  1633. if ((o != null) && osc.hasField(fields[i]))
  1634. setFloatField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), floatValue);
  1635. break;
  1636. case TCKind._tk_double:
  1637. double doubleValue = orbStream.read_double();
  1638. if ((o != null) && osc.hasField(fields[i]))
  1639. setDoubleField(o, cl, fields[i].name, ValueUtility.getSignature(fields[i]), doubleValue);
  1640. break;
  1641. case TCKind._tk_value:
  1642. case TCKind._tk_objref:
  1643. case TCKind._tk_value_box:
  1644. Object objectValue = null;
  1645. try {
  1646. objectValue = inputObjectField(fields[i], sender);
  1647. } catch (IndirectionException cdrie) {
  1648. // The CDR stream had never seen the given offset before,
  1649. // so check the recursion manager (it will throw an
  1650. // IOException if it doesn't have a reference, either).
  1651. objectValue = activeRecursionMgr.getObject(cdrie.offset);
  1652. }
  1653. if (o == null)
  1654. continue;
  1655. try {
  1656. if (osc.hasField(fields[i])){
  1657. setObjectField(o,
  1658. cl,
  1659. fields[i].name,
  1660. ValueUtility.getSignature(fields[i]),
  1661. objectValue);
  1662. }
  1663. } catch (IllegalArgumentException e) {
  1664. throw new ClassCastException("Assigning instance of class " +
  1665. objectValue.getClass().getName() +
  1666. " to field " +
  1667. fields[i].name);
  1668. }
  1669. break;
  1670. default:
  1671. throw new StreamCorruptedException("Unknown kind: "
  1672. + fields[i].type.kind().value());
  1673. }
  1674. } catch (IllegalArgumentException e) {
  1675. /* This case should never happen. If the field types
  1676. are not the same, InvalidClassException is raised when
  1677. matching the local class to the serialized ObjectStreamClass. */
  1678. throw new ClassCastException("Assigning instance of class " +
  1679. fields[i].id +
  1680. " to field " +
  1681. currentClassDesc.getName() + '#' +
  1682. fields[i].name);
  1683. }
  1684. }
  1685. }
  1686. catch(Throwable t){
  1687. throw new StreamCorruptedException(t.getMessage());
  1688. }
  1689. }
  1690. /*
  1691. * Read the fields of the specified class from the input stream throw data away.
  1692. * This must handle same switch logic as above.
  1693. */
  1694. private void throwAwayData(ValueMember[] fields,
  1695. com.sun.org.omg.SendingContext.CodeBase sender)
  1696. throws InvalidClassException, StreamCorruptedException,
  1697. ClassNotFoundException, IOException
  1698. {
  1699. for (int i = 0; i < fields.length; ++i) {
  1700. try {
  1701. switch (fields[i].type.kind().value()) {
  1702. case TCKind._tk_octet:
  1703. orbStream.read_octet();
  1704. break;
  1705. case TCKind._tk_boolean:
  1706. orbStream.read_boolean();
  1707. break;
  1708. case TCKind._tk_char:
  1709. // Backwards compatibility. Older Sun ORBs sent
  1710. // _tk_char even though they read and wrote wchars
  1711. // correctly.
  1712. //
  1713. // Fall through to the _tk_wchar case.
  1714. case TCKind._tk_wchar:
  1715. orbStream.read_wchar();
  1716. break;
  1717. case TCKind._tk_short:
  1718. orbStream.read_short();
  1719. break;
  1720. case TCKind._tk_long:
  1721. orbStream.read_long();
  1722. break;
  1723. case TCKind._tk_longlong:
  1724. orbStream.read_longlong();
  1725. break;
  1726. case TCKind._tk_float:
  1727. orbStream.read_float();
  1728. break;
  1729. case TCKind._tk_double:
  1730. orbStream.read_double();
  1731. break;
  1732. case TCKind._tk_value:
  1733. case TCKind._tk_objref:
  1734. case TCKind._tk_value_box:
  1735. Class type = null;
  1736. String id = fields[i].id;
  1737. try {
  1738. type = vhandler.getClassFromType(id);
  1739. }
  1740. catch(ClassNotFoundException cnfe){
  1741. // Make sure type = null
  1742. type = null;
  1743. }
  1744. String signature = null;
  1745. if (type != null)
  1746. signature = ValueUtility.getSignature(fields[i]);
  1747. // Read value
  1748. try {
  1749. if ((signature != null) && ( signature.equals("Ljava/lang/Object;") ||
  1750. signature.equals("Ljava/io/Serializable;") ||
  1751. signature.equals("Ljava/io/Externalizable;")) ) {
  1752. javax.rmi.CORBA.Util.readAny(orbStream);
  1753. }
  1754. else {
  1755. // Decide what method call to make based on the type.
  1756. //
  1757. // NOTE : Since FullValueDescription does not allow us
  1758. // to ask whether something is an interface we do not
  1759. // have the ability to optimize this check.
  1760. int callType = ValueHandlerImpl.kValueType;
  1761. if (!vhandler.isSequence(id)) {
  1762. FullValueDescription fieldFVD = sender.meta(fields[i].id);
  1763. if (kRemoteTypeCode == fields[i].type) {
  1764. // RMI Object reference...
  1765. callType = ValueHandlerImpl.kRemoteType;
  1766. } else if (fieldFVD.is_abstract) {
  1767. // RMI Abstract Object reference...
  1768. callType = ValueHandlerImpl.kAbstractType;
  1769. }
  1770. }
  1771. // Now that we have used the FVD of the field to determine the proper course
  1772. // of action, it is ok to use the type (Class) from this point forward since
  1773. // the rep. id for this read will also follow on the wire.
  1774. switch (callType) {
  1775. case ValueHandlerImpl.kRemoteType:
  1776. orbStream.read_Object();
  1777. break;
  1778. case ValueHandlerImpl.kAbstractType:
  1779. orbStream.read_abstract_interface();
  1780. break;
  1781. case ValueHandlerImpl.kValueType:
  1782. if (type != null) {
  1783. orbStream.read_value(type);
  1784. } else {
  1785. orbStream.read_value();
  1786. }
  1787. break;
  1788. default:
  1789. throw new StreamCorruptedException("Unknown callType: "
  1790. + callType);
  1791. }
  1792. }
  1793. }
  1794. catch(IndirectionException cdrie) {
  1795. // Since we are throwing this away, don't bother handling recursion.
  1796. continue;
  1797. }
  1798. break;
  1799. default:
  1800. throw new StreamCorruptedException("Unknown kind: "
  1801. + fields[i].type.kind().value());
  1802. }
  1803. } catch (IllegalArgumentException e) {
  1804. /* This case should never happen. If the field types
  1805. are not the same, InvalidClassException is raised when
  1806. matching the local class to the serialized ObjectStreamClass. */
  1807. throw new ClassCastException("Assigning instance of class " +
  1808. fields[i].id +
  1809. " to field " +
  1810. currentClassDesc.getName() + '#' +
  1811. fields[i].name);
  1812. }
  1813. }
  1814. }
  1815. /* Allocate a new object for the specified class
  1816. *
  1817. */
  1818. private static native Object allocateNewObject(Class aclass,
  1819. Class initclass)
  1820. throws InstantiationException, IllegalAccessException;
  1821. /* Create a pending exception. This is needed to get around
  1822. * the fact that the *Delegate methods do not explicitly
  1823. * declare that they throw exceptions.
  1824. *
  1825. * This native methods creates an exception of the given type with
  1826. * the given message string and posts it to the pending queue.
  1827. */
  1828. private static native void throwExceptionType(Class c, String message);
  1829. /* The following native methods of the form set*Field are used
  1830. * to set private, protected, and package private fields
  1831. * of an Object.
  1832. */
  1833. private static native void setObjectField(Object o, Class c, String fieldName, String fieldSig, Object v);
  1834. private static native void setBooleanField(Object o, Class c, String fieldName, String fieldSig, boolean v);
  1835. private static native void setByteField(Object o, Class c, String fieldName, String fieldSig, byte v);
  1836. private static native void setCharField(Object o, Class c, String fieldName, String fieldSig, char v);
  1837. private static native void setShortField(Object o, Class c, String fieldName, String fieldSig, short v);
  1838. private static native void setIntField(Object o, Class c, String fieldName, String fieldSig, int v);
  1839. private static native void setLongField(Object o, Class c, String fieldName, String fieldSig, long v);
  1840. private static native void setFloatField(Object o, Class c, String fieldName, String fieldSig, float v);
  1841. private static native void setDoubleField(Object o, Class c, String fieldName, String fieldSig, double v);
  1842. private static native void readObject(Object obj, Class asClass, Object ois)
  1843. throws InvocationTargetException, IllegalAccessException;
  1844. private static native void setObjectFieldOpt(Object o, long fieldID, Object v);
  1845. private static native void setBooleanFieldOpt(Object o, long fieldID, boolean v);
  1846. private static native void setByteFieldOpt(Object o, long fieldID, byte v);
  1847. private static native void setCharFieldOpt(Object o, long fieldID, char v);
  1848. private static native void setShortFieldOpt(Object o, long fieldID, short v);
  1849. private static native void setIntFieldOpt(Object o, long fieldID, int v);
  1850. private static native void setLongFieldOpt(Object o, long fieldID, long v);
  1851. private static native void setFloatFieldOpt(Object o, long fieldID, float v);
  1852. private static native void setDoubleFieldOpt(Object o, long fieldID, double v);
  1853. /**
  1854. * This class maintains a map of stream position to
  1855. * an Object currently being deserialized. It is used
  1856. * to handle the cases where the are indirections to
  1857. * an object on the recursion stack. The CDR level
  1858. * handles indirections to objects previously seen
  1859. * (and completely deserialized) in the stream.
  1860. */
  1861. static class ActiveRecursionManager
  1862. {
  1863. private Map offsetToObjectMap;
  1864. public ActiveRecursionManager() {
  1865. // A hash map is unsynchronized and allows
  1866. // null values
  1867. offsetToObjectMap = new HashMap();
  1868. }
  1869. // Called right after allocating a new object.
  1870. // Offset is the starting position in the stream
  1871. // of the object.
  1872. public void addObject(int offset, Object value) {
  1873. offsetToObjectMap.put(new Integer(offset), value);
  1874. }
  1875. // If the given starting position doesn't refer
  1876. // to the beginning of an object currently being
  1877. // deserialized, this throws an IOException.
  1878. // Otherwise, it returns a reference to the
  1879. // object.
  1880. public Object getObject(int offset) throws IOException {
  1881. Integer position = new Integer(offset);
  1882. if (!offsetToObjectMap.containsKey(position))
  1883. throw new IOException("Invalid indirection to offset "
  1884. + offset);
  1885. return offsetToObjectMap.get(position);
  1886. }
  1887. // Called when an object has been completely
  1888. // deserialized, so it should no longer be in
  1889. // this mapping. The CDR level can handle
  1890. // further indirections.
  1891. public void removeObject(int offset) {
  1892. offsetToObjectMap.remove(new Integer(offset));
  1893. }
  1894. // If the given offset doesn't map to an Object,
  1895. // then it isn't an indirection to an object
  1896. // currently being deserialized.
  1897. public boolean containsObject(int offset) {
  1898. return offsetToObjectMap.containsKey(new Integer(offset));
  1899. }
  1900. }
  1901. }