src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java

Thu, 31 Aug 2017 18:10:36 +0800

author
aoqi
date
Thu, 31 Aug 2017 18:10:36 +0800
changeset 748
6845b95cba6b
parent 443
3c73273667ae
parent 0
7ef37b2cdcad
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25 /*
aoqi@0 26 * Licensed Materials - Property of IBM
aoqi@0 27 * RMI-IIOP v1.0
aoqi@0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved
aoqi@0 29 *
aoqi@0 30 */
aoqi@0 31
aoqi@0 32 package com.sun.corba.se.impl.encoding;
aoqi@0 33
aoqi@0 34 import java.io.ByteArrayOutputStream;
aoqi@0 35 import java.io.IOException;
aoqi@0 36 import java.io.Serializable;
aoqi@0 37 import java.io.ByteArrayOutputStream;
aoqi@0 38 import java.io.ObjectOutputStream;
aoqi@0 39 import java.io.IOException;
aoqi@0 40 import java.lang.reflect.Method;
aoqi@0 41 import java.lang.reflect.InvocationTargetException;
aoqi@0 42 import java.math.BigDecimal;
aoqi@0 43 import java.nio.ByteBuffer;
aoqi@0 44 import java.rmi.Remote;
aoqi@0 45 import java.security.AccessController;
aoqi@0 46 import java.security.PrivilegedExceptionAction;
aoqi@0 47 import java.security.PrivilegedActionException;
aoqi@0 48 import java.util.Hashtable;
aoqi@0 49 import java.util.Stack;
aoqi@0 50
aoqi@0 51 import javax.rmi.CORBA.Util;
aoqi@0 52 import javax.rmi.CORBA.ValueHandler;
aoqi@0 53 import javax.rmi.CORBA.ValueHandlerMultiFormat;
aoqi@0 54
aoqi@0 55 import org.omg.CORBA.CustomMarshal;
aoqi@0 56 import org.omg.CORBA.DataOutputStream;
aoqi@0 57 import org.omg.CORBA.TypeCodePackage.BadKind;
aoqi@0 58 import org.omg.CORBA.SystemException;
aoqi@0 59 import org.omg.CORBA.CompletionStatus;
aoqi@0 60 import org.omg.CORBA.Object;
aoqi@0 61 import org.omg.CORBA.Principal;
aoqi@0 62 import org.omg.CORBA.TypeCode;
aoqi@0 63 import org.omg.CORBA.Any;
aoqi@0 64 import org.omg.CORBA.VM_CUSTOM;
aoqi@0 65 import org.omg.CORBA.VM_TRUNCATABLE;
aoqi@0 66 import org.omg.CORBA.VM_NONE;
aoqi@0 67 import org.omg.CORBA.portable.IDLEntity;
aoqi@0 68 import org.omg.CORBA.portable.CustomValue;
aoqi@0 69 import org.omg.CORBA.portable.StreamableValue;
aoqi@0 70 import org.omg.CORBA.portable.BoxedValueHelper;
aoqi@0 71 import org.omg.CORBA.portable.OutputStream;
aoqi@0 72 import org.omg.CORBA.portable.ValueBase;
aoqi@0 73
aoqi@0 74 import com.sun.org.omg.CORBA.portable.ValueHelper;
aoqi@0 75
aoqi@0 76 import com.sun.corba.se.pept.protocol.MessageMediator;
aoqi@0 77 import com.sun.corba.se.pept.transport.ByteBufferPool;
aoqi@0 78
aoqi@0 79 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
aoqi@0 80 import com.sun.corba.se.spi.ior.IOR;
aoqi@0 81 import com.sun.corba.se.spi.ior.IORFactories;
aoqi@0 82 import com.sun.corba.se.spi.orb.ORB;
aoqi@0 83 import com.sun.corba.se.spi.orb.ORBVersionFactory;
aoqi@0 84 import com.sun.corba.se.spi.orb.ORBVersion;
aoqi@0 85 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
aoqi@0 86 import com.sun.corba.se.spi.logging.CORBALogDomains;
aoqi@0 87
aoqi@0 88 import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
aoqi@0 89 import com.sun.corba.se.impl.encoding.MarshalOutputStream;
aoqi@0 90 import com.sun.corba.se.impl.encoding.CodeSetConversion;
aoqi@0 91 import com.sun.corba.se.impl.corba.TypeCodeImpl;
aoqi@0 92 import com.sun.corba.se.impl.orbutil.CacheTable;
aoqi@0 93 import com.sun.corba.se.impl.orbutil.ORBUtility;
aoqi@0 94 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
aoqi@0 95 import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
aoqi@0 96 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
aoqi@0 97 import com.sun.corba.se.impl.util.Utility;
aoqi@0 98 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
aoqi@0 99
aoqi@0 100 public class CDROutputStream_1_0 extends CDROutputStreamBase
aoqi@0 101 {
aoqi@0 102 private static final int INDIRECTION_TAG = 0xffffffff;
aoqi@0 103
aoqi@0 104 protected boolean littleEndian;
aoqi@0 105 protected BufferManagerWrite bufferManagerWrite;
aoqi@0 106 ByteBufferWithInfo bbwi;
aoqi@0 107
aoqi@0 108 protected ORB orb;
aoqi@0 109 protected ORBUtilSystemException wrapper ;
aoqi@0 110
aoqi@0 111 protected boolean debug = false;
aoqi@0 112
aoqi@0 113 protected int blockSizeIndex = -1;
aoqi@0 114 protected int blockSizePosition = 0;
aoqi@0 115
aoqi@0 116 protected byte streamFormatVersion;
aoqi@0 117
aoqi@0 118 private static final int DEFAULT_BUFFER_SIZE = 1024;
aoqi@0 119 private static final String kWriteMethod = "write";
aoqi@0 120
aoqi@0 121 // Codebase cache
aoqi@0 122 private CacheTable codebaseCache = null;
aoqi@0 123
aoqi@0 124 // Value cache
aoqi@0 125 private CacheTable valueCache = null;
aoqi@0 126
aoqi@0 127 // Repository ID cache
aoqi@0 128 private CacheTable repositoryIdCache = null;
aoqi@0 129
aoqi@0 130 // Write end flag
aoqi@0 131 private int end_flag = 0;
aoqi@0 132
aoqi@0 133 // Beginning with the resolution to interop issue 3526,
aoqi@0 134 // only enclosing chunked valuetypes are taken into account
aoqi@0 135 // when computing the nesting level. However, we still need
aoqi@0 136 // the old computation around for interoperability with our
aoqi@0 137 // older ORBs.
aoqi@0 138 private int chunkedValueNestingLevel = 0;
aoqi@0 139
aoqi@0 140 private boolean mustChunk = false;
aoqi@0 141
aoqi@0 142 // In block marker
aoqi@0 143 protected boolean inBlock = false;
aoqi@0 144
aoqi@0 145 // Last end tag position
aoqi@0 146 private int end_flag_position = 0;
aoqi@0 147 private int end_flag_index = 0;
aoqi@0 148
aoqi@0 149 // ValueHandler
aoqi@0 150 private ValueHandler valueHandler = null;
aoqi@0 151
aoqi@0 152 // Repository ID handlers
aoqi@0 153 private RepositoryIdUtility repIdUtil;
aoqi@0 154 private RepositoryIdStrings repIdStrs;
aoqi@0 155
aoqi@0 156 // Code set converters (created when first needed)
aoqi@0 157 private CodeSetConversion.CTBConverter charConverter;
aoqi@0 158 private CodeSetConversion.CTBConverter wcharConverter;
aoqi@0 159
aoqi@0 160 // REVISIT - This should be re-factored so that including whether
aoqi@0 161 // to use pool byte buffers or not doesn't need to be known.
aoqi@0 162 public void init(org.omg.CORBA.ORB orb,
aoqi@0 163 boolean littleEndian,
aoqi@0 164 BufferManagerWrite bufferManager,
aoqi@0 165 byte streamFormatVersion,
aoqi@0 166 boolean usePooledByteBuffers)
aoqi@0 167 {
aoqi@0 168 // ORB must not be null. See CDROutputStream constructor.
aoqi@0 169 this.orb = (ORB)orb;
aoqi@0 170 this.wrapper = ORBUtilSystemException.get( this.orb,
aoqi@0 171 CORBALogDomains.RPC_ENCODING ) ;
aoqi@0 172 debug = this.orb.transportDebugFlag;
aoqi@0 173
aoqi@0 174 this.littleEndian = littleEndian;
aoqi@0 175 this.bufferManagerWrite = bufferManager;
aoqi@0 176 this.bbwi = new ByteBufferWithInfo(orb, bufferManager, usePooledByteBuffers);
aoqi@0 177 this.streamFormatVersion = streamFormatVersion;
aoqi@0 178
aoqi@0 179 createRepositoryIdHandlers();
aoqi@0 180 }
aoqi@0 181
aoqi@0 182 public void init(org.omg.CORBA.ORB orb,
aoqi@0 183 boolean littleEndian,
aoqi@0 184 BufferManagerWrite bufferManager,
aoqi@0 185 byte streamFormatVersion)
aoqi@0 186 {
aoqi@0 187 init(orb, littleEndian, bufferManager, streamFormatVersion, true);
aoqi@0 188 }
aoqi@0 189
aoqi@0 190 private final void createRepositoryIdHandlers()
aoqi@0 191 {
aoqi@0 192 repIdUtil = RepositoryIdFactory.getRepIdUtility();
aoqi@0 193 repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
aoqi@0 194 }
aoqi@0 195
aoqi@0 196 public BufferManagerWrite getBufferManager()
aoqi@0 197 {
aoqi@0 198 return bufferManagerWrite;
aoqi@0 199 }
aoqi@0 200
aoqi@0 201 public byte[] toByteArray() {
aoqi@0 202 byte[] it;
aoqi@0 203
aoqi@0 204 it = new byte[bbwi.position()];
aoqi@0 205
aoqi@0 206 // Micro-benchmarks show ByteBuffer.get(int) out perform the bulk
aoqi@0 207 // ByteBuffer.get(byte[], offset, length).
aoqi@0 208 for (int i = 0; i < bbwi.position(); i++)
aoqi@0 209 it[i] = bbwi.byteBuffer.get(i);
aoqi@0 210
aoqi@0 211 return it;
aoqi@0 212 }
aoqi@0 213
aoqi@0 214 public GIOPVersion getGIOPVersion() {
aoqi@0 215 return GIOPVersion.V1_0;
aoqi@0 216 }
aoqi@0 217
aoqi@0 218 // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
aoqi@0 219 // Illegal for GIOP versions < 1.2.
aoqi@0 220 void setHeaderPadding(boolean headerPadding) {
aoqi@0 221 throw wrapper.giopVersionError();
aoqi@0 222 }
aoqi@0 223
aoqi@0 224 protected void handleSpecialChunkBegin(int requiredSize)
aoqi@0 225 {
aoqi@0 226 // No-op for GIOP 1.0
aoqi@0 227 }
aoqi@0 228
aoqi@0 229 protected void handleSpecialChunkEnd()
aoqi@0 230 {
aoqi@0 231 // No-op for GIOP 1.0
aoqi@0 232 }
aoqi@0 233
aoqi@0 234 protected final int computeAlignment(int align) {
aoqi@0 235 if (align > 1) {
aoqi@0 236 int incr = bbwi.position() & (align - 1);
aoqi@0 237 if (incr != 0)
aoqi@0 238 return align - incr;
aoqi@0 239 }
aoqi@0 240
aoqi@0 241 return 0;
aoqi@0 242 }
aoqi@0 243
aoqi@0 244 protected void alignAndReserve(int align, int n) {
aoqi@0 245
aoqi@0 246 bbwi.position(bbwi.position() + computeAlignment(align));
aoqi@0 247
aoqi@0 248 if (bbwi.position() + n > bbwi.buflen)
aoqi@0 249 grow(align, n);
aoqi@0 250 }
aoqi@0 251
aoqi@0 252 //
aoqi@0 253 // Default implementation of grow. Subclassers may override this.
aoqi@0 254 // Always grow the single buffer. This needs to delegate
aoqi@0 255 // fragmentation policy for IIOP 1.1.
aoqi@0 256 //
aoqi@0 257 protected void grow(int align, int n)
aoqi@0 258 {
aoqi@0 259 bbwi.needed = n;
aoqi@0 260
aoqi@0 261 bufferManagerWrite.overflow(bbwi);
aoqi@0 262 }
aoqi@0 263
aoqi@0 264 public final void putEndian() throws SystemException {
aoqi@0 265 write_boolean(littleEndian);
aoqi@0 266 }
aoqi@0 267
aoqi@0 268 public final boolean littleEndian() {
aoqi@0 269 return littleEndian;
aoqi@0 270 }
aoqi@0 271
aoqi@0 272 void freeInternalCaches() {
aoqi@0 273 if (codebaseCache != null)
aoqi@0 274 codebaseCache.done();
aoqi@0 275
aoqi@0 276 if (valueCache != null)
aoqi@0 277 valueCache.done();
aoqi@0 278
aoqi@0 279 if (repositoryIdCache != null)
aoqi@0 280 repositoryIdCache.done();
aoqi@0 281 }
aoqi@0 282
aoqi@0 283 // No such type in java
aoqi@0 284 public final void write_longdouble(double x)
aoqi@0 285 {
aoqi@0 286 throw wrapper.longDoubleNotImplemented(
aoqi@0 287 CompletionStatus.COMPLETED_MAYBE ) ;
aoqi@0 288 }
aoqi@0 289
aoqi@0 290 public void write_octet(byte x)
aoqi@0 291 {
aoqi@0 292 // The 'if' stmt is commented out since we need the alignAndReserve to
aoqi@0 293 // be called, particularly when the first body byte is written,
aoqi@0 294 // to induce header padding to align the body on a 8-octet boundary,
aoqi@0 295 // for GIOP versions 1.2 and above. Refer to internalWriteOctetArray()
aoqi@0 296 // method that also has a similar change.
aoqi@0 297 //if (bbwi.position() + 1 > bbwi.buflen)
aoqi@0 298 alignAndReserve(1, 1);
aoqi@0 299
aoqi@0 300 // REVISIT - Should just use ByteBuffer.put(byte) and let it
aoqi@0 301 // increment the ByteBuffer position. This is true
aoqi@0 302 // for all write operations in this file.
aoqi@0 303
aoqi@0 304 bbwi.byteBuffer.put(bbwi.position(), x);
aoqi@0 305 bbwi.position(bbwi.position() + 1);
aoqi@0 306
aoqi@0 307 }
aoqi@0 308
aoqi@0 309 public final void write_boolean(boolean x)
aoqi@0 310 {
aoqi@0 311 write_octet(x? (byte)1:(byte)0);
aoqi@0 312 }
aoqi@0 313
aoqi@0 314 public void write_char(char x)
aoqi@0 315 {
aoqi@0 316 CodeSetConversion.CTBConverter converter = getCharConverter();
aoqi@0 317
aoqi@0 318 converter.convert(x);
aoqi@0 319
aoqi@0 320 // CORBA formal 99-10-07 15.3.1.6: "In the case of multi-byte encodings
aoqi@0 321 // of characters, a single instance of the char type may only
aoqi@0 322 // hold one octet of any multi-byte character encoding."
aoqi@0 323 if (converter.getNumBytes() > 1)
aoqi@0 324 throw wrapper.invalidSingleCharCtb(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 325
aoqi@0 326 write_octet(converter.getBytes()[0]);
aoqi@0 327 }
aoqi@0 328
aoqi@0 329 // These wchar methods are only used when talking to
aoqi@0 330 // legacy ORBs, now.
aoqi@0 331 private final void writeLittleEndianWchar(char x) {
aoqi@0 332 bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
aoqi@0 333 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
aoqi@0 334 bbwi.position(bbwi.position() + 2);
aoqi@0 335 }
aoqi@0 336
aoqi@0 337 private final void writeBigEndianWchar(char x) {
aoqi@0 338 bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
aoqi@0 339 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
aoqi@0 340 bbwi.position(bbwi.position() + 2);
aoqi@0 341 }
aoqi@0 342
aoqi@0 343 private final void writeLittleEndianShort(short x) {
aoqi@0 344 bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
aoqi@0 345 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
aoqi@0 346 bbwi.position(bbwi.position() + 2);
aoqi@0 347 }
aoqi@0 348
aoqi@0 349 private final void writeBigEndianShort(short x) {
aoqi@0 350 bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF));
aoqi@0 351 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF));
aoqi@0 352 bbwi.position(bbwi.position() + 2);
aoqi@0 353 }
aoqi@0 354
aoqi@0 355 private final void writeLittleEndianLong(int x) {
aoqi@0 356 bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
aoqi@0 357 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
aoqi@0 358 bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
aoqi@0 359 bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
aoqi@0 360 bbwi.position(bbwi.position() + 4);
aoqi@0 361 }
aoqi@0 362
aoqi@0 363 private final void writeBigEndianLong(int x) {
aoqi@0 364 bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 24) & 0xFF));
aoqi@0 365 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 16) & 0xFF));
aoqi@0 366 bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 8) & 0xFF));
aoqi@0 367 bbwi.byteBuffer.put(bbwi.position() + 3, (byte)(x & 0xFF));
aoqi@0 368 bbwi.position(bbwi.position() + 4);
aoqi@0 369 }
aoqi@0 370
aoqi@0 371 private final void writeLittleEndianLongLong(long x) {
aoqi@0 372 bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF));
aoqi@0 373 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF));
aoqi@0 374 bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF));
aoqi@0 375 bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF));
aoqi@0 376 bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 32) & 0xFF));
aoqi@0 377 bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 40) & 0xFF));
aoqi@0 378 bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 48) & 0xFF));
aoqi@0 379 bbwi.byteBuffer.put(bbwi.position() + 7, (byte)((x >>> 56) & 0xFF));
aoqi@0 380 bbwi.position(bbwi.position() + 8);
aoqi@0 381 }
aoqi@0 382
aoqi@0 383 private final void writeBigEndianLongLong(long x) {
aoqi@0 384 bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 56) & 0xFF));
aoqi@0 385 bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 48) & 0xFF));
aoqi@0 386 bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 40) & 0xFF));
aoqi@0 387 bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 32) & 0xFF));
aoqi@0 388 bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 24) & 0xFF));
aoqi@0 389 bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 16) & 0xFF));
aoqi@0 390 bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 8) & 0xFF));
aoqi@0 391 bbwi.byteBuffer.put(bbwi.position() + 7, (byte)(x & 0xFF));
aoqi@0 392 bbwi.position(bbwi.position() + 8);
aoqi@0 393 }
aoqi@0 394
aoqi@0 395 public void write_wchar(char x)
aoqi@0 396 {
aoqi@0 397 // Don't allow transmission of wchar/wstring data with
aoqi@0 398 // foreign ORBs since it's against the spec.
aoqi@0 399 if (ORBUtility.isForeignORB(orb)) {
aoqi@0 400 throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 401 }
aoqi@0 402
aoqi@0 403 // If it's one of our legacy ORBs, do what they did:
aoqi@0 404 alignAndReserve(2, 2);
aoqi@0 405
aoqi@0 406 if (littleEndian) {
aoqi@0 407 writeLittleEndianWchar(x);
aoqi@0 408 } else {
aoqi@0 409 writeBigEndianWchar(x);
aoqi@0 410 }
aoqi@0 411 }
aoqi@0 412
aoqi@0 413 public void write_short(short x)
aoqi@0 414 {
aoqi@0 415 alignAndReserve(2, 2);
aoqi@0 416
aoqi@0 417 if (littleEndian) {
aoqi@0 418 writeLittleEndianShort(x);
aoqi@0 419 } else {
aoqi@0 420 writeBigEndianShort(x);
aoqi@0 421 }
aoqi@0 422 }
aoqi@0 423
aoqi@0 424 public final void write_ushort(short x)
aoqi@0 425 {
aoqi@0 426 write_short(x);
aoqi@0 427 }
aoqi@0 428
aoqi@0 429 public void write_long(int x)
aoqi@0 430 {
aoqi@0 431 alignAndReserve(4, 4);
aoqi@0 432
aoqi@0 433 if (littleEndian) {
aoqi@0 434 writeLittleEndianLong(x);
aoqi@0 435 } else {
aoqi@0 436 writeBigEndianLong(x);
aoqi@0 437 }
aoqi@0 438 }
aoqi@0 439
aoqi@0 440 public final void write_ulong(int x)
aoqi@0 441 {
aoqi@0 442 write_long(x);
aoqi@0 443 }
aoqi@0 444
aoqi@0 445 public void write_longlong(long x)
aoqi@0 446 {
aoqi@0 447 alignAndReserve(8, 8);
aoqi@0 448
aoqi@0 449 if (littleEndian) {
aoqi@0 450 writeLittleEndianLongLong(x);
aoqi@0 451 } else {
aoqi@0 452 writeBigEndianLongLong(x);
aoqi@0 453 }
aoqi@0 454 }
aoqi@0 455
aoqi@0 456 public final void write_ulonglong(long x)
aoqi@0 457 {
aoqi@0 458 write_longlong(x);
aoqi@0 459 }
aoqi@0 460
aoqi@0 461 public final void write_float(float x)
aoqi@0 462 {
aoqi@0 463 write_long(Float.floatToIntBits(x));
aoqi@0 464 }
aoqi@0 465
aoqi@0 466 public final void write_double(double x)
aoqi@0 467 {
aoqi@0 468 write_longlong(Double.doubleToLongBits(x));
aoqi@0 469 }
aoqi@0 470
aoqi@0 471 public void write_string(String value)
aoqi@0 472 {
aoqi@0 473 writeString(value);
aoqi@0 474 }
aoqi@0 475
aoqi@0 476 protected int writeString(String value)
aoqi@0 477 {
aoqi@0 478 if (value == null) {
aoqi@0 479 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 480 }
aoqi@0 481
aoqi@0 482 CodeSetConversion.CTBConverter converter = getCharConverter();
aoqi@0 483
aoqi@0 484 converter.convert(value);
aoqi@0 485
aoqi@0 486 // A string is encoded as an unsigned CORBA long for the
aoqi@0 487 // number of bytes to follow (including a terminating null).
aoqi@0 488 // There is only one octet per character in the string.
aoqi@0 489 int len = converter.getNumBytes() + 1;
aoqi@0 490
aoqi@0 491 handleSpecialChunkBegin(computeAlignment(4) + 4 + len);
aoqi@0 492
aoqi@0 493 write_long(len);
aoqi@0 494 int indirection = get_offset() - 4;
aoqi@0 495
aoqi@0 496 internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes());
aoqi@0 497
aoqi@0 498 // Write the null ending
aoqi@0 499 write_octet((byte)0);
aoqi@0 500
aoqi@0 501 handleSpecialChunkEnd();
aoqi@0 502 return indirection;
aoqi@0 503 }
aoqi@0 504
aoqi@0 505 public void write_wstring(String value)
aoqi@0 506 {
aoqi@0 507 if (value == null)
aoqi@0 508 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 509
aoqi@0 510 // Don't allow transmission of wchar/wstring data with
aoqi@0 511 // foreign ORBs since it's against the spec.
aoqi@0 512 if (ORBUtility.isForeignORB(orb)) {
aoqi@0 513 throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 514 }
aoqi@0 515
aoqi@0 516 // When talking to our legacy ORBs, do what they did:
aoqi@0 517 int len = value.length() + 1;
aoqi@0 518
aoqi@0 519 // This will only have an effect if we're already chunking
aoqi@0 520 handleSpecialChunkBegin(4 + (len * 2) + computeAlignment(4));
aoqi@0 521
aoqi@0 522 write_long(len);
aoqi@0 523
aoqi@0 524 for (int i = 0; i < len - 1; i++)
aoqi@0 525 write_wchar(value.charAt(i));
aoqi@0 526
aoqi@0 527 // Write the null ending
aoqi@0 528 write_short((short)0);
aoqi@0 529
aoqi@0 530 // This will only have an effect if we're already chunking
aoqi@0 531 handleSpecialChunkEnd();
aoqi@0 532 }
aoqi@0 533
aoqi@0 534 // Performs no checks and doesn't tamper with chunking
aoqi@0 535 void internalWriteOctetArray(byte[] value, int offset, int length)
aoqi@0 536 {
aoqi@0 537 int n = offset;
aoqi@0 538
aoqi@0 539 // This flag forces the alignAndReserve method to be called the
aoqi@0 540 // first time an octet is written. This is necessary to ensure
aoqi@0 541 // that the body is aligned on an 8-octet boundary. Note the 'if'
aoqi@0 542 // condition inside the 'while' loop below. Also, refer to the
aoqi@0 543 // write_octet() method that has a similar change.
aoqi@0 544 boolean align = true;
aoqi@0 545
aoqi@0 546 while (n < length+offset) {
aoqi@0 547 int avail;
aoqi@0 548 int bytes;
aoqi@0 549 int wanted;
aoqi@0 550
aoqi@0 551 if ((bbwi.position() + 1 > bbwi.buflen) || align) {
aoqi@0 552 align = false;
aoqi@0 553 alignAndReserve(1, 1);
aoqi@0 554 }
aoqi@0 555 avail = bbwi.buflen - bbwi.position();
aoqi@0 556 wanted = (length + offset) - n;
aoqi@0 557 bytes = (wanted < avail) ? wanted : avail;
aoqi@0 558 for (int i = 0; i < bytes; i++)
aoqi@0 559 bbwi.byteBuffer.put(bbwi.position() + i, value[n+i]);
aoqi@0 560 bbwi.position(bbwi.position() + bytes);
aoqi@0 561 n += bytes;
aoqi@0 562 }
aoqi@0 563 }
aoqi@0 564
aoqi@0 565 public final void write_octet_array(byte b[], int offset, int length)
aoqi@0 566 {
aoqi@0 567 if ( b == null )
aoqi@0 568 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 569
aoqi@0 570 // This will only have an effect if we're already chunking
aoqi@0 571 handleSpecialChunkBegin(length);
aoqi@0 572
aoqi@0 573 internalWriteOctetArray(b, offset, length);
aoqi@0 574
aoqi@0 575 // This will only have an effect if we're already chunking
aoqi@0 576 handleSpecialChunkEnd();
aoqi@0 577 }
aoqi@0 578
aoqi@0 579 public void write_Principal(Principal p)
aoqi@0 580 {
aoqi@0 581 write_long(p.name().length);
aoqi@0 582 write_octet_array(p.name(), 0, p.name().length);
aoqi@0 583 }
aoqi@0 584
aoqi@0 585 public void write_any(Any any)
aoqi@0 586 {
aoqi@0 587 if ( any == null )
aoqi@0 588 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 589
aoqi@0 590 write_TypeCode(any.type());
aoqi@0 591 any.write_value(parent);
aoqi@0 592 }
aoqi@0 593
aoqi@0 594 public void write_TypeCode(TypeCode tc)
aoqi@0 595 {
aoqi@0 596 if ( tc == null ) {
aoqi@0 597 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 598 }
aoqi@0 599 TypeCodeImpl tci;
aoqi@0 600 if (tc instanceof TypeCodeImpl) {
aoqi@0 601 tci = (TypeCodeImpl)tc;
aoqi@0 602 }
aoqi@0 603 else {
aoqi@0 604 tci = new TypeCodeImpl(orb, tc);
aoqi@0 605 }
aoqi@0 606
aoqi@0 607 tci.write_value((org.omg.CORBA_2_3.portable.OutputStream)parent);
aoqi@0 608 }
aoqi@0 609
aoqi@0 610 public void write_Object(org.omg.CORBA.Object ref)
aoqi@0 611 {
aoqi@0 612 if (ref == null) {
aoqi@0 613 IOR nullIOR = IORFactories.makeIOR( orb ) ;
aoqi@0 614 nullIOR.write(parent);
aoqi@0 615 return;
aoqi@0 616 }
aoqi@0 617
aoqi@0 618 // IDL to Java formal 01-06-06 1.21.4.2
aoqi@0 619 if (ref instanceof org.omg.CORBA.LocalObject)
aoqi@0 620 throw wrapper.writeLocalObject(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 621
aoqi@0 622 IOR ior = ORBUtility.connectAndGetIOR( orb, ref ) ;
aoqi@0 623 ior.write(parent);
aoqi@0 624 return;
aoqi@0 625 }
aoqi@0 626
aoqi@0 627 // ------------ RMI related methods --------------------------
aoqi@0 628
aoqi@0 629 public void write_abstract_interface(java.lang.Object obj) {
aoqi@0 630 boolean corbaObject = false; // Assume value type.
aoqi@0 631 org.omg.CORBA.Object theObject = null;
aoqi@0 632
aoqi@0 633 // Is it a CORBA.Object?
aoqi@0 634
aoqi@0 635 if (obj != null && obj instanceof org.omg.CORBA.Object) {
aoqi@0 636
aoqi@0 637 // Yes.
aoqi@0 638
aoqi@0 639 theObject = (org.omg.CORBA.Object)obj;
aoqi@0 640 corbaObject = true;
aoqi@0 641 }
aoqi@0 642
aoqi@0 643 // Write our flag...
aoqi@0 644
aoqi@0 645 write_boolean(corbaObject);
aoqi@0 646
aoqi@0 647 // Now write out the object...
aoqi@0 648
aoqi@0 649 if (corbaObject) {
aoqi@0 650 write_Object(theObject);
aoqi@0 651 } else {
aoqi@0 652 try {
aoqi@0 653 write_value((java.io.Serializable)obj);
aoqi@0 654 } catch(ClassCastException cce) {
aoqi@0 655 if (obj instanceof java.io.Serializable)
aoqi@0 656 throw cce;
aoqi@0 657 else
aoqi@0 658 ORBUtility.throwNotSerializableForCorba(obj.getClass().getName());
aoqi@0 659 }
aoqi@0 660 }
aoqi@0 661 }
aoqi@0 662
aoqi@0 663 public void write_value(Serializable object, Class clz) {
aoqi@0 664
aoqi@0 665 write_value(object);
aoqi@0 666 }
aoqi@0 667
aoqi@0 668 private void writeWStringValue(String string) {
aoqi@0 669
aoqi@0 670 int indirection = writeValueTag(mustChunk, true, null);
aoqi@0 671
aoqi@0 672 // Write WStringValue's repository ID
aoqi@0 673 write_repositoryId(repIdStrs.getWStringValueRepId());
aoqi@0 674
aoqi@0 675 // Add indirection for object to indirection table
aoqi@0 676 updateIndirectionTable(indirection, string, string);
aoqi@0 677
aoqi@0 678 // Write Value chunk
aoqi@0 679 if (mustChunk) {
aoqi@0 680 start_block();
aoqi@0 681 end_flag--;
aoqi@0 682 chunkedValueNestingLevel--;
aoqi@0 683 } else
aoqi@0 684 end_flag--;
aoqi@0 685
aoqi@0 686 write_wstring(string);
aoqi@0 687
aoqi@0 688 if (mustChunk)
aoqi@0 689 end_block();
aoqi@0 690
aoqi@0 691 // Write end tag
aoqi@0 692 writeEndTag(mustChunk);
aoqi@0 693 }
aoqi@0 694
aoqi@0 695 private void writeArray(Serializable array, Class clazz) {
aoqi@0 696
aoqi@0 697 if (valueHandler == null)
aoqi@0 698 valueHandler = ORBUtility.createValueHandler(); //d11638
aoqi@0 699
aoqi@0 700 // Write value_tag
aoqi@0 701 int indirection = writeValueTag(mustChunk, true,
aoqi@0 702 Util.getCodebase(clazz));
aoqi@0 703
aoqi@0 704 // Write repository ID
aoqi@0 705 write_repositoryId(repIdStrs.createSequenceRepID(clazz));
aoqi@0 706
aoqi@0 707 // Add indirection for object to indirection table
aoqi@0 708 updateIndirectionTable(indirection, array, array);
aoqi@0 709
aoqi@0 710 // Write Value chunk
aoqi@0 711 if (mustChunk) {
aoqi@0 712 start_block();
aoqi@0 713 end_flag--;
aoqi@0 714 chunkedValueNestingLevel--;
aoqi@0 715 } else
aoqi@0 716 end_flag--;
aoqi@0 717
aoqi@0 718 if (valueHandler instanceof ValueHandlerMultiFormat) {
aoqi@0 719 ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler;
aoqi@0 720 vh.writeValue(parent, array, streamFormatVersion);
aoqi@0 721 } else
aoqi@0 722 valueHandler.writeValue(parent, array);
aoqi@0 723
aoqi@0 724 if (mustChunk)
aoqi@0 725 end_block();
aoqi@0 726
aoqi@0 727 // Write end tag
aoqi@0 728 writeEndTag(mustChunk);
aoqi@0 729 }
aoqi@0 730
aoqi@0 731 private void writeValueBase(org.omg.CORBA.portable.ValueBase object,
aoqi@0 732 Class clazz) {
aoqi@0 733 // _REVISIT_ could check to see whether chunking really needed
aoqi@0 734 mustChunk = true;
aoqi@0 735
aoqi@0 736 // Write value_tag
aoqi@0 737 int indirection = writeValueTag(true, true, Util.getCodebase(clazz));
aoqi@0 738
aoqi@0 739 // Get rep id
aoqi@0 740 String repId = ((ValueBase)object)._truncatable_ids()[0];
aoqi@0 741
aoqi@0 742 // Write rep id
aoqi@0 743 write_repositoryId(repId);
aoqi@0 744
aoqi@0 745 // Add indirection for object to indirection table
aoqi@0 746 updateIndirectionTable(indirection, object, object);
aoqi@0 747
aoqi@0 748 // Write Value chunk
aoqi@0 749 start_block();
aoqi@0 750 end_flag--;
aoqi@0 751 chunkedValueNestingLevel--;
aoqi@0 752 writeIDLValue(object, repId);
aoqi@0 753 end_block();
aoqi@0 754
aoqi@0 755 // Write end tag
aoqi@0 756 writeEndTag(true);
aoqi@0 757 }
aoqi@0 758
aoqi@0 759 private void writeRMIIIOPValueType(Serializable object, Class clazz) {
aoqi@0 760 if (valueHandler == null)
aoqi@0 761 valueHandler = ORBUtility.createValueHandler(); //d11638
aoqi@0 762
aoqi@0 763 Serializable key = object;
aoqi@0 764
aoqi@0 765 // Allow the ValueHandler to call writeReplace on
aoqi@0 766 // the Serializable (if the method is present)
aoqi@0 767 object = valueHandler.writeReplace(key);
aoqi@0 768
aoqi@0 769 if (object == null) {
aoqi@0 770 // Write null tag and return
aoqi@0 771 write_long(0);
aoqi@0 772 return;
aoqi@0 773 }
aoqi@0 774
aoqi@0 775 if (object != key) {
aoqi@0 776 if (valueCache != null && valueCache.containsKey(object)) {
aoqi@0 777 writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
aoqi@0 778 return;
aoqi@0 779 }
aoqi@0 780
aoqi@0 781 clazz = object.getClass();
aoqi@0 782 }
aoqi@0 783
aoqi@0 784 if (mustChunk || valueHandler.isCustomMarshaled(clazz)) {
aoqi@0 785 mustChunk = true;
aoqi@0 786 }
aoqi@0 787
aoqi@0 788 // Write value_tag
aoqi@0 789 int indirection = writeValueTag(mustChunk, true, Util.getCodebase(clazz));
aoqi@0 790
aoqi@0 791 // Write rep. id
aoqi@0 792 write_repositoryId(repIdStrs.createForJavaType(clazz));
aoqi@0 793
aoqi@0 794 // Add indirection for object to indirection table
aoqi@0 795 updateIndirectionTable(indirection, object, key);
aoqi@0 796
aoqi@0 797 if (mustChunk) {
aoqi@0 798 // Write Value chunk
aoqi@0 799 end_flag--;
aoqi@0 800 chunkedValueNestingLevel--;
aoqi@0 801 start_block();
aoqi@0 802 } else
aoqi@0 803 end_flag--;
aoqi@0 804
aoqi@0 805 if (valueHandler instanceof ValueHandlerMultiFormat) {
aoqi@0 806 ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler;
aoqi@0 807 vh.writeValue(parent, object, streamFormatVersion);
aoqi@0 808 } else
aoqi@0 809 valueHandler.writeValue(parent, object);
aoqi@0 810
aoqi@0 811 if (mustChunk)
aoqi@0 812 end_block();
aoqi@0 813
aoqi@0 814 // Write end tag
aoqi@0 815 writeEndTag(mustChunk);
aoqi@0 816 }
aoqi@0 817
aoqi@0 818 public void write_value(Serializable object, String repository_id) {
aoqi@0 819
aoqi@0 820 // Handle null references
aoqi@0 821 if (object == null) {
aoqi@0 822 // Write null tag and return
aoqi@0 823 write_long(0);
aoqi@0 824 return;
aoqi@0 825 }
aoqi@0 826
aoqi@0 827 // Handle shared references
aoqi@0 828 if (valueCache != null && valueCache.containsKey(object)) {
aoqi@0 829 writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
aoqi@0 830 return;
aoqi@0 831 }
aoqi@0 832
aoqi@0 833 Class clazz = object.getClass();
aoqi@0 834 boolean oldMustChunk = mustChunk;
aoqi@0 835
aoqi@0 836 if (mustChunk)
aoqi@0 837 mustChunk = true;
aoqi@0 838
aoqi@0 839 if (inBlock)
aoqi@0 840 end_block();
aoqi@0 841
aoqi@0 842 if (clazz.isArray()) {
aoqi@0 843 // Handle arrays
aoqi@0 844 writeArray(object, clazz);
aoqi@0 845 } else if (object instanceof org.omg.CORBA.portable.ValueBase) {
aoqi@0 846 // Handle IDL Value types
aoqi@0 847 writeValueBase((org.omg.CORBA.portable.ValueBase)object, clazz);
aoqi@0 848 } else if (shouldWriteAsIDLEntity(object)) {
aoqi@0 849 writeIDLEntity((IDLEntity)object);
aoqi@0 850 } else if (object instanceof java.lang.String) {
aoqi@0 851 writeWStringValue((String)object);
aoqi@0 852 } else if (object instanceof java.lang.Class) {
aoqi@0 853 writeClass(repository_id, (Class)object);
aoqi@0 854 } else {
aoqi@0 855 // RMI-IIOP value type
aoqi@0 856 writeRMIIIOPValueType(object, clazz);
aoqi@0 857 }
aoqi@0 858
aoqi@0 859 mustChunk = oldMustChunk;
aoqi@0 860
aoqi@0 861 // Check to see if we need to start another block for a
aoqi@0 862 // possible outer value
aoqi@0 863 if (mustChunk)
aoqi@0 864 start_block();
aoqi@0 865
aoqi@0 866 }
aoqi@0 867
aoqi@0 868 public void write_value(Serializable object)
aoqi@0 869 {
aoqi@0 870 write_value(object, (String)null);
aoqi@0 871 }
aoqi@0 872
aoqi@0 873 public void write_value(Serializable object, org.omg.CORBA.portable.BoxedValueHelper factory)
aoqi@0 874 {
aoqi@0 875 // Handle null references
aoqi@0 876 if (object == null) {
aoqi@0 877 // Write null tag and return
aoqi@0 878 write_long(0);
aoqi@0 879 return;
aoqi@0 880 }
aoqi@0 881
aoqi@0 882 // Handle shared references
aoqi@0 883 if ((valueCache != null) && valueCache.containsKey(object)) {
aoqi@0 884 writeIndirection(INDIRECTION_TAG, valueCache.getVal(object));
aoqi@0 885 return;
aoqi@0 886 }
aoqi@0 887
aoqi@0 888 boolean oldMustChunk = mustChunk;
aoqi@0 889
aoqi@0 890 boolean isCustom = false;
aoqi@0 891 if (factory instanceof ValueHelper) {
aoqi@0 892 short modifier;
aoqi@0 893 try {
aoqi@0 894 modifier = ((ValueHelper)factory).get_type().type_modifier();
aoqi@0 895 } catch(BadKind ex) { // tk_value_box
aoqi@0 896 modifier = VM_NONE.value;
aoqi@0 897 }
aoqi@0 898 if (object instanceof CustomMarshal &&
aoqi@0 899 modifier == VM_CUSTOM.value) {
aoqi@0 900 isCustom = true;
aoqi@0 901 mustChunk = true;
aoqi@0 902 }
aoqi@0 903 if (modifier == VM_TRUNCATABLE.value)
aoqi@0 904 mustChunk = true;
aoqi@0 905 }
aoqi@0 906
aoqi@0 907 if (mustChunk) {
aoqi@0 908
aoqi@0 909 if (inBlock)
aoqi@0 910 end_block();
aoqi@0 911
aoqi@0 912 // Write value_tag
aoqi@0 913 int indirection = writeValueTag(true,
aoqi@0 914 orb.getORBData().useRepId(),
aoqi@0 915 Util.getCodebase(object.getClass())
aoqi@0 916 );
aoqi@0 917
aoqi@0 918 if (orb.getORBData().useRepId()) {
aoqi@0 919 write_repositoryId(factory.get_id());
aoqi@0 920 }
aoqi@0 921
aoqi@0 922 // Add indirection for object to indirection table
aoqi@0 923 updateIndirectionTable(indirection, object, object);
aoqi@0 924
aoqi@0 925 // Write Value chunk
aoqi@0 926 start_block();
aoqi@0 927 end_flag--;
aoqi@0 928 chunkedValueNestingLevel--;
aoqi@0 929 if (isCustom)
aoqi@0 930 ((CustomMarshal)object).marshal(parent);
aoqi@0 931 else
aoqi@0 932 factory.write_value(parent, object);
aoqi@0 933 end_block();
aoqi@0 934
aoqi@0 935 // Write end tag
aoqi@0 936 writeEndTag(true);
aoqi@0 937 }
aoqi@0 938 else {
aoqi@0 939 // Write value_tag
aoqi@0 940 int indirection = writeValueTag(false,
aoqi@0 941 orb.getORBData().useRepId(),
aoqi@0 942 Util.getCodebase(object.getClass())
aoqi@0 943 );
aoqi@0 944
aoqi@0 945 if (orb.getORBData().useRepId()) {
aoqi@0 946 write_repositoryId(factory.get_id());
aoqi@0 947 }
aoqi@0 948
aoqi@0 949 // Add indirection for object to indirection table
aoqi@0 950 updateIndirectionTable(indirection, object, object);
aoqi@0 951
aoqi@0 952 // Write Value chunk
aoqi@0 953 end_flag--;
aoqi@0 954 // no need to test for custom on the non-chunked path
aoqi@0 955 factory.write_value(parent, object);
aoqi@0 956
aoqi@0 957 // Write end tag
aoqi@0 958 writeEndTag(false);
aoqi@0 959 }
aoqi@0 960
aoqi@0 961 mustChunk = oldMustChunk;
aoqi@0 962
aoqi@0 963 // Check to see if we need to start another block for a
aoqi@0 964 // possible outer value
aoqi@0 965 if (mustChunk)
aoqi@0 966 start_block();
aoqi@0 967
aoqi@0 968 }
aoqi@0 969
aoqi@0 970 public int get_offset() {
aoqi@0 971 return bbwi.position();
aoqi@0 972 }
aoqi@0 973
aoqi@0 974 public void start_block() {
aoqi@0 975 if (debug) {
aoqi@0 976 dprint("CDROutputStream_1_0 start_block, position" + bbwi.position());
aoqi@0 977 }
aoqi@0 978
aoqi@0 979 //Move inBlock=true to after write_long since write_long might
aoqi@0 980 //trigger grow which will lead to erroneous behavior with a
aoqi@0 981 //missing blockSizeIndex.
aoqi@0 982 //inBlock = true;
aoqi@0 983
aoqi@0 984 // Save space in the buffer for block size
aoqi@0 985 write_long(0);
aoqi@0 986
aoqi@0 987 //Has to happen after write_long since write_long could
aoqi@0 988 //trigger grow which is overridden by supper classes to
aoqi@0 989 //depend on inBlock.
aoqi@0 990 inBlock = true;
aoqi@0 991
aoqi@0 992 blockSizePosition = get_offset();
aoqi@0 993
aoqi@0 994 // Remember where to put the size of the endblock less 4
aoqi@0 995 blockSizeIndex = bbwi.position();
aoqi@0 996
aoqi@0 997 if (debug) {
aoqi@0 998 dprint("CDROutputStream_1_0 start_block, blockSizeIndex "
aoqi@0 999 + blockSizeIndex);
aoqi@0 1000 }
aoqi@0 1001
aoqi@0 1002 }
aoqi@0 1003
aoqi@0 1004 // Utility method which will hopefully decrease chunking complexity
aoqi@0 1005 // by allowing us to end_block and update chunk lengths without
aoqi@0 1006 // calling alignAndReserve. Otherwise, it's possible to get into
aoqi@0 1007 // recursive scenarios which lose the chunking state.
aoqi@0 1008 protected void writeLongWithoutAlign(int x) {
aoqi@0 1009 if (littleEndian) {
aoqi@0 1010 writeLittleEndianLong(x);
aoqi@0 1011 } else {
aoqi@0 1012 writeBigEndianLong(x);
aoqi@0 1013 }
aoqi@0 1014 }
aoqi@0 1015
aoqi@0 1016 public void end_block() {
aoqi@0 1017 if (debug) {
aoqi@0 1018 dprint("CDROutputStream_1_0.java end_block");
aoqi@0 1019 }
aoqi@0 1020
aoqi@0 1021 if (!inBlock)
aoqi@0 1022 return;
aoqi@0 1023
aoqi@0 1024 if (debug) {
aoqi@0 1025 dprint("CDROutputStream_1_0.java end_block, in a block");
aoqi@0 1026 }
aoqi@0 1027
aoqi@0 1028 inBlock = false;
aoqi@0 1029
aoqi@0 1030 // Test to see if the block was of zero length
aoqi@0 1031 // If so, remove the block instead of ending it
aoqi@0 1032 // (This can happen if the last field written
aoqi@0 1033 // in a value was another value)
aoqi@0 1034 if (get_offset() == blockSizePosition) {
aoqi@0 1035 // Need to assert that blockSizeIndex == bbwi.position()? REVISIT
aoqi@0 1036
aoqi@0 1037 bbwi.position(bbwi.position() - 4);
aoqi@0 1038 blockSizeIndex = -1;
aoqi@0 1039 blockSizePosition = -1;
aoqi@0 1040 return;
aoqi@0 1041 }
aoqi@0 1042
aoqi@0 1043 int oldSize = bbwi.position();
aoqi@0 1044 bbwi.position(blockSizeIndex - 4);
aoqi@0 1045
aoqi@0 1046 writeLongWithoutAlign(oldSize - blockSizeIndex);
aoqi@0 1047
aoqi@0 1048 bbwi.position(oldSize);
aoqi@0 1049 blockSizeIndex = -1;
aoqi@0 1050 blockSizePosition = -1;
aoqi@0 1051
aoqi@0 1052 // System.out.println(" post end_block: " + get_offset() + " " + bbwi.position());
aoqi@0 1053 }
aoqi@0 1054
aoqi@0 1055 public org.omg.CORBA.ORB orb()
aoqi@0 1056 {
aoqi@0 1057 return orb;
aoqi@0 1058 }
aoqi@0 1059
aoqi@0 1060 // ------------ End RMI related methods --------------------------
aoqi@0 1061
aoqi@0 1062 public final void write_boolean_array(boolean[]value, int offset, int length) {
aoqi@0 1063 if ( value == null )
aoqi@0 1064 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1065
aoqi@0 1066 // This will only have an effect if we're already chunking
aoqi@0 1067 handleSpecialChunkBegin(length);
aoqi@0 1068
aoqi@0 1069 for (int i = 0; i < length; i++)
aoqi@0 1070 write_boolean(value[offset + i]);
aoqi@0 1071
aoqi@0 1072 // This will only have an effect if we're already chunking
aoqi@0 1073 handleSpecialChunkEnd();
aoqi@0 1074 }
aoqi@0 1075
aoqi@0 1076 public final void write_char_array(char[]value, int offset, int length) {
aoqi@0 1077 if ( value == null )
aoqi@0 1078 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1079
aoqi@0 1080 // This will only have an effect if we're already chunking
aoqi@0 1081 handleSpecialChunkBegin(length);
aoqi@0 1082
aoqi@0 1083 for (int i = 0; i < length; i++)
aoqi@0 1084 write_char(value[offset + i]);
aoqi@0 1085
aoqi@0 1086 // This will only have an effect if we're already chunking
aoqi@0 1087 handleSpecialChunkEnd();
aoqi@0 1088 }
aoqi@0 1089
aoqi@0 1090 public void write_wchar_array(char[]value, int offset, int length) {
aoqi@0 1091 if ( value == null )
aoqi@0 1092 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1093
aoqi@0 1094 // This will only have an effect if we're already chunking
aoqi@0 1095 handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
aoqi@0 1096
aoqi@0 1097 for (int i = 0; i < length; i++)
aoqi@0 1098 write_wchar(value[offset + i]);
aoqi@0 1099
aoqi@0 1100 // This will only have an effect if we're already chunking
aoqi@0 1101 handleSpecialChunkEnd();
aoqi@0 1102 }
aoqi@0 1103
aoqi@0 1104 public final void write_short_array(short[]value, int offset, int length) {
aoqi@0 1105 if ( value == null )
aoqi@0 1106 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1107
aoqi@0 1108 // This will only have an effect if we're already chunking
aoqi@0 1109 handleSpecialChunkBegin(computeAlignment(2) + (length * 2));
aoqi@0 1110
aoqi@0 1111 for (int i = 0; i < length; i++)
aoqi@0 1112 write_short(value[offset + i]);
aoqi@0 1113
aoqi@0 1114 // This will only have an effect if we're already chunking
aoqi@0 1115 handleSpecialChunkEnd();
aoqi@0 1116 }
aoqi@0 1117
aoqi@0 1118 public final void write_ushort_array(short[]value, int offset, int length) {
aoqi@0 1119 write_short_array(value, offset, length);
aoqi@0 1120 }
aoqi@0 1121
aoqi@0 1122 public final void write_long_array(int[]value, int offset, int length) {
aoqi@0 1123 if ( value == null )
aoqi@0 1124 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1125
aoqi@0 1126 // This will only have an effect if we're already chunking
aoqi@0 1127 handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
aoqi@0 1128
aoqi@0 1129 for (int i = 0; i < length; i++)
aoqi@0 1130 write_long(value[offset + i]);
aoqi@0 1131
aoqi@0 1132 // This will only have an effect if we're already chunking
aoqi@0 1133 handleSpecialChunkEnd();
aoqi@0 1134 }
aoqi@0 1135
aoqi@0 1136 public final void write_ulong_array(int[]value, int offset, int length) {
aoqi@0 1137 write_long_array(value, offset, length);
aoqi@0 1138 }
aoqi@0 1139
aoqi@0 1140 public final void write_longlong_array(long[]value, int offset, int length) {
aoqi@0 1141 if ( value == null )
aoqi@0 1142 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1143
aoqi@0 1144 // This will only have an effect if we're already chunking
aoqi@0 1145 handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
aoqi@0 1146
aoqi@0 1147 for (int i = 0; i < length; i++)
aoqi@0 1148 write_longlong(value[offset + i]);
aoqi@0 1149
aoqi@0 1150 // This will only have an effect if we're already chunking
aoqi@0 1151 handleSpecialChunkEnd();
aoqi@0 1152 }
aoqi@0 1153
aoqi@0 1154 public final void write_ulonglong_array(long[]value, int offset, int length) {
aoqi@0 1155 write_longlong_array(value, offset, length);
aoqi@0 1156 }
aoqi@0 1157
aoqi@0 1158 public final void write_float_array(float[]value, int offset, int length) {
aoqi@0 1159 if ( value == null )
aoqi@0 1160 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1161
aoqi@0 1162 // This will only have an effect if we're already chunking
aoqi@0 1163 handleSpecialChunkBegin(computeAlignment(4) + (length * 4));
aoqi@0 1164
aoqi@0 1165 for (int i = 0; i < length; i++)
aoqi@0 1166 write_float(value[offset + i]);
aoqi@0 1167
aoqi@0 1168 // This will only have an effect if we're already chunking
aoqi@0 1169 handleSpecialChunkEnd();
aoqi@0 1170 }
aoqi@0 1171
aoqi@0 1172 public final void write_double_array(double[]value, int offset, int length) {
aoqi@0 1173 if ( value == null )
aoqi@0 1174 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1175
aoqi@0 1176 // This will only have an effect if we're already chunking
aoqi@0 1177 handleSpecialChunkBegin(computeAlignment(8) + (length * 8));
aoqi@0 1178
aoqi@0 1179 for (int i = 0; i < length; i++)
aoqi@0 1180 write_double(value[offset + i]);
aoqi@0 1181
aoqi@0 1182 // This will only have an effect if we're already chunking
aoqi@0 1183 handleSpecialChunkEnd();
aoqi@0 1184 }
aoqi@0 1185
aoqi@0 1186 public void write_string_array(String[] value, int offset, int length) {
aoqi@0 1187 if ( value == null )
aoqi@0 1188 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1189
aoqi@0 1190 for(int i = 0; i < length; i++)
aoqi@0 1191 write_string(value[offset + i]);
aoqi@0 1192 }
aoqi@0 1193
aoqi@0 1194 public void write_wstring_array(String[] value, int offset, int length) {
aoqi@0 1195 if ( value == null )
aoqi@0 1196 throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE);
aoqi@0 1197
aoqi@0 1198 for(int i = 0; i < length; i++)
aoqi@0 1199 write_wstring(value[offset + i]);
aoqi@0 1200 }
aoqi@0 1201
aoqi@0 1202 public final void write_any_array(org.omg.CORBA.Any value[], int offset, int length)
aoqi@0 1203 {
aoqi@0 1204 for(int i = 0; i < length; i++)
aoqi@0 1205 write_any(value[offset + i]);
aoqi@0 1206 }
aoqi@0 1207
aoqi@0 1208 //--------------------------------------------------------------------//
aoqi@0 1209 // CDROutputStream state management.
aoqi@0 1210 //
aoqi@0 1211
aoqi@0 1212 public void writeTo(java.io.OutputStream s)
aoqi@0 1213 throws java.io.IOException
aoqi@0 1214 {
aoqi@0 1215 byte[] tmpBuf = null;
aoqi@0 1216
aoqi@0 1217 if (bbwi.byteBuffer.hasArray())
aoqi@0 1218 {
aoqi@0 1219 tmpBuf = bbwi.byteBuffer.array();
aoqi@0 1220 }
aoqi@0 1221 else
aoqi@0 1222 {
aoqi@0 1223 int size = bbwi.position();
aoqi@0 1224 tmpBuf = new byte[size];
aoqi@0 1225 // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
aoqi@0 1226 // faster than ByteBuffer.get(byte[], offset, length)
aoqi@0 1227 for (int i = 0; i < size; i++)
aoqi@0 1228 tmpBuf[i] = bbwi.byteBuffer.get(i);
aoqi@0 1229 }
aoqi@0 1230
aoqi@0 1231 s.write(tmpBuf, 0, bbwi.position());
aoqi@0 1232 }
aoqi@0 1233
aoqi@0 1234 public void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream s) {
aoqi@0 1235
aoqi@0 1236 byte[] buf = null;
aoqi@0 1237
aoqi@0 1238 if (bbwi.byteBuffer.hasArray())
aoqi@0 1239 {
aoqi@0 1240 buf = bbwi.byteBuffer.array();
aoqi@0 1241 }
aoqi@0 1242 else
aoqi@0 1243 {
aoqi@0 1244 int size = bbwi.position();
aoqi@0 1245 buf = new byte[size];
aoqi@0 1246 // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is
aoqi@0 1247 // faster than ByteBuffer.get(byte[], offset, length)
aoqi@0 1248 for (int i = 0; i < size; i++)
aoqi@0 1249 buf[i] = bbwi.byteBuffer.get(i);
aoqi@0 1250 }
aoqi@0 1251
aoqi@0 1252 s.write_long(bbwi.position());
aoqi@0 1253 s.write_octet_array(buf, 0, bbwi.position());
aoqi@0 1254
aoqi@0 1255 }
aoqi@0 1256
aoqi@0 1257 public final int getSize() {
aoqi@0 1258 return bbwi.position();
aoqi@0 1259 }
aoqi@0 1260
aoqi@0 1261 public int getIndex() {
aoqi@0 1262 return bbwi.position();
aoqi@0 1263 }
aoqi@0 1264
aoqi@0 1265 public boolean isLittleEndian() {
aoqi@0 1266 return littleEndian;
aoqi@0 1267 }
aoqi@0 1268
aoqi@0 1269 public void setIndex(int value) {
aoqi@0 1270 bbwi.position(value);
aoqi@0 1271 }
aoqi@0 1272
aoqi@0 1273 public ByteBufferWithInfo getByteBufferWithInfo() {
aoqi@0 1274 return bbwi;
aoqi@0 1275 }
aoqi@0 1276
aoqi@0 1277 public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
aoqi@0 1278 this.bbwi = bbwi;
aoqi@0 1279 }
aoqi@0 1280
aoqi@0 1281 public ByteBuffer getByteBuffer() {
aoqi@0 1282 ByteBuffer result = null;;
aoqi@0 1283 if (bbwi != null) {
aoqi@0 1284 result = bbwi.byteBuffer;
aoqi@0 1285 }
aoqi@0 1286 return result;
aoqi@0 1287 }
aoqi@0 1288
aoqi@0 1289 public void setByteBuffer(ByteBuffer byteBuffer) {
aoqi@0 1290 bbwi.byteBuffer = byteBuffer;
aoqi@0 1291 }
aoqi@0 1292
aoqi@0 1293 private final void updateIndirectionTable(int indirection, java.lang.Object object,
aoqi@0 1294 java.lang.Object key) {
aoqi@0 1295 // int indirection = get_offset();
aoqi@0 1296 if (valueCache == null)
aoqi@0 1297 valueCache = new CacheTable(orb,true);
aoqi@0 1298 valueCache.put(object, indirection);
aoqi@0 1299 if (key != object)
aoqi@0 1300 valueCache.put(key, indirection);
aoqi@0 1301 }
aoqi@0 1302
aoqi@0 1303 private final void write_repositoryId(String id) {
aoqi@0 1304 // Use an indirection if available
aoqi@0 1305 if (repositoryIdCache != null && repositoryIdCache.containsKey(id)) {
aoqi@0 1306 writeIndirection(INDIRECTION_TAG, repositoryIdCache.getVal(id));
aoqi@0 1307 return;
aoqi@0 1308 }
aoqi@0 1309
aoqi@0 1310 // Write it as a string. Note that we have already done the
aoqi@0 1311 // special case conversion of non-Latin-1 characters to escaped
aoqi@0 1312 // Latin-1 sequences in RepositoryId.
aoqi@0 1313
aoqi@0 1314 // It's not a good idea to cache them now that we can have
aoqi@0 1315 // multiple code sets.
aoqi@0 1316 int indirection = writeString(id);
aoqi@0 1317
aoqi@0 1318 // Add indirection for id to indirection table
aoqi@0 1319 if (repositoryIdCache == null)
aoqi@0 1320 repositoryIdCache = new CacheTable(orb,true);
aoqi@0 1321 repositoryIdCache.put(id, indirection);
aoqi@0 1322 }
aoqi@0 1323
aoqi@0 1324 private void write_codebase(String str, int pos) {
aoqi@0 1325 if (codebaseCache != null && codebaseCache.containsKey(str)) {
aoqi@0 1326 writeIndirection(INDIRECTION_TAG, codebaseCache.getVal(str));
aoqi@0 1327 }
aoqi@0 1328 else {
aoqi@0 1329 write_string(str);
aoqi@0 1330 if (codebaseCache == null)
aoqi@0 1331 codebaseCache = new CacheTable(orb,true);
aoqi@0 1332 codebaseCache.put(str, pos);
aoqi@0 1333 }
aoqi@0 1334 }
aoqi@0 1335
aoqi@0 1336 private final int writeValueTag(boolean chunkIt, boolean useRepId,
aoqi@0 1337 String codebase) {
aoqi@0 1338 int indirection = 0;
aoqi@0 1339 if (chunkIt && !useRepId){
aoqi@0 1340 if (codebase == null) {
aoqi@0 1341 write_long(repIdUtil.getStandardRMIChunkedNoRepStrId());
aoqi@0 1342 indirection = get_offset() - 4;
aoqi@0 1343 } else {
aoqi@0 1344 write_long(repIdUtil.getCodeBaseRMIChunkedNoRepStrId());
aoqi@0 1345 indirection = get_offset() - 4;
aoqi@0 1346 write_codebase(codebase, get_offset());
aoqi@0 1347 }
aoqi@0 1348 } else if (chunkIt && useRepId){
aoqi@0 1349 if (codebase == null) {
aoqi@0 1350 write_long(repIdUtil.getStandardRMIChunkedId());
aoqi@0 1351 indirection = get_offset() - 4;
aoqi@0 1352 } else {
aoqi@0 1353 write_long(repIdUtil.getCodeBaseRMIChunkedId());
aoqi@0 1354 indirection = get_offset() - 4;
aoqi@0 1355 write_codebase(codebase, get_offset());
aoqi@0 1356 }
aoqi@0 1357 } else if (!chunkIt && !useRepId) {
aoqi@0 1358 if (codebase == null) {
aoqi@0 1359 write_long(repIdUtil.getStandardRMIUnchunkedNoRepStrId());
aoqi@0 1360 indirection = get_offset() - 4;
aoqi@0 1361 } else {
aoqi@0 1362 write_long(repIdUtil.getCodeBaseRMIUnchunkedNoRepStrId());
aoqi@0 1363 indirection = get_offset() - 4;
aoqi@0 1364 write_codebase(codebase, get_offset());
aoqi@0 1365 }
aoqi@0 1366 } else if (!chunkIt && useRepId) {
aoqi@0 1367 if (codebase == null) {
aoqi@0 1368 write_long(repIdUtil.getStandardRMIUnchunkedId());
aoqi@0 1369 indirection = get_offset() - 4;
aoqi@0 1370 } else {
aoqi@0 1371 write_long(repIdUtil.getCodeBaseRMIUnchunkedId());
aoqi@0 1372 indirection = get_offset() - 4;
aoqi@0 1373 write_codebase(codebase, get_offset());
aoqi@0 1374 }
aoqi@0 1375 }
aoqi@0 1376 return indirection;
aoqi@0 1377 }
aoqi@0 1378
aoqi@0 1379 private void writeIDLValue(Serializable object, String repID)
aoqi@0 1380 {
aoqi@0 1381 if (object instanceof StreamableValue) {
aoqi@0 1382 ((StreamableValue)object)._write(parent);
aoqi@0 1383
aoqi@0 1384 } else if (object instanceof CustomValue) {
aoqi@0 1385 ((CustomValue)object).marshal(parent);
aoqi@0 1386
aoqi@0 1387 } else {
aoqi@0 1388 BoxedValueHelper helper = Utility.getHelper(object.getClass(), null, repID);
aoqi@0 1389 boolean isCustom = false;
aoqi@0 1390 if (helper instanceof ValueHelper && object instanceof CustomMarshal) {
aoqi@0 1391 try {
aoqi@0 1392 if (((ValueHelper)helper).get_type().type_modifier() == VM_CUSTOM.value)
aoqi@0 1393 isCustom = true;
aoqi@0 1394 } catch(BadKind ex) {
aoqi@0 1395 throw wrapper.badTypecodeForCustomValue( CompletionStatus.COMPLETED_MAYBE,
aoqi@0 1396 ex ) ;
aoqi@0 1397 }
aoqi@0 1398 }
aoqi@0 1399 if (isCustom)
aoqi@0 1400 ((CustomMarshal)object).marshal(parent);
aoqi@0 1401 else
aoqi@0 1402 helper.write_value(parent, object);
aoqi@0 1403 }
aoqi@0 1404 }
aoqi@0 1405
aoqi@0 1406 // Handles end tag compaction...
aoqi@0 1407 private void writeEndTag(boolean chunked){
aoqi@0 1408
aoqi@0 1409 if (chunked) {
aoqi@0 1410 if (get_offset() == end_flag_position) {
aoqi@0 1411
aoqi@0 1412 if (bbwi.position() == end_flag_index) {
aoqi@0 1413
aoqi@0 1414 // We are exactly at the same position and index as the
aoqi@0 1415 // end of the last end tag. Thus, we can back up over it
aoqi@0 1416 // and compact the tags.
aoqi@0 1417 bbwi.position(bbwi.position() - 4);
aoqi@0 1418
aoqi@0 1419 } else {
aoqi@0 1420
aoqi@0 1421 // Special case in which we're at the beginning of a new
aoqi@0 1422 // fragment, but the position is the same. We can't back up,
aoqi@0 1423 // so we just write the new end tag without compaction. This
aoqi@0 1424 // occurs when a value ends and calls start_block to open a
aoqi@0 1425 // continuation chunk, but it's called at the very end of
aoqi@0 1426 // a fragment.
aoqi@0 1427 }
aoqi@0 1428 }
aoqi@0 1429
aoqi@0 1430 writeNestingLevel();
aoqi@0 1431
aoqi@0 1432 // Remember the last index and position. These are only used when chunking.
aoqi@0 1433 end_flag_index = bbwi.position();
aoqi@0 1434 end_flag_position = get_offset();
aoqi@0 1435
aoqi@0 1436 chunkedValueNestingLevel++;
aoqi@0 1437 }
aoqi@0 1438
aoqi@0 1439 // Increment the nesting level
aoqi@0 1440 end_flag++;
aoqi@0 1441 }
aoqi@0 1442
aoqi@0 1443 /**
aoqi@0 1444 * Handles ORB versioning of the end tag. Should only
aoqi@0 1445 * be called if chunking.
aoqi@0 1446 *
aoqi@0 1447 * If talking to our older ORBs (Standard Extension,
aoqi@0 1448 * Kestrel, and Ladybird), write the end flag that takes
aoqi@0 1449 * into account all enclosing valuetypes.
aoqi@0 1450 *
aoqi@0 1451 * If talking a newer or foreign ORB, or if the orb
aoqi@0 1452 * instance is null, write the end flag that only takes
aoqi@0 1453 * into account the enclosing chunked valuetypes.
aoqi@0 1454 */
aoqi@0 1455 private void writeNestingLevel() {
aoqi@0 1456 if (orb == null ||
aoqi@0 1457 ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
aoqi@0 1458 ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
aoqi@0 1459
aoqi@0 1460 write_long(chunkedValueNestingLevel);
aoqi@0 1461
aoqi@0 1462 } else {
aoqi@0 1463 write_long(end_flag);
aoqi@0 1464 }
aoqi@0 1465 }
aoqi@0 1466
aoqi@0 1467 private void writeClass(String repository_id, Class clz) {
aoqi@0 1468
aoqi@0 1469 if (repository_id == null)
aoqi@0 1470 repository_id = repIdStrs.getClassDescValueRepId();
aoqi@0 1471
aoqi@0 1472 // Write value_tag
aoqi@0 1473 int indirection = writeValueTag(mustChunk, true, null);
aoqi@0 1474 updateIndirectionTable(indirection, clz, clz);
aoqi@0 1475
aoqi@0 1476 write_repositoryId(repository_id);
aoqi@0 1477
aoqi@0 1478 if (mustChunk) {
aoqi@0 1479 // Write Value chunk
aoqi@0 1480 start_block();
aoqi@0 1481 end_flag--;
aoqi@0 1482 chunkedValueNestingLevel--;
aoqi@0 1483 } else
aoqi@0 1484 end_flag--;
aoqi@0 1485
aoqi@0 1486 writeClassBody(clz);
aoqi@0 1487
aoqi@0 1488 if (mustChunk)
aoqi@0 1489 end_block();
aoqi@0 1490
aoqi@0 1491 // Write end tag
aoqi@0 1492 writeEndTag(mustChunk);
aoqi@0 1493 }
aoqi@0 1494
aoqi@0 1495 // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
aoqi@0 1496 // and codebase strings in the wrong order. This handles
aoqi@0 1497 // backwards compatibility.
aoqi@0 1498 private void writeClassBody(Class clz) {
aoqi@0 1499 if (orb == null ||
aoqi@0 1500 ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
aoqi@0 1501 ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
aoqi@0 1502
aoqi@0 1503 write_value(Util.getCodebase(clz));
aoqi@0 1504 write_value(repIdStrs.createForAnyType(clz));
aoqi@0 1505 } else {
aoqi@0 1506
aoqi@0 1507 write_value(repIdStrs.createForAnyType(clz));
aoqi@0 1508 write_value(Util.getCodebase(clz));
aoqi@0 1509 }
aoqi@0 1510 }
aoqi@0 1511
aoqi@0 1512 // Casts and returns an Object as a Serializable
aoqi@0 1513 // This is required for JDK 1.1 only to avoid VerifyErrors when
aoqi@0 1514 // passing arrays as Serializable
aoqi@0 1515 // private java.io.Serializable make_serializable(java.lang.Object object)
aoqi@0 1516 // {
aoqi@0 1517 // return (java.io.Serializable)object;
aoqi@0 1518 // }
aoqi@0 1519
aoqi@0 1520 private boolean shouldWriteAsIDLEntity(Serializable object)
aoqi@0 1521 {
aoqi@0 1522 return ((object instanceof IDLEntity) && (!(object instanceof ValueBase)) &&
aoqi@0 1523 (!(object instanceof org.omg.CORBA.Object)));
aoqi@0 1524
aoqi@0 1525 }
aoqi@0 1526
aoqi@0 1527 private void writeIDLEntity(IDLEntity object) {
aoqi@0 1528
aoqi@0 1529 // _REVISIT_ could check to see whether chunking really needed
aoqi@0 1530 mustChunk = true;
aoqi@0 1531
aoqi@0 1532 String repository_id = repIdStrs.createForJavaType(object);
aoqi@0 1533 Class clazz = object.getClass();
aoqi@0 1534 String codebase = Util.getCodebase(clazz);
aoqi@0 1535
aoqi@0 1536 // Write value_tag
aoqi@0 1537 int indirection = writeValueTag(true, true, codebase);
aoqi@0 1538 updateIndirectionTable(indirection, object, object);
aoqi@0 1539
aoqi@0 1540 // Write rep. id
aoqi@0 1541 write_repositoryId(repository_id);
aoqi@0 1542
aoqi@0 1543 // Write Value chunk
aoqi@0 1544 end_flag--;
aoqi@0 1545 chunkedValueNestingLevel--;
aoqi@0 1546 start_block();
aoqi@0 1547
aoqi@0 1548 // Write the IDLEntity using reflection
aoqi@0 1549 try {
aoqi@0 1550 ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
aoqi@0 1551 final Class helperClass = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
aoqi@0 1552 clazzLoader, clazz, clazzLoader);
aoqi@0 1553 final Class argTypes[] = {org.omg.CORBA.portable.OutputStream.class, clazz};
aoqi@0 1554 // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
aoqi@0 1555 // if a different class loader is used (even though the javadoc says otherwise)
aoqi@0 1556 Method writeMethod = null;
aoqi@0 1557 try {
aoqi@0 1558 writeMethod = (Method)AccessController.doPrivileged(
aoqi@0 1559 new PrivilegedExceptionAction() {
aoqi@0 1560 public java.lang.Object run() throws NoSuchMethodException {
aoqi@0 1561 return helperClass.getDeclaredMethod(kWriteMethod, argTypes);
aoqi@0 1562 }
aoqi@0 1563 }
aoqi@0 1564 );
aoqi@0 1565 } catch (PrivilegedActionException pae) {
aoqi@0 1566 // this gets caught below
aoqi@0 1567 throw (NoSuchMethodException)pae.getException();
aoqi@0 1568 }
aoqi@0 1569 java.lang.Object args[] = {parent, object};
aoqi@0 1570 writeMethod.invoke(null, args);
aoqi@0 1571 } catch (ClassNotFoundException cnfe) {
aoqi@0 1572 throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, cnfe ) ;
aoqi@0 1573 } catch(NoSuchMethodException nsme) {
aoqi@0 1574 throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, nsme ) ;
aoqi@0 1575 } catch(IllegalAccessException iae) {
aoqi@0 1576 throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, iae ) ;
aoqi@0 1577 } catch(InvocationTargetException ite) {
aoqi@0 1578 throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, ite ) ;
aoqi@0 1579 }
aoqi@0 1580 end_block();
aoqi@0 1581
aoqi@0 1582 // Write end tag
aoqi@0 1583 writeEndTag(true);
aoqi@0 1584 }
aoqi@0 1585
aoqi@0 1586 /* DataOutputStream methods */
aoqi@0 1587
aoqi@0 1588 public void write_Abstract (java.lang.Object value) {
aoqi@0 1589 write_abstract_interface(value);
aoqi@0 1590 }
aoqi@0 1591
aoqi@0 1592 public void write_Value (java.io.Serializable value) {
aoqi@0 1593 write_value(value);
aoqi@0 1594 }
aoqi@0 1595
aoqi@0 1596 // This will stay a custom add-on until the java-rtf issue is resolved.
aoqi@0 1597 // Then it should be declared in org.omg.CORBA.portable.OutputStream.
aoqi@0 1598 //
aoqi@0 1599 // Pads the string representation of bigDecimal with zeros to fit the given
aoqi@0 1600 // digits and scale before it gets written to the stream.
aoqi@0 1601 public void write_fixed(java.math.BigDecimal bigDecimal, short digits, short scale) {
aoqi@0 1602 String string = bigDecimal.toString();
aoqi@0 1603 String integerPart;
aoqi@0 1604 String fractionPart;
aoqi@0 1605 StringBuffer stringBuffer;
aoqi@0 1606
aoqi@0 1607 // Get rid of the sign
aoqi@0 1608 if (string.charAt(0) == '-' || string.charAt(0) == '+') {
aoqi@0 1609 string = string.substring(1);
aoqi@0 1610 }
aoqi@0 1611
aoqi@0 1612 // Determine integer and fraction parts
aoqi@0 1613 int dotIndex = string.indexOf('.');
aoqi@0 1614 if (dotIndex == -1) {
aoqi@0 1615 integerPart = string;
aoqi@0 1616 fractionPart = null;
aoqi@0 1617 } else if (dotIndex == 0 ) {
aoqi@0 1618 integerPart = null;
aoqi@0 1619 fractionPart = string;
aoqi@0 1620 } else {
aoqi@0 1621 integerPart = string.substring(0, dotIndex);
aoqi@0 1622 fractionPart = string.substring(dotIndex + 1);
aoqi@0 1623 }
aoqi@0 1624
aoqi@0 1625 // Pad both parts with zeros as necessary
aoqi@0 1626 stringBuffer = new StringBuffer(digits);
aoqi@0 1627 if (fractionPart != null) {
aoqi@0 1628 stringBuffer.append(fractionPart);
aoqi@0 1629 }
aoqi@0 1630 while (stringBuffer.length() < scale) {
aoqi@0 1631 stringBuffer.append('0');
aoqi@0 1632 }
aoqi@0 1633 if (integerPart != null) {
aoqi@0 1634 stringBuffer.insert(0, integerPart);
aoqi@0 1635 }
aoqi@0 1636 while (stringBuffer.length() < digits) {
aoqi@0 1637 stringBuffer.insert(0, '0');
aoqi@0 1638 }
aoqi@0 1639
aoqi@0 1640 // This string contains no sign or dot
aoqi@0 1641 this.write_fixed(stringBuffer.toString(), bigDecimal.signum());
aoqi@0 1642 }
aoqi@0 1643
aoqi@0 1644 // This method should be remove by the java-rtf issue.
aoqi@0 1645 // Right now the scale and digits information of the type code is lost.
aoqi@0 1646 public void write_fixed(java.math.BigDecimal bigDecimal) {
aoqi@0 1647 // This string might contain sign and/or dot
aoqi@0 1648 this.write_fixed(bigDecimal.toString(), bigDecimal.signum());
aoqi@0 1649 }
aoqi@0 1650
aoqi@0 1651 // The string may contain a sign and dot
aoqi@0 1652 public void write_fixed(String string, int signum) {
aoqi@0 1653 int stringLength = string.length();
aoqi@0 1654 // Each octet contains (up to) two decimal digits
aoqi@0 1655 byte doubleDigit = 0;
aoqi@0 1656 char ch;
aoqi@0 1657 byte digit;
aoqi@0 1658
aoqi@0 1659 // First calculate the length of the string without optional sign and dot
aoqi@0 1660 int numDigits = 0;
aoqi@0 1661 for (int i=0; i<stringLength; i++) {
aoqi@0 1662 ch = string.charAt(i);
aoqi@0 1663 if (ch == '-' || ch == '+' || ch == '.')
aoqi@0 1664 continue;
aoqi@0 1665 numDigits++;
aoqi@0 1666 }
aoqi@0 1667 for (int i=0; i<stringLength; i++) {
aoqi@0 1668 ch = string.charAt(i);
aoqi@0 1669 if (ch == '-' || ch == '+' || ch == '.')
aoqi@0 1670 continue;
aoqi@0 1671 digit = (byte)Character.digit(ch, 10);
aoqi@0 1672 if (digit == -1) {
aoqi@0 1673 throw wrapper.badDigitInFixed( CompletionStatus.COMPLETED_MAYBE ) ;
aoqi@0 1674 }
aoqi@0 1675 // If the fixed type has an odd number of decimal digits,
aoqi@0 1676 // then the representation begins with the first (most significant) digit.
aoqi@0 1677 // Otherwise, this first half-octet is all zero, and the first digit
aoqi@0 1678 // is in the second half-octet.
aoqi@0 1679 if (numDigits % 2 == 0) {
aoqi@0 1680 doubleDigit |= digit;
aoqi@0 1681 this.write_octet(doubleDigit);
aoqi@0 1682 doubleDigit = 0;
aoqi@0 1683 } else {
aoqi@0 1684 doubleDigit |= (digit << 4);
aoqi@0 1685 }
aoqi@0 1686 numDigits--;
aoqi@0 1687 }
aoqi@0 1688 // The sign configuration, in the last half-octet of the representation,
aoqi@0 1689 // is 0xD for negative numbers and 0xC for positive and zero values
aoqi@0 1690 if (signum == -1) {
aoqi@0 1691 doubleDigit |= 0xd;
aoqi@0 1692 } else {
aoqi@0 1693 doubleDigit |= 0xc;
aoqi@0 1694 }
aoqi@0 1695 this.write_octet(doubleDigit);
aoqi@0 1696 }
aoqi@0 1697
aoqi@0 1698 private final static String _id = "IDL:omg.org/CORBA/DataOutputStream:1.0";
aoqi@0 1699 private final static String[] _ids = { _id };
aoqi@0 1700
aoqi@0 1701 public String[] _truncatable_ids() {
aoqi@0 1702 if (_ids == null)
aoqi@0 1703 return null;
aoqi@0 1704
aoqi@0 1705 return (String[])_ids.clone();
aoqi@0 1706 }
aoqi@0 1707
aoqi@0 1708 /* for debugging */
aoqi@0 1709
aoqi@0 1710 public void printBuffer() {
aoqi@0 1711 CDROutputStream_1_0.printBuffer(this.bbwi);
aoqi@0 1712 }
aoqi@0 1713
aoqi@0 1714 public static void printBuffer(ByteBufferWithInfo bbwi) {
aoqi@0 1715
aoqi@0 1716 System.out.println("+++++++ Output Buffer ++++++++");
aoqi@0 1717 System.out.println();
aoqi@0 1718 System.out.println("Current position: " + bbwi.position());
aoqi@0 1719 System.out.println("Total length : " + bbwi.buflen);
aoqi@0 1720 System.out.println();
aoqi@0 1721
aoqi@0 1722 char[] charBuf = new char[16];
aoqi@0 1723
aoqi@0 1724 try {
aoqi@0 1725
aoqi@0 1726 for (int i = 0; i < bbwi.position(); i += 16) {
aoqi@0 1727
aoqi@0 1728 int j = 0;
aoqi@0 1729
aoqi@0 1730 // For every 16 bytes, there is one line
aoqi@0 1731 // of output. First, the hex output of
aoqi@0 1732 // the 16 bytes with each byte separated
aoqi@0 1733 // by a space.
aoqi@0 1734 while (j < 16 && j + i < bbwi.position()) {
aoqi@0 1735 int k = bbwi.byteBuffer.get(i + j);
aoqi@0 1736 if (k < 0)
aoqi@0 1737 k = 256 + k;
aoqi@0 1738 String hex = Integer.toHexString(k);
aoqi@0 1739 if (hex.length() == 1)
aoqi@0 1740 hex = "0" + hex;
aoqi@0 1741 System.out.print(hex + " ");
aoqi@0 1742 j++;
aoqi@0 1743 }
aoqi@0 1744
aoqi@0 1745 // Add any extra spaces to align the
aoqi@0 1746 // text column in case we didn't end
aoqi@0 1747 // at 16
aoqi@0 1748 while (j < 16) {
aoqi@0 1749 System.out.print(" ");
aoqi@0 1750 j++;
aoqi@0 1751 }
aoqi@0 1752
aoqi@0 1753 // Now output the ASCII equivalents. Non-ASCII
aoqi@0 1754 // characters are shown as periods.
aoqi@0 1755 int x = 0;
aoqi@0 1756
aoqi@0 1757 while (x < 16 && x + i < bbwi.position()) {
aoqi@0 1758 if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
aoqi@0 1759 charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
aoqi@0 1760 else
aoqi@0 1761 charBuf[x] = '.';
aoqi@0 1762 x++;
aoqi@0 1763 }
aoqi@0 1764 System.out.println(new String(charBuf, 0, x));
aoqi@0 1765 }
aoqi@0 1766 } catch (Throwable t) {
aoqi@0 1767 t.printStackTrace();
aoqi@0 1768 }
aoqi@0 1769 System.out.println("++++++++++++++++++++++++++++++");
aoqi@0 1770 }
aoqi@0 1771
aoqi@0 1772 public void writeIndirection(int tag, int posIndirectedTo)
aoqi@0 1773 {
aoqi@0 1774 // Must ensure that there are no chunks between the tag
aoqi@0 1775 // and the actual indirection value. This isn't talked about
aoqi@0 1776 // in the spec, but seems to cause headaches in our code.
aoqi@0 1777 // At the very least, this method isolates the indirection code
aoqi@0 1778 // that was duplicated so often.
aoqi@0 1779
aoqi@0 1780 handleSpecialChunkBegin(computeAlignment(4) + 8);
aoqi@0 1781
aoqi@0 1782 // write indirection tag
aoqi@0 1783 write_long(tag);
aoqi@0 1784
aoqi@0 1785 // write indirection
aoqi@0 1786 // Use parent.getRealIndex() so that it can be overridden by TypeCodeOutputStreams
aoqi@0 1787 /*
aoqi@0 1788 System.out.println("CDROutputStream_1_0 writing indirection pos " + posIndirectedTo +
aoqi@0 1789 " - real index " + parent.getRealIndex(get_offset()) + " = " +
aoqi@0 1790 (posIndirectedTo - parent.getRealIndex(get_offset())));
aoqi@0 1791 */
aoqi@0 1792 write_long(posIndirectedTo - parent.getRealIndex(get_offset()));
aoqi@0 1793
aoqi@0 1794 handleSpecialChunkEnd();
aoqi@0 1795 }
aoqi@0 1796
aoqi@0 1797 protected CodeSetConversion.CTBConverter getCharConverter() {
aoqi@0 1798 if (charConverter == null)
aoqi@0 1799 charConverter = parent.createCharCTBConverter();
aoqi@0 1800
aoqi@0 1801 return charConverter;
aoqi@0 1802 }
aoqi@0 1803
aoqi@0 1804 protected CodeSetConversion.CTBConverter getWCharConverter() {
aoqi@0 1805 if (wcharConverter == null)
aoqi@0 1806 wcharConverter = parent.createWCharCTBConverter();
aoqi@0 1807
aoqi@0 1808 return wcharConverter;
aoqi@0 1809 }
aoqi@0 1810
aoqi@0 1811 protected void dprint(String msg) {
aoqi@0 1812 if (debug)
aoqi@0 1813 ORBUtility.dprint(this, msg);
aoqi@0 1814 }
aoqi@0 1815
aoqi@0 1816 void alignOnBoundary(int octetBoundary) {
aoqi@0 1817 alignAndReserve(octetBoundary, 0);
aoqi@0 1818 }
aoqi@0 1819
aoqi@0 1820 public void start_value(String rep_id) {
aoqi@0 1821
aoqi@0 1822 if (debug) {
aoqi@0 1823 dprint("start_value w/ rep id "
aoqi@0 1824 + rep_id
aoqi@0 1825 + " called at pos "
aoqi@0 1826 + get_offset()
aoqi@0 1827 + " position "
aoqi@0 1828 + bbwi.position());
aoqi@0 1829 }
aoqi@0 1830
aoqi@0 1831 if (inBlock)
aoqi@0 1832 end_block();
aoqi@0 1833
aoqi@0 1834 // Write value_tag
aoqi@0 1835 writeValueTag(true, true, null);
aoqi@0 1836
aoqi@0 1837 // Write rep. id
aoqi@0 1838 write_repositoryId(rep_id);
aoqi@0 1839
aoqi@0 1840 // Write Value chunk
aoqi@0 1841 end_flag--;
aoqi@0 1842 chunkedValueNestingLevel--;
aoqi@0 1843
aoqi@0 1844 // Make sure to chunk the custom data
aoqi@0 1845 start_block();
aoqi@0 1846 }
aoqi@0 1847
aoqi@0 1848 public void end_value() {
aoqi@0 1849
aoqi@0 1850 if (debug) {
aoqi@0 1851 dprint("end_value called at pos "
aoqi@0 1852 + get_offset()
aoqi@0 1853 + " position "
aoqi@0 1854 + bbwi.position());
aoqi@0 1855 }
aoqi@0 1856
aoqi@0 1857 end_block();
aoqi@0 1858
aoqi@0 1859 writeEndTag(true);
aoqi@0 1860
aoqi@0 1861 // Check to see if we need to start another block for a
aoqi@0 1862 // possible outer value. Since we're in the stream
aoqi@0 1863 // format 2 custom type contained by another custom
aoqi@0 1864 // type, mustChunk should always be true.
aoqi@0 1865 //
aoqi@0 1866 // Here's why we need to open a continuation chunk:
aoqi@0 1867 //
aoqi@0 1868 // We need to enclose the default data of the
aoqi@0 1869 // next subclass down in chunks. There won't be
aoqi@0 1870 // an end tag separating the superclass optional
aoqi@0 1871 // data and the subclass's default data.
aoqi@0 1872
aoqi@0 1873 if (debug) {
aoqi@0 1874 dprint("mustChunk is " + mustChunk);
aoqi@0 1875 }
aoqi@0 1876
aoqi@0 1877 if (mustChunk) {
aoqi@0 1878 start_block();
aoqi@0 1879 }
aoqi@0 1880 }
aoqi@0 1881
aoqi@0 1882 public void close() throws IOException
aoqi@0 1883 {
aoqi@0 1884 // tell BufferManagerWrite to release any ByteBuffers
aoqi@0 1885 getBufferManager().close();
aoqi@0 1886
aoqi@0 1887 // It's possible bbwi.byteBuffer is shared between
aoqi@0 1888 // this OutputStream and an InputStream. Thus, we check
aoqi@0 1889 // if the Input/Output streams are using the same ByteBuffer.
aoqi@0 1890 // If they sharing the same ByteBuffer we need to ensure only
aoqi@0 1891 // one of those ByteBuffers are released to the ByteBufferPool.
aoqi@0 1892
aoqi@0 1893 if (getByteBufferWithInfo() != null && getByteBuffer() != null)
aoqi@0 1894 {
aoqi@0 1895 MessageMediator messageMediator = parent.getMessageMediator();
aoqi@0 1896 if (messageMediator != null)
aoqi@0 1897 {
aoqi@0 1898 CDRInputObject inputObj =
aoqi@0 1899 (CDRInputObject)messageMediator.getInputObject();
aoqi@0 1900 if (inputObj != null)
aoqi@0 1901 {
aoqi@0 1902 if (inputObj.isSharing(getByteBuffer()))
aoqi@0 1903 {
aoqi@0 1904 // Set InputStream's ByteBuffer and bbwi to null
aoqi@0 1905 // so its ByteBuffer cannot be released to the pool
aoqi@0 1906 inputObj.setByteBuffer(null);
aoqi@0 1907 inputObj.setByteBufferWithInfo(null);
aoqi@0 1908 }
aoqi@0 1909 }
aoqi@0 1910 }
aoqi@0 1911
aoqi@0 1912 // release this stream's ByteBuffer to the pool
aoqi@0 1913 ByteBufferPool byteBufferPool = orb.getByteBufferPool();
aoqi@0 1914 if (debug)
aoqi@0 1915 {
aoqi@0 1916 // print address of ByteBuffer being released
aoqi@0 1917 int bbAddress = System.identityHashCode(bbwi.byteBuffer);
aoqi@0 1918 StringBuffer sb = new StringBuffer(80);
aoqi@0 1919 sb.append(".close - releasing ByteBuffer id (");
aoqi@0 1920 sb.append(bbAddress).append(") to ByteBufferPool.");
aoqi@0 1921 String msg = sb.toString();
aoqi@0 1922 dprint(msg);
aoqi@0 1923 }
aoqi@0 1924 byteBufferPool.releaseByteBuffer(getByteBuffer());
aoqi@0 1925 bbwi.byteBuffer = null;
aoqi@0 1926 bbwi = null;
aoqi@0 1927 }
aoqi@0 1928 }
aoqi@0 1929 }

mercurial