/* * Copyright (c) 2004, 2013, 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. */ package com.sun.corba.se.impl.encoding; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import com.sun.corba.se.spi.orb.ORB; import com.sun.corba.se.spi.ior.IOR; import com.sun.corba.se.spi.ior.IORFactories; import com.sun.corba.se.spi.ior.iiop.GIOPVersion; import com.sun.corba.se.spi.logging.CORBALogDomains; import com.sun.corba.se.spi.presentation.rmi.StubAdapter; import com.sun.corba.se.impl.util.Utility; import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.impl.orbutil.ORBUtility; import com.sun.corba.se.impl.corba.TypeCodeImpl; import com.sun.corba.se.impl.logging.ORBUtilSystemException; import com.sun.corba.se.impl.protocol.giopmsgheaders.Message; import org.omg.CORBA.Any; import org.omg.CORBA.TypeCode; import org.omg.CORBA.Principal; import org.omg.CORBA.CompletionStatus; /** * Implementation class that uses Java serialization for output streams. * This assumes a GIOP version 1.2 message format. * * This class uses a ByteArrayOutputStream as the underlying buffer. The * first 16 bytes are direct writes into the underlying buffer. This allows * [GIOPHeader (12 bytes) + requestID (4 bytes)] to be written as bytes. * Subsequent write operations on this output stream object uses * ObjectOutputStream class to write into the buffer. This allows marshaling * complex types and graphs using the ObjectOutputStream implementation. * * Note, this class assumes a GIOP 1.2 style header. Note, we expect that the * first 16 bytes are written only using the write_octet, write_long or * write_ulong method calls. * * @author Ram Jeyaraman */ final class IDLJavaSerializationOutputStream extends CDROutputStreamBase { private ORB orb; private byte encodingVersion; private ObjectOutputStream os; private _ByteArrayOutputStream bos; private BufferManagerWrite bufferManager; // [GIOPHeader(12) + requestID(4)] bytes private final int directWriteLength = Message.GIOPMessageHeaderLength + 4; protected ORBUtilSystemException wrapper; class _ByteArrayOutputStream extends ByteArrayOutputStream { _ByteArrayOutputStream(int initialSize) { super(initialSize); } byte[] getByteArray() { return this.buf; } } class MarshalObjectOutputStream extends ObjectOutputStream { ORB orb; MarshalObjectOutputStream(java.io.OutputStream out, ORB orb) throws IOException { super(out); this.orb = orb; java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { // needs SerializablePermission("enableSubstitution") enableReplaceObject(true); return null; } } ); } /** * Checks for objects that are instances of java.rmi.Remote * that need to be serialized as proxy (Stub) objects. */ protected final Object replaceObject(Object obj) throws IOException { try { if ((obj instanceof java.rmi.Remote) && !(StubAdapter.isStub(obj))) { return Utility.autoConnect(obj, orb, true); } } catch (Exception e) { IOException ie = new IOException("replaceObject failed"); ie.initCause(e); throw ie; } return obj; } } public IDLJavaSerializationOutputStream(byte encodingVersion) { super(); this.encodingVersion = encodingVersion; } public void init(org.omg.CORBA.ORB orb, boolean littleEndian, BufferManagerWrite bufferManager, byte streamFormatVersion, boolean usePooledByteBuffers) { this.orb = (ORB) orb; this.bufferManager = bufferManager; wrapper = ORBUtilSystemException.get((ORB) orb, CORBALogDomains.RPC_ENCODING); bos = new _ByteArrayOutputStream(ORBConstants.GIOP_DEFAULT_BUFFER_SIZE); } // Called from read_octet or read_long or read_ulong method. private void initObjectOutputStream() { //System.out.print(" os "); if (os != null) { throw wrapper.javaStreamInitFailed(); } try { os = new MarshalObjectOutputStream(bos, orb); } catch (Exception e) { throw wrapper.javaStreamInitFailed(e); } } // org.omg.CORBA.portable.OutputStream // Primitive types. public final void write_boolean(boolean value) { try { os.writeBoolean(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_boolean"); } } public final void write_char(char value) { try { os.writeChar(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_char"); } } public final void write_wchar(char value) { this.write_char(value); } public final void write_octet(byte value) { // check if size < [ GIOPHeader(12) + requestID(4)] bytes if (bos.size() < directWriteLength) { bos.write(value); // direct write. if (bos.size() == directWriteLength) { initObjectOutputStream(); } return; } try { os.writeByte(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_octet"); } } public final void write_short(short value) { try { os.writeShort(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_short"); } } public final void write_ushort(short value) { this.write_short(value); } public final void write_long(int value) { // check if size < [ GIOPHeader(12) + requestID(4)] bytes if (bos.size() < directWriteLength) { // Use big endian (network byte order). This is fixed. // Both the writer and reader use the same byte order. bos.write((byte)((value >>> 24) & 0xFF)); bos.write((byte)((value >>> 16) & 0xFF)); bos.write((byte)((value >>> 8) & 0xFF)); bos.write((byte)((value >>> 0) & 0xFF)); if (bos.size() == directWriteLength) { initObjectOutputStream(); } else if (bos.size() > directWriteLength) { // Cannot happen. All direct writes are contained // within the first 16 bytes. wrapper.javaSerializationException("write_long"); } return; } try { os.writeInt(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_long"); } } public final void write_ulong(int value) { this.write_long(value); } public final void write_longlong(long value) { try { os.writeLong(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_longlong"); } } public final void write_ulonglong(long value) { this.write_longlong(value); } public final void write_float(float value) { try { os.writeFloat(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_float"); } } public final void write_double(double value) { try { os.writeDouble(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_double"); } } // String types. public final void write_string(String value) { try { os.writeUTF(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_string"); } } public final void write_wstring(String value) { try { os.writeObject(value); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_wstring"); } } // Array types. public final void write_boolean_array(boolean[] value, int offset, int length) { for (int i = 0; i < length; i++) { write_boolean(value[offset + i]); } } public final void write_char_array(char[] value, int offset, int length) { for (int i = 0; i < length; i++) { write_char(value[offset + i]); } } public final void write_wchar_array(char[] value, int offset, int length) { write_char_array(value, offset, length); } public final void write_octet_array(byte[] value, int offset, int length) { try { os.write(value, offset, length); } catch (Exception e) { throw wrapper.javaSerializationException(e, "write_octet_array"); } } public final void write_short_array(short[] value, int offset, int length) { for (int i = 0; i < length; i++) { write_short(value[offset + i]); } } 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) { for (int i = 0; i < length; i++) { write_long(value[offset + i]); } } 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) { for (int i = 0; i < length; i++) { write_longlong(value[offset + i]); } } 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) { for (int i = 0; i < length; i++) { write_float(value[offset + i]); } } public final void write_double_array(double[] value, int offset, int length) { for (int i = 0; i < length; i++) { write_double(value[offset + i]); } } // Complex types (objects and graphs). public final void write_Object(org.omg.CORBA.Object value) { if (value == null) { IOR nullIOR = IORFactories.makeIOR(orb); nullIOR.write(parent); return; } // IDL to Java formal 01-06-06 1.21.4.2 if (value instanceof org.omg.CORBA.LocalObject) { throw wrapper.writeLocalObject(CompletionStatus.COMPLETED_MAYBE); } IOR ior = ORBUtility.connectAndGetIOR(orb, value); ior.write(parent); return; } public final 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 final void write_any(Any any) { if (any == null) { throw wrapper.nullParam(CompletionStatus.COMPLETED_MAYBE); } write_TypeCode(any.type()); any.write_value(parent); } public final void write_Principal(Principal p) { // We don't need an implementation for this method, since principal // is absent in GIOP version 1.2 or above. write_long(p.name().length); write_octet_array(p.name(), 0, p.name().length); } public final 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 private 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 string length without optional sign and dot. int numDigits = 0; for (int i=0; i= 1.2 only. public void setHeaderPadding(boolean headerPadding) { // no-op. We don't care about body alignment while using // Java serialization. What the GIOP spec states does not apply here. } // ValueOutputStream ----------------------------- public void start_value(String rep_id) { throw wrapper.giopVersionError(); } public void end_value() { throw wrapper.giopVersionError(); } // java.io.OutputStream // Note: These methods are defined in the super class and accessible. //public abstract void write(byte b[]) throws IOException; //public abstract void write(byte b[], int off, int len) // throws IOException; //public abstract void flush() throws IOException; //public abstract void close() throws IOException; }