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, new Integer( anEndTag ),
  1191. new Integer( chunkedValueNestingLevel ) ) ;
  1192. // If the end tag is bigger than what we expected, but
  1193. // still negative, then the sender has done some end tag
  1194. // compaction. We back up the stream 4 bytes so that the
  1195. // next time readEndTag is called, it will get down here
  1196. // again. Even with fragmentation, we'll always be able
  1197. // to do this.
  1198. if (anEndTag != chunkedValueNestingLevel) {
  1199. bbwi.position(bbwi.position() - 4);
  1200. }
  1201. } else {
  1202. // When talking to Kestrel or Ladybird, we use our old
  1203. // end tag rules and are less strict. If the end tag
  1204. // isn't what we expected, we back up, assuming
  1205. // compaction.
  1206. if (anEndTag != end_flag) {
  1207. bbwi.position(bbwi.position() - 4);
  1208. }
  1209. }
  1210. // This only keeps track of the enclosing chunked
  1211. // valuetypes
  1212. chunkedValueNestingLevel++;
  1213. }
  1214. // This keeps track of all enclosing valuetypes
  1215. end_flag++;
  1216. }
  1217. protected int get_offset() {
  1218. return bbwi.position();
  1219. }
  1220. private void start_block() {
  1221. // if (outerValueDone)
  1222. if (!isChunked)
  1223. return;
  1224. // if called from alignAndCheck, need to reset blockLength
  1225. // to avoid an infinite recursion loop on read_long() call
  1226. blockLength = maxBlockLength;
  1227. blockLength = read_long();
  1228. // Must remember where we began the chunk to calculate how far
  1229. // along we are. See notes above about chunkBeginPos.
  1230. if (blockLength > 0 && blockLength < maxBlockLength) {
  1231. blockLength += get_offset(); // _REVISIT_ unsafe, should use a Java long
  1232. // inBlock = true;
  1233. } else {
  1234. // System.out.println("start_block snooped a " + Integer.toHexString(blockLength));
  1235. // not a chunk length field
  1236. blockLength = maxBlockLength;
  1237. bbwi.position(bbwi.position() - 4);
  1238. }
  1239. }
  1240. // Makes sure that if we were reading a chunked value, we end up
  1241. // at the right place in the stream, no matter how little the
  1242. // unmarshalling code read.
  1243. //
  1244. // After calling this method, if we are chunking, we should be
  1245. // in position to read the end tag.
  1246. private void handleEndOfValue() {
  1247. // If we're not chunking, we don't have to worry about
  1248. // skipping remaining chunks or finding end tags
  1249. if (!isChunked)
  1250. return;
  1251. // Skip any remaining chunks
  1252. while (blockLength != maxBlockLength) {
  1253. end_block();
  1254. start_block();
  1255. }
  1256. // Now look for the end tag
  1257. // This is a little wasteful since we're reading
  1258. // this long up to 3 times in the worst cases (once
  1259. // in start_block, once here, and once in readEndTag
  1260. //
  1261. // Peek next long
  1262. int nextLong = read_long();
  1263. bbwi.position(bbwi.position() - 4);
  1264. // We did find an end tag, so we're done. readEndTag
  1265. // should take care of making sure it's the correct
  1266. // end tag, etc. Remember that since end tags,
  1267. // chunk lengths, and valuetags have non overlapping
  1268. // ranges, we can tell by the value what the longs are.
  1269. if (nextLong < 0)
  1270. return;
  1271. if (nextLong == 0 || nextLong >= maxBlockLength) {
  1272. // A custom marshaled valuetype left extra data
  1273. // on the wire, and that data had another
  1274. // nested value inside of it. We've just
  1275. // read the value tag or null of that nested value.
  1276. //
  1277. // In an attempt to get by it, we'll try to call
  1278. // read_value() to get the nested value off of
  1279. // the wire. Afterwards, we must call handleEndOfValue
  1280. // recursively to read any further chunks that the containing
  1281. // valuetype might still have after the nested
  1282. // value.
  1283. read_value();
  1284. handleEndOfValue();
  1285. } else {
  1286. // This probably means that the code to skip chunks has
  1287. // an error, and ended up setting blockLength to something
  1288. // other than maxBlockLength even though we weren't
  1289. // starting a new chunk.
  1290. throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE,
  1291. new Integer( nextLong ), new Integer( get_offset() ) ) ;
  1292. }
  1293. }
  1294. private void end_block() {
  1295. // if in a chunk, check for underflow or overflow
  1296. if (blockLength != maxBlockLength) {
  1297. if (blockLength == get_offset()) {
  1298. // Chunk ended correctly
  1299. blockLength = maxBlockLength;
  1300. } else {
  1301. // Skip over anything left by bad unmarshaling code (ex:
  1302. // a buggy custom unmarshaler). See handleEndOfValue.
  1303. if (blockLength > get_offset()) {
  1304. skipToOffset(blockLength);
  1305. } else {
  1306. throw wrapper.badChunkLength( new Integer( blockLength ),
  1307. new Integer( get_offset() ) ) ;
  1308. }
  1309. }
  1310. }
  1311. }
  1312. private int readValueTag(){
  1313. // outerValueDone = false;
  1314. return read_long();
  1315. }
  1316. public org.omg.CORBA.ORB orb() {
  1317. return orb;
  1318. }
  1319. // ------------ End RMI related methods --------------------------
  1320. public final void read_boolean_array(boolean[] value, int offset, int length) {
  1321. for(int i=0; i < length; i++) {
  1322. value[i+offset] = read_boolean();
  1323. }
  1324. }
  1325. public final void read_char_array(char[] value, int offset, int length) {
  1326. for(int i=0; i < length; i++) {
  1327. value[i+offset] = read_char();
  1328. }
  1329. }
  1330. public final void read_wchar_array(char[] value, int offset, int length) {
  1331. for(int i=0; i < length; i++) {
  1332. value[i+offset] = read_wchar();
  1333. }
  1334. }
  1335. public final void read_short_array(short[] value, int offset, int length) {
  1336. for(int i=0; i < length; i++) {
  1337. value[i+offset] = read_short();
  1338. }
  1339. }
  1340. public final void read_ushort_array(short[] value, int offset, int length) {
  1341. read_short_array(value, offset, length);
  1342. }
  1343. public final void read_long_array(int[] value, int offset, int length) {
  1344. for(int i=0; i < length; i++) {
  1345. value[i+offset] = read_long();
  1346. }
  1347. }
  1348. public final void read_ulong_array(int[] value, int offset, int length) {
  1349. read_long_array(value, offset, length);
  1350. }
  1351. public final void read_longlong_array(long[] value, int offset, int length) {
  1352. for(int i=0; i < length; i++) {
  1353. value[i+offset] = read_longlong();
  1354. }
  1355. }
  1356. public final void read_ulonglong_array(long[] value, int offset, int length) {
  1357. read_longlong_array(value, offset, length);
  1358. }
  1359. public final void read_float_array(float[] value, int offset, int length) {
  1360. for(int i=0; i < length; i++) {
  1361. value[i+offset] = read_float();
  1362. }
  1363. }
  1364. public final void read_double_array(double[] value, int offset, int length) {
  1365. for(int i=0; i < length; i++) {
  1366. value[i+offset] = read_double();
  1367. }
  1368. }
  1369. public final void read_any_array(org.omg.CORBA.Any[] value, int offset, int length) {
  1370. for(int i=0; i < length; i++) {
  1371. value[i+offset] = read_any();
  1372. }
  1373. }
  1374. //--------------------------------------------------------------------//
  1375. // CDRInputStream state management.
  1376. //
  1377. /**
  1378. * Are we at the end of the input stream?
  1379. */
  1380. // public final boolean isAtEnd() {
  1381. // return bbwi.position() == bbwi.buflen;
  1382. // }
  1383. // public int available() throws IOException {
  1384. // return bbwi.buflen - bbwi.position();
  1385. // }
  1386. private String read_repositoryIds() {
  1387. // Read # of repository ids
  1388. int numRepIds = read_long();
  1389. if (numRepIds == 0xffffffff) {
  1390. int indirection = read_long() + get_offset() - 4;
  1391. if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
  1392. return (String)repositoryIdCache.getKey(indirection);
  1393. else
  1394. throw wrapper.unableToLocateRepIdArray( new Integer( indirection ) ) ;
  1395. } else {
  1396. // read first array element and store it as an indirection to the whole array
  1397. int indirection = get_offset();
  1398. String repID = read_repositoryId();
  1399. if (repositoryIdCache == null)
  1400. repositoryIdCache = new CacheTable(orb,false);
  1401. repositoryIdCache.put(repID, indirection);
  1402. // read and ignore the subsequent array elements, but put them in the
  1403. // indirection table in case there are later indirections back to them
  1404. for (int i = 1; i < numRepIds; i++) {
  1405. read_repositoryId();
  1406. }
  1407. return repID;
  1408. }
  1409. }
  1410. private final String read_repositoryId()
  1411. {
  1412. String result = readStringOrIndirection(true);
  1413. if (result == null) { // Indirection
  1414. int indirection = read_long() + get_offset() - 4;
  1415. if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
  1416. return (String)repositoryIdCache.getKey(indirection);
  1417. else
  1418. throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE,
  1419. new Integer(bbwi.position()) ) ;
  1420. } else {
  1421. if (repositoryIdCache == null)
  1422. repositoryIdCache = new CacheTable(orb,false);
  1423. repositoryIdCache.put(result, stringIndirection);
  1424. }
  1425. return result ;
  1426. }
  1427. private final String read_codebase_URL()
  1428. {
  1429. String result = readStringOrIndirection(true);
  1430. if (result == null) { // Indirection
  1431. int indirection = read_long() + get_offset() - 4;
  1432. if (codebaseCache != null && codebaseCache.containsVal(indirection))
  1433. return (String)codebaseCache.getKey(indirection);
  1434. else
  1435. throw wrapper.badCodebaseIndirection(
  1436. CompletionStatus.COMPLETED_MAYBE,
  1437. new Integer(bbwi.position()) ) ;
  1438. } else {
  1439. if (codebaseCache == null)
  1440. codebaseCache = new CacheTable(orb,false);
  1441. codebaseCache.put(result, stringIndirection);
  1442. }
  1443. return result;
  1444. }
  1445. /* DataInputStream methods */
  1446. public java.lang.Object read_Abstract () {
  1447. return read_abstract_interface();
  1448. }
  1449. public java.io.Serializable read_Value () {
  1450. return read_value();
  1451. }
  1452. public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
  1453. read_any_array(seq.value, offset, length);
  1454. }
  1455. public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
  1456. read_boolean_array(seq.value, offset, length);
  1457. }
  1458. public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
  1459. read_char_array(seq.value, offset, length);
  1460. }
  1461. public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
  1462. read_wchar_array(seq.value, offset, length);
  1463. }
  1464. public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
  1465. read_octet_array(seq.value, offset, length);
  1466. }
  1467. public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
  1468. read_short_array(seq.value, offset, length);
  1469. }
  1470. public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
  1471. read_ushort_array(seq.value, offset, length);
  1472. }
  1473. public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
  1474. read_long_array(seq.value, offset, length);
  1475. }
  1476. public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
  1477. read_ulong_array(seq.value, offset, length);
  1478. }
  1479. public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
  1480. read_ulonglong_array(seq.value, offset, length);
  1481. }
  1482. public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
  1483. read_longlong_array(seq.value, offset, length);
  1484. }
  1485. public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
  1486. read_float_array(seq.value, offset, length);
  1487. }
  1488. public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
  1489. read_double_array(seq.value, offset, length);
  1490. }
  1491. public java.math.BigDecimal read_fixed(short digits, short scale) {
  1492. // digits isn't really needed here
  1493. StringBuffer buffer = read_fixed_buffer();
  1494. if (digits != buffer.length())
  1495. throw wrapper.badFixed( new Integer(digits),
  1496. new Integer(buffer.length()) ) ;
  1497. buffer.insert(digits - scale, '.');
  1498. return new BigDecimal(buffer.toString());
  1499. }
  1500. // This method is unable to yield the correct scale.
  1501. public java.math.BigDecimal read_fixed() {
  1502. return new BigDecimal(read_fixed_buffer().toString());
  1503. }
  1504. // Each octet contains (up to) two decimal digits.
  1505. // If the fixed type has an odd number of decimal digits, then the representation
  1506. // begins with the first (most significant) digit.
  1507. // Otherwise, this first half-octet is all zero, and the first digit
  1508. // is in the second half-octet.
  1509. // The sign configuration, in the last half-octet of the representation,
  1510. // is 0xD for negative numbers and 0xC for positive and zero values.
  1511. private StringBuffer read_fixed_buffer() {
  1512. StringBuffer buffer = new StringBuffer(64);
  1513. byte doubleDigit;
  1514. int firstDigit;
  1515. int secondDigit;
  1516. boolean wroteFirstDigit = false;
  1517. boolean more = true;
  1518. while (more) {
  1519. doubleDigit = this.read_octet();
  1520. firstDigit = (int)((doubleDigit & 0xf0) >> 4);
  1521. secondDigit = (int)(doubleDigit & 0x0f);
  1522. if (wroteFirstDigit || firstDigit != 0) {
  1523. buffer.append(Character.forDigit(firstDigit, 10));
  1524. wroteFirstDigit = true;
  1525. }
  1526. if (secondDigit == 12) {
  1527. // positive number or zero
  1528. if ( ! wroteFirstDigit) {
  1529. // zero
  1530. return new StringBuffer("0.0");
  1531. } else {
  1532. // positive number
  1533. // done
  1534. }
  1535. more = false;
  1536. } else if (secondDigit == 13) {
  1537. // negative number
  1538. buffer.insert(0, '-');
  1539. more = false;
  1540. } else {
  1541. buffer.append(Character.forDigit(secondDigit, 10));
  1542. wroteFirstDigit = true;
  1543. }
  1544. }
  1545. return buffer;
  1546. }
  1547. private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0";
  1548. private final static String[] _ids = { _id };
  1549. public String[] _truncatable_ids() {
  1550. if (_ids == null)
  1551. return null;
  1552. return (String[])_ids.clone();
  1553. }
  1554. /* for debugging */
  1555. public void printBuffer() {
  1556. CDRInputStream_1_0.printBuffer(this.bbwi);
  1557. }
  1558. public static void printBuffer(ByteBufferWithInfo bbwi) {
  1559. System.out.println("----- Input Buffer -----");
  1560. System.out.println();
  1561. System.out.println("Current position: " + bbwi.position());
  1562. System.out.println("Total length : " + bbwi.buflen);
  1563. System.out.println();
  1564. try {
  1565. char[] charBuf = new char[16];
  1566. for (int i = 0; i < bbwi.buflen; i += 16) {
  1567. int j = 0;
  1568. // For every 16 bytes, there is one line
  1569. // of output. First, the hex output of
  1570. // the 16 bytes with each byte separated
  1571. // by a space.
  1572. while (j < 16 && j + i < bbwi.buflen) {
  1573. int k = bbwi.byteBuffer.get(i + j);
  1574. if (k < 0)
  1575. k = 256 + k;
  1576. String hex = Integer.toHexString(k);
  1577. if (hex.length() == 1)
  1578. hex = "0" + hex;
  1579. System.out.print(hex + " ");
  1580. j++;
  1581. }
  1582. // Add any extra spaces to align the
  1583. // text column in case we didn't end
  1584. // at 16
  1585. while (j < 16) {
  1586. System.out.print(" ");
  1587. j++;
  1588. }
  1589. // Now output the ASCII equivalents. Non-ASCII
  1590. // characters are shown as periods.
  1591. int x = 0;
  1592. while (x < 16 && x + i < bbwi.buflen) {
  1593. if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
  1594. charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
  1595. else
  1596. charBuf[x] = '.';
  1597. x++;
  1598. }
  1599. System.out.println(new String(charBuf, 0, x));
  1600. }
  1601. } catch (Throwable t) {
  1602. t.printStackTrace();
  1603. }
  1604. System.out.println("------------------------");
  1605. }
  1606. public ByteBuffer getByteBuffer() {
  1607. ByteBuffer result = null;
  1608. if (bbwi != null) {
  1609. result = bbwi.byteBuffer;
  1610. }
  1611. return result;
  1612. }
  1613. public int getBufferLength() {
  1614. return bbwi.buflen;
  1615. }
  1616. public void setBufferLength(int value) {
  1617. bbwi.buflen = value;
  1618. bbwi.byteBuffer.limit(bbwi.buflen);
  1619. }
  1620. public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
  1621. this.bbwi = bbwi;
  1622. }
  1623. public void setByteBuffer(ByteBuffer byteBuffer) {
  1624. bbwi.byteBuffer = byteBuffer;
  1625. }
  1626. public int getIndex() {
  1627. return bbwi.position();
  1628. }
  1629. public void setIndex(int value) {
  1630. bbwi.position(value);
  1631. }
  1632. public boolean isLittleEndian() {
  1633. return littleEndian;
  1634. }
  1635. public void orb(org.omg.CORBA.ORB orb) {
  1636. this.orb = (ORB)orb;
  1637. }
  1638. public BufferManagerRead getBufferManager() {
  1639. return bufferManagerRead;
  1640. }
  1641. private void skipToOffset(int offset) {
  1642. // Number of bytes to skip
  1643. int len = offset - get_offset();
  1644. int n = 0;
  1645. while (n < len) {
  1646. int avail;
  1647. int bytes;
  1648. int wanted;
  1649. avail = bbwi.buflen - bbwi.position();
  1650. if (avail <= 0) {
  1651. grow(1, 1);
  1652. avail = bbwi.buflen - bbwi.position();
  1653. }
  1654. wanted = len - n;
  1655. bytes = (wanted < avail) ? wanted : avail;
  1656. bbwi.position(bbwi.position() + bytes);
  1657. n += bytes;
  1658. }
  1659. }
  1660. // Mark and reset -------------------------------------------------
  1661. protected MarkAndResetHandler markAndResetHandler = null;
  1662. protected class StreamMemento
  1663. {
  1664. // These are the fields that may change after marking
  1665. // the stream position, so we need to save them.
  1666. private int blockLength_;
  1667. private int end_flag_;
  1668. private int chunkedValueNestingLevel_;
  1669. private int valueIndirection_;
  1670. private int stringIndirection_;
  1671. private boolean isChunked_;
  1672. private javax.rmi.CORBA.ValueHandler valueHandler_;
  1673. private ByteBufferWithInfo bbwi_;
  1674. private boolean specialNoOptionalDataState_;
  1675. public StreamMemento()
  1676. {
  1677. blockLength_ = blockLength;
  1678. end_flag_ = end_flag;
  1679. chunkedValueNestingLevel_ = chunkedValueNestingLevel;
  1680. valueIndirection_ = valueIndirection;
  1681. stringIndirection_ = stringIndirection;
  1682. isChunked_ = isChunked;
  1683. valueHandler_ = valueHandler;
  1684. specialNoOptionalDataState_ = specialNoOptionalDataState;
  1685. bbwi_ = new ByteBufferWithInfo(bbwi);
  1686. }
  1687. }
  1688. public java.lang.Object createStreamMemento() {
  1689. return new StreamMemento();
  1690. }
  1691. public void restoreInternalState(java.lang.Object streamMemento) {
  1692. StreamMemento mem = (StreamMemento)streamMemento;
  1693. blockLength = mem.blockLength_;
  1694. end_flag = mem.end_flag_;
  1695. chunkedValueNestingLevel = mem.chunkedValueNestingLevel_;
  1696. valueIndirection = mem.valueIndirection_;
  1697. stringIndirection = mem.stringIndirection_;
  1698. isChunked = mem.isChunked_;
  1699. valueHandler = mem.valueHandler_;
  1700. specialNoOptionalDataState = mem.specialNoOptionalDataState_;
  1701. bbwi = mem.bbwi_;
  1702. }
  1703. public int getPosition() {
  1704. return get_offset();
  1705. }
  1706. public void mark(int readlimit) {
  1707. markAndResetHandler.mark(this);
  1708. }
  1709. public void reset() {
  1710. markAndResetHandler.reset();
  1711. }
  1712. // ---------------------------------- end Mark and Reset
  1713. // Provides a hook so subclasses of CDRInputStream can provide
  1714. // a CodeBase. This ultimately allows us to grab a Connection
  1715. // instance in IIOPInputStream, the only subclass where this
  1716. // is actually used.
  1717. CodeBase getCodeBase() {
  1718. return parent.getCodeBase();
  1719. }
  1720. /**
  1721. * Attempts to find the class described by the given
  1722. * repository ID string and expected type. The first
  1723. * attempt is to find the class locally, falling back
  1724. * on the URL that came with the value. The second
  1725. * attempt is to use a URL from the remote CodeBase.
  1726. */
  1727. private Class getClassFromString(String repositoryIDString,
  1728. String codebaseURL,
  1729. Class expectedType)
  1730. {
  1731. RepositoryIdInterface repositoryID
  1732. = repIdStrs.getFromString(repositoryIDString);
  1733. try {
  1734. try {
  1735. // First try to load the class locally, then use
  1736. // the provided URL (if it isn't null)
  1737. return repositoryID.getClassFromType(expectedType,
  1738. codebaseURL);
  1739. } catch (ClassNotFoundException cnfeOuter) {
  1740. try {
  1741. if (getCodeBase() == null) {
  1742. return null; // class cannot be loaded remotely.
  1743. }
  1744. // Get a URL from the remote CodeBase and retry
  1745. codebaseURL = getCodeBase().implementation(repositoryIDString);
  1746. // Don't bother trying to find it locally again if
  1747. // we got a null URL
  1748. if (codebaseURL == null)
  1749. return null;
  1750. return repositoryID.getClassFromType(expectedType,
  1751. codebaseURL);
  1752. } catch (ClassNotFoundException cnfeInner) {
  1753. dprintThrowable(cnfeInner);
  1754. // Failed to load the class
  1755. return null;
  1756. }
  1757. }
  1758. } catch (MalformedURLException mue) {
  1759. // Always report a bad URL
  1760. throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  1761. mue, repositoryIDString, codebaseURL ) ;
  1762. }
  1763. }
  1764. /**
  1765. * Attempts to find the class described by the given
  1766. * repository ID string. At most, three attempts are made:
  1767. * Try to find it locally, through the provided URL, and
  1768. * finally, via a URL from the remote CodeBase.
  1769. */
  1770. private Class getClassFromString(String repositoryIDString,
  1771. String codebaseURL)
  1772. {
  1773. RepositoryIdInterface repositoryID
  1774. = repIdStrs.getFromString(repositoryIDString);
  1775. for (int i = 0; i < 3; i++) {
  1776. try {
  1777. switch (i)
  1778. {
  1779. case 0:
  1780. // First try to load the class locally
  1781. return repositoryID.getClassFromType();
  1782. case 1:
  1783. // Try to load the class using the provided
  1784. // codebase URL (falls out below)
  1785. break;
  1786. case 2:
  1787. // Try to load the class using a URL from the
  1788. // remote CodeBase
  1789. codebaseURL = getCodeBase().implementation(repositoryIDString);
  1790. break;
  1791. }
  1792. // Don't bother if the codebaseURL is null
  1793. if (codebaseURL == null)
  1794. continue;
  1795. return repositoryID.getClassFromType(codebaseURL);
  1796. } catch(ClassNotFoundException cnfe) {
  1797. // Will ultimately return null if all three
  1798. // attempts fail, but don't do anything here.
  1799. } catch (MalformedURLException mue) {
  1800. throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  1801. mue, repositoryIDString, codebaseURL ) ;
  1802. }
  1803. }
  1804. // If we get here, we have failed to load the class
  1805. dprint("getClassFromString failed with rep id "
  1806. + repositoryIDString
  1807. + " and codebase "
  1808. + codebaseURL);
  1809. return null;
  1810. }
  1811. // Utility method used to get chars from bytes
  1812. char[] getConvertedChars(int numBytes,
  1813. CodeSetConversion.BTCConverter converter) {
  1814. // REVISIT - Look at CodeSetConversion.BTCConverter to see
  1815. // if it can work with an NIO ByteBuffer. We should
  1816. // avoid getting the bytes into an array if possible.
  1817. // To be honest, I doubt this saves much real time
  1818. if (bbwi.buflen - bbwi.position() >= numBytes) {
  1819. // If the entire string is in this buffer,
  1820. // just convert directly from the bbwi rather than
  1821. // allocating and copying.
  1822. byte[] tmpBuf;
  1823. if (bbwi.byteBuffer.hasArray())
  1824. {
  1825. tmpBuf = bbwi.byteBuffer.array();
  1826. }
  1827. else
  1828. {
  1829. tmpBuf = new byte[bbwi.buflen];
  1830. // Microbenchmarks are showing a loop of ByteBuffer.get(int)
  1831. // being faster than ByteBuffer.get(byte[], int, int).
  1832. for (int i = 0; i < bbwi.buflen; i++)
  1833. tmpBuf[i] = bbwi.byteBuffer.get(i);
  1834. }
  1835. char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes);
  1836. bbwi.position(bbwi.position() + numBytes);
  1837. return result;
  1838. } else {
  1839. // Stretches across buffers. Unless we provide an
  1840. // incremental conversion interface, allocate and
  1841. // copy the bytes.
  1842. byte[] bytes = new byte[numBytes];
  1843. read_octet_array(bytes, 0, bytes.length);
  1844. return converter.getChars(bytes, 0, numBytes);
  1845. }
  1846. }
  1847. protected CodeSetConversion.BTCConverter getCharConverter() {
  1848. if (charConverter == null)
  1849. charConverter = parent.createCharBTCConverter();
  1850. return charConverter;
  1851. }
  1852. protected CodeSetConversion.BTCConverter getWCharConverter() {
  1853. if (wcharConverter == null)
  1854. wcharConverter = parent.createWCharBTCConverter();
  1855. return wcharConverter;
  1856. }
  1857. protected void dprintThrowable(Throwable t) {
  1858. if (debug && t != null)
  1859. t.printStackTrace();
  1860. }
  1861. protected void dprint(String msg) {
  1862. if (debug) {
  1863. ORBUtility.dprint(this, msg);
  1864. }
  1865. }
  1866. /**
  1867. * Aligns the current position on the given octet boundary
  1868. * if there are enough bytes available to do so. Otherwise,
  1869. * it just returns. This is used for some (but not all)
  1870. * GIOP 1.2 message headers.
  1871. */
  1872. void alignOnBoundary(int octetBoundary) {
  1873. int needed = computeAlignment(bbwi.position(), octetBoundary);
  1874. if (bbwi.position() + needed <= bbwi.buflen)
  1875. {
  1876. bbwi.position(bbwi.position() + needed);
  1877. }
  1878. }
  1879. public void resetCodeSetConverters() {
  1880. charConverter = null;
  1881. wcharConverter = null;
  1882. }
  1883. public void start_value() {
  1884. // Read value tag
  1885. int vType = readValueTag();
  1886. if (vType == 0) {
  1887. // Stream needs to go into a state where it
  1888. // throws standard exception until end_value
  1889. // is called. This means the sender didn't
  1890. // send any custom data. If the reader here
  1891. // tries to read more, we need to throw an
  1892. // exception before reading beyond where
  1893. // we're supposed to
  1894. specialNoOptionalDataState = true;
  1895. return;
  1896. }
  1897. if (vType == 0xffffffff) {
  1898. // One should never indirect to a custom wrapper
  1899. throw wrapper.customWrapperIndirection(
  1900. CompletionStatus.COMPLETED_MAYBE);
  1901. }
  1902. if (repIdUtil.isCodeBasePresent(vType)) {
  1903. throw wrapper.customWrapperWithCodebase(
  1904. CompletionStatus.COMPLETED_MAYBE);
  1905. }
  1906. if (repIdUtil.getTypeInfo(vType)
  1907. != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) {
  1908. throw wrapper.customWrapperNotSingleRepid(
  1909. CompletionStatus.COMPLETED_MAYBE);
  1910. }
  1911. // REVISIT - Could verify repository ID even though
  1912. // it isn't used elsewhere
  1913. read_repositoryId();
  1914. // Note: isChunked should be true here. Should have
  1915. // been set to true in the containing value's read_value
  1916. // method.
  1917. start_block();
  1918. end_flag--;
  1919. chunkedValueNestingLevel--;
  1920. }
  1921. public void end_value() {
  1922. if (specialNoOptionalDataState) {
  1923. specialNoOptionalDataState = false;
  1924. return;
  1925. }
  1926. handleEndOfValue();
  1927. readEndTag();
  1928. // Note that isChunked should still be true here.
  1929. // If the containing valuetype is the highest
  1930. // chunked value, it will get set to false
  1931. // at the end of read_value.
  1932. // allow for possible continuation chunk
  1933. start_block();
  1934. }
  1935. public void close() throws IOException
  1936. {
  1937. // tell BufferManagerRead to release any ByteBuffers
  1938. getBufferManager().close(bbwi);
  1939. // It's possible bbwi.byteBuffer is shared between
  1940. // this InputStream and an OutputStream. Thus, we check
  1941. // if the Input/Output streams are using the same ByteBuffer.
  1942. // If they sharing the same ByteBuffer we need to ensure only
  1943. // one of those ByteBuffers are released to the ByteBufferPool.
  1944. if (bbwi != null && getByteBuffer() != null)
  1945. {
  1946. int bbHash = System.identityHashCode(bbwi.byteBuffer);
  1947. MessageMediator messageMediator = parent.getMessageMediator();
  1948. if (messageMediator != null)
  1949. {
  1950. CDROutputObject outputObj =
  1951. (CDROutputObject)messageMediator.getOutputObject();
  1952. if (outputObj != null)
  1953. {
  1954. ByteBuffer outputBb = outputObj.getByteBuffer();
  1955. int oBbHash = 0;
  1956. if (outputBb != null)
  1957. {
  1958. oBbHash = System.identityHashCode(outputBb);
  1959. if (bbHash == oBbHash) // shared?
  1960. {
  1961. // Set OutputStream's ByteBuffer and bbwi to null
  1962. // so its ByteBuffer cannot be released to the pool
  1963. outputObj.setByteBuffer(null);
  1964. outputObj.setByteBufferWithInfo(null);
  1965. }
  1966. }
  1967. }
  1968. }
  1969. // release this stream's ByteBuffer to the pool
  1970. ByteBufferPool byteBufferPool = orb.getByteBufferPool();
  1971. if (debug)
  1972. {
  1973. // print address of ByteBuffer being released
  1974. int bbAddress = System.identityHashCode(bbwi.byteBuffer);
  1975. StringBuffer sb = new StringBuffer(80);
  1976. sb.append(".close - releasing ByteBuffer id (");
  1977. sb.append(bbAddress).append(") to ByteBufferPool.");
  1978. String msg = sb.toString();
  1979. dprint(msg);
  1980. }
  1981. byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
  1982. bbwi.byteBuffer = null;
  1983. bbwi = null;
  1984. }
  1985. }
  1986. }