1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.corba.se.impl.encoding; 27 28 import org.omg.CORBA.TypeCode ; 29 import org.omg.CORBA.StructMember ; 30 import org.omg.CORBA.UnionMember ; 31 import org.omg.CORBA.ValueMember ; 32 import org.omg.CORBA.TCKind ; 33 import org.omg.CORBA.Any ; 34 import org.omg.CORBA.Principal ; 35 import org.omg.CORBA.CompletionStatus ; 36 37 import org.omg.CORBA.TypeCodePackage.BadKind ; 38 39 import org.omg.CORBA_2_3.portable.InputStream; 40 import org.omg.CORBA_2_3.portable.OutputStream; 41 42 import com.sun.corba.se.spi.orb.ORB; 43 import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry; 44 import com.sun.corba.se.impl.encoding.MarshalInputStream; 45 import com.sun.corba.se.spi.ior.iiop.GIOPVersion; 46 import com.sun.corba.se.impl.encoding.CodeSetConversion; 47 48 import com.sun.corba.se.impl.encoding.CDRInputStream; 49 import com.sun.corba.se.impl.encoding.CDROutputStream; 50 51 import java.util.HashMap; 52 import java.util.Map; 53 import java.util.Iterator; 54 import java.util.List; 55 import java.util.Collections; 56 import java.util.ArrayList; 57 import java.io.IOException; 58 import java.io.PrintStream; 59 import java.io.ByteArrayOutputStream; 60 import java.math.BigDecimal; 61 import java.math.BigInteger; 62 import java.nio.ByteBuffer; 63 64 import sun.corba.EncapsInputStreamFactory; 65 66 public final class TypeCodeOutputStream extends EncapsOutputStream 67 { 68 private OutputStream enclosure = null; 69 private Map typeMap = null; 70 private boolean isEncapsulation = false; 71 72 public TypeCodeOutputStream(ORB orb) { 73 super(orb, false); 74 } 75 76 public TypeCodeOutputStream(ORB orb, boolean littleEndian) { 77 super(orb, littleEndian); 78 } 79 80 public org.omg.CORBA.portable.InputStream create_input_stream() 81 { 82 TypeCodeInputStream tcis = EncapsInputStreamFactory 83 .newTypeCodeInputStream((ORB) orb(), getByteBuffer(), 84 getIndex(), isLittleEndian(), getGIOPVersion()); 85 //if (TypeCodeImpl.debug) { 86 //System.out.println("Created TypeCodeInputStream " + tcis + " with no parent"); 87 //tcis.printBuffer(); 88 //} 89 return tcis; 90 } 91 92 public void setEnclosingOutputStream(OutputStream enclosure) { 93 this.enclosure = enclosure; 94 } 95 96 /* 97 public boolean isEncapsulatedIn(TypeCodeOutputStream outerEnclosure) { 98 if (outerEnclosure == this) 99 return true; 100 if (enclosure == null) 101 return false; 102 if (enclosure instanceof TypeCodeOutputStream) 103 return ((TypeCodeOutputStream)enclosure).isEncapsulatedIn(outerEnclosure); 104 // Last chance! Recursion ends with first non TypeCodeOutputStream. 105 return (enclosure == outerEnclosure); 106 } 107 */ 108 109 public TypeCodeOutputStream getTopLevelStream() { 110 if (enclosure == null) 111 return this; 112 if (enclosure instanceof TypeCodeOutputStream) 113 return ((TypeCodeOutputStream)enclosure).getTopLevelStream(); 114 return this; 115 } 116 117 public int getTopLevelPosition() { 118 if (enclosure != null && enclosure instanceof TypeCodeOutputStream) { 119 int pos = ((TypeCodeOutputStream)enclosure).getTopLevelPosition() + getPosition(); 120 // Add four bytes for the encaps length, not another 4 for the byte order 121 // which is included in getPosition(). 122 if (isEncapsulation) pos += 4; 123 //if (TypeCodeImpl.debug) { 124 //System.out.println("TypeCodeOutputStream.getTopLevelPosition using getTopLevelPosition " + 125 //((TypeCodeOutputStream)enclosure).getTopLevelPosition() + 126 //" + getPosition() " + getPosition() + 127 //(isEncapsulation ? " + encaps length 4" : "") + 128 //" = " + pos); 129 //} 130 return pos; 131 } 132 //if (TypeCodeImpl.debug) { 133 //System.out.println("TypeCodeOutputStream.getTopLevelPosition returning getPosition() = " + 134 //getPosition() + ", enclosure is " + enclosure); 135 //} 136 return getPosition(); 137 } 138 139 public void addIDAtPosition(String id, int position) { 140 if (typeMap == null) 141 typeMap = new HashMap(16); 142 //if (TypeCodeImpl.debug) System.out.println(this + " adding id " + id + " at position " + position); 143 typeMap.put(id, new Integer(position)); 144 } 145 146 public int getPositionForID(String id) { 147 if (typeMap == null) 148 throw wrapper.refTypeIndirType( CompletionStatus.COMPLETED_NO ) ; 149 //if (TypeCodeImpl.debug) System.out.println("Getting position " + ((Integer)typeMap.get(id)).intValue() + 150 //" for id " + id); 151 return ((Integer)typeMap.get(id)).intValue(); 152 } 153 154 public void writeRawBuffer(org.omg.CORBA.portable.OutputStream s, int firstLong) { 155 // Writes this streams buffer to the given OutputStream 156 // without byte order flag and length as is the case for encapsulations. 157 158 // Make sure to align s to 4 byte boundaries. 159 // Unfortunately we can't do just this: 160 // s.alignAndReserve(4, 4); 161 // So we have to take the first four bytes given in firstLong and write them 162 // with a call to write_long which will trigger the alignment. 163 // Then write the rest of the byte array. 164 165 //if (TypeCodeImpl.debug) { 166 //System.out.println(this + ".writeRawBuffer(" + s + ", " + firstLong + ")"); 167 //if (s instanceof CDROutputStream) { 168 //System.out.println("Parent position before writing kind = " + ((CDROutputStream)s).getIndex()); 169 //} 170 //} 171 s.write_long(firstLong); 172 //if (TypeCodeImpl.debug) { 173 //if (s instanceof CDROutputStream) { 174 //System.out.println("Parent position after writing kind = " + ((CDROutputStream)s).getIndex()); 175 //} 176 //} 177 ByteBuffer byteBuffer = getByteBuffer(); 178 if (byteBuffer.hasArray()) 179 { 180 s.write_octet_array(byteBuffer.array(), 4, getIndex() - 4); 181 } 182 else 183 { 184 // get bytes from DirectByteBuffer 185 // NOTE: Microbenchmarks are showing it is faster to do 186 // a loop of ByteBuffer.get(int) than it is to do 187 // a bulk ByteBuffer.get(byte[], offset, length) 188 byte[] buf = new byte[byteBuffer.limit()]; 189 for (int i = 0; i < buf.length; i++) 190 buf[i] = byteBuffer.get(i); 191 s.write_octet_array(buf, 4, getIndex() - 4); 192 } 193 //if (TypeCodeImpl.debug) { 194 //if (s instanceof CDROutputStream) { 195 //System.out.println("Parent position after writing all " + getIndex() + " bytes = " + ((CDROutputStream)s).getIndex()); 196 //} 197 //} 198 } 199 200 public TypeCodeOutputStream createEncapsulation(org.omg.CORBA.ORB _orb) { 201 TypeCodeOutputStream encap = 202 sun.corba.OutputStreamFactory.newTypeCodeOutputStream((ORB)_orb, isLittleEndian()); 203 encap.setEnclosingOutputStream(this); 204 encap.makeEncapsulation(); 205 //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + encap + " with parent " + this); 206 return encap; 207 } 208 209 protected void makeEncapsulation() { 210 // first entry in an encapsulation is the endianess 211 putEndian(); 212 isEncapsulation = true; 213 } 214 215 public static TypeCodeOutputStream wrapOutputStream(OutputStream os) { 216 boolean littleEndian = ((os instanceof CDROutputStream) ? ((CDROutputStream)os).isLittleEndian() : false); 217 TypeCodeOutputStream tos = 218 sun.corba.OutputStreamFactory.newTypeCodeOutputStream((ORB)os.orb(), littleEndian); 219 tos.setEnclosingOutputStream(os); 220 //if (TypeCodeImpl.debug) System.out.println("Created TypeCodeOutputStream " + tos + " with parent " + os); 221 return tos; 222 } 223 224 public int getPosition() { 225 return getIndex(); 226 } 227 228 public int getRealIndex(int index) { 229 int topPos = getTopLevelPosition(); 230 //if (TypeCodeImpl.debug) System.out.println("TypeCodeOutputStream.getRealIndex using getTopLevelPosition " + 231 //topPos + " instead of getPosition " + getPosition()); 232 return topPos; 233 } 234 /* 235 protected void printBuffer() { 236 super.printBuffer(); 237 } 238 */ 239 public byte[] getTypeCodeBuffer() { 240 // Returns the buffer trimmed of the trailing zeros and without the 241 // known _kind value at the beginning. 242 ByteBuffer theBuffer = getByteBuffer(); 243 //System.out.println("outBuffer length = " + (getIndex() - 4)); 244 byte[] tcBuffer = new byte[getIndex() - 4]; 245 // Micro-benchmarks show that DirectByteBuffer.get(int) is faster 246 // than DirectByteBuffer.get(byte[], offset, length). 247 // REVISIT - May want to check if buffer is direct or non-direct 248 // and use array copy if ByteBuffer is non-direct. 249 for (int i = 0; i < tcBuffer.length; i++) 250 tcBuffer[i] = theBuffer.get(i+4); 251 return tcBuffer; 252 } 253 254 public void printTypeMap() { 255 System.out.println("typeMap = {"); 256 Iterator i = typeMap.keySet().iterator(); 257 while (i.hasNext()) { 258 String id = (String)i.next(); 259 Integer pos = (Integer)typeMap.get(id); 260 System.out.println(" key = " + id + ", value = " + pos); 261 } 262 System.out.println("}"); 263 } 264 }