1. /*
  2. * @(#)CDROutputStream_1_0.java 1.107 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.internal.iiop;
  16. import java.io.ByteArrayOutputStream;
  17. import java.io.IOException;
  18. import org.omg.CORBA.SystemException;
  19. import org.omg.CORBA.CompletionStatus;
  20. import org.omg.CORBA.INTERNAL;
  21. import org.omg.CORBA.MARSHAL;
  22. import org.omg.CORBA.DATA_CONVERSION;
  23. import org.omg.CORBA.BAD_INV_ORDER;
  24. import org.omg.CORBA.BAD_OPERATION;
  25. import org.omg.CORBA.BAD_PARAM;
  26. import org.omg.CORBA.Object;
  27. import org.omg.CORBA.Principal;
  28. import org.omg.CORBA.TypeCode;
  29. import org.omg.CORBA.Any;
  30. import org.omg.CORBA.portable.ObjectImpl;
  31. import org.omg.CORBA.portable.OutputStream;
  32. import org.omg.CORBA.portable.ValueBase;
  33. import org.omg.CORBA.NO_IMPLEMENT;
  34. import org.omg.CORBA.CompletionStatus;
  35. import org.omg.CORBA.portable.IDLEntity;
  36. import org.omg.CORBA.VM_CUSTOM;
  37. import org.omg.CORBA.VM_TRUNCATABLE;
  38. import org.omg.CORBA.VM_NONE;
  39. import java.rmi.Remote;
  40. import java.io.Serializable;
  41. import java.lang.reflect.Method;
  42. import java.lang.reflect.InvocationTargetException;
  43. import java.io.ByteArrayOutputStream;
  44. import java.io.ObjectOutputStream;
  45. import com.sun.corba.se.internal.orbutil.MinorCodes;
  46. import com.sun.corba.se.internal.core.MarshalOutputStream;
  47. import com.sun.corba.se.internal.core.IOR;
  48. import com.sun.corba.se.internal.core.ClientSubcontract;
  49. import com.sun.corba.se.internal.corba.TypeCodeImpl;
  50. import com.sun.org.omg.CORBA.portable.ValueHelper;
  51. import org.omg.CORBA.portable.CustomValue;
  52. import org.omg.CORBA.portable.StreamableValue;
  53. import org.omg.CORBA.CustomMarshal;
  54. import org.omg.CORBA.DataOutputStream;
  55. import org.omg.CORBA.portable.BoxedValueHelper;
  56. import org.omg.CORBA.TypeCodePackage.BadKind;
  57. import java.io.IOException;
  58. import java.util.Hashtable;
  59. import java.util.Stack;
  60. import com.sun.corba.se.internal.orbutil.CacheTable;
  61. import com.sun.corba.se.internal.orbutil.ORBUtility;
  62. import com.sun.corba.se.internal.orbutil.RepositoryIdStrings;
  63. import com.sun.corba.se.internal.orbutil.RepositoryIdUtility;
  64. import com.sun.corba.se.internal.orbutil.RepositoryIdFactory;
  65. import com.sun.corba.se.internal.core.ORBVersionImpl;
  66. import com.sun.corba.se.internal.core.ORBVersion;
  67. import com.sun.corba.se.internal.core.GIOPVersion;
  68. import com.sun.corba.se.internal.util.Utility;
  69. import com.sun.corba.se.internal.iiop.ByteBufferWithInfo;
  70. import javax.rmi.CORBA.Util;
  71. import java.math.BigDecimal;
  72. import javax.rmi.CORBA.ValueHandler;
  73. import com.sun.corba.se.internal.core.CodeSetConversion;
  74. import java.security.AccessController;
  75. import java.security.PrivilegedExceptionAction;
  76. import java.security.PrivilegedActionException;
  77. public class CDROutputStream_1_0 extends CDROutputStreamBase
  78. {
  79. private static final int INDIRECTION_TAG = 0xffffffff;
  80. protected boolean littleEndian;
  81. protected BufferManagerWrite bufferManagerWrite;
  82. ByteBufferWithInfo bbwi;
  83. protected com.sun.corba.se.internal.corba.ORB orb;
  84. protected boolean debug = false;
  85. protected int blockSizeIndex = -1;
  86. protected int blockSizePosition = 0;
  87. private static final int DEFAULT_BUFFER_SIZE = 1024;
  88. private static final String kWriteMethod = "write";
  89. // Codebase cache
  90. private CacheTable codebaseCache = null;
  91. // Value cache
  92. private CacheTable valueCache = null;
  93. // Repository ID cache
  94. private CacheTable repositoryIdCache = null;
  95. // Write end flag
  96. private int end_flag = 0;
  97. // Beginning with the resolution to interop issue 4328,
  98. // only enclosing chunked valuetypes are taken into account
  99. // when computing the nesting level. However, we still need
  100. // the old computation around for interoperability with our
  101. // older ORBs.
  102. private int chunkedValueNestingLevel = 0;
  103. // Nesting custom marshaling - used to tell whether we can skip chunking
  104. private boolean mustChunk = false;
  105. // In block marker
  106. protected boolean inBlock = false;
  107. // Last end tag position
  108. private int end_flag_position = 0;
  109. private int end_flag_index = 0;
  110. // ValueHandler
  111. private ValueHandler valueHandler = null;
  112. // Repository ID handlers
  113. private RepositoryIdUtility repIdUtil;
  114. private RepositoryIdStrings repIdStrs;
  115. // Code set converters (created when first needed)
  116. private CodeSetConversion.CTBConverter charConverter;
  117. private CodeSetConversion.CTBConverter wcharConverter;
  118. protected void init(org.omg.CORBA.ORB orb,
  119. boolean littleEndian,
  120. int size,
  121. BufferManagerWrite bufferManager)
  122. {
  123. this.orb = (com.sun.corba.se.internal.corba.ORB)orb;
  124. if (this.orb != null)
  125. debug = this.orb.transportDebugFlag;
  126. this.littleEndian = littleEndian;
  127. this.bufferManagerWrite = bufferManager;
  128. this.bbwi = bufferManagerWrite.getInitialBuffer(size);
  129. createRepositoryIdHandlers();
  130. }
  131. private final void createRepositoryIdHandlers()
  132. {
  133. if (orb != null) {
  134. // Get the appropriate versions based on the ORB version. The
  135. // ORB versioning info is only in the corba ORB.
  136. repIdUtil
  137. = RepositoryIdFactory.getRepIdUtility(orb);
  138. repIdStrs
  139. = RepositoryIdFactory.getRepIdStringsFactory(orb);
  140. } else {
  141. // Get the latest versions
  142. repIdUtil = RepositoryIdFactory.getRepIdUtility();
  143. repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
  144. }
  145. }
  146. public BufferManagerWrite getBufferManager()
  147. {
  148. return bufferManagerWrite;
  149. }
  150. public byte[] toByteArray() {
  151. byte[] it;
  152. it = new byte[bbwi.index];
  153. System.arraycopy(bbwi.buf, 0, it, 0, bbwi.index);
  154. return it;
  155. }
  156. public GIOPVersion getGIOPVersion() {
  157. return GIOPVersion.V1_0;
  158. }
  159. protected void handleSpecialChunkBegin(int requiredSize)
  160. {
  161. // No-op for GIOP 1.0
  162. }
  163. protected void handleSpecialChunkEnd()
  164. {
  165. // No-op for GIOP 1.0
  166. }
  167. protected final int computeAlignment(int align) {
  168. if (align > 1) {
  169. int incr = bbwi.index & (align - 1);
  170. if (incr != 0)
  171. return align - incr;
  172. }
  173. return 0;
  174. }
  175. protected void alignAndReserve(int align, int n) {
  176. bbwi.index += computeAlignment(align);
  177. if (bbwi.index + n > bbwi.buflen)
  178. grow(align, n);
  179. }
  180. //
  181. // Default implementation of grow. Subclassers may override this.
  182. // Always grow the single buffer. This needs to delegate
  183. // fragmentation policy for IIOP 1.1.
  184. //
  185. protected void grow(int align, int n)
  186. {
  187. bbwi.needed = n;
  188. bufferManagerWrite.overflow(bbwi);
  189. }
  190. public final void putEndian() throws SystemException {
  191. write_boolean(littleEndian);
  192. }
  193. public final boolean littleEndian() {
  194. return littleEndian;
  195. }
  196. void freeInternalCaches() {
  197. if (codebaseCache != null)
  198. codebaseCache.done();
  199. if (valueCache != null)
  200. valueCache.done();
  201. if (repositoryIdCache != null)
  202. repositoryIdCache.done();
  203. }
  204. // No such type in java
  205. public final void write_longdouble(double x)
  206. {
  207. throw new NO_IMPLEMENT(MinorCodes.SEND_DEFERRED_NOTIMPLEMENTED,
  208. CompletionStatus.COMPLETED_MAYBE);
  209. }
  210. public void write_octet(byte x)
  211. {
  212. if (bbwi.index + 1 > bbwi.buflen)
  213. alignAndReserve(1, 1);
  214. bbwi.buf[bbwi.index++] = x;
  215. }
  216. public final void write_boolean(boolean x)
  217. {
  218. write_octet(x? (byte)1:(byte)0);
  219. }
  220. public void write_char(char x)
  221. {
  222. CodeSetConversion.CTBConverter converter = getCharConverter();
  223. converter.convert(x);
  224. // CORBA formal 99-10-07 15.3.1.6: "In the case of multi-byte encodings
  225. // of characters, a single instance of the char type may only
  226. // hold one octet of any multi-byte character encoding."
  227. if (converter.getNumBytes() > 1)
  228. throw new DATA_CONVERSION(MinorCodes.INVALID_SINGLE_CHAR_CTB,
  229. CompletionStatus.COMPLETED_MAYBE);
  230. write_octet(converter.getBytes()[0]);
  231. }
  232. // These wchar methods are only used when talking to
  233. // legacy ORBs, now.
  234. private final void writeLittleEndianWchar(char x) {
  235. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  236. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  237. }
  238. private final void writeBigEndianWchar(char x) {
  239. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  240. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  241. }
  242. private final void writeLittleEndianShort(short x) {
  243. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  244. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  245. }
  246. private final void writeBigEndianShort(short x) {
  247. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  248. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  249. }
  250. private final void writeLittleEndianLong(int x) {
  251. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  252. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  253. bbwi.buf[bbwi.index++] = (byte)((x >>> 16) & 0xFF);
  254. bbwi.buf[bbwi.index++] = (byte)((x >>> 24) & 0xFF);
  255. }
  256. private final void writeBigEndianLong(int x) {
  257. bbwi.buf[bbwi.index++] = (byte)((x >>> 24) & 0xFF);
  258. bbwi.buf[bbwi.index++] = (byte)((x >>> 16) & 0xFF);
  259. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  260. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  261. }
  262. private final void writeLittleEndianLongLong(long x) {
  263. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  264. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  265. bbwi.buf[bbwi.index++] = (byte)((x >>> 16) & 0xFF);
  266. bbwi.buf[bbwi.index++] = (byte)((x >>> 24) & 0xFF);
  267. bbwi.buf[bbwi.index++] = (byte)((x >>> 32) & 0xFF);
  268. bbwi.buf[bbwi.index++] = (byte)((x >>> 40) & 0xFF);
  269. bbwi.buf[bbwi.index++] = (byte)((x >>> 48) & 0xFF);
  270. bbwi.buf[bbwi.index++] = (byte)((x >>> 56) & 0xFF);
  271. }
  272. private final void writeBigEndianLongLong(long x) {
  273. bbwi.buf[bbwi.index++] = (byte)((x >>> 56) & 0xFF);
  274. bbwi.buf[bbwi.index++] = (byte)((x >>> 48) & 0xFF);
  275. bbwi.buf[bbwi.index++] = (byte)((x >>> 40) & 0xFF);
  276. bbwi.buf[bbwi.index++] = (byte)((x >>> 32) & 0xFF);
  277. bbwi.buf[bbwi.index++] = (byte)((x >>> 24) & 0xFF);
  278. bbwi.buf[bbwi.index++] = (byte)((x >>> 16) & 0xFF);
  279. bbwi.buf[bbwi.index++] = (byte)((x >>> 8) & 0xFF);
  280. bbwi.buf[bbwi.index++] = (byte)(x & 0xFF);
  281. }
  282. public void write_wchar(char x)
  283. {
  284. // Don't allow transmission of wchar/wstring data with
  285. // foreign ORBs since it's against the spec.
  286. if (ORBUtility.isForeignORB(orb)) {
  287. throw new MARSHAL(MinorCodes.WCHAR_DATA_IN_GIOP_1_0,
  288. CompletionStatus.COMPLETED_MAYBE);
  289. }
  290. // If it's one of our legacy ORBs, do what they did:
  291. alignAndReserve(2, 2);
  292. if (littleEndian) {
  293. writeLittleEndianWchar(x);
  294. } else {
  295. writeBigEndianWchar(x);
  296. }
  297. }
  298. public void write_short(short x)
  299. {
  300. alignAndReserve(2, 2);
  301. if (littleEndian) {
  302. writeLittleEndianShort(x);
  303. } else {
  304. writeBigEndianShort(x);
  305. }
  306. }
  307. public final void write_ushort(short x)
  308. {
  309. write_short(x);
  310. }
  311. public void write_long(int x)
  312. {
  313. alignAndReserve(4, 4);
  314. if (littleEndian) {
  315. writeLittleEndianLong(x);
  316. } else {
  317. writeBigEndianLong(x);
  318. }
  319. }
  320. public final void write_ulong(int x)
  321. {
  322. write_long(x);
  323. }
  324. public void write_longlong(long x)
  325. {
  326. alignAndReserve(8, 8);
  327. if (littleEndian) {
  328. writeLittleEndianLongLong(x);
  329. } else {
  330. writeBigEndianLongLong(x);
  331. }
  332. }
  333. public final void write_ulonglong(long x)
  334. {
  335. write_longlong(x);
  336. }
  337. public final void write_float(float x)
  338. {
  339. write_long(Float.floatToIntBits(x));
  340. }
  341. public final void write_double(double x)
  342. {
  343. write_longlong(Double.doubleToLongBits(x));
  344. }
  345. public void write_string(String value)
  346. {
  347. if (value == null) {
  348. throw new BAD_PARAM(MinorCodes.NULL_PARAM,
  349. CompletionStatus.COMPLETED_MAYBE);
  350. }
  351. CodeSetConversion.CTBConverter converter = getCharConverter();
  352. converter.convert(value);
  353. // A string is encoded as an unsigned CORBA long for the
  354. // number of bytes to follow (including a terminating null).
  355. // There is only one octet per character in the string.
  356. int len = converter.getNumBytes() + 1;
  357. handleSpecialChunkBegin(computeAlignment(4) + 4 + len);
  358. write_long(len);
  359. internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());
  360. // Write the null ending
  361. write_octet((byte)0);
  362. handleSpecialChunkEnd();
  363. }
  364. public void write_wstring(String value)
  365. {
  366. if (value == null)
  367. throw new BAD_PARAM(MinorCodes.NULL_PARAM,
  368. CompletionStatus.COMPLETED_MAYBE);
  369. // Don't allow transmission of wchar/wstring data with
  370. // foreign ORBs since it's against the spec.
  371. if (ORBUtility.isForeignORB(orb)) {
  372. throw new MARSHAL(MinorCodes.WCHAR_DATA_IN_GIOP_1_0,
  373. CompletionStatus.COMPLETED_MAYBE);
  374. }
  375. // When talking to our legacy ORBs, do what they did:
  376. int len = value.length() + 1;
  377. // This will only have an effect if we're already chunking
  378. handleSpecialChunkBegin(4 + (len * 2) + computeAlignment(4));
  379. write_long(len);
  380. for (int i = 0; i < len - 1; i++)
  381. write_wchar(value.charAt(i));
  382. // Write the null ending
  383. write_short((short)0);
  384. // This will only have an effect if we're already chunking
  385. handleSpecialChunkEnd();
  386. }
  387. // Performs no checks and doesn't tamper with chunking
  388. void internalWriteOctetArray(byte[] value, int offset, int length)
  389. {
  390. int n = offset;
  391. while (n < length+offset) {
  392. int avail;
  393. int bytes;
  394. int wanted;
  395. if (bbwi.index + 1 > bbwi.buflen)
  396. alignAndReserve(1, 1);
  397. avail = bbwi.buf.length - bbwi.index;
  398. wanted = (length + offset) - n;
  399. bytes = (wanted < avail) ? wanted : avail;
  400. System.arraycopy(value, n, bbwi.buf, bbwi.index, bytes);
  401. bbwi.index += bytes;
  402. n += bytes;
  403. }
  404. }
  405. public final void write_octet_array(byte b[], int offset, int length)
  406. {
  407. if ( b == null )
  408. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM,
  409. CompletionStatus.COMPLETED_MAYBE);
  410. // This will only have an effect if we're already chunking
  411. handleSpecialChunkBegin(length);
  412. internalWriteOctetArray(b, offset, length);
  413. // This will only have an effect if we're already chunking
  414. handleSpecialChunkEnd();
  415. }
  416. public void write_Principal(Principal p)
  417. {
  418. write_long(p.name().length);
  419. write_octet_array(p.name(), 0, p.name().length);
  420. }
  421. public void write_any(Any any)
  422. {
  423. if ( any == null )
  424. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  425. write_TypeCode(any.type());
  426. any.write_value(parent);
  427. }
  428. public void write_TypeCode(TypeCode tc)
  429. {
  430. if ( tc == null ) {
  431. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  432. }
  433. TypeCodeImpl tci;
  434. if (tc instanceof TypeCodeImpl) {
  435. tci = (TypeCodeImpl)tc;
  436. }
  437. else {
  438. tci = new TypeCodeImpl(orb, tc);
  439. }
  440. tci.write_value(parent);
  441. }
  442. public void write_Object(org.omg.CORBA.Object ref)
  443. {
  444. if (ref == null) {
  445. IOR.NULL.write(parent);
  446. return;
  447. }
  448. // IDL to Java formal 01-06-06 1.21.4.2
  449. if (ref instanceof org.omg.CORBA.LocalObject)
  450. throw new MARSHAL("write_Object called with LocalObject",
  451. MinorCodes.WRITE_LOCAL_OBJECT,
  452. CompletionStatus.COMPLETED_MAYBE);
  453. ObjectImpl oi = (ObjectImpl)ref;
  454. ClientSubcontract rep = null;
  455. try {
  456. // If no delegate set:
  457. // org.omg.CORBA.portable.ObjectImpl throws BAD_OPERATION
  458. // org.omg.PortableServer.Servant throws BAD_INV_ORDER
  459. rep = (ClientSubcontract) oi._get_delegate();
  460. } catch ( BAD_OPERATION ex ) {
  461. debugPrintThrowable(ex);
  462. } catch ( BAD_INV_ORDER ex ) {
  463. debugPrintThrowable(ex);
  464. }
  465. if ( rep == null ) {
  466. // no delegate: servant was not connected to ORB
  467. if (ref instanceof javax.rmi.CORBA.Stub) {
  468. try {
  469. ((javax.rmi.CORBA.Stub)ref).connect(orb);
  470. } catch (java.rmi.RemoteException e) {
  471. debugPrintThrowable(e);
  472. throw new MARSHAL("Error connecting servant: "
  473. + e.getMessage(),
  474. MinorCodes.CONNECTING_SERVANT,
  475. CompletionStatus.COMPLETED_MAYBE);
  476. }
  477. } else {
  478. orb.connect(ref);
  479. }
  480. rep = (ClientSubcontract) oi._get_delegate();
  481. }
  482. IOR ior = rep.marshal();
  483. ior.write(parent);
  484. return;
  485. }
  486. // ------------ RMI related methods --------------------------
  487. public void write_abstract_interface(java.lang.Object obj) {
  488. boolean corbaObject = false; // Assume value type.
  489. org.omg.CORBA.Object theObject = null;
  490. // Is it a CORBA.Object?
  491. if (obj != null && obj instanceof org.omg.CORBA.Object) {
  492. // Yes.
  493. theObject = (org.omg.CORBA.Object)obj;
  494. corbaObject = true;
  495. }
  496. // Write our flag...
  497. write_boolean(corbaObject);
  498. // Now write out the object...
  499. if (corbaObject) {
  500. write_Object(theObject);
  501. } else {
  502. try {
  503. write_value((java.io.Serializable)obj);
  504. } catch(ClassCastException cce) {
  505. if (obj instanceof java.io.Serializable)
  506. throw cce;
  507. else
  508. ORBUtility.throwNotSerializableForCorba(obj.getClass().getName());
  509. }
  510. }
  511. }
  512. public void write_value(Serializable object, Class clz) {
  513. write_value(object);
  514. }
  515. public void write_value(Serializable object, String repository_id) {
  516. // Handle null references
  517. if (object == null) {
  518. // Write null tag and return
  519. write_long(0);
  520. return;
  521. }
  522. // Handle shared references
  523. if ((valueCache != null) && valueCache.containsKey(object)) {
  524. writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
  525. return;
  526. }
  527. Class clazz = object.getClass();
  528. boolean oldMustChunk = mustChunk;
  529. // _REVISIT_ should this be done when mustChunk is false?
  530. if (inBlock)
  531. end_block();
  532. // Handle arrays
  533. if (clazz.isArray())
  534. {
  535. if (valueHandler == null)
  536. valueHandler = ORBUtility.createValueHandler(orb); //d11638
  537. if (mustChunk) {
  538. // Write value_tag
  539. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  540. // Write repository ID
  541. write_repositoryId(repIdStrs.createSequenceRepID(clazz));
  542. // Add indirection for object to indirection table
  543. updateIndirectionTable(indirection, object, object);
  544. // Write Value chunk
  545. start_block();
  546. end_flag--;
  547. chunkedValueNestingLevel--;
  548. valueHandler.writeValue(parent, object);
  549. end_block();
  550. // Write end tag
  551. writeEndTag(true);
  552. }
  553. else {
  554. // Write value_tag
  555. int indirection = writeValueTag(false, false, Util.getCodebase(clazz));
  556. // Write repository ID
  557. write_repositoryId(repIdStrs.createSequenceRepID(clazz));
  558. // Add indirection for object to indirection table
  559. updateIndirectionTable(indirection, object, object);
  560. // Write Value chunk
  561. end_flag--;
  562. valueHandler.writeValue(parent, object);
  563. // Write end tag
  564. writeEndTag(false);
  565. }
  566. }
  567. // Handle IDL Value types
  568. else if (object instanceof org.omg.CORBA.portable.ValueBase)
  569. {
  570. // _REVISIT_ could check to see whether chunking really needed
  571. mustChunk = true;
  572. // Write value_tag
  573. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  574. // Get rep id
  575. String repId = ((ValueBase)object)._truncatable_ids()[0];
  576. // Write rep id
  577. write_repositoryId(repId);
  578. // Add indirection for object to indirection table
  579. updateIndirectionTable(indirection, object, object);
  580. // Write Value chunk
  581. start_block();
  582. end_flag--;
  583. chunkedValueNestingLevel--;
  584. writeIDLValue(object, repId);
  585. end_block();
  586. // Write end tag
  587. writeEndTag(true);
  588. }
  589. else if (shouldWriteAsIDLEntity(object))
  590. {
  591. writeIDLEntity((IDLEntity)object);
  592. }
  593. else if (object instanceof java.lang.String)
  594. {
  595. if (mustChunk) {
  596. // Write value_tag
  597. int indirection = writeValueTag(true, false, null);
  598. // Write WStringValue's repository ID
  599. write_repositoryId(repIdStrs.getWStringValueRepId());
  600. // Add indirection for object to indirection table
  601. updateIndirectionTable(indirection, object, object);
  602. // Write Value chunk
  603. start_block();
  604. end_flag--;
  605. chunkedValueNestingLevel--;
  606. write_wstring((java.lang.String)object);
  607. end_block();
  608. // Write end tag
  609. writeEndTag(true);
  610. }
  611. else {
  612. int indirection = writeValueTag(false, false, null);
  613. // Write WStringValue's repository ID
  614. write_repositoryId(repIdStrs.getWStringValueRepId());
  615. // Add indirection for object to indirection table
  616. updateIndirectionTable(indirection, object, object);
  617. // Write Value chunk
  618. end_flag--;
  619. write_wstring((java.lang.String)object);
  620. // Write end tag
  621. writeEndTag(false);
  622. }
  623. }
  624. else if (object instanceof java.lang.Class)
  625. {
  626. writeClass(repository_id, (Class)object);
  627. }
  628. else // Not a CORBA Value Type
  629. {
  630. if (valueHandler == null)
  631. valueHandler = ORBUtility.createValueHandler(orb); //d11638
  632. Serializable key = object;
  633. object = valueHandler.writeReplace(key);
  634. if (object == null) {
  635. // Write null tag and return
  636. write_long(0);
  637. return;
  638. }
  639. if (object != key) {
  640. if ((valueCache != null) && valueCache.containsKey(object)) {
  641. writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
  642. return;
  643. }
  644. clazz = object.getClass();
  645. }
  646. if (mustChunk || valueHandler.isCustomMarshaled(clazz)) {
  647. mustChunk = true;
  648. // Write value_tag
  649. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  650. // Write rep. id
  651. write_repositoryId(repIdStrs.createForJavaType(clazz));
  652. // Add indirection for object to indirection table
  653. updateIndirectionTable(indirection, object, key);
  654. // Write Value chunk
  655. end_flag--;
  656. chunkedValueNestingLevel--;
  657. start_block();
  658. valueHandler.writeValue(parent, object);
  659. end_block();
  660. // Write end tag
  661. writeEndTag(true);
  662. }
  663. else {
  664. // Write value_tag
  665. int indirection = writeValueTag(false, false, Util.getCodebase(clazz));
  666. // Write rep. id
  667. write_repositoryId(repIdStrs.createForJavaType(clazz));
  668. // Add indirection for object to indirection table
  669. updateIndirectionTable(indirection, object, key);
  670. // Write Value chunk
  671. end_flag--;
  672. valueHandler.writeValue(parent, object);
  673. // Write end tag
  674. writeEndTag(false);
  675. }
  676. }
  677. mustChunk = oldMustChunk;
  678. // Check to see if we need to start another block for a
  679. // possible outer value
  680. if (mustChunk)
  681. start_block();
  682. }
  683. public void write_value(Serializable object)
  684. {
  685. // Handle null references
  686. if (object == null) {
  687. // Write null tag and return
  688. write_long(0);
  689. return;
  690. }
  691. // Handle shared references
  692. if ((valueCache != null) && valueCache.containsKey(object)) {
  693. writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
  694. return;
  695. }
  696. Class clazz = object.getClass();
  697. boolean oldMustChunk = mustChunk;
  698. // _REVISIT_ should this be done when mustChunk is false?
  699. if (inBlock)
  700. end_block();
  701. // Handle arrays
  702. if (clazz.isArray())
  703. {
  704. if (valueHandler == null)
  705. valueHandler = ORBUtility.createValueHandler(orb); //d11638
  706. if (mustChunk) {
  707. // Write value_tag
  708. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  709. // Write repository ID
  710. write_repositoryId(repIdStrs.createSequenceRepID(clazz));
  711. // Add indirection for object to indirection table
  712. updateIndirectionTable(indirection, object, object);
  713. // Write Value chunk
  714. start_block();
  715. end_flag--;
  716. chunkedValueNestingLevel--;
  717. valueHandler.writeValue(parent, object);
  718. end_block();
  719. // Write end tag
  720. writeEndTag(true);
  721. }
  722. else {
  723. // Write value_tag
  724. int indirection = writeValueTag(false, false, Util.getCodebase(clazz));
  725. // Write repository ID
  726. write_repositoryId(repIdStrs.createSequenceRepID(clazz));
  727. // Add indirection for object to indirection table
  728. updateIndirectionTable(indirection, object, object);
  729. // Write Value chunk
  730. end_flag--;
  731. valueHandler.writeValue(parent, object);
  732. // Write end tag
  733. writeEndTag(false);
  734. }
  735. }
  736. // Handle IDL Value types
  737. else if (object instanceof org.omg.CORBA.portable.ValueBase)
  738. {
  739. // _REVISIT_ could check to see whether chunking really needed
  740. mustChunk = true;
  741. // Write value_tag
  742. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  743. // Get rep id
  744. String repId = ((ValueBase)object)._truncatable_ids()[0];
  745. // Write rep id
  746. write_repositoryId(repId);
  747. // Add indirection for object to indirection table
  748. updateIndirectionTable(indirection, object, object);
  749. // Write Value chunk
  750. start_block();
  751. end_flag--;
  752. chunkedValueNestingLevel--;
  753. writeIDLValue(object, repId);
  754. end_block();
  755. writeEndTag(true);
  756. }
  757. else if (shouldWriteAsIDLEntity(object))
  758. {
  759. writeIDLEntity((IDLEntity)object);
  760. }
  761. else if (object instanceof java.lang.String)
  762. {
  763. // Write value_tag
  764. // Are we nested ?
  765. if (mustChunk) {
  766. int indirection = writeValueTag(true, false, null);
  767. // Write WStringValue's repository ID
  768. write_repositoryId(repIdStrs.getWStringValueRepId());
  769. // Add indirection for object to indirection table
  770. updateIndirectionTable(indirection, object, object);
  771. // Write Value chunk
  772. start_block();
  773. end_flag--;
  774. chunkedValueNestingLevel--;
  775. write_wstring((java.lang.String)object);
  776. end_block();
  777. // Write end tag
  778. writeEndTag(true);
  779. }
  780. else {
  781. int indirection = writeValueTag(false, false, null);
  782. // Write WStringValue's repository ID
  783. write_repositoryId(repIdStrs.getWStringValueRepId());
  784. // Add indirection for object to indirection table
  785. updateIndirectionTable(indirection, object, object);
  786. // Write Value chunk
  787. end_flag--;
  788. write_wstring((java.lang.String)object);
  789. // Write end tag
  790. writeEndTag(false);
  791. }
  792. }
  793. else if (object instanceof java.lang.Class)
  794. {
  795. writeClass(repIdStrs.getClassDescValueRepId(), (Class)object);
  796. }
  797. else // Not a CORBA Value Type
  798. {
  799. if (valueHandler == null)
  800. valueHandler = ORBUtility.createValueHandler(orb); //d11638
  801. Serializable key = object;
  802. object = valueHandler.writeReplace(key);
  803. if (object == null) {
  804. // Write null tag and return
  805. write_long(0);
  806. return;
  807. }
  808. if (object != key) {
  809. if ((valueCache != null) && valueCache.containsKey(object)) {
  810. writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
  811. return;
  812. }
  813. clazz = object.getClass();
  814. }
  815. if (mustChunk || valueHandler.isCustomMarshaled(clazz)) {
  816. mustChunk = true;
  817. // Write value_tag
  818. int indirection = writeValueTag(true, false, Util.getCodebase(clazz));
  819. // Write rep. id
  820. write_repositoryId(repIdStrs.createForJavaType(clazz));
  821. // Add indirection for object to indirection table
  822. updateIndirectionTable(indirection, object, key);
  823. // Write Value chunk
  824. end_flag--;
  825. chunkedValueNestingLevel--;
  826. start_block();
  827. valueHandler.writeValue(parent, object);
  828. end_block();
  829. // Write end tag
  830. writeEndTag(true);
  831. }
  832. else {
  833. // Write value_tag
  834. int indirection = writeValueTag(false, false, Util.getCodebase(clazz));
  835. // Write rep. id
  836. write_repositoryId(repIdStrs.createForJavaType(clazz));
  837. // Add indirection for object to indirection table
  838. updateIndirectionTable(indirection, object, key);
  839. // Write Value chunk
  840. end_flag--;
  841. valueHandler.writeValue(parent, object);
  842. // Write end tag
  843. writeEndTag(false);
  844. }
  845. }
  846. mustChunk = oldMustChunk;
  847. // Check to see if we need to start another block for a
  848. // possible outer value
  849. if (mustChunk)
  850. start_block();
  851. }
  852. public void write_value(Serializable object, org.omg.CORBA.portable.BoxedValueHelper factory)
  853. {
  854. // Handle null references
  855. if (object == null) {
  856. // Write null tag and return
  857. write_long(0);
  858. return;
  859. }
  860. // Handle shared references
  861. if ((valueCache != null) && valueCache.containsKey(object)) {
  862. writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
  863. return;
  864. }
  865. boolean oldMustChunk = mustChunk;
  866. boolean isCustom = false;
  867. if (factory instanceof ValueHelper) {
  868. short modifier;
  869. try {
  870. modifier = ((ValueHelper)factory).get_type().type_modifier();
  871. } catch(BadKind ex) { // tk_value_box
  872. modifier = VM_NONE.value;
  873. }
  874. if (object instanceof CustomMarshal &&
  875. modifier == VM_CUSTOM.value) {
  876. isCustom = true;
  877. mustChunk = true;
  878. }
  879. if (modifier == VM_TRUNCATABLE.value)
  880. mustChunk = true;
  881. }
  882. if (mustChunk) {
  883. if (inBlock)
  884. end_block();
  885. // Write value_tag
  886. int indirection = writeValueTag(true, false, Util.getCodebase(object.getClass()));
  887. write_repositoryId(factory.get_id());
  888. // Add indirection for object to indirection table
  889. updateIndirectionTable(indirection, object, object);
  890. // Write Value chunk
  891. start_block();
  892. end_flag--;
  893. chunkedValueNestingLevel--;
  894. if (isCustom)
  895. ((CustomMarshal)object).marshal(parent);
  896. else
  897. factory.write_value(parent, object);
  898. end_block();
  899. // Write end tag
  900. writeEndTag(true);
  901. }
  902. else {
  903. // Write value_tag
  904. int indirection = writeValueTag(false, false, Util.getCodebase(object.getClass()));
  905. write_repositoryId(factory.get_id());
  906. // Add indirection for object to indirection table
  907. updateIndirectionTable(indirection, object, object);
  908. // Write Value chunk
  909. end_flag--;
  910. // no need to test for custom on the non-chunked path
  911. factory.write_value(parent, object);
  912. // Write end tag
  913. writeEndTag(false);
  914. }
  915. mustChunk = oldMustChunk;
  916. // Check to see if we need to start another block for a
  917. // possible outer value
  918. if (mustChunk)
  919. start_block();
  920. }
  921. public int get_offset() {
  922. return bbwi.index;
  923. }
  924. public void start_block() {
  925. if (debug)
  926. debugPrintMessage("CDROutputStream_1_0 start_block, index" + bbwi.index);
  927. //Move inBlock=true to after write_long since write_long might
  928. //trigger grow which will lead to erroneous behavior with a
  929. //missing blockSizeIndex.
  930. //inBlock = true;
  931. // Save space in the buffer for block size
  932. write_long(0);
  933. //Has to happen after write_long since write_long could
  934. //trigger grow which is overridden by supper classes to
  935. //depend on inBlock.
  936. inBlock = true;
  937. blockSizePosition = get_offset();
  938. // Remember where to put the size of the endblock less 4
  939. blockSizeIndex = bbwi.index;
  940. if (debug)
  941. debugPrintMessage("CDROutputStream_1_0 start_block, blockSizeIndex "
  942. + blockSizeIndex);
  943. }
  944. // Utility method which will hopefully decrease chunking complexity
  945. // by allowing us to end_block and update chunk lengths without
  946. // calling alignAndReserve. Otherwise, it's possible to get into
  947. // recursive scenarios which lose the chunking state.
  948. protected void writeLongWithoutAlign(int x) {
  949. if (littleEndian) {
  950. writeLittleEndianLong(x);
  951. } else {
  952. writeBigEndianLong(x);
  953. }
  954. }
  955. public void end_block() {
  956. if (debug)
  957. debugPrintMessage("CDROutputStream_1_0.java end_block");
  958. if (!inBlock)
  959. return;
  960. if (debug)
  961. debugPrintMessage("CDROutputStream_1_0.java end_block, in a block");
  962. inBlock = false;
  963. // Test to see if the block was of zero length
  964. // If so, remove the block instead of ending it
  965. // (This can happen if the last field written
  966. // in a value was another value)
  967. if (get_offset() == blockSizePosition) {
  968. // Need to assert that blockSizeIndex == bbwi.index? REVISIT
  969. bbwi.index = bbwi.index - 4;
  970. blockSizeIndex = -1;
  971. blockSizePosition = -1;
  972. return;
  973. }
  974. int oldSize = bbwi.index;
  975. bbwi.index = blockSizeIndex - 4;
  976. writeLongWithoutAlign(oldSize - blockSizeIndex);
  977. bbwi.index = oldSize;
  978. blockSizeIndex = -1;
  979. blockSizePosition = -1;
  980. // System.out.println(" post end_block: " + get_offset() + " " + bbwi.index);
  981. }
  982. public org.omg.CORBA.ORB orb()
  983. {
  984. return orb;
  985. }
  986. // ------------ End RMI related methods --------------------------
  987. public final void write_boolean_array(boolean[]value, int offset, int length) {
  988. if ( value == null )
  989. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  990. // This will only have an effect if we're already chunking
  991. handleSpecialChunkBegin(length);
  992. for (int i = 0; i < length; i++)
  993. write_boolean(value[offset + i]);
  994. // This will only have an effect if we're already chunking
  995. handleSpecialChunkEnd();
  996. }
  997. public final void write_char_array(char[]value, int offset, int length) {
  998. if ( value == null )
  999. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1000. // This will only have an effect if we're already chunking
  1001. handleSpecialChunkBegin(length);
  1002. for (int i = 0; i < length; i++)
  1003. write_char(value[offset + i]);
  1004. // This will only have an effect if we're already chunking
  1005. handleSpecialChunkEnd();
  1006. }
  1007. public void write_wchar_array(char[]value, int offset, int length) {
  1008. if ( value == null )
  1009. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1010. // This will only have an effect if we're already chunking
  1011. handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
  1012. for (int i = 0; i < length; i++)
  1013. write_wchar(value[offset + i]);
  1014. // This will only have an effect if we're already chunking
  1015. handleSpecialChunkEnd();
  1016. }
  1017. public final void write_short_array(short[]value, int offset, int length) {
  1018. if ( value == null )
  1019. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1020. // This will only have an effect if we're already chunking
  1021. handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
  1022. for (int i = 0; i < length; i++)
  1023. write_short(value[offset + i]);
  1024. // This will only have an effect if we're already chunking
  1025. handleSpecialChunkEnd();
  1026. }
  1027. public final void write_ushort_array(short[]value, int offset, int length) {
  1028. write_short_array(value, offset, length);
  1029. }
  1030. public final void write_long_array(int[]value, int offset, int length) {
  1031. if ( value == null )
  1032. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1033. // This will only have an effect if we're already chunking
  1034. handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
  1035. for (int i = 0; i < length; i++)
  1036. write_long(value[offset + i]);
  1037. // This will only have an effect if we're already chunking
  1038. handleSpecialChunkEnd();
  1039. }
  1040. public final void write_ulong_array(int[]value, int offset, int length) {
  1041. write_long_array(value, offset, length);
  1042. }
  1043. public final void write_longlong_array(long[]value, int offset, int length) {
  1044. if ( value == null )
  1045. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1046. // This will only have an effect if we're already chunking
  1047. handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
  1048. for (int i = 0; i < length; i++)
  1049. write_longlong(value[offset + i]);
  1050. // This will only have an effect if we're already chunking
  1051. handleSpecialChunkEnd();
  1052. }
  1053. public final void write_ulonglong_array(long[]value, int offset, int length) {
  1054. write_longlong_array(value, offset, length);
  1055. }
  1056. public final void write_float_array(float[]value, int offset, int length) {
  1057. if ( value == null )
  1058. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1059. // This will only have an effect if we're already chunking
  1060. handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
  1061. for (int i = 0; i < length; i++)
  1062. write_float(value[offset + i]);
  1063. // This will only have an effect if we're already chunking
  1064. handleSpecialChunkEnd();
  1065. }
  1066. public final void write_double_array(double[]value, int offset, int length) {
  1067. if ( value == null )
  1068. throw new BAD_PARAM(com.sun.corba.se.internal.orbutil.MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1069. // This will only have an effect if we're already chunking
  1070. handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
  1071. for (int i = 0; i < length; i++)
  1072. write_double(value[offset + i]);
  1073. // This will only have an effect if we're already chunking
  1074. handleSpecialChunkEnd();
  1075. }
  1076. public void write_string_array(String[] value, int offset, int length) {
  1077. if ( value == null )
  1078. throw new BAD_PARAM(MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1079. for(int i = 0; i < length; i++)
  1080. write_string(value[offset + i]);
  1081. }
  1082. public void write_wstring_array(String[] value, int offset, int length) {
  1083. if ( value == null )
  1084. throw new BAD_PARAM(MinorCodes.NULL_PARAM, CompletionStatus.COMPLETED_MAYBE);
  1085. for(int i = 0; i < length; i++)
  1086. write_wstring(value[offset + i]);
  1087. }
  1088. public final void write_any_array(org.omg.CORBA.Any value[], int offset, int length)
  1089. {
  1090. for(int i = 0; i < length; i++)
  1091. write_any(value[offset + i]);
  1092. }
  1093. //--------------------------------------------------------------------//
  1094. // CDROutputStream state management.
  1095. //
  1096. /**
  1097. * Write the contents of the CDROutputStream to the specified output stream.
  1098. * @param s The output stream to write to.
  1099. */
  1100. public void writeTo(java.io.OutputStream s) throws java.io.IOException {
  1101. s.write(bbwi.buf, 0, bbwi.index);
  1102. }
  1103. public void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream s) {
  1104. s.write_long(bbwi.index);
  1105. s.write_octet_array(bbwi.buf, 0, bbwi.index);
  1106. }
  1107. public final int getSize() {
  1108. return bbwi.index;
  1109. }
  1110. public int getIndex() {
  1111. return bbwi.index;
  1112. }
  1113. public boolean isLittleEndian() {
  1114. return littleEndian;
  1115. }
  1116. public void setIndex(int value) {
  1117. bbwi.index = value;
  1118. }
  1119. public ByteBufferWithInfo getByteBufferWithInfo() {
  1120. return bbwi;
  1121. }
  1122. public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
  1123. this.bbwi = bbwi;
  1124. }
  1125. public byte[] getByteBuffer() {
  1126. return bbwi.buf;
  1127. }
  1128. public void setByteBuffer(byte[] value) {
  1129. bbwi.buf = value;
  1130. }
  1131. private final void updateIndirectionTable(int indirection, java.lang.Object object,
  1132. java.lang.Object key) {
  1133. // int indirection = get_offset();
  1134. if (valueCache == null)
  1135. valueCache = new CacheTable(true);
  1136. valueCache.put(object, indirection);
  1137. if (key != object)
  1138. valueCache.put(key, indirection);
  1139. }
  1140. private final void write_repositoryId(String id) {
  1141. // Use an indirection if available
  1142. if (repositoryIdCache != null && repositoryIdCache.containsKey(id)) {
  1143. writeIndirection(INDIRECTION_TAG, repositoryIdCache.getVal(id));
  1144. return;
  1145. }
  1146. // Write it as a string. Note that we have already done the
  1147. // special case conversion of non-Latin-1 characters to escaped
  1148. // Latin-1 sequences in RepositoryId.
  1149. // It's not a good idea to cache them now that we can have
  1150. // multiple code sets.
  1151. write_string(id);
  1152. }
  1153. private void write_codebase(String str, int pos) {
  1154. if (codebaseCache != null && codebaseCache.containsKey(str)) {
  1155. writeIndirection(INDIRECTION_TAG, codebaseCache.getVal(str));
  1156. }
  1157. else {
  1158. write_string(str);
  1159. if (codebaseCache == null)
  1160. codebaseCache = new CacheTable(true);
  1161. codebaseCache.put(str, pos);
  1162. }
  1163. }
  1164. private final int writeValueTag(boolean chunkIt, boolean repNotWritten,
  1165. String codebase) {
  1166. int indirection = 0;
  1167. if (chunkIt && repNotWritten){
  1168. if (codebase == null) {
  1169. write_long(repIdUtil.getStandardRMIChunkedNoRepStrId());
  1170. indirection = get_offset() - 4;
  1171. } else {
  1172. write_long(repIdUtil.getCodeBaseRMIChunkedNoRepStrId());
  1173. indirection = get_offset() - 4;
  1174. write_codebase(codebase, get_offset());
  1175. }
  1176. } else if (chunkIt && !repNotWritten){
  1177. if (codebase == null) {
  1178. write_long(repIdUtil.getStandardRMIChunkedId());
  1179. indirection = get_offset() - 4;
  1180. } else {
  1181. write_long(repIdUtil.getCodeBaseRMIChunkedId());
  1182. indirection = get_offset() - 4;
  1183. write_codebase(codebase, get_offset());
  1184. }
  1185. } else {
  1186. if (codebase == null) {
  1187. write_long(repIdUtil.getStandardRMIUnchunkedId());
  1188. indirection = get_offset() - 4;
  1189. } else {
  1190. write_long(repIdUtil.getCodeBaseRMIUnchunkedId());
  1191. indirection = get_offset() - 4;
  1192. write_codebase(codebase, get_offset());
  1193. }
  1194. }
  1195. return indirection;
  1196. }
  1197. private void writeIDLValue(Serializable object, String repID)
  1198. {
  1199. if (object instanceof StreamableValue) {
  1200. ((StreamableValue)object)._write(parent);
  1201. } else if (object instanceof CustomValue) {
  1202. ((CustomValue)object).marshal(parent);
  1203. } else {
  1204. BoxedValueHelper helper = Utility.getHelper(object.getClass(), null, repID);
  1205. boolean isCustom = false;
  1206. if (helper instanceof ValueHelper && object instanceof CustomMarshal) {
  1207. try {
  1208. if (((ValueHelper)helper).get_type().type_modifier() == VM_CUSTOM.value)
  1209. isCustom = true;
  1210. } catch(BadKind ex) {
  1211. debugPrintThrowable(ex);
  1212. throw new org.omg.CORBA.MARSHAL();
  1213. }
  1214. }
  1215. if (isCustom)
  1216. ((CustomMarshal)object).marshal(parent);
  1217. else
  1218. helper.write_value(parent, object);
  1219. }
  1220. }
  1221. // Handles end tag compaction...
  1222. private void writeEndTag(boolean chunked){
  1223. if (chunked) {
  1224. if (get_offset() == end_flag_position) {
  1225. if (bbwi.index == end_flag_index) {
  1226. // We are exactly at the same position and index as the
  1227. // end of the last end tag. Thus, we can back up over it
  1228. // and compact the tags.
  1229. bbwi.index -= 4;
  1230. } else {
  1231. // Special case in which we're at the beginning of a new
  1232. // fragment, but the position is the same. We can't back up,
  1233. // so we just write the new end tag without compaction. This
  1234. // occurs when a value ends and calls start_block to open a
  1235. // continuation chunk, but it's called at the very end of
  1236. // a fragment.
  1237. }
  1238. }
  1239. writeNestingLevel();
  1240. // Remember the last index and position. These are only used when chunking.
  1241. end_flag_index = bbwi.index;
  1242. end_flag_position = get_offset();
  1243. chunkedValueNestingLevel++;
  1244. }
  1245. // Increment the nesting level
  1246. end_flag++;
  1247. }
  1248. /**
  1249. * Handles ORB versioning of the end tag. Should only
  1250. * be called if chunking.
  1251. *
  1252. * If talking to our older ORBs (Standard Extension,
  1253. * Kestrel, and Ladybird), write the end flag that takes
  1254. * into account all enclosing valuetypes.
  1255. *
  1256. * If talking a newer or foreign ORB, or if the orb
  1257. * instance is null, write the end flag that only takes
  1258. * into account the enclosing chunked valuetypes.
  1259. */
  1260. private void writeNestingLevel() {
  1261. if (orb == null ||
  1262. ORBVersionImpl.FOREIGN.equals(orb.getORBVersion()) ||
  1263. ORBVersionImpl.NEWER.compareTo(orb.getORBVersion()) <= 0) {
  1264. write_long(chunkedValueNestingLevel);
  1265. } else {
  1266. write_long(end_flag);
  1267. }
  1268. }
  1269. private void writeClass(String repository_id, Class clz) {
  1270. if (mustChunk) {
  1271. // Write value_tag
  1272. int indirection = writeValueTag(true, false, null);
  1273. updateIndirectionTable(indirection, clz, clz);
  1274. // Write repository ID
  1275. if (repository_id != null)
  1276. write_repositoryId(repository_id);
  1277. else {
  1278. write_repositoryId(repIdStrs.getClassDescValueRepId());
  1279. }
  1280. // Write Value chunk
  1281. start_block();
  1282. end_flag--;
  1283. chunkedValueNestingLevel--;
  1284. writeClassBody(clz);
  1285. end_block();
  1286. // Write end tag
  1287. writeEndTag(true);
  1288. }
  1289. else {
  1290. // Write value_tag
  1291. int indirection = writeValueTag(false, false, null);
  1292. updateIndirectionTable(indirection, clz, clz);
  1293. // Write repository ID
  1294. if (repository_id != null)
  1295. write_repositoryId(repository_id);
  1296. else {
  1297. write_repositoryId(repIdStrs.getClassDescValueRepId());
  1298. }
  1299. // Write Value chunk
  1300. end_flag--;
  1301. writeClassBody(clz);
  1302. // Write end tag
  1303. writeEndTag(false);
  1304. }
  1305. }
  1306. // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
  1307. // and codebase strings in the wrong order. This handles
  1308. // backwards compatibility.
  1309. private void writeClassBody(Class clz) {
  1310. if (orb == null ||
  1311. ORBVersionImpl.FOREIGN.equals(orb.getORBVersion()) ||
  1312. ORBVersionImpl.NEWER.compareTo(orb.getORBVersion()) <= 0) {
  1313. write_value(Util.getCodebase(clz));
  1314. write_value(repIdStrs.createForAnyType(clz));
  1315. } else {
  1316. write_value(repIdStrs.createForAnyType(clz));
  1317. write_value(Util.getCodebase(clz));
  1318. }
  1319. }
  1320. // Casts and returns an Object as a Serializable
  1321. // This is required for JDK 1.1 only to avoid VerifyErrors when
  1322. // passing arrays as Serializable
  1323. // private java.io.Serializable make_serializable(java.lang.Object object)
  1324. // {
  1325. // return (java.io.Serializable)object;
  1326. // }
  1327. private boolean shouldWriteAsIDLEntity(Serializable object)
  1328. {
  1329. return ((object instanceof IDLEntity) && (!(object instanceof ValueBase)) &&
  1330. (!(object instanceof org.omg.CORBA.Object)));
  1331. }
  1332. private void writeIDLEntity(IDLEntity object) {
  1333. // _REVISIT_ could check to see whether chunking really needed
  1334. mustChunk = true;
  1335. String repository_id = repIdStrs.createForJavaType(object);
  1336. Class clazz = object.getClass();
  1337. String codebase = Util.getCodebase(clazz);
  1338. // Write value_tag
  1339. int indirection = writeValueTag(true, false, codebase);
  1340. updateIndirectionTable(indirection, object, object);
  1341. // Write rep. id
  1342. write_repositoryId(repository_id);
  1343. // Write Value chunk
  1344. end_flag--;
  1345. chunkedValueNestingLevel--;
  1346. start_block();
  1347. // Write the IDLEntity using reflection
  1348. try {
  1349. ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
  1350. final Class helperClass = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
  1351. clazzLoader, clazz, clazzLoader);
  1352. final Class argTypes[] = {org.omg.CORBA.portable.OutputStream.class, clazz};
  1353. // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
  1354. // if a different class loader is used (even though the javadoc says otherwise)
  1355. Method writeMethod = null;
  1356. try {
  1357. writeMethod = (Method)AccessController.doPrivileged(
  1358. new PrivilegedExceptionAction() {
  1359. public java.lang.Object run() throws NoSuchMethodException {
  1360. return helperClass.getDeclaredMethod(kWriteMethod, argTypes);
  1361. }
  1362. }
  1363. );
  1364. } catch (PrivilegedActionException pae) {
  1365. // this gets caught below
  1366. throw (NoSuchMethodException)pae.getException();
  1367. }
  1368. java.lang.Object args[] = {parent, object};
  1369. writeMethod.invoke(null, args);
  1370. } catch (ClassNotFoundException cnfe) {
  1371. debugPrintThrowable(cnfe);
  1372. throw new org.omg.CORBA.MARSHAL(cnfe.getMessage());
  1373. } catch(NoSuchMethodException nsme) {
  1374. debugPrintThrowable(nsme);
  1375. throw new org.omg.CORBA.MARSHAL(nsme.getMessage());
  1376. } catch(IllegalAccessException iae) {
  1377. debugPrintThrowable(iae);
  1378. throw new org.omg.CORBA.MARSHAL(iae.getMessage());
  1379. } catch(InvocationTargetException ite) {
  1380. debugPrintThrowable(ite);
  1381. throw new org.omg.CORBA.MARSHAL(ite.getMessage());
  1382. }
  1383. end_block();
  1384. // Write end tag
  1385. writeEndTag(true);
  1386. }
  1387. /* DataOutputStream methods */
  1388. public void write_Abstract (java.lang.Object value) {
  1389. write_abstract_interface(value);
  1390. }
  1391. public void write_Value (java.io.Serializable value) {
  1392. write_value(value);
  1393. }
  1394. // This will stay a custom add-on until the java-rtf issue is resolved.
  1395. // Then it should be declared in org.omg.CORBA.portable.OutputStream.
  1396. //
  1397. // Pads the string representation of bigDecimal with zeros to fit the given
  1398. // digits and scale before it gets written to the stream.
  1399. public void write_fixed(java.math.BigDecimal bigDecimal, short digits, short scale) {
  1400. String string = bigDecimal.toString();
  1401. String integerPart;
  1402. String fractionPart;
  1403. StringBuffer stringBuffer;
  1404. // Get rid of the sign
  1405. if (string.charAt(0) == '-' || string.charAt(0) == '+') {
  1406. string = string.substring(1);
  1407. }
  1408. // Determine integer and fraction parts
  1409. int dotIndex = string.indexOf('.');
  1410. if (dotIndex == -1) {
  1411. integerPart = string;
  1412. fractionPart = null;
  1413. } else if (dotIndex == 0 ) {
  1414. integerPart = null;
  1415. fractionPart = string;
  1416. } else {
  1417. integerPart = string.substring(0, dotIndex);
  1418. fractionPart = string.substring(dotIndex + 1);
  1419. }
  1420. // Pad both parts with zeros as necessary
  1421. stringBuffer = new StringBuffer(digits);
  1422. if (fractionPart != null) {
  1423. stringBuffer.append(fractionPart);
  1424. }
  1425. while (stringBuffer.length() < scale) {
  1426. stringBuffer.append('0');
  1427. }
  1428. if (integerPart != null) {
  1429. stringBuffer.insert(0, integerPart);
  1430. }
  1431. while (stringBuffer.length() < digits) {
  1432. stringBuffer.insert(0, '0');
  1433. }
  1434. // This string contains no sign or dot
  1435. this.write_fixed(stringBuffer.toString(), bigDecimal.signum());
  1436. }
  1437. // This method should be remove by the java-rtf issue.
  1438. // Right now the scale and digits information of the type code is lost.
  1439. public void write_fixed(java.math.BigDecimal bigDecimal) {
  1440. // This string might contain sign and/or dot
  1441. this.write_fixed(bigDecimal.toString(), bigDecimal.signum());
  1442. }
  1443. // The string may contain a sign and dot
  1444. public void write_fixed(String string, int signum) {
  1445. int stringLength = string.length();
  1446. // Each octet contains (up to) two decimal digits
  1447. byte doubleDigit = 0;
  1448. char ch;
  1449. byte digit;
  1450. // First calculate the length of the string without optional sign and dot
  1451. int numDigits = 0;
  1452. for (int i=0; i<stringLength; i++) {
  1453. ch = string.charAt(i);
  1454. if (ch == '-' || ch == '+' || ch == '.')
  1455. continue;
  1456. numDigits++;
  1457. }
  1458. for (int i=0; i<stringLength; i++) {
  1459. ch = string.charAt(i);
  1460. if (ch == '-' || ch == '+' || ch == '.')
  1461. continue;
  1462. digit = (byte)Character.digit(ch, 10);
  1463. if (digit == -1) {
  1464. debugPrintMessage("Digit is -1, throwing MARSHAL");
  1465. throw new MARSHAL();
  1466. }
  1467. // If the fixed type has an odd number of decimal digits,
  1468. // then the representation begins with the first (most significant) digit.
  1469. // Otherwise, this first half-octet is all zero, and the first digit
  1470. // is in the second half-octet.
  1471. if (numDigits % 2 == 0) {
  1472. doubleDigit |= digit;
  1473. this.write_octet(doubleDigit);
  1474. doubleDigit = 0;
  1475. } else {
  1476. doubleDigit |= (digit << 4);
  1477. }
  1478. numDigits--;
  1479. }
  1480. // The sign configuration, in the last half-octet of the representation,
  1481. // is 0xD for negative numbers and 0xC for positive and zero values
  1482. if (signum == -1) {
  1483. doubleDigit |= 0xd;
  1484. } else {
  1485. doubleDigit |= 0xc;
  1486. }
  1487. this.write_octet(doubleDigit);
  1488. }
  1489. private final static String _id = "IDL:omg.org/CORBA/DataOutputStream:1.0";
  1490. private final static String[] _ids = { _id };
  1491. public String[] _truncatable_ids() {
  1492. if (_ids == null)
  1493. return null;
  1494. return (String[])_ids.clone();
  1495. }
  1496. /* for debugging */
  1497. public void printBuffer() {
  1498. CDROutputStream_1_0.printBuffer(this.bbwi);
  1499. }
  1500. public static void printBuffer(ByteBufferWithInfo bbwi) {
  1501. System.out.println("+++++++ Output Buffer ++++++++");
  1502. System.out.println();
  1503. System.out.println("Current index: " + bbwi.index);
  1504. System.out.println("Total length : " + bbwi.buflen);
  1505. System.out.println();
  1506. char[] charBuf = new char[16];
  1507. try {
  1508. for (int i = 0; i < bbwi.index; i += 16) {
  1509. int j = 0;
  1510. // For every 16 bytes, there is one line
  1511. // of output. First, the hex output of
  1512. // the 16 bytes with each byte separated
  1513. // by a space.
  1514. while (j < 16 && j + i < bbwi.index) {
  1515. int k = bbwi.buf[i + j];
  1516. if (k < 0)
  1517. k = 256 + k;
  1518. String hex = Integer.toHexString(k);
  1519. if (hex.length() == 1)
  1520. hex = "0" + hex;
  1521. System.out.print(hex + " ");
  1522. j++;
  1523. }
  1524. // Add any extra spaces to align the
  1525. // text column in case we didn't end
  1526. // at 16
  1527. while (j < 16) {
  1528. System.out.print(" ");
  1529. j++;
  1530. }
  1531. // Now output the ASCII equivalents. Non-ASCII
  1532. // characters are shown as periods.
  1533. int x = 0;
  1534. while (x < 16 && x + i < bbwi.index) {
  1535. if (Character.isLetterOrDigit((char)bbwi.buf[i + x]))
  1536. charBuf[x] = (char)bbwi.buf[i + x];
  1537. else
  1538. charBuf[x] = '.';
  1539. x++;
  1540. }
  1541. System.out.println(new String(charBuf, 0, x));
  1542. }
  1543. } catch (Throwable t) {
  1544. t.printStackTrace();
  1545. }
  1546. System.out.println("++++++++++++++++++++++++++++++");
  1547. }
  1548. public void writeIndirection(int tag, int posIndirectedTo)
  1549. {
  1550. // Must ensure that there are no chunks between the tag
  1551. // and the actual indirection value. This isn't talked about
  1552. // in the spec, but seems to cause headaches in our code.
  1553. // At the very least, this method isolates the indirection code
  1554. // that was duplicated so often.
  1555. handleSpecialChunkBegin(computeAlignment(4) + 8);
  1556. // write indirection tag
  1557. write_long(tag);
  1558. // write indirection
  1559. // Use parent.getRealIndex() so that it can be overridden by TypeCodeOutputStreams
  1560. /*
  1561. System.out.println("CDROutputStream_1_0 writing indirection pos " + posIndirectedTo +
  1562. " - real index " + parent.getRealIndex(get_offset()) + " = " +
  1563. (posIndirectedTo - parent.getRealIndex(get_offset())));
  1564. */
  1565. write_long(posIndirectedTo - parent.getRealIndex(get_offset()));
  1566. handleSpecialChunkEnd();
  1567. }
  1568. protected CodeSetConversion.CTBConverter getCharConverter() {
  1569. if (charConverter == null)
  1570. charConverter = parent.createCharCTBConverter();
  1571. return charConverter;
  1572. }
  1573. protected CodeSetConversion.CTBConverter getWCharConverter() {
  1574. if (wcharConverter == null)
  1575. wcharConverter = parent.createWCharCTBConverter();
  1576. return wcharConverter;
  1577. }
  1578. protected void debugPrintThrowable(Throwable t) {
  1579. if (debug && t != null)
  1580. t.printStackTrace();
  1581. }
  1582. protected void debugPrintMessage(String msg) {
  1583. if (debug)
  1584. ORBUtility.dprint(this, msg);
  1585. }
  1586. void alignOnBoundary(int octetBoundary) {
  1587. alignAndReserve(octetBoundary, 0);
  1588. }
  1589. }