--- old/src/java.corba/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java 2018-01-30 20:16:56.000000000 -0500 +++ /dev/null 2018-01-30 20:16:56.000000000 -0500 @@ -1,1929 +0,0 @@ -/* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -/* - * Licensed Materials - Property of IBM - * RMI-IIOP v1.0 - * Copyright IBM Corp. 1998 1999 All Rights Reserved - * - */ - -package com.sun.corba.se.impl.encoding; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.nio.ByteBuffer; -import java.rmi.Remote; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; -import java.util.Hashtable; -import java.util.Stack; - -import javax.rmi.CORBA.Util; -import javax.rmi.CORBA.ValueHandler; -import javax.rmi.CORBA.ValueHandlerMultiFormat; - -import org.omg.CORBA.CustomMarshal; -import org.omg.CORBA.DataOutputStream; -import org.omg.CORBA.TypeCodePackage.BadKind; -import org.omg.CORBA.SystemException; -import org.omg.CORBA.CompletionStatus; -import org.omg.CORBA.Object; -import org.omg.CORBA.Principal; -import org.omg.CORBA.TypeCode; -import org.omg.CORBA.Any; -import org.omg.CORBA.VM_CUSTOM; -import org.omg.CORBA.VM_TRUNCATABLE; -import org.omg.CORBA.VM_NONE; -import org.omg.CORBA.portable.IDLEntity; -import org.omg.CORBA.portable.CustomValue; -import org.omg.CORBA.portable.StreamableValue; -import org.omg.CORBA.portable.BoxedValueHelper; -import org.omg.CORBA.portable.OutputStream; -import org.omg.CORBA.portable.ValueBase; - -import com.sun.org.omg.CORBA.portable.ValueHelper; - -import com.sun.corba.se.pept.protocol.MessageMediator; -import com.sun.corba.se.pept.transport.ByteBufferPool; - -import com.sun.corba.se.spi.ior.iiop.GIOPVersion; -import com.sun.corba.se.spi.ior.IOR; -import com.sun.corba.se.spi.ior.IORFactories; -import com.sun.corba.se.spi.orb.ORB; -import com.sun.corba.se.spi.orb.ORBVersionFactory; -import com.sun.corba.se.spi.orb.ORBVersion; -import com.sun.corba.se.spi.protocol.CorbaMessageMediator; -import com.sun.corba.se.spi.logging.CORBALogDomains; - -import com.sun.corba.se.impl.encoding.ByteBufferWithInfo; -import com.sun.corba.se.impl.encoding.MarshalOutputStream; -import com.sun.corba.se.impl.encoding.CodeSetConversion; -import com.sun.corba.se.impl.corba.TypeCodeImpl; -import com.sun.corba.se.impl.orbutil.CacheTable; -import com.sun.corba.se.impl.orbutil.ORBUtility; -import com.sun.corba.se.impl.orbutil.RepositoryIdStrings; -import com.sun.corba.se.impl.orbutil.RepositoryIdUtility; -import com.sun.corba.se.impl.orbutil.RepositoryIdFactory; -import com.sun.corba.se.impl.util.Utility; -import com.sun.corba.se.impl.logging.ORBUtilSystemException; - -public class CDROutputStream_1_0 extends CDROutputStreamBase -{ - private static final int INDIRECTION_TAG = 0xffffffff; - - protected boolean littleEndian; - protected BufferManagerWrite bufferManagerWrite; - ByteBufferWithInfo bbwi; - - protected ORB orb; - protected ORBUtilSystemException wrapper ; - - protected boolean debug = false; - - protected int blockSizeIndex = -1; - protected int blockSizePosition = 0; - - protected byte streamFormatVersion; - - private static final int DEFAULT_BUFFER_SIZE = 1024; - private static final String kWriteMethod = "write"; - - // Codebase cache - private CacheTable codebaseCache = null; - - // Value cache - private CacheTable valueCache = null; - - // Repository ID cache - private CacheTable repositoryIdCache = null; - - // Write end flag - private int end_flag = 0; - - // Beginning with the resolution to interop issue 3526, - // only enclosing chunked valuetypes are taken into account - // when computing the nesting level. However, we still need - // the old computation around for interoperability with our - // older ORBs. - private int chunkedValueNestingLevel = 0; - - private boolean mustChunk = false; - - // In block marker - protected boolean inBlock = false; - - // Last end tag position - private int end_flag_position = 0; - private int end_flag_index = 0; - - // ValueHandler - private ValueHandler valueHandler = null; - - // Repository ID handlers - private RepositoryIdUtility repIdUtil; - private RepositoryIdStrings repIdStrs; - - // Code set converters (created when first needed) - private CodeSetConversion.CTBConverter charConverter; - private CodeSetConversion.CTBConverter wcharConverter; - - // REVISIT - This should be re-factored so that including whether - // to use pool byte buffers or not doesn't need to be known. - public void init(org.omg.CORBA.ORB orb, - boolean littleEndian, - BufferManagerWrite bufferManager, - byte streamFormatVersion, - boolean usePooledByteBuffers) - { - // ORB must not be null. See CDROutputStream constructor. - this.orb = (ORB)orb; - this.wrapper = ORBUtilSystemException.get( this.orb, - CORBALogDomains.RPC_ENCODING ) ; - debug = this.orb.transportDebugFlag; - - this.littleEndian = littleEndian; - this.bufferManagerWrite = bufferManager; - this.bbwi = new ByteBufferWithInfo(orb, bufferManager, usePooledByteBuffers); - this.streamFormatVersion = streamFormatVersion; - - createRepositoryIdHandlers(); - } - - public void init(org.omg.CORBA.ORB orb, - boolean littleEndian, - BufferManagerWrite bufferManager, - byte streamFormatVersion) - { - init(orb, littleEndian, bufferManager, streamFormatVersion, true); - } - - private final void createRepositoryIdHandlers() - { - repIdUtil = RepositoryIdFactory.getRepIdUtility(); - repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(); - } - - public BufferManagerWrite getBufferManager() - { - return bufferManagerWrite; - } - - public byte[] toByteArray() { - byte[] it; - - it = new byte[bbwi.position()]; - - // Micro-benchmarks show ByteBuffer.get(int) out perform the bulk - // ByteBuffer.get(byte[], offset, length). - for (int i = 0; i < bbwi.position(); i++) - it[i] = bbwi.byteBuffer.get(i); - - return it; - } - - public GIOPVersion getGIOPVersion() { - return GIOPVersion.V1_0; - } - - // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only. - // Illegal for GIOP versions < 1.2. - void setHeaderPadding(boolean headerPadding) { - throw wrapper.giopVersionError(); - } - - protected void handleSpecialChunkBegin(int requiredSize) - { - // No-op for GIOP 1.0 - } - - protected void handleSpecialChunkEnd() - { - // No-op for GIOP 1.0 - } - - protected final int computeAlignment(int align) { - if (align > 1) { - int incr = bbwi.position() & (align - 1); - if (incr != 0) - return align - incr; - } - - return 0; - } - - protected void alignAndReserve(int align, int n) { - - bbwi.position(bbwi.position() + computeAlignment(align)); - - if (bbwi.position() + n > bbwi.buflen) - grow(align, n); - } - - // - // Default implementation of grow. Subclassers may override this. - // Always grow the single buffer. This needs to delegate - // fragmentation policy for IIOP 1.1. - // - protected void grow(int align, int n) - { - bbwi.needed = n; - - bufferManagerWrite.overflow(bbwi); - } - - public final void putEndian() throws SystemException { - write_boolean(littleEndian); - } - - public final boolean littleEndian() { - return littleEndian; - } - - void freeInternalCaches() { - if (codebaseCache != null) - codebaseCache.done(); - - if (valueCache != null) - valueCache.done(); - - if (repositoryIdCache != null) - repositoryIdCache.done(); - } - - // No such type in java - public final void write_longdouble(double x) - { - throw wrapper.longDoubleNotImplemented( - CompletionStatus.COMPLETED_MAYBE ) ; - } - - public void write_octet(byte x) - { - // The 'if' stmt is commented out since we need the alignAndReserve to - // be called, particularly when the first body byte is written, - // to induce header padding to align the body on a 8-octet boundary, - // for GIOP versions 1.2 and above. Refer to internalWriteOctetArray() - // method that also has a similar change. - //if (bbwi.position() + 1 > bbwi.buflen) - alignAndReserve(1, 1); - -// REVISIT - Should just use ByteBuffer.put(byte) and let it -// increment the ByteBuffer position. This is true -// for all write operations in this file. - - bbwi.byteBuffer.put(bbwi.position(), x); - bbwi.position(bbwi.position() + 1); - - } - - public final void write_boolean(boolean x) - { - write_octet(x? (byte)1:(byte)0); - } - - public void write_char(char x) - { - CodeSetConversion.CTBConverter converter = getCharConverter(); - - converter.convert(x); - - // CORBA formal 99-10-07 15.3.1.6: "In the case of multi-byte encodings - // of characters, a single instance of the char type may only - // hold one octet of any multi-byte character encoding." - if (converter.getNumBytes() > 1) - throw wrapper.invalidSingleCharCtb(CompletionStatus.COMPLETED_MAYBE); - - write_octet(converter.getBytes()[0]); - } - - // These wchar methods are only used when talking to - // legacy ORBs, now. - private final void writeLittleEndianWchar(char x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF)); - bbwi.position(bbwi.position() + 2); - } - - private final void writeBigEndianWchar(char x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF)); - bbwi.position(bbwi.position() + 2); - } - - private final void writeLittleEndianShort(short x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF)); - bbwi.position(bbwi.position() + 2); - } - - private final void writeBigEndianShort(short x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)(x & 0xFF)); - bbwi.position(bbwi.position() + 2); - } - - private final void writeLittleEndianLong(int x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF)); - bbwi.position(bbwi.position() + 4); - } - - private final void writeBigEndianLong(int x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 24) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 16) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 3, (byte)(x & 0xFF)); - bbwi.position(bbwi.position() + 4); - } - - private final void writeLittleEndianLongLong(long x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)(x & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 16) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 24) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 32) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 40) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 48) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 7, (byte)((x >>> 56) & 0xFF)); - bbwi.position(bbwi.position() + 8); - } - - private final void writeBigEndianLongLong(long x) { - bbwi.byteBuffer.put(bbwi.position(), (byte)((x >>> 56) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 1, (byte)((x >>> 48) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 2, (byte)((x >>> 40) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 3, (byte)((x >>> 32) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 4, (byte)((x >>> 24) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 5, (byte)((x >>> 16) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 6, (byte)((x >>> 8) & 0xFF)); - bbwi.byteBuffer.put(bbwi.position() + 7, (byte)(x & 0xFF)); - bbwi.position(bbwi.position() + 8); - } - - public void write_wchar(char x) - { - // Don't allow transmission of wchar/wstring data with - // foreign ORBs since it's against the spec. - if (ORBUtility.isForeignORB(orb)) { - throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE); - } - - // If it's one of our legacy ORBs, do what they did: - alignAndReserve(2, 2); - - if (littleEndian) { - writeLittleEndianWchar(x); - } else { - writeBigEndianWchar(x); - } - } - - public void write_short(short x) - { - alignAndReserve(2, 2); - - if (littleEndian) { - writeLittleEndianShort(x); - } else { - writeBigEndianShort(x); - } - } - - public final void write_ushort(short x) - { - write_short(x); - } - - public void write_long(int x) - { - alignAndReserve(4, 4); - - if (littleEndian) { - writeLittleEndianLong(x); - } else { - writeBigEndianLong(x); - } - } - - public final void write_ulong(int x) - { - write_long(x); - } - - public void write_longlong(long x) - { - alignAndReserve(8, 8); - - if (littleEndian) { - writeLittleEndianLongLong(x); - } else { - writeBigEndianLongLong(x); - } - } - - public final void write_ulonglong(long x) - { - write_longlong(x); - } - - public final void write_float(float x) - { - write_long(Float.floatToIntBits(x)); - } - - public final void write_double(double x) - { - write_longlong(Double.doubleToLongBits(x)); - } - - public void write_string(String value) - { - writeString(value); - } - - protected int writeString(String value) - { - if (value == null) { - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - } - - CodeSetConversion.CTBConverter converter = getCharConverter(); - - converter.convert(value); - - // A string is encoded as an unsigned CORBA long for the - // number of bytes to follow (including a terminating null). - // There is only one octet per character in the string. - int len = converter.getNumBytes() + 1; - - handleSpecialChunkBegin(computeAlignment(4) + 4 + len); - - write_long(len); - int indirection = get_offset() - 4; - - internalWriteOctetArray(converter.getBytes(), 0, converter.getNumBytes()); - - // Write the null ending - write_octet((byte)0); - - handleSpecialChunkEnd(); - return indirection; - } - - public void write_wstring(String value) - { - if (value == null) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // Don't allow transmission of wchar/wstring data with - // foreign ORBs since it's against the spec. - if (ORBUtility.isForeignORB(orb)) { - throw wrapper.wcharDataInGiop10(CompletionStatus.COMPLETED_MAYBE); - } - - // When talking to our legacy ORBs, do what they did: - int len = value.length() + 1; - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(4 + (len * 2) + computeAlignment(4)); - - write_long(len); - - for (int i = 0; i < len - 1; i++) - write_wchar(value.charAt(i)); - - // Write the null ending - write_short((short)0); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - // Performs no checks and doesn't tamper with chunking - void internalWriteOctetArray(byte[] value, int offset, int length) - { - int n = offset; - - // This flag forces the alignAndReserve method to be called the - // first time an octet is written. This is necessary to ensure - // that the body is aligned on an 8-octet boundary. Note the 'if' - // condition inside the 'while' loop below. Also, refer to the - // write_octet() method that has a similar change. - boolean align = true; - - while (n < length+offset) { - int avail; - int bytes; - int wanted; - - if ((bbwi.position() + 1 > bbwi.buflen) || align) { - align = false; - alignAndReserve(1, 1); - } - avail = bbwi.buflen - bbwi.position(); - wanted = (length + offset) - n; - bytes = (wanted < avail) ? wanted : avail; - for (int i = 0; i < bytes; i++) - bbwi.byteBuffer.put(bbwi.position() + i, value[n+i]); - bbwi.position(bbwi.position() + bytes); - n += bytes; - } - } - - public final void write_octet_array(byte b[], int offset, int length) - { - if ( b == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(length); - - internalWriteOctetArray(b, offset, length); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public void write_Principal(Principal p) - { - write_long(p.name().length); - write_octet_array(p.name(), 0, p.name().length); - } - - public void write_any(Any any) - { - if ( any == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - write_TypeCode(any.type()); - any.write_value(parent); - } - - public void write_TypeCode(TypeCode tc) - { - if ( tc == null ) { - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - } - TypeCodeImpl tci; - if (tc instanceof TypeCodeImpl) { - tci = (TypeCodeImpl)tc; - } - else { - tci = new TypeCodeImpl(orb, tc); - } - - tci.write_value((org.omg.CORBA_2_3.portable.OutputStream)parent); - } - - public void write_Object(org.omg.CORBA.Object ref) - { - if (ref == null) { - IOR nullIOR = IORFactories.makeIOR( orb ) ; - nullIOR.write(parent); - return; - } - - // IDL to Java formal 01-06-06 1.21.4.2 - if (ref instanceof org.omg.CORBA.LocalObject) - throw wrapper.writeLocalObject(CompletionStatus.COMPLETED_MAYBE); - - IOR ior = ORBUtility.connectAndGetIOR( orb, ref ) ; - ior.write(parent); - return; - } - - // ------------ RMI related methods -------------------------- - - public void write_abstract_interface(java.lang.Object obj) { - boolean corbaObject = false; // Assume value type. - org.omg.CORBA.Object theObject = null; - - // Is it a CORBA.Object? - - if (obj != null && obj instanceof org.omg.CORBA.Object) { - - // Yes. - - theObject = (org.omg.CORBA.Object)obj; - corbaObject = true; - } - - // Write our flag... - - write_boolean(corbaObject); - - // Now write out the object... - - if (corbaObject) { - write_Object(theObject); - } else { - try { - write_value((java.io.Serializable)obj); - } catch(ClassCastException cce) { - if (obj instanceof java.io.Serializable) - throw cce; - else - ORBUtility.throwNotSerializableForCorba(obj.getClass().getName()); - } - } - } - - public void write_value(Serializable object, Class clz) { - - write_value(object); - } - - private void writeWStringValue(String string) { - - int indirection = writeValueTag(mustChunk, true, null); - - // Write WStringValue's repository ID - write_repositoryId(repIdStrs.getWStringValueRepId()); - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, string, string); - - // Write Value chunk - if (mustChunk) { - start_block(); - end_flag--; - chunkedValueNestingLevel--; - } else - end_flag--; - - write_wstring(string); - - if (mustChunk) - end_block(); - - // Write end tag - writeEndTag(mustChunk); - } - - private void writeArray(Serializable array, Class clazz) { - - if (valueHandler == null) - valueHandler = ORBUtility.createValueHandler(); //d11638 - - // Write value_tag - int indirection = writeValueTag(mustChunk, true, - Util.getCodebase(clazz)); - - // Write repository ID - write_repositoryId(repIdStrs.createSequenceRepID(clazz)); - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, array, array); - - // Write Value chunk - if (mustChunk) { - start_block(); - end_flag--; - chunkedValueNestingLevel--; - } else - end_flag--; - - if (valueHandler instanceof ValueHandlerMultiFormat) { - ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler; - vh.writeValue(parent, array, streamFormatVersion); - } else - valueHandler.writeValue(parent, array); - - if (mustChunk) - end_block(); - - // Write end tag - writeEndTag(mustChunk); - } - - private void writeValueBase(org.omg.CORBA.portable.ValueBase object, - Class clazz) { - // _REVISIT_ could check to see whether chunking really needed - mustChunk = true; - - // Write value_tag - int indirection = writeValueTag(true, true, Util.getCodebase(clazz)); - - // Get rep id - String repId = ((ValueBase)object)._truncatable_ids()[0]; - - // Write rep id - write_repositoryId(repId); - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, object, object); - - // Write Value chunk - start_block(); - end_flag--; - chunkedValueNestingLevel--; - writeIDLValue(object, repId); - end_block(); - - // Write end tag - writeEndTag(true); - } - - private void writeRMIIIOPValueType(Serializable object, Class clazz) { - if (valueHandler == null) - valueHandler = ORBUtility.createValueHandler(); //d11638 - - Serializable key = object; - - // Allow the ValueHandler to call writeReplace on - // the Serializable (if the method is present) - object = valueHandler.writeReplace(key); - - if (object == null) { - // Write null tag and return - write_long(0); - return; - } - - if (object != key) { - if (valueCache != null && valueCache.containsKey(object)) { - writeIndirection(INDIRECTION_TAG, valueCache.getVal(object)); - return; - } - - clazz = object.getClass(); - } - - if (mustChunk || valueHandler.isCustomMarshaled(clazz)) { - mustChunk = true; - } - - // Write value_tag - int indirection = writeValueTag(mustChunk, true, Util.getCodebase(clazz)); - - // Write rep. id - write_repositoryId(repIdStrs.createForJavaType(clazz)); - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, object, key); - - if (mustChunk) { - // Write Value chunk - end_flag--; - chunkedValueNestingLevel--; - start_block(); - } else - end_flag--; - - if (valueHandler instanceof ValueHandlerMultiFormat) { - ValueHandlerMultiFormat vh = (ValueHandlerMultiFormat)valueHandler; - vh.writeValue(parent, object, streamFormatVersion); - } else - valueHandler.writeValue(parent, object); - - if (mustChunk) - end_block(); - - // Write end tag - writeEndTag(mustChunk); - } - - public void write_value(Serializable object, String repository_id) { - - // Handle null references - if (object == null) { - // Write null tag and return - write_long(0); - return; - } - - // Handle shared references - if (valueCache != null && valueCache.containsKey(object)) { - writeIndirection(INDIRECTION_TAG, valueCache.getVal(object)); - return; - } - - Class clazz = object.getClass(); - boolean oldMustChunk = mustChunk; - - if (mustChunk) - mustChunk = true; - - if (inBlock) - end_block(); - - if (clazz.isArray()) { - // Handle arrays - writeArray(object, clazz); - } else if (object instanceof org.omg.CORBA.portable.ValueBase) { - // Handle IDL Value types - writeValueBase((org.omg.CORBA.portable.ValueBase)object, clazz); - } else if (shouldWriteAsIDLEntity(object)) { - writeIDLEntity((IDLEntity)object); - } else if (object instanceof java.lang.String) { - writeWStringValue((String)object); - } else if (object instanceof java.lang.Class) { - writeClass(repository_id, (Class)object); - } else { - // RMI-IIOP value type - writeRMIIIOPValueType(object, clazz); - } - - mustChunk = oldMustChunk; - - // Check to see if we need to start another block for a - // possible outer value - if (mustChunk) - start_block(); - - } - - public void write_value(Serializable object) - { - write_value(object, (String)null); - } - - public void write_value(Serializable object, org.omg.CORBA.portable.BoxedValueHelper factory) - { - // Handle null references - if (object == null) { - // Write null tag and return - write_long(0); - return; - } - - // Handle shared references - if ((valueCache != null) && valueCache.containsKey(object)) { - writeIndirection(INDIRECTION_TAG, valueCache.getVal(object)); - return; - } - - boolean oldMustChunk = mustChunk; - - boolean isCustom = false; - if (factory instanceof ValueHelper) { - short modifier; - try { - modifier = ((ValueHelper)factory).get_type().type_modifier(); - } catch(BadKind ex) { // tk_value_box - modifier = VM_NONE.value; - } - if (object instanceof CustomMarshal && - modifier == VM_CUSTOM.value) { - isCustom = true; - mustChunk = true; - } - if (modifier == VM_TRUNCATABLE.value) - mustChunk = true; - } - - if (mustChunk) { - - if (inBlock) - end_block(); - - // Write value_tag - int indirection = writeValueTag(true, - orb.getORBData().useRepId(), - Util.getCodebase(object.getClass()) - ); - - if (orb.getORBData().useRepId()) { - write_repositoryId(factory.get_id()); - } - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, object, object); - - // Write Value chunk - start_block(); - end_flag--; - chunkedValueNestingLevel--; - if (isCustom) - ((CustomMarshal)object).marshal(parent); - else - factory.write_value(parent, object); - end_block(); - - // Write end tag - writeEndTag(true); - } - else { - // Write value_tag - int indirection = writeValueTag(false, - orb.getORBData().useRepId(), - Util.getCodebase(object.getClass()) - ); - - if (orb.getORBData().useRepId()) { - write_repositoryId(factory.get_id()); - } - - // Add indirection for object to indirection table - updateIndirectionTable(indirection, object, object); - - // Write Value chunk - end_flag--; - // no need to test for custom on the non-chunked path - factory.write_value(parent, object); - - // Write end tag - writeEndTag(false); - } - - mustChunk = oldMustChunk; - - // Check to see if we need to start another block for a - // possible outer value - if (mustChunk) - start_block(); - - } - - public int get_offset() { - return bbwi.position(); - } - - public void start_block() { - if (debug) { - dprint("CDROutputStream_1_0 start_block, position" + bbwi.position()); - } - - //Move inBlock=true to after write_long since write_long might - //trigger grow which will lead to erroneous behavior with a - //missing blockSizeIndex. - //inBlock = true; - - // Save space in the buffer for block size - write_long(0); - - //Has to happen after write_long since write_long could - //trigger grow which is overridden by supper classes to - //depend on inBlock. - inBlock = true; - - blockSizePosition = get_offset(); - - // Remember where to put the size of the endblock less 4 - blockSizeIndex = bbwi.position(); - - if (debug) { - dprint("CDROutputStream_1_0 start_block, blockSizeIndex " - + blockSizeIndex); - } - - } - - // Utility method which will hopefully decrease chunking complexity - // by allowing us to end_block and update chunk lengths without - // calling alignAndReserve. Otherwise, it's possible to get into - // recursive scenarios which lose the chunking state. - protected void writeLongWithoutAlign(int x) { - if (littleEndian) { - writeLittleEndianLong(x); - } else { - writeBigEndianLong(x); - } - } - - public void end_block() { - if (debug) { - dprint("CDROutputStream_1_0.java end_block"); - } - - if (!inBlock) - return; - - if (debug) { - dprint("CDROutputStream_1_0.java end_block, in a block"); - } - - inBlock = false; - - // Test to see if the block was of zero length - // If so, remove the block instead of ending it - // (This can happen if the last field written - // in a value was another value) - if (get_offset() == blockSizePosition) { - // Need to assert that blockSizeIndex == bbwi.position()? REVISIT - - bbwi.position(bbwi.position() - 4); - blockSizeIndex = -1; - blockSizePosition = -1; - return; - } - - int oldSize = bbwi.position(); - bbwi.position(blockSizeIndex - 4); - - writeLongWithoutAlign(oldSize - blockSizeIndex); - - bbwi.position(oldSize); - blockSizeIndex = -1; - blockSizePosition = -1; - - // System.out.println(" post end_block: " + get_offset() + " " + bbwi.position()); - } - - public org.omg.CORBA.ORB orb() - { - return orb; - } - - // ------------ End RMI related methods -------------------------- - - public final void write_boolean_array(boolean[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(length); - - for (int i = 0; i < length; i++) - write_boolean(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_char_array(char[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(length); - - for (int i = 0; i < length; i++) - write_char(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public void write_wchar_array(char[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(2) + (length * 2)); - - for (int i = 0; i < length; i++) - write_wchar(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_short_array(short[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(2) + (length * 2)); - - for (int i = 0; i < length; i++) - write_short(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_ushort_array(short[]value, int offset, int length) { - write_short_array(value, offset, length); - } - - public final void write_long_array(int[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(4) + (length * 4)); - - for (int i = 0; i < length; i++) - write_long(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_ulong_array(int[]value, int offset, int length) { - write_long_array(value, offset, length); - } - - public final void write_longlong_array(long[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(8) + (length * 8)); - - for (int i = 0; i < length; i++) - write_longlong(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_ulonglong_array(long[]value, int offset, int length) { - write_longlong_array(value, offset, length); - } - - public final void write_float_array(float[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(4) + (length * 4)); - - for (int i = 0; i < length; i++) - write_float(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public final void write_double_array(double[]value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - // This will only have an effect if we're already chunking - handleSpecialChunkBegin(computeAlignment(8) + (length * 8)); - - for (int i = 0; i < length; i++) - write_double(value[offset + i]); - - // This will only have an effect if we're already chunking - handleSpecialChunkEnd(); - } - - public void write_string_array(String[] value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - for(int i = 0; i < length; i++) - write_string(value[offset + i]); - } - - public void write_wstring_array(String[] value, int offset, int length) { - if ( value == null ) - throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); - - for(int i = 0; i < length; i++) - write_wstring(value[offset + i]); - } - - public final void write_any_array(org.omg.CORBA.Any value[], int offset, int length) - { - for(int i = 0; i < length; i++) - write_any(value[offset + i]); - } - - //--------------------------------------------------------------------// - // CDROutputStream state management. - // - - public void writeTo(java.io.OutputStream s) - throws java.io.IOException - { - byte[] tmpBuf = null; - - if (bbwi.byteBuffer.hasArray()) - { - tmpBuf = bbwi.byteBuffer.array(); - } - else - { - int size = bbwi.position(); - tmpBuf = new byte[size]; - // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is - // faster than ByteBuffer.get(byte[], offset, length) - for (int i = 0; i < size; i++) - tmpBuf[i] = bbwi.byteBuffer.get(i); - } - - s.write(tmpBuf, 0, bbwi.position()); - } - - public void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream s) { - - byte[] buf = null; - - if (bbwi.byteBuffer.hasArray()) - { - buf = bbwi.byteBuffer.array(); - } - else - { - int size = bbwi.position(); - buf = new byte[size]; - // Micro-benchmarks are showing a loop of ByteBuffer.get(int) is - // faster than ByteBuffer.get(byte[], offset, length) - for (int i = 0; i < size; i++) - buf[i] = bbwi.byteBuffer.get(i); - } - - s.write_long(bbwi.position()); - s.write_octet_array(buf, 0, bbwi.position()); - - } - - public final int getSize() { - return bbwi.position(); - } - - public int getIndex() { - return bbwi.position(); - } - - public boolean isLittleEndian() { - return littleEndian; - } - - public void setIndex(int value) { - bbwi.position(value); - } - - public ByteBufferWithInfo getByteBufferWithInfo() { - return bbwi; - } - - public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) { - this.bbwi = bbwi; - } - - public ByteBuffer getByteBuffer() { - ByteBuffer result = null;; - if (bbwi != null) { - result = bbwi.byteBuffer; - } - return result; - } - - public void setByteBuffer(ByteBuffer byteBuffer) { - bbwi.byteBuffer = byteBuffer; - } - - private final void updateIndirectionTable(int indirection, java.lang.Object object, - java.lang.Object key) { - // int indirection = get_offset(); - if (valueCache == null) - valueCache = new CacheTable(orb,true); - valueCache.put(object, indirection); - if (key != object) - valueCache.put(key, indirection); - } - - private final void write_repositoryId(String id) { - // Use an indirection if available - if (repositoryIdCache != null && repositoryIdCache.containsKey(id)) { - writeIndirection(INDIRECTION_TAG, repositoryIdCache.getVal(id)); - return; - } - - // Write it as a string. Note that we have already done the - // special case conversion of non-Latin-1 characters to escaped - // Latin-1 sequences in RepositoryId. - - // It's not a good idea to cache them now that we can have - // multiple code sets. - int indirection = writeString(id); - - // Add indirection for id to indirection table - if (repositoryIdCache == null) - repositoryIdCache = new CacheTable(orb,true); - repositoryIdCache.put(id, indirection); - } - - private void write_codebase(String str, int pos) { - if (codebaseCache != null && codebaseCache.containsKey(str)) { - writeIndirection(INDIRECTION_TAG, codebaseCache.getVal(str)); - } - else { - write_string(str); - if (codebaseCache == null) - codebaseCache = new CacheTable(orb,true); - codebaseCache.put(str, pos); - } - } - - private final int writeValueTag(boolean chunkIt, boolean useRepId, - String codebase) { - int indirection = 0; - if (chunkIt && !useRepId){ - if (codebase == null) { - write_long(repIdUtil.getStandardRMIChunkedNoRepStrId()); - indirection = get_offset() - 4; - } else { - write_long(repIdUtil.getCodeBaseRMIChunkedNoRepStrId()); - indirection = get_offset() - 4; - write_codebase(codebase, get_offset()); - } - } else if (chunkIt && useRepId){ - if (codebase == null) { - write_long(repIdUtil.getStandardRMIChunkedId()); - indirection = get_offset() - 4; - } else { - write_long(repIdUtil.getCodeBaseRMIChunkedId()); - indirection = get_offset() - 4; - write_codebase(codebase, get_offset()); - } - } else if (!chunkIt && !useRepId) { - if (codebase == null) { - write_long(repIdUtil.getStandardRMIUnchunkedNoRepStrId()); - indirection = get_offset() - 4; - } else { - write_long(repIdUtil.getCodeBaseRMIUnchunkedNoRepStrId()); - indirection = get_offset() - 4; - write_codebase(codebase, get_offset()); - } - } else if (!chunkIt && useRepId) { - if (codebase == null) { - write_long(repIdUtil.getStandardRMIUnchunkedId()); - indirection = get_offset() - 4; - } else { - write_long(repIdUtil.getCodeBaseRMIUnchunkedId()); - indirection = get_offset() - 4; - write_codebase(codebase, get_offset()); - } - } - return indirection; - } - - private void writeIDLValue(Serializable object, String repID) - { - if (object instanceof StreamableValue) { - ((StreamableValue)object)._write(parent); - - } else if (object instanceof CustomValue) { - ((CustomValue)object).marshal(parent); - - } else { - BoxedValueHelper helper = Utility.getHelper(object.getClass(), null, repID); - boolean isCustom = false; - if (helper instanceof ValueHelper && object instanceof CustomMarshal) { - try { - if (((ValueHelper)helper).get_type().type_modifier() == VM_CUSTOM.value) - isCustom = true; - } catch(BadKind ex) { - throw wrapper.badTypecodeForCustomValue( CompletionStatus.COMPLETED_MAYBE, - ex ) ; - } - } - if (isCustom) - ((CustomMarshal)object).marshal(parent); - else - helper.write_value(parent, object); - } - } - - // Handles end tag compaction... - private void writeEndTag(boolean chunked){ - - if (chunked) { - if (get_offset() == end_flag_position) { - - if (bbwi.position() == end_flag_index) { - - // We are exactly at the same position and index as the - // end of the last end tag. Thus, we can back up over it - // and compact the tags. - bbwi.position(bbwi.position() - 4); - - } else { - - // Special case in which we're at the beginning of a new - // fragment, but the position is the same. We can't back up, - // so we just write the new end tag without compaction. This - // occurs when a value ends and calls start_block to open a - // continuation chunk, but it's called at the very end of - // a fragment. - } - } - - writeNestingLevel(); - - // Remember the last index and position. These are only used when chunking. - end_flag_index = bbwi.position(); - end_flag_position = get_offset(); - - chunkedValueNestingLevel++; - } - - // Increment the nesting level - end_flag++; - } - - /** - * Handles ORB versioning of the end tag. Should only - * be called if chunking. - * - * If talking to our older ORBs (Standard Extension, - * Kestrel, and Ladybird), write the end flag that takes - * into account all enclosing valuetypes. - * - * If talking a newer or foreign ORB, or if the orb - * instance is null, write the end flag that only takes - * into account the enclosing chunked valuetypes. - */ - private void writeNestingLevel() { - if (orb == null || - ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || - ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { - - write_long(chunkedValueNestingLevel); - - } else { - write_long(end_flag); - } - } - - private void writeClass(String repository_id, Class clz) { - - if (repository_id == null) - repository_id = repIdStrs.getClassDescValueRepId(); - - // Write value_tag - int indirection = writeValueTag(mustChunk, true, null); - updateIndirectionTable(indirection, clz, clz); - - write_repositoryId(repository_id); - - if (mustChunk) { - // Write Value chunk - start_block(); - end_flag--; - chunkedValueNestingLevel--; - } else - end_flag--; - - writeClassBody(clz); - - if (mustChunk) - end_block(); - - // Write end tag - writeEndTag(mustChunk); - } - - // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID - // and codebase strings in the wrong order. This handles - // backwards compatibility. - private void writeClassBody(Class clz) { - if (orb == null || - ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || - ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { - - write_value(Util.getCodebase(clz)); - write_value(repIdStrs.createForAnyType(clz)); - } else { - - write_value(repIdStrs.createForAnyType(clz)); - write_value(Util.getCodebase(clz)); - } - } - - // Casts and returns an Object as a Serializable - // This is required for JDK 1.1 only to avoid VerifyErrors when - // passing arrays as Serializable - // private java.io.Serializable make_serializable(java.lang.Object object) - // { - // return (java.io.Serializable)object; - // } - - private boolean shouldWriteAsIDLEntity(Serializable object) - { - return ((object instanceof IDLEntity) && (!(object instanceof ValueBase)) && - (!(object instanceof org.omg.CORBA.Object))); - - } - - private void writeIDLEntity(IDLEntity object) { - - // _REVISIT_ could check to see whether chunking really needed - mustChunk = true; - - String repository_id = repIdStrs.createForJavaType(object); - Class clazz = object.getClass(); - String codebase = Util.getCodebase(clazz); - - // Write value_tag - int indirection = writeValueTag(true, true, codebase); - updateIndirectionTable(indirection, object, object); - - // Write rep. id - write_repositoryId(repository_id); - - // Write Value chunk - end_flag--; - chunkedValueNestingLevel--; - start_block(); - - // Write the IDLEntity using reflection - try { - ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader()); - final Class helperClass = Utility.loadClassForClass(clazz.getName()+"Helper", codebase, - clazzLoader, clazz, clazzLoader); - final Class argTypes[] = {org.omg.CORBA.portable.OutputStream.class, clazz}; - // getDeclaredMethod requires RuntimePermission accessDeclaredMembers - // if a different class loader is used (even though the javadoc says otherwise) - Method writeMethod = null; - try { - writeMethod = (Method)AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public java.lang.Object run() throws NoSuchMethodException { - return helperClass.getDeclaredMethod(kWriteMethod, argTypes); - } - } - ); - } catch (PrivilegedActionException pae) { - // this gets caught below - throw (NoSuchMethodException)pae.getException(); - } - java.lang.Object args[] = {parent, object}; - writeMethod.invoke(null, args); - } catch (ClassNotFoundException cnfe) { - throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, cnfe ) ; - } catch(NoSuchMethodException nsme) { - throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, nsme ) ; - } catch(IllegalAccessException iae) { - throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, iae ) ; - } catch(InvocationTargetException ite) { - throw wrapper.errorInvokingHelperWrite( CompletionStatus.COMPLETED_MAYBE, ite ) ; - } - end_block(); - - // Write end tag - writeEndTag(true); - } - - /* DataOutputStream methods */ - - public void write_Abstract (java.lang.Object value) { - write_abstract_interface(value); - } - - public void write_Value (java.io.Serializable value) { - write_value(value); - } - - // This will stay a custom add-on until the java-rtf issue is resolved. - // Then it should be declared in org.omg.CORBA.portable.OutputStream. - // - // Pads the string representation of bigDecimal with zeros to fit the given - // digits and scale before it gets written to the stream. - public void write_fixed(java.math.BigDecimal bigDecimal, short digits, short scale) { - String string = bigDecimal.toString(); - String integerPart; - String fractionPart; - StringBuffer stringBuffer; - - // Get rid of the sign - if (string.charAt(0) == '-' || string.charAt(0) == '+') { - string = string.substring(1); - } - - // Determine integer and fraction parts - int dotIndex = string.indexOf('.'); - if (dotIndex == -1) { - integerPart = string; - fractionPart = null; - } else if (dotIndex == 0 ) { - integerPart = null; - fractionPart = string; - } else { - integerPart = string.substring(0, dotIndex); - fractionPart = string.substring(dotIndex + 1); - } - - // Pad both parts with zeros as necessary - stringBuffer = new StringBuffer(digits); - if (fractionPart != null) { - stringBuffer.append(fractionPart); - } - while (stringBuffer.length() < scale) { - stringBuffer.append('0'); - } - if (integerPart != null) { - stringBuffer.insert(0, integerPart); - } - while (stringBuffer.length() < digits) { - stringBuffer.insert(0, '0'); - } - - // This string contains no sign or dot - this.write_fixed(stringBuffer.toString(), bigDecimal.signum()); - } - - // This method should be remove by the java-rtf issue. - // Right now the scale and digits information of the type code is lost. - public void write_fixed(java.math.BigDecimal bigDecimal) { - // This string might contain sign and/or dot - this.write_fixed(bigDecimal.toString(), bigDecimal.signum()); - } - - // The string may contain a sign and dot - public void write_fixed(String string, int signum) { - int stringLength = string.length(); - // Each octet contains (up to) two decimal digits - byte doubleDigit = 0; - char ch; - byte digit; - - // First calculate the length of the string without optional sign and dot - int numDigits = 0; - for (int i=0; i