/* * Copyright (c) 2002, 2003, 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 org.jboss.com.sun.corba.se.impl.encoding; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.jboss.com.sun.corba.se.spi.orb.ORB; import org.omg.CORBA.CompletionStatus; import org.omg.CORBA_2_3.portable.OutputStream; public final class TypeCodeOutputStream extends EncapsOutputStream { private OutputStream enclosure = null; private Map<String, Integer> typeMap = null; private boolean isEncapsulation = false; public TypeCodeOutputStream(ORB orb) { super(orb, false); } public TypeCodeOutputStream(ORB orb, boolean littleEndian) { super(orb, littleEndian); } public org.omg.CORBA.portable.InputStream create_input_stream() { // return new TypeCodeInputStream((ORB)orb(), getByteBuffer(), getIndex(), isLittleEndian()); TypeCodeInputStream tcis = new TypeCodeInputStream(orb(), getByteBuffer(), getIndex(), isLittleEndian(), getGIOPVersion()); return tcis; } public void setEnclosingOutputStream(OutputStream enclosure) { this.enclosure = enclosure; } public TypeCodeOutputStream getTopLevelStream() { if (enclosure == null) return this; if (enclosure instanceof TypeCodeOutputStream) return ((TypeCodeOutputStream) enclosure).getTopLevelStream(); return this; } public int getTopLevelPosition() { if (enclosure != null && enclosure instanceof TypeCodeOutputStream) { int pos = ((TypeCodeOutputStream) enclosure).getTopLevelPosition() + getPosition(); // Add four bytes for the encaps length, not another 4 for the byte order which is included in // getPosition(). if (isEncapsulation) pos += 4; return pos; } return getPosition(); } public void addIDAtPosition(String id, int position) { if (typeMap == null) typeMap = new HashMap<String, Integer>(16); typeMap.put(id, position); } public int getPositionForID(String id) { if (typeMap == null) throw wrapper.refTypeIndirType(CompletionStatus.COMPLETED_NO); return typeMap.get(id); } public void writeRawBuffer(org.omg.CORBA.portable.OutputStream s, int firstLong) { // Writes this streams buffer to the given OutputStream without byte order flag and length as is the case for // encapsulations. // Make sure to align s to 4 byte boundaries. Unfortunately we can't do just this: // s.alignAndReserve(4, 4); So we have to take the first four bytes given in firstLong and write them with a // call to write_long which will trigger the alignment. Then write the rest of the byte array. s.write_long(firstLong); ByteBuffer byteBuffer = getByteBuffer(); if (byteBuffer.hasArray()) { s.write_octet_array(byteBuffer.array(), 4, getIndex() - 4); } else { // get bytes from DirectByteBuffer NOTE: Microbenchmarks are showing it is faster to do a loop of // ByteBuffer.get(int) than it is to do a bulk ByteBuffer.get(byte[], offset, length) byte[] buf = new byte[byteBuffer.limit()]; for (int i = 0; i < buf.length; i++) buf[i] = byteBuffer.get(i); s.write_octet_array(buf, 4, getIndex() - 4); } } public TypeCodeOutputStream createEncapsulation(org.omg.CORBA.ORB _orb) { TypeCodeOutputStream encap = new TypeCodeOutputStream((ORB) _orb, isLittleEndian()); encap.setEnclosingOutputStream(this); encap.makeEncapsulation(); // if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + encap + " with parent " + this); return encap; } protected void makeEncapsulation() { // first entry in an encapsulation is the endianess putEndian(); isEncapsulation = true; } public static TypeCodeOutputStream wrapOutputStream(OutputStream os) { boolean littleEndian = ((os instanceof CDROutputStream) ? ((CDROutputStream) os).isLittleEndian() : false); TypeCodeOutputStream tos = new TypeCodeOutputStream((ORB) os.orb(), littleEndian); tos.setEnclosingOutputStream(os); return tos; } public int getPosition() { return getIndex(); } public int getRealIndex(int index) { int topPos = getTopLevelPosition(); return topPos; } public byte[] getTypeCodeBuffer() { // Returns the buffer trimmed of the trailing zeros and without the known _kind value at the beginning. ByteBuffer theBuffer = getByteBuffer(); byte[] tcBuffer = new byte[getIndex() - 4]; // Micro-benchmarks show that DirectByteBuffer.get(int) is faster than DirectByteBuffer.get(byte[], offset, // length). // REVISIT - May want to check if buffer is direct or non-direct and use array copy if ByteBuffer is non-direct. for (int i = 0; i < tcBuffer.length; i++) tcBuffer[i] = theBuffer.get(i + 4); return tcBuffer; } public void printTypeMap() { System.out.println("typeMap = {"); Iterator<String> i = typeMap.keySet().iterator(); while (i.hasNext()) { String id = i.next(); Integer pos = typeMap.get(id); System.out.println(" key = " + id + ", value = " + pos); } System.out.println("}"); } }