1. /*
  2. * @(#)CDRInputStream_1_0.java 1.132 04/06/21
  3. *
  4. * Copyright 2004 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.impl.encoding;
  16. import java.io.IOException;
  17. import java.io.Serializable;
  18. import java.io.ByteArrayInputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. import java.io.StreamCorruptedException;
  22. import java.io.OptionalDataException;
  23. import java.io.IOException;
  24. import java.util.Stack;
  25. import java.net.URL;
  26. import java.net.MalformedURLException;
  27. import java.nio.ByteBuffer;
  28. import java.lang.reflect.InvocationTargetException;
  29. import java.lang.reflect.Method;
  30. import java.math.BigDecimal;
  31. import java.rmi.Remote;
  32. import java.rmi.StubNotFoundException;
  33. import java.security.AccessController;
  34. import java.security.PrivilegedExceptionAction;
  35. import java.security.PrivilegedActionException;
  36. import org.omg.CORBA.SystemException;
  37. import org.omg.CORBA.Object;
  38. import org.omg.CORBA.Principal;
  39. import org.omg.CORBA.TypeCode;
  40. import org.omg.CORBA.Any;
  41. import org.omg.CORBA.portable.Delegate;
  42. import org.omg.CORBA.portable.ValueBase;
  43. import org.omg.CORBA.portable.IndirectionException;
  44. import org.omg.CORBA.CompletionStatus;
  45. import org.omg.CORBA.TCKind;
  46. import org.omg.CORBA.TypeCodePackage.BadKind;
  47. import org.omg.CORBA.CustomMarshal;
  48. import org.omg.CORBA.TypeCode;
  49. import org.omg.CORBA.Principal;
  50. import org.omg.CORBA.Any;
  51. import org.omg.CORBA.portable.BoxedValueHelper;
  52. import org.omg.CORBA.portable.ValueFactory;
  53. import org.omg.CORBA.portable.CustomValue;
  54. import org.omg.CORBA.portable.StreamableValue;
  55. import org.omg.CORBA.MARSHAL;
  56. import org.omg.CORBA.portable.IDLEntity;
  57. import javax.rmi.PortableRemoteObject;
  58. import javax.rmi.CORBA.Tie;
  59. import javax.rmi.CORBA.Util;
  60. import javax.rmi.CORBA.ValueHandler;
  61. import com.sun.corba.se.pept.protocol.MessageMediator;
  62. import com.sun.corba.se.pept.transport.ByteBufferPool;
  63. import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
  64. import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
  65. import com.sun.corba.se.spi.ior.IOR;
  66. import com.sun.corba.se.spi.ior.IORFactories;
  67. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  68. import com.sun.corba.se.spi.orb.ORB;
  69. import com.sun.corba.se.spi.orb.ORBVersionFactory;
  70. import com.sun.corba.se.spi.orb.ORBVersion;
  71. import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
  72. import com.sun.corba.se.spi.logging.CORBALogDomains;
  73. import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
  74. import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
  75. import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
  76. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  77. import com.sun.corba.se.impl.logging.OMGSystemException;
  78. import com.sun.corba.se.impl.corba.PrincipalImpl;
  79. import com.sun.corba.se.impl.corba.TypeCodeImpl;
  80. import com.sun.corba.se.impl.corba.CORBAObjectImpl;
  81. import com.sun.corba.se.impl.encoding.CDROutputObject;
  82. import com.sun.corba.se.impl.encoding.CodeSetConversion;
  83. import com.sun.corba.se.impl.util.Utility;
  84. import com.sun.corba.se.impl.util.RepositoryId;
  85. import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
  86. import com.sun.corba.se.impl.orbutil.RepositoryIdInterface;
  87. import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
  88. import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
  89. import com.sun.corba.se.impl.orbutil.ORBUtility;
  90. import com.sun.corba.se.impl.orbutil.CacheTable;
  91. import com.sun.org.omg.CORBA.portable.ValueHelper;
  92. import com.sun.org.omg.SendingContext.CodeBase;
  93. public class CDRInputStream_1_0 extends CDRInputStreamBase
  94. implements RestorableInputStream
  95. {
  96. private static final String kReadMethod = "read";
  97. private static final int maxBlockLength = 0x7fffff00;
  98. protected BufferManagerRead bufferManagerRead;
  99. protected ByteBufferWithInfo bbwi;
  100. // Set to the ORB's transportDebugFlag value. This value is
  101. // used if the ORB is null.
  102. private boolean debug = false;
  103. protected boolean littleEndian;
  104. protected ORB orb;
  105. protected ORBUtilSystemException wrapper ;
  106. protected OMGSystemException omgWrapper ;
  107. protected ValueHandler valueHandler = null;
  108. // Value cache
  109. private CacheTable valueCache = null;
  110. // Repository ID cache
  111. private CacheTable repositoryIdCache = null;
  112. // codebase cache
  113. private CacheTable codebaseCache = null;
  114. // Current Class Stack (repository Ids of current class being read)
  115. // private Stack currentStack = null;
  116. // Length of current chunk, or a large positive number if not in a chunk
  117. protected int blockLength = maxBlockLength;
  118. // Read end flag (value nesting depth)
  119. protected int end_flag = 0;
  120. // Beginning with the resolution to interop issue 3526 (4328?),
  121. // only enclosing chunked valuetypes are taken into account
  122. // when computing the nesting level. However, we still need
  123. // the old computation around for interoperability with our
  124. // older ORBs.
  125. private int chunkedValueNestingLevel = 0;
  126. // Flag used to determine whether blocksize was zero
  127. // private int checkForNullBlock = -1;
  128. // In block flag
  129. // private boolean inBlock = false;
  130. // Indicates whether we are inside a value
  131. // private boolean outerValueDone = true;
  132. // Int used by read_value(Serializable) that is set by this class
  133. // before calling ValueFactory.read_value
  134. protected int valueIndirection = 0;
  135. // Int set by readStringOrIndirection to communicate the actual
  136. // offset of the string length field back to the caller
  137. protected int stringIndirection = 0;
  138. // Flag indicating whether we are unmarshalling a chunked value
  139. protected boolean isChunked = false;
  140. // Repository ID handlers
  141. private RepositoryIdUtility repIdUtil;
  142. private RepositoryIdStrings repIdStrs;
  143. // Code set converters (created when first needed)
  144. private CodeSetConversion.BTCConverter charConverter;
  145. private CodeSetConversion.BTCConverter wcharConverter;
  146. // RMI-IIOP stream format version 2 case in which we know
  147. // that there is no more optional data available. If the
  148. // Serializable's readObject method tries to read anything,
  149. // we must throw a MARSHAL with the special minor code
  150. // so that the ValueHandler can give the correct exception
  151. // to readObject. The state is cleared when the ValueHandler
  152. // calls end_value after the readObject method exits.
  153. private boolean specialNoOptionalDataState = false;
  154. // Template method
  155. public CDRInputStreamBase dup()
  156. {
  157. CDRInputStreamBase result = null ;
  158. try {
  159. result = (CDRInputStreamBase)this.getClass().newInstance();
  160. } catch (Exception e) {
  161. throw wrapper.couldNotDuplicateCdrInputStream( e ) ;
  162. }
  163. result.init(this.orb,
  164. this.bbwi.byteBuffer,
  165. this.bbwi.buflen,
  166. this.littleEndian,
  167. this.bufferManagerRead);
  168. ((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position());
  169. // To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen.
  170. ((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen);
  171. return result;
  172. }
  173. /**
  174. * NOTE: size passed to init means buffer size
  175. */
  176. public void init(org.omg.CORBA.ORB orb,
  177. ByteBuffer byteBuffer,
  178. int size,
  179. boolean littleEndian,
  180. BufferManagerRead bufferManager)
  181. {
  182. this.orb = (ORB)orb;
  183. this.wrapper = ORBUtilSystemException.get( (ORB)orb,
  184. CORBALogDomains.RPC_ENCODING ) ;
  185. this.omgWrapper = OMGSystemException.get( (ORB)orb,
  186. CORBALogDomains.RPC_ENCODING ) ;
  187. this.littleEndian = littleEndian;
  188. this.bufferManagerRead = bufferManager;
  189. this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0);
  190. this.bbwi.buflen = size;
  191. this.bbwi.byteBuffer.limit(bbwi.buflen);
  192. this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler();
  193. debug = ((ORB)orb).transportDebugFlag;
  194. }
  195. // See description in CDRInputStream
  196. void performORBVersionSpecificInit() {
  197. createRepositoryIdHandlers();
  198. }
  199. private final void createRepositoryIdHandlers()
  200. {
  201. repIdUtil = RepositoryIdFactory.getRepIdUtility(orb);
  202. repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(orb);
  203. }
  204. public GIOPVersion getGIOPVersion() {
  205. return GIOPVersion.V1_0;
  206. }
  207. // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
  208. // Illegal for GIOP versions < 1.2.
  209. void setHeaderPadding(boolean headerPadding) {
  210. throw wrapper.giopVersionError();
  211. }
  212. protected final int computeAlignment(int index, int align) {
  213. if (align > 1) {
  214. int incr = index & (align - 1);
  215. if (incr != 0)
  216. return align - incr;
  217. }
  218. return 0;
  219. }
  220. public int getSize()
  221. {
  222. return bbwi.position();
  223. }
  224. protected void checkBlockLength(int align, int dataSize) {
  225. // Since chunks can end at arbitrary points (though not within
  226. // primitive CDR types, arrays of primitives, strings, wstrings,
  227. // or indirections),
  228. // we must check here for termination of the current chunk.
  229. if (!isChunked)
  230. return;
  231. // RMI-IIOP stream format version 2 case in which we know
  232. // that there is no more optional data available. If the
  233. // Serializable's readObject method tries to read anything,
  234. // we must throw a MARSHAL exception with the special minor code
  235. // so that the ValueHandler can give the correct exception
  236. // to readObject. The state is cleared when the ValueHandler
  237. // calls end_value after the readObject method exits.
  238. if (specialNoOptionalDataState) {
  239. throw omgWrapper.rmiiiopOptionalDataIncompatible1() ;
  240. }
  241. boolean checkForEndTag = false;
  242. // Are we at the end of the current chunk? If so,
  243. // try to interpret the next long as a chunk length.
  244. // (It has to be either a chunk length, end tag,
  245. // or valuetag.)
  246. //
  247. // If it isn't a chunk length, blockLength will
  248. // remain set to maxBlockLength.
  249. if (blockLength == get_offset()) {
  250. blockLength = maxBlockLength;
  251. start_block();
  252. // What's next is either a valuetag or
  253. // an end tag. If it's a valuetag, we're
  254. // probably being called as part of the process
  255. // to read the valuetag. If it's an end tag,
  256. // then there isn't enough data left in
  257. // this valuetype to read!
  258. if (blockLength == maxBlockLength)
  259. checkForEndTag = true;
  260. } else
  261. if (blockLength < get_offset()) {
  262. // Are we already past the end of the current chunk?
  263. // This is always an error.
  264. throw wrapper.chunkOverflow() ;
  265. }
  266. // If what's next on the wire isn't a chunk length or
  267. // what we want to read (which can't be split across chunks)
  268. // won't fit in the current chunk, throw this exception.
  269. // This probably means that we're in an RMI-IIOP
  270. // Serializable's readObject method or a custom marshaled
  271. // IDL type is reading too much/in an incorrect order
  272. int requiredNumBytes =
  273. computeAlignment(bbwi.position(), align) + dataSize;
  274. if (blockLength != maxBlockLength &&
  275. blockLength < get_offset() + requiredNumBytes) {
  276. throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
  277. }
  278. // REVISIT - We should look at using the built in advancement
  279. // of using ByteBuffer.get() rather than explicitly
  280. // advancing the ByteBuffer's position.
  281. // This is true for anywhere we are incrementing
  282. // the ByteBuffer's position.
  283. if (checkForEndTag) {
  284. int nextLong = read_long();
  285. bbwi.position(bbwi.position() - 4);
  286. // It was an end tag, so there wasn't enough data
  287. // left in the valuetype's encoding on the wire
  288. // to read what we wanted
  289. if (nextLong < 0)
  290. throw omgWrapper.rmiiiopOptionalDataIncompatible3() ;
  291. }
  292. }
  293. protected void alignAndCheck(int align, int n) {
  294. checkBlockLength(align, n);
  295. // WARNING: Must compute real alignment after calling
  296. // checkBlockLength since it may move the position
  297. int alignResult = computeAlignment(bbwi.position(), align);
  298. bbwi.position(bbwi.position() + alignResult);
  299. if (bbwi.position() + n > bbwi.buflen)
  300. grow(align, n);
  301. }
  302. //
  303. // This can be overridden....
  304. //
  305. protected void grow(int align, int n) {
  306. bbwi.needed = n;
  307. bbwi = bufferManagerRead.underflow(bbwi);
  308. }
  309. //
  310. // Marshal primitives.
  311. //
  312. public final void consumeEndian() {
  313. littleEndian = read_boolean();
  314. }
  315. // No such type in java
  316. public final double read_longdouble() {
  317. throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE);
  318. }
  319. public final boolean read_boolean() {
  320. return (read_octet() != 0);
  321. }
  322. public final char read_char() {
  323. alignAndCheck(1, 1);
  324. return getConvertedChars(1, getCharConverter())[0];
  325. }
  326. public char read_wchar() {
  327. // Don't allow transmission of wchar/wstring data with
  328. // foreign ORBs since it's against the spec.
  329. if (ORBUtility.isForeignORB((ORB)orb)) {
  330. throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
  331. }
  332. // If we're talking to one of our legacy ORBs, do what
  333. // they did:
  334. int b1, b2;
  335. alignAndCheck(2, 2);
  336. if (littleEndian) {
  337. b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
  338. bbwi.position(bbwi.position() + 1);
  339. b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
  340. bbwi.position(bbwi.position() + 1);
  341. } else {
  342. b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
  343. bbwi.position(bbwi.position() + 1);
  344. b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
  345. bbwi.position(bbwi.position() + 1);
  346. }
  347. return (char)((b1 << 8) + (b2 << 0));
  348. }
  349. public final byte read_octet() {
  350. alignAndCheck(1, 1);
  351. byte b = bbwi.byteBuffer.get(bbwi.position());
  352. bbwi.position(bbwi.position() + 1);
  353. return b;
  354. }
  355. public final short read_short() {
  356. int b1, b2;
  357. alignAndCheck(2, 2);
  358. if (littleEndian) {
  359. b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
  360. bbwi.position(bbwi.position() + 1);
  361. b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
  362. bbwi.position(bbwi.position() + 1);
  363. } else {
  364. b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
  365. bbwi.position(bbwi.position() + 1);
  366. b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
  367. bbwi.position(bbwi.position() + 1);
  368. }
  369. return (short)(b1 | b2);
  370. }
  371. public final short read_ushort() {
  372. return read_short();
  373. }
  374. public final int read_long() {
  375. int b1, b2, b3, b4;
  376. alignAndCheck(4, 4);
  377. int bufPos = bbwi.position();
  378. if (littleEndian) {
  379. b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  380. b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  381. b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  382. b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  383. } else {
  384. b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  385. b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  386. b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  387. b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
  388. }
  389. bbwi.position(bufPos);
  390. return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
  391. }
  392. public final int read_ulong() {
  393. return read_long();
  394. }
  395. public final long read_longlong() {
  396. long i1, i2;
  397. alignAndCheck(8, 8);
  398. if (littleEndian) {
  399. i2 = read_long() & 0xFFFFFFFFL;
  400. i1 = (long)read_long() << 32;
  401. } else {
  402. i1 = (long)read_long() << 32;
  403. i2 = read_long() & 0xFFFFFFFFL;
  404. }
  405. return (i1 | i2);
  406. }
  407. public final long read_ulonglong() {
  408. return read_longlong();
  409. }
  410. public final float read_float() {
  411. return Float.intBitsToFloat(read_long());
  412. }
  413. public final double read_double() {
  414. return Double.longBitsToDouble(read_longlong());
  415. }
  416. protected final void checkForNegativeLength(int length) {
  417. if (length < 0)
  418. throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE,
  419. new Integer(length) ) ;
  420. }
  421. protected final String readStringOrIndirection(boolean allowIndirection) {
  422. int len = read_long();
  423. //
  424. // Check for indirection
  425. //
  426. if (allowIndirection) {
  427. if (len == 0xffffffff)
  428. return null;
  429. else
  430. stringIndirection = get_offset() - 4;
  431. }
  432. checkForNegativeLength(len);
  433. if (orb != null && ORBUtility.isLegacyORB((ORB)orb))
  434. return legacyReadString(len);
  435. else
  436. return internalReadString(len);
  437. }
  438. private final String internalReadString(int len) {
  439. // Workaround for ORBs which send string lengths of
  440. // zero to mean empty string.
  441. //
  442. // IMPORTANT: Do not replace 'new String("")' with "", it may result
  443. // in a Serialization bug (See serialization.zerolengthstring) and
  444. // bug id: 4728756 for details
  445. if (len == 0)
  446. return new String("");
  447. char[] result = getConvertedChars(len - 1, getCharConverter());
  448. // Skip over the 1 byte null
  449. read_octet();
  450. return new String(result, 0, getCharConverter().getNumChars());
  451. }
  452. private final String legacyReadString(int len) {
  453. //
  454. // Workaround for ORBs which send string lengths of
  455. // zero to mean empty string.
  456. //
  457. //
  458. // IMPORTANT: Do not replace 'new String("")' with "", it may result
  459. // in a Serialization bug (See serialization.zerolengthstring) and
  460. // bug id: 4728756 for details
  461. if (len == 0)
  462. return new String("");
  463. len--;
  464. char[] c = new char[len];
  465. int n = 0;
  466. while (n < len) {
  467. int avail;
  468. int bytes;
  469. int wanted;
  470. avail = bbwi.buflen - bbwi.position();
  471. if (avail <= 0) {
  472. grow(1, 1);
  473. avail = bbwi.buflen - bbwi.position();
  474. }
  475. wanted = len - n;
  476. bytes = (wanted < avail) ? wanted : avail;
  477. // Microbenchmarks are showing a loop of ByteBuffer.get(int) being
  478. // faster than ByteBuffer.get(byte[], int, int).
  479. for (int i=0; i<bytes; i++) {
  480. c[n+i] = (char) (bbwi.byteBuffer.get(bbwi.position()+i) & 0xFF);
  481. }
  482. bbwi.position(bbwi.position() + bytes);
  483. n += bytes;
  484. }
  485. //
  486. // Skip past terminating null byte
  487. //
  488. if (bbwi.position() + 1 > bbwi.buflen)
  489. alignAndCheck(1, 1);
  490. bbwi.position(bbwi.position() + 1);
  491. return new String(c);
  492. }
  493. public final String read_string() {
  494. return readStringOrIndirection(false);
  495. }
  496. public String read_wstring() {
  497. // Don't allow transmission of wchar/wstring data with
  498. // foreign ORBs since it's against the spec.
  499. if (ORBUtility.isForeignORB((ORB)orb)) {
  500. throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
  501. }
  502. int len = read_long();
  503. //
  504. // Workaround for ORBs which send string lengths of
  505. // zero to mean empty string.
  506. //
  507. //
  508. // IMPORTANT: Do not replace 'new String("")' with "", it may result
  509. // in a Serialization bug (See serialization.zerolengthstring) and
  510. // bug id: 4728756 for details
  511. if (len == 0)
  512. return new String("");
  513. checkForNegativeLength(len);
  514. len--;
  515. char[] c = new char[len];
  516. for (int i = 0; i < len; i++)
  517. c[i] = read_wchar();
  518. // skip the two null terminator bytes
  519. read_wchar();
  520. // bbwi.position(bbwi.position() + 2);
  521. return new String(c);
  522. }
  523. public final void read_octet_array(byte[] b, int offset, int length) {
  524. if ( b == null )
  525. throw wrapper.nullParam() ;
  526. // Must call alignAndCheck at least once to ensure
  527. // we aren't at the end of a chunk. Of course, we
  528. // should only call it if we actually need to read
  529. // something, otherwise we might end up with an
  530. // exception at the end of the stream.
  531. if (length == 0)
  532. return;
  533. alignAndCheck(1, 1);
  534. int n = offset;
  535. while (n < length+offset) {
  536. int avail;
  537. int bytes;
  538. int wanted;
  539. avail = bbwi.buflen - bbwi.position();
  540. if (avail <= 0) {
  541. grow(1, 1);
  542. avail = bbwi.buflen - bbwi.position();
  543. }
  544. wanted = (length + offset) - n;
  545. bytes = (wanted < avail) ? wanted : avail;
  546. // Microbenchmarks are showing a loop of ByteBuffer.get(int) being
  547. // faster than ByteBuffer.get(byte[], int, int).
  548. for (int i = 0; i < bytes; i++) {
  549. b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i);
  550. }
  551. bbwi.position(bbwi.position() + bytes);
  552. n += bytes;
  553. }
  554. }
  555. public Principal read_Principal() {
  556. int len = read_long();
  557. byte[] pvalue = new byte[len];
  558. read_octet_array(pvalue,0,len);
  559. Principal p = new PrincipalImpl();
  560. p.name(pvalue);
  561. return p;
  562. }
  563. public TypeCode read_TypeCode() {
  564. TypeCodeImpl tc = new TypeCodeImpl(orb);
  565. tc.read_value(parent);
  566. return tc;
  567. }
  568. public Any read_any() {
  569. Any any = orb.create_any();
  570. TypeCodeImpl tc = new TypeCodeImpl(orb);
  571. // read off the typecode
  572. // REVISIT We could avoid this try-catch if we could peek the typecode
  573. // kind off this stream and see if it is a tk_value. Looking at the
  574. // code we know that for tk_value the Any.read_value() below
  575. // ignores the tc argument anyway (except for the kind field).
  576. // But still we would need to make sure that the whole typecode,
  577. // including encapsulations, is read off.
  578. try {
  579. tc.read_value(parent);
  580. } catch (MARSHAL ex) {
  581. if (tc.kind().value() != TCKind._tk_value)
  582. throw ex;
  583. // We can be sure that the whole typecode encapsulation has been
  584. // read off.
  585. dprintThrowable(ex);
  586. }
  587. // read off the value of the any
  588. any.read_value(parent, tc);
  589. return any;
  590. }
  591. public org.omg.CORBA.Object read_Object() {
  592. return read_Object(null);
  593. }
  594. // ------------ RMI related methods --------------------------
  595. // IDL to Java ptc-00-01-08 1.21.4.1
  596. //
  597. // The clz argument to read_Object can be either a stub
  598. // Class or the "Class object for the RMI/IDL interface type
  599. // that is statically expected."
  600. // This functions as follows:
  601. // 1. If clz==null, just use the repository ID from the stub
  602. // 2. If clz is a stub class, just use it as a static factory.
  603. // clz is a stub class iff StubAdapter.isStubClass( clz ).
  604. // In addition, clz is a IDL stub class iff
  605. // IDLEntity.class.isAssignableFrom( clz ).
  606. // 3. If clz is an interface, use it to create the appropriate
  607. // stub factory.
  608. public org.omg.CORBA.Object read_Object(Class clz)
  609. {
  610. // In any case, we must first read the IOR.
  611. IOR ior = IORFactories.makeIOR(parent) ;
  612. if (ior.isNil())
  613. return null ;
  614. PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ;
  615. String codeBase = ior.getProfile().getCodebase() ;
  616. PresentationManager.StubFactory stubFactory = null ;
  617. if (clz == null) {
  618. RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ;
  619. String className = rid.getClassName() ;
  620. boolean isIDLInterface = rid.isIDLType() ;
  621. if (className == null || className.equals( "" ))
  622. stubFactory = null ;
  623. else
  624. try {
  625. stubFactory = sff.createStubFactory( className,
  626. isIDLInterface, codeBase, (Class)null,
  627. (ClassLoader)null );
  628. } catch (Exception exc) {
  629. // Could not create stubFactory, so use null.
  630. // XXX stubFactory handling is still too complex:
  631. // Can we resolve the stubFactory question once in
  632. // a single place?
  633. stubFactory = null ;
  634. }
  635. } else if (StubAdapter.isStubClass( clz )) {
  636. stubFactory = PresentationDefaults.makeStaticStubFactory(
  637. clz ) ;
  638. } else {
  639. // clz is an interface class
  640. boolean isIDL = IDLEntity.class.isAssignableFrom( clz ) ;
  641. stubFactory = sff.createStubFactory( clz.getName(),
  642. isIDL, codeBase, clz, clz.getClassLoader() ) ;
  643. }
  644. return internalIORToObject( ior, stubFactory, orb ) ;
  645. }
  646. /*
  647. * This is used as a general utility (e.g., the PortableInterceptor
  648. * implementation uses it. If stubFactory is null, the ior's
  649. * IIOPProfile must support getServant.
  650. */
  651. public static org.omg.CORBA.Object internalIORToObject(
  652. IOR ior, PresentationManager.StubFactory stubFactory, ORB orb)
  653. {
  654. ORBUtilSystemException wrapper = ORBUtilSystemException.get(
  655. (ORB)orb, CORBALogDomains.RPC_ENCODING ) ;
  656. java.lang.Object servant = ior.getProfile().getServant() ;
  657. if (servant != null ) {
  658. if (servant instanceof Tie) {
  659. String codebase = ior.getProfile().getCodebase();
  660. org.omg.CORBA.Object objref = (org.omg.CORBA.Object)
  661. Utility.loadStub( (Tie)servant, stubFactory, codebase,
  662. false);
  663. // If we managed to load a stub, return it, otherwise we
  664. // must fail...
  665. if (objref != null) {
  666. return objref;
  667. } else {
  668. throw wrapper.readObjectException() ;
  669. }
  670. } else if (servant instanceof org.omg.CORBA.Object) {
  671. if (!(servant instanceof
  672. org.omg.CORBA.portable.InvokeHandler)) {
  673. return (org.omg.CORBA.Object) servant;
  674. }
  675. } else
  676. throw wrapper.badServantReadObject() ;
  677. }
  678. CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ;
  679. org.omg.CORBA.Object objref = null ;
  680. try {
  681. objref = stubFactory.makeStub() ;
  682. } catch (Throwable e) {
  683. wrapper.stubCreateError( e ) ;
  684. if (e instanceof ThreadDeath) {
  685. throw (ThreadDeath) e;
  686. }
  687. // Return the "default" stub...
  688. objref = new CORBAObjectImpl() ;
  689. }
  690. StubAdapter.setDelegate( objref, del ) ;
  691. return objref;
  692. }
  693. public java.lang.Object read_abstract_interface()
  694. {
  695. return read_abstract_interface(null);
  696. }
  697. public java.lang.Object read_abstract_interface(java.lang.Class clz)
  698. {
  699. boolean object = read_boolean();
  700. if (object) {
  701. return read_Object(clz);
  702. } else {
  703. return read_value();
  704. }
  705. }
  706. public Serializable read_value()
  707. {
  708. return read_value((Class)null);
  709. }
  710. private Serializable handleIndirection() {
  711. int indirection = read_long() + get_offset() - 4;
  712. if (valueCache != null && valueCache.containsVal(indirection)) {
  713. java.io.Serializable cachedValue
  714. = (java.io.Serializable)valueCache.getKey(indirection);
  715. return cachedValue;
  716. } else {
  717. // In RMI-IIOP the ValueHandler will recognize this
  718. // exception and use the provided indirection value
  719. // to lookup a possible indirection to an object
  720. // currently on the deserialization stack.
  721. throw new IndirectionException(indirection);
  722. }
  723. }
  724. /**
  725. * Examines the valuetag to see how many (if any) repository IDs
  726. * are present on the wire. If no repository ID information
  727. * is on the wire but the expectedType or expectedTypeRepId
  728. * is known, it will return one of those (favoring the
  729. * expectedType's repId).
  730. */
  731. private String readRepositoryIds(int valueTag,
  732. Class expectedType,
  733. String expectedTypeRepId)
  734. {
  735. switch(repIdUtil.getTypeInfo(valueTag)) {
  736. case RepositoryIdUtility.NO_TYPE_INFO :
  737. // Throw an exception if we have no repository ID info and
  738. // no expectedType to work with. Otherwise, how would we
  739. // know what to unmarshal?
  740. if (expectedType == null) {
  741. if (expectedTypeRepId != null)
  742. return expectedTypeRepId;
  743. else
  744. throw wrapper.expectedTypeNullAndNoRepId(
  745. CompletionStatus.COMPLETED_MAYBE);
  746. }
  747. return repIdStrs.createForAnyType(expectedType);
  748. case RepositoryIdUtility.SINGLE_REP_TYPE_INFO :
  749. return read_repositoryId();
  750. case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO :
  751. return read_repositoryIds();
  752. default:
  753. throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE,
  754. Integer.toHexString(valueTag) ) ;
  755. }
  756. }
  757. public Serializable read_value(Class expectedType) {
  758. // Read value tag
  759. int vType = readValueTag();
  760. // Is value null?
  761. if (vType == 0)
  762. return null;
  763. // Is this an indirection to a previously
  764. // read valuetype?
  765. if (vType == 0xffffffff)
  766. return handleIndirection();
  767. // Save where this valuetype started so we
  768. // can put it in the indirection valueCache
  769. // later
  770. int indirection = get_offset() - 4;
  771. // Need to save this special marker variable
  772. // to restore its value during recursion
  773. boolean saveIsChunked = isChunked;
  774. isChunked = repIdUtil.isChunkedEncoding(vType);
  775. java.lang.Object value = null;
  776. String codebase_URL = null;
  777. if (repIdUtil.isCodeBasePresent(vType)) {
  778. codebase_URL = read_codebase_URL();
  779. }
  780. // Read repository id(s)
  781. String repositoryIDString
  782. = readRepositoryIds(vType, expectedType, null);
  783. // If isChunked was determined to be true based
  784. // on the valuetag, this will read a chunk length
  785. start_block();
  786. // Remember that end_flag keeps track of all nested
  787. // valuetypes and is used for older ORBs
  788. end_flag--;
  789. if (isChunked)
  790. chunkedValueNestingLevel--;
  791. if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) {
  792. value = read_wstring();
  793. } else
  794. if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) {
  795. // read in the class whether with the old ClassDesc or the
  796. // new one
  797. value = readClass();
  798. } else {
  799. Class valueClass = expectedType;
  800. // By this point, either the expectedType or repositoryIDString
  801. // is guaranteed to be non-null.
  802. if (expectedType == null ||
  803. !repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) {
  804. valueClass = getClassFromString(repositoryIDString,
  805. codebase_URL,
  806. expectedType);
  807. }
  808. if (valueClass == null) {
  809. // No point attempting to use value handler below, since the
  810. // class information is not available.
  811. throw wrapper.couldNotFindClass(
  812. CompletionStatus.COMPLETED_MAYBE,
  813. new ClassNotFoundException());
  814. }
  815. if (valueClass != null &&
  816. org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) {
  817. value = readIDLValue(indirection,
  818. repositoryIDString,
  819. valueClass,
  820. codebase_URL);
  821. } else {
  822. // Must be some form of RMI-IIOP valuetype
  823. try {
  824. if (valueHandler == null)
  825. valueHandler = ORBUtility.createValueHandler(orb);
  826. value = valueHandler.readValue(parent,
  827. indirection,
  828. valueClass,
  829. repositoryIDString,
  830. getCodeBase());
  831. } catch(SystemException sysEx) {
  832. // Just rethrow any CORBA system exceptions
  833. // that come out of the ValueHandler
  834. throw sysEx;
  835. } catch(Exception ex) {
  836. throw wrapper.valuehandlerReadException(
  837. CompletionStatus.COMPLETED_MAYBE, ex ) ;
  838. } catch(Error e) {
  839. throw wrapper.valuehandlerReadError(
  840. CompletionStatus.COMPLETED_MAYBE, e ) ;
  841. }
  842. }
  843. }
  844. // Skip any remaining chunks until we get to
  845. // an end tag or a valuetag. If we see a valuetag,
  846. // that means there was another valuetype in the sender's
  847. // version of this class that we need to skip over.
  848. handleEndOfValue();
  849. // Read and process the end tag if we're chunking.
  850. // Assumes that we're at the position of the end tag
  851. // (handleEndOfValue should assure this)
  852. readEndTag();
  853. // Cache the valuetype that we read
  854. if (valueCache == null)
  855. valueCache = new CacheTable(orb,false);
  856. valueCache.put(value, indirection);
  857. // Allow for possible continuation chunk.
  858. // If we're a nested valuetype inside of a chunked
  859. // valuetype, and that enclosing valuetype has
  860. // more data to write, it will need to have this
  861. // new chunk begin after we wrote our end tag.
  862. isChunked = saveIsChunked;
  863. start_block();
  864. return (java.io.Serializable)value;
  865. }
  866. public Serializable read_value(BoxedValueHelper factory) {
  867. // Read value tag
  868. int vType = readValueTag();
  869. if (vType == 0)
  870. return null; // value is null
  871. else if (vType == 0xffffffff) { // Indirection tag
  872. int indirection = read_long() + get_offset() - 4;
  873. if (valueCache != null && valueCache.containsVal(indirection))
  874. {
  875. java.io.Serializable cachedValue =
  876. (java.io.Serializable)valueCache.getKey(indirection);
  877. return cachedValue;
  878. }
  879. else {
  880. throw new IndirectionException(indirection);
  881. }
  882. }
  883. else {
  884. int indirection = get_offset() - 4;
  885. // end_block();
  886. boolean saveIsChunked = isChunked;
  887. isChunked = repIdUtil.isChunkedEncoding(vType);
  888. java.lang.Object value = null;
  889. String codebase_URL = null;
  890. if (repIdUtil.isCodeBasePresent(vType)){
  891. codebase_URL = read_codebase_URL();
  892. }
  893. // Read repository id
  894. String repositoryIDString
  895. = readRepositoryIds(vType, null, null);
  896. // Compare rep. ids to see if we should use passed helper
  897. if (!repositoryIDString.equals(factory.get_id()))
  898. factory = Utility.getHelper(null, codebase_URL, repositoryIDString);
  899. start_block();
  900. end_flag--;
  901. if (isChunked)
  902. chunkedValueNestingLevel--;
  903. if (factory instanceof ValueHelper) {
  904. value = readIDLValueWithHelper((ValueHelper)factory, indirection);
  905. } else {
  906. valueIndirection = indirection; // for callback
  907. value = factory.read_value(parent);
  908. }
  909. handleEndOfValue();
  910. readEndTag();
  911. // Put into valueCache
  912. if (valueCache == null)
  913. valueCache = new CacheTable(orb,false);
  914. valueCache.put(value, indirection);
  915. // allow for possible continuation chunk
  916. isChunked = saveIsChunked;
  917. start_block();
  918. return (java.io.Serializable)value;
  919. }
  920. }
  921. private boolean isCustomType(ValueHelper helper) {
  922. try{
  923. TypeCode tc = helper.get_type();
  924. int kind = tc.kind().value();
  925. if (kind == TCKind._tk_value) {
  926. return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value);
  927. }
  928. } catch(BadKind ex) {
  929. throw wrapper.badKind(ex) ;
  930. }
  931. return false;
  932. }
  933. // This method is actually called indirectly by
  934. // read_value(String repositoryId).
  935. // Therefore, it is not a truly independent read call that handles
  936. // header information itself.
  937. public java.io.Serializable read_value(java.io.Serializable value) {
  938. // Put into valueCache using valueIndirection
  939. if (valueCache == null)
  940. valueCache = new CacheTable(orb,false);
  941. valueCache.put(value, valueIndirection);
  942. if (value instanceof StreamableValue)
  943. ((StreamableValue)value)._read(parent);
  944. else if (value instanceof CustomValue)
  945. ((CustomValue)value).unmarshal(parent);
  946. return value;
  947. }
  948. public java.io.Serializable read_value(java.lang.String repositoryId) {
  949. // if (inBlock)
  950. // end_block();
  951. // Read value tag
  952. int vType = readValueTag();
  953. if (vType == 0)
  954. return null; // value is null
  955. else if (vType == 0xffffffff) { // Indirection tag
  956. int indirection = read_long() + get_offset() - 4;
  957. if (valueCache != null && valueCache.containsVal(indirection))
  958. {
  959. java.io.Serializable cachedValue =
  960. (java.io.Serializable)valueCache.getKey(indirection);
  961. return cachedValue;
  962. }
  963. else {
  964. throw new IndirectionException(indirection);
  965. }
  966. }
  967. else {
  968. int indirection = get_offset() - 4;
  969. // end_block();
  970. boolean saveIsChunked = isChunked;
  971. isChunked = repIdUtil.isChunkedEncoding(vType);
  972. java.lang.Object value = null;
  973. String codebase_URL = null;
  974. if (repIdUtil.isCodeBasePresent(vType)){
  975. codebase_URL = read_codebase_URL();
  976. }
  977. // Read repository id
  978. String repositoryIDString
  979. = readRepositoryIds(vType, null, repositoryId);
  980. ValueFactory factory =
  981. Utility.getFactory(null, codebase_URL, orb, repositoryIDString);
  982. start_block();
  983. end_flag--;
  984. if (isChunked)
  985. chunkedValueNestingLevel--;
  986. valueIndirection = indirection; // for callback
  987. value = factory.read_value(parent);
  988. handleEndOfValue();
  989. readEndTag();
  990. // Put into valueCache
  991. if (valueCache == null)
  992. valueCache = new CacheTable(orb,false);
  993. valueCache.put(value, indirection);
  994. // allow for possible continuation chunk
  995. isChunked = saveIsChunked;
  996. start_block();
  997. return (java.io.Serializable)value;
  998. }
  999. }
  1000. private Class readClass() {
  1001. String codebases = null, classRepId = null;
  1002. if (orb == null ||
  1003. ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
  1004. ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
  1005. codebases = (String)read_value(java.lang.String.class);
  1006. classRepId = (String)read_value(java.lang.String.class);
  1007. } else {
  1008. // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
  1009. // and codebase strings in the wrong order.
  1010. classRepId = (String)read_value(java.lang.String.class);
  1011. codebases = (String)read_value(java.lang.String.class);
  1012. }
  1013. if (debug) {
  1014. dprint("readClass codebases: "
  1015. + codebases
  1016. + " rep Id: "
  1017. + classRepId);
  1018. }
  1019. Class cl = null;
  1020. RepositoryIdInterface repositoryID
  1021. = repIdStrs.getFromString(classRepId);
  1022. try {
  1023. cl = repositoryID.getClassFromType(codebases);
  1024. } catch(ClassNotFoundException cnfe) {
  1025. throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE,
  1026. cnfe, repositoryID.getClassName() ) ;
  1027. } catch(MalformedURLException me) {
  1028. throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  1029. me, repositoryID.getClassName(), codebases ) ;
  1030. }
  1031. return cl;
  1032. }
  1033. private java.lang.Object readIDLValueWithHelper(ValueHelper helper, int indirection)
  1034. {
  1035. // look for two-argument static read method
  1036. Method readMethod;
  1037. try {
  1038. Class argTypes[] = {org.omg.CORBA.portable.InputStream.class, helper.get_class()};
  1039. readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes);
  1040. }
  1041. catch(NoSuchMethodException nsme) { // must be boxed value helper
  1042. java.lang.Object result = helper.read_value(parent);
  1043. return result;
  1044. }
  1045. // found two-argument read method, so must be non-boxed value...
  1046. // ...create a blank instance
  1047. java.lang.Object val = null;
  1048. try {
  1049. val = helper.get_class().newInstance();
  1050. } catch(java.lang.InstantiationException ie) {
  1051. throw wrapper.couldNotInstantiateHelper( ie,
  1052. helper.get_class() ) ;
  1053. } catch(IllegalAccessException iae){
  1054. // Value's constructor is protected or private
  1055. //
  1056. // So, use the helper to read the value.
  1057. //
  1058. // NOTE : This means that in this particular case a recursive ref.
  1059. // would fail.
  1060. return helper.read_value(parent);
  1061. }
  1062. // add blank instance to cache table
  1063. if (valueCache == null)
  1064. valueCache = new CacheTable(orb,false);
  1065. valueCache.put(val, indirection);
  1066. // if custom type, call unmarshal method
  1067. if (val instanceof CustomMarshal && isCustomType(helper)) {
  1068. ((CustomMarshal)val).unmarshal(parent);
  1069. return val;
  1070. }
  1071. // call two-argument read method using reflection
  1072. try {
  1073. java.lang.Object args[] = {parent, val};
  1074. readMethod.invoke(helper, args);
  1075. return val;
  1076. } catch(IllegalAccessException iae2) {
  1077. throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ;
  1078. } catch(InvocationTargetException ite){
  1079. throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ;
  1080. }
  1081. }
  1082. private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase)
  1083. {
  1084. Class cls = null ;
  1085. try {
  1086. ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
  1087. cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
  1088. clazzLoader, clazz, clazzLoader);
  1089. final Class helperClass = cls ;
  1090. final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class};
  1091. // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
  1092. // if a different class loader is used (even though the javadoc says otherwise)
  1093. Method readMethod = null;
  1094. try {
  1095. readMethod = (Method)AccessController.doPrivileged(
  1096. new PrivilegedExceptionAction() {
  1097. public java.lang.Object run() throws NoSuchMethodException {
  1098. return helperClass.getDeclaredMethod(kReadMethod, argTypes);
  1099. }
  1100. }
  1101. );
  1102. } catch (PrivilegedActionException pae) {
  1103. // this gets caught below
  1104. throw (NoSuchMethodException)pae.getException();
  1105. }
  1106. java.lang.Object args[] = {parent};
  1107. return readMethod.invoke(null, args);
  1108. } catch (ClassNotFoundException cnfe) {
  1109. throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ;
  1110. } catch(NoSuchMethodException nsme) {
  1111. throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ;
  1112. } catch(IllegalAccessException iae) {
  1113. throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ;
  1114. } catch(InvocationTargetException ite) {
  1115. throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ;
  1116. }
  1117. }
  1118. private java.lang.Object readIDLValue(int indirection, String repId,
  1119. Class clazz, String codebase)
  1120. {
  1121. ValueFactory factory ;
  1122. // Always try to find a ValueFactory first, as required by the spec.
  1123. // There are some complications here in the IDL 3.0 mapping (see 1.13.8),
  1124. // but basically we must always be able to override the DefaultFactory
  1125. // or Helper mappings that are also used. This appears to be the case
  1126. // even in the boxed value cases. The original code only did the lookup
  1127. // in the case of class implementing either StreamableValue or CustomValue,
  1128. // but abstract valuetypes only implement ValueBase, and really require
  1129. // the use of the repId to find a factory (including the DefaultFactory).
  1130. try {
  1131. // use new-style OBV support (factory object)
  1132. factory = Utility.getFactory(clazz, codebase, orb, repId);
  1133. } catch (MARSHAL marshal) {
  1134. // XXX log marshal at one of the INFO levels
  1135. // Could not get a factory, so try alternatives
  1136. if (!StreamableValue.class.isAssignableFrom(clazz) &&
  1137. !CustomValue.class.isAssignableFrom(clazz) &&
  1138. ValueBase.class.isAssignableFrom(clazz)) {
  1139. // use old-style OBV support (helper object)
  1140. BoxedValueHelper helper = Utility.getHelper(clazz, codebase, repId);
  1141. if (helper instanceof ValueHelper)
  1142. return readIDLValueWithHelper((ValueHelper)helper, indirection);
  1143. else
  1144. return helper.read_value(parent);
  1145. } else {
  1146. // must be a boxed IDLEntity, so make a reflective call to the
  1147. // helper's static read method...
  1148. return readBoxedIDLEntity(clazz, codebase);
  1149. }
  1150. }
  1151. // If there was no error in getting the factory, use it.
  1152. valueIndirection = indirection; // for callback
  1153. return factory.read_value(parent);
  1154. }
  1155. /**
  1156. * End tags are only written for chunked valuetypes.
  1157. *
  1158. * Before Merlin, our ORBs wrote end tags which took into account
  1159. * all enclosing valuetypes. This was changed by an interop resolution
  1160. * (see details around chunkedValueNestingLevel) to only include
  1161. * enclosing chunked types.
  1162. *
  1163. * ORB versioning and end tag compaction are handled here.
  1164. */
  1165. private void readEndTag() {
  1166. if (isChunked) {
  1167. // Read the end tag
  1168. int anEndTag = read_long();
  1169. // End tags should always be negative, and the outermost
  1170. // enclosing chunked valuetype should have a -1 end tag.
  1171. //
  1172. // handleEndOfValue should have assured that we were
  1173. // at the end tag position!
  1174. if (anEndTag >= 0) {
  1175. throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE,
  1176. new Integer(anEndTag), new Integer( get_offset() - 4 ) ) ;
  1177. }
  1178. // If the ORB is null, or if we're sure we're talking to
  1179. // a foreign ORB, Merlin, or something more recent, we
  1180. // use the updated end tag computation, and are more strenuous
  1181. // about the values.
  1182. if (orb == null ||
  1183. ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
  1184. ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
  1185. // If the end tag we read was less than what we were expecting,
  1186. // then the sender must think it's sent more enclosing
  1187. // chunked valuetypes than we have. Throw an exception.
  1188. if (anEndTag < chunkedValueNestingLevel)
  1189. throw wrapper.unexpectedEnclosingValuetype(
  1190. CompletionStatus.COMPLETED_MAYBE,