Wed, 27 Apr 2016 01:21:28 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/corba/
changeset: 765:f46df0af2ca8
tag: jdk8u25-b17
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 | /* |
aoqi@0 | 27 | * Licensed Materials - Property of IBM |
aoqi@0 | 28 | * RMI-IIOP v1.0 |
aoqi@0 | 29 | * Copyright IBM Corp. 1998 1999 All Rights Reserved |
aoqi@0 | 30 | * |
aoqi@0 | 31 | */ |
aoqi@0 | 32 | |
aoqi@0 | 33 | package com.sun.corba.se.impl.encoding; |
aoqi@0 | 34 | |
aoqi@0 | 35 | import java.io.IOException; |
aoqi@0 | 36 | import java.io.Serializable; |
aoqi@0 | 37 | import java.io.ByteArrayInputStream; |
aoqi@0 | 38 | import java.io.ObjectInputStream; |
aoqi@0 | 39 | import java.io.IOException; |
aoqi@0 | 40 | import java.io.StreamCorruptedException; |
aoqi@0 | 41 | import java.io.OptionalDataException; |
aoqi@0 | 42 | import java.io.IOException; |
aoqi@0 | 43 | |
aoqi@0 | 44 | import java.util.Stack; |
aoqi@0 | 45 | |
aoqi@0 | 46 | import java.net.URL; |
aoqi@0 | 47 | import java.net.MalformedURLException; |
aoqi@0 | 48 | |
aoqi@0 | 49 | import java.nio.ByteBuffer; |
aoqi@0 | 50 | |
aoqi@0 | 51 | import java.lang.reflect.InvocationTargetException; |
aoqi@0 | 52 | import java.lang.reflect.Method; |
aoqi@0 | 53 | |
aoqi@0 | 54 | import java.math.BigDecimal; |
aoqi@0 | 55 | |
aoqi@0 | 56 | import java.rmi.Remote; |
aoqi@0 | 57 | import java.rmi.StubNotFoundException; |
aoqi@0 | 58 | |
aoqi@0 | 59 | import java.security.AccessController; |
aoqi@0 | 60 | import java.security.PrivilegedExceptionAction; |
aoqi@0 | 61 | import java.security.PrivilegedActionException; |
aoqi@0 | 62 | |
aoqi@0 | 63 | import org.omg.CORBA.SystemException; |
aoqi@0 | 64 | import org.omg.CORBA.Object; |
aoqi@0 | 65 | import org.omg.CORBA.Principal; |
aoqi@0 | 66 | import org.omg.CORBA.TypeCode; |
aoqi@0 | 67 | import org.omg.CORBA.Any; |
aoqi@0 | 68 | import org.omg.CORBA.portable.Delegate; |
aoqi@0 | 69 | import org.omg.CORBA.portable.ValueBase; |
aoqi@0 | 70 | import org.omg.CORBA.portable.IndirectionException; |
aoqi@0 | 71 | import org.omg.CORBA.CompletionStatus; |
aoqi@0 | 72 | import org.omg.CORBA.TCKind; |
aoqi@0 | 73 | import org.omg.CORBA.TypeCodePackage.BadKind; |
aoqi@0 | 74 | import org.omg.CORBA.CustomMarshal; |
aoqi@0 | 75 | import org.omg.CORBA.TypeCode; |
aoqi@0 | 76 | import org.omg.CORBA.Principal; |
aoqi@0 | 77 | import org.omg.CORBA.Any; |
aoqi@0 | 78 | import org.omg.CORBA.portable.BoxedValueHelper; |
aoqi@0 | 79 | import org.omg.CORBA.portable.ValueFactory; |
aoqi@0 | 80 | import org.omg.CORBA.portable.CustomValue; |
aoqi@0 | 81 | import org.omg.CORBA.portable.StreamableValue; |
aoqi@0 | 82 | import org.omg.CORBA.MARSHAL; |
aoqi@0 | 83 | import org.omg.CORBA.portable.IDLEntity; |
aoqi@0 | 84 | |
aoqi@0 | 85 | import javax.rmi.PortableRemoteObject; |
aoqi@0 | 86 | import javax.rmi.CORBA.Tie; |
aoqi@0 | 87 | import javax.rmi.CORBA.Util; |
aoqi@0 | 88 | import javax.rmi.CORBA.ValueHandler; |
aoqi@0 | 89 | |
aoqi@0 | 90 | import com.sun.corba.se.pept.protocol.MessageMediator; |
aoqi@0 | 91 | import com.sun.corba.se.pept.transport.ByteBufferPool; |
aoqi@0 | 92 | |
aoqi@0 | 93 | import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry; |
aoqi@0 | 94 | import com.sun.corba.se.spi.protocol.CorbaClientDelegate; |
aoqi@0 | 95 | |
aoqi@0 | 96 | import com.sun.corba.se.spi.ior.IOR; |
aoqi@0 | 97 | import com.sun.corba.se.spi.ior.IORFactories; |
aoqi@0 | 98 | import com.sun.corba.se.spi.ior.iiop.GIOPVersion; |
aoqi@0 | 99 | |
aoqi@0 | 100 | import com.sun.corba.se.spi.orb.ORB; |
aoqi@0 | 101 | import com.sun.corba.se.spi.orb.ORBVersionFactory; |
aoqi@0 | 102 | import com.sun.corba.se.spi.orb.ORBVersion; |
aoqi@0 | 103 | |
aoqi@0 | 104 | import com.sun.corba.se.spi.protocol.CorbaMessageMediator; |
aoqi@0 | 105 | |
aoqi@0 | 106 | import com.sun.corba.se.spi.logging.CORBALogDomains; |
aoqi@0 | 107 | import com.sun.corba.se.spi.presentation.rmi.PresentationManager; |
aoqi@0 | 108 | import com.sun.corba.se.spi.presentation.rmi.StubAdapter; |
aoqi@0 | 109 | import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults; |
aoqi@0 | 110 | |
aoqi@0 | 111 | import com.sun.corba.se.impl.logging.ORBUtilSystemException; |
aoqi@0 | 112 | import com.sun.corba.se.impl.logging.OMGSystemException; |
aoqi@0 | 113 | |
aoqi@0 | 114 | import com.sun.corba.se.impl.corba.PrincipalImpl; |
aoqi@0 | 115 | import com.sun.corba.se.impl.corba.TypeCodeImpl; |
aoqi@0 | 116 | import com.sun.corba.se.impl.corba.CORBAObjectImpl; |
aoqi@0 | 117 | |
aoqi@0 | 118 | import com.sun.corba.se.impl.encoding.CDROutputObject; |
aoqi@0 | 119 | import com.sun.corba.se.impl.encoding.CodeSetConversion; |
aoqi@0 | 120 | |
aoqi@0 | 121 | import com.sun.corba.se.impl.util.Utility; |
aoqi@0 | 122 | import com.sun.corba.se.impl.util.RepositoryId; |
aoqi@0 | 123 | |
aoqi@0 | 124 | import com.sun.corba.se.impl.orbutil.RepositoryIdStrings; |
aoqi@0 | 125 | import com.sun.corba.se.impl.orbutil.RepositoryIdInterface; |
aoqi@0 | 126 | import com.sun.corba.se.impl.orbutil.RepositoryIdUtility; |
aoqi@0 | 127 | import com.sun.corba.se.impl.orbutil.RepositoryIdFactory; |
aoqi@0 | 128 | |
aoqi@0 | 129 | import com.sun.corba.se.impl.orbutil.ORBUtility; |
aoqi@0 | 130 | import com.sun.corba.se.impl.orbutil.CacheTable; |
aoqi@0 | 131 | |
aoqi@0 | 132 | |
aoqi@0 | 133 | import com.sun.org.omg.CORBA.portable.ValueHelper; |
aoqi@0 | 134 | |
aoqi@0 | 135 | import com.sun.org.omg.SendingContext.CodeBase; |
aoqi@0 | 136 | |
aoqi@0 | 137 | public class CDRInputStream_1_0 extends CDRInputStreamBase |
aoqi@0 | 138 | implements RestorableInputStream |
aoqi@0 | 139 | { |
aoqi@0 | 140 | private static final String kReadMethod = "read"; |
aoqi@0 | 141 | private static final int maxBlockLength = 0x7fffff00; |
aoqi@0 | 142 | |
aoqi@0 | 143 | protected BufferManagerRead bufferManagerRead; |
aoqi@0 | 144 | protected ByteBufferWithInfo bbwi; |
aoqi@0 | 145 | |
aoqi@0 | 146 | // Set to the ORB's transportDebugFlag value. This value is |
aoqi@0 | 147 | // used if the ORB is null. |
aoqi@0 | 148 | private boolean debug = false; |
aoqi@0 | 149 | |
aoqi@0 | 150 | protected boolean littleEndian; |
aoqi@0 | 151 | protected ORB orb; |
aoqi@0 | 152 | protected ORBUtilSystemException wrapper ; |
aoqi@0 | 153 | protected OMGSystemException omgWrapper ; |
aoqi@0 | 154 | protected ValueHandler valueHandler = null; |
aoqi@0 | 155 | |
aoqi@0 | 156 | // Value cache |
aoqi@0 | 157 | private CacheTable valueCache = null; |
aoqi@0 | 158 | |
aoqi@0 | 159 | // Repository ID cache |
aoqi@0 | 160 | private CacheTable repositoryIdCache = null; |
aoqi@0 | 161 | |
aoqi@0 | 162 | // codebase cache |
aoqi@0 | 163 | private CacheTable codebaseCache = null; |
aoqi@0 | 164 | |
aoqi@0 | 165 | // Current Class Stack (repository Ids of current class being read) |
aoqi@0 | 166 | // private Stack currentStack = null; |
aoqi@0 | 167 | |
aoqi@0 | 168 | // Length of current chunk, or a large positive number if not in a chunk |
aoqi@0 | 169 | protected int blockLength = maxBlockLength; |
aoqi@0 | 170 | |
aoqi@0 | 171 | // Read end flag (value nesting depth) |
aoqi@0 | 172 | protected int end_flag = 0; |
aoqi@0 | 173 | |
aoqi@0 | 174 | // Beginning with the resolution to interop issue 3526 (4328?), |
aoqi@0 | 175 | // only enclosing chunked valuetypes are taken into account |
aoqi@0 | 176 | // when computing the nesting level. However, we still need |
aoqi@0 | 177 | // the old computation around for interoperability with our |
aoqi@0 | 178 | // older ORBs. |
aoqi@0 | 179 | private int chunkedValueNestingLevel = 0; |
aoqi@0 | 180 | |
aoqi@0 | 181 | // Flag used to determine whether blocksize was zero |
aoqi@0 | 182 | // private int checkForNullBlock = -1; |
aoqi@0 | 183 | |
aoqi@0 | 184 | // In block flag |
aoqi@0 | 185 | // private boolean inBlock = false; |
aoqi@0 | 186 | |
aoqi@0 | 187 | // Indicates whether we are inside a value |
aoqi@0 | 188 | // private boolean outerValueDone = true; |
aoqi@0 | 189 | |
aoqi@0 | 190 | // Int used by read_value(Serializable) that is set by this class |
aoqi@0 | 191 | // before calling ValueFactory.read_value |
aoqi@0 | 192 | protected int valueIndirection = 0; |
aoqi@0 | 193 | |
aoqi@0 | 194 | // Int set by readStringOrIndirection to communicate the actual |
aoqi@0 | 195 | // offset of the string length field back to the caller |
aoqi@0 | 196 | protected int stringIndirection = 0; |
aoqi@0 | 197 | |
aoqi@0 | 198 | // Flag indicating whether we are unmarshalling a chunked value |
aoqi@0 | 199 | protected boolean isChunked = false; |
aoqi@0 | 200 | |
aoqi@0 | 201 | // Repository ID handlers |
aoqi@0 | 202 | private RepositoryIdUtility repIdUtil; |
aoqi@0 | 203 | private RepositoryIdStrings repIdStrs; |
aoqi@0 | 204 | |
aoqi@0 | 205 | // Code set converters (created when first needed) |
aoqi@0 | 206 | private CodeSetConversion.BTCConverter charConverter; |
aoqi@0 | 207 | private CodeSetConversion.BTCConverter wcharConverter; |
aoqi@0 | 208 | |
aoqi@0 | 209 | // RMI-IIOP stream format version 2 case in which we know |
aoqi@0 | 210 | // that there is no more optional data available. If the |
aoqi@0 | 211 | // Serializable's readObject method tries to read anything, |
aoqi@0 | 212 | // we must throw a MARSHAL with the special minor code |
aoqi@0 | 213 | // so that the ValueHandler can give the correct exception |
aoqi@0 | 214 | // to readObject. The state is cleared when the ValueHandler |
aoqi@0 | 215 | // calls end_value after the readObject method exits. |
aoqi@0 | 216 | private boolean specialNoOptionalDataState = false; |
aoqi@0 | 217 | |
aoqi@0 | 218 | // Template method |
aoqi@0 | 219 | public CDRInputStreamBase dup() |
aoqi@0 | 220 | { |
aoqi@0 | 221 | CDRInputStreamBase result = null ; |
aoqi@0 | 222 | |
aoqi@0 | 223 | try { |
aoqi@0 | 224 | result = (CDRInputStreamBase)this.getClass().newInstance(); |
aoqi@0 | 225 | } catch (Exception e) { |
aoqi@0 | 226 | throw wrapper.couldNotDuplicateCdrInputStream( e ) ; |
aoqi@0 | 227 | } |
aoqi@0 | 228 | result.init(this.orb, |
aoqi@0 | 229 | this.bbwi.byteBuffer, |
aoqi@0 | 230 | this.bbwi.buflen, |
aoqi@0 | 231 | this.littleEndian, |
aoqi@0 | 232 | this.bufferManagerRead); |
aoqi@0 | 233 | |
aoqi@0 | 234 | ((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position()); |
aoqi@0 | 235 | // To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen. |
aoqi@0 | 236 | ((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen); |
aoqi@0 | 237 | |
aoqi@0 | 238 | return result; |
aoqi@0 | 239 | } |
aoqi@0 | 240 | |
aoqi@0 | 241 | /** |
aoqi@0 | 242 | * NOTE: size passed to init means buffer size |
aoqi@0 | 243 | */ |
aoqi@0 | 244 | public void init(org.omg.CORBA.ORB orb, |
aoqi@0 | 245 | ByteBuffer byteBuffer, |
aoqi@0 | 246 | int size, |
aoqi@0 | 247 | boolean littleEndian, |
aoqi@0 | 248 | BufferManagerRead bufferManager) |
aoqi@0 | 249 | { |
aoqi@0 | 250 | this.orb = (ORB)orb; |
aoqi@0 | 251 | this.wrapper = ORBUtilSystemException.get( (ORB)orb, |
aoqi@0 | 252 | CORBALogDomains.RPC_ENCODING ) ; |
aoqi@0 | 253 | this.omgWrapper = OMGSystemException.get( (ORB)orb, |
aoqi@0 | 254 | CORBALogDomains.RPC_ENCODING ) ; |
aoqi@0 | 255 | this.littleEndian = littleEndian; |
aoqi@0 | 256 | this.bufferManagerRead = bufferManager; |
aoqi@0 | 257 | this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0); |
aoqi@0 | 258 | this.bbwi.buflen = size; |
aoqi@0 | 259 | this.bbwi.byteBuffer.limit(bbwi.buflen); |
aoqi@0 | 260 | this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler(); |
aoqi@0 | 261 | |
aoqi@0 | 262 | debug = ((ORB)orb).transportDebugFlag; |
aoqi@0 | 263 | } |
aoqi@0 | 264 | |
aoqi@0 | 265 | // See description in CDRInputStream |
aoqi@0 | 266 | void performORBVersionSpecificInit() { |
aoqi@0 | 267 | createRepositoryIdHandlers(); |
aoqi@0 | 268 | } |
aoqi@0 | 269 | |
aoqi@0 | 270 | private final void createRepositoryIdHandlers() |
aoqi@0 | 271 | { |
aoqi@0 | 272 | repIdUtil = RepositoryIdFactory.getRepIdUtility(); |
aoqi@0 | 273 | repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(); |
aoqi@0 | 274 | } |
aoqi@0 | 275 | |
aoqi@0 | 276 | public GIOPVersion getGIOPVersion() { |
aoqi@0 | 277 | return GIOPVersion.V1_0; |
aoqi@0 | 278 | } |
aoqi@0 | 279 | |
aoqi@0 | 280 | // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only. |
aoqi@0 | 281 | // Illegal for GIOP versions < 1.2. |
aoqi@0 | 282 | void setHeaderPadding(boolean headerPadding) { |
aoqi@0 | 283 | throw wrapper.giopVersionError(); |
aoqi@0 | 284 | } |
aoqi@0 | 285 | |
aoqi@0 | 286 | protected final int computeAlignment(int index, int align) { |
aoqi@0 | 287 | if (align > 1) { |
aoqi@0 | 288 | int incr = index & (align - 1); |
aoqi@0 | 289 | if (incr != 0) |
aoqi@0 | 290 | return align - incr; |
aoqi@0 | 291 | } |
aoqi@0 | 292 | |
aoqi@0 | 293 | return 0; |
aoqi@0 | 294 | } |
aoqi@0 | 295 | |
aoqi@0 | 296 | public int getSize() |
aoqi@0 | 297 | { |
aoqi@0 | 298 | return bbwi.position(); |
aoqi@0 | 299 | } |
aoqi@0 | 300 | |
aoqi@0 | 301 | protected void checkBlockLength(int align, int dataSize) { |
aoqi@0 | 302 | // Since chunks can end at arbitrary points (though not within |
aoqi@0 | 303 | // primitive CDR types, arrays of primitives, strings, wstrings, |
aoqi@0 | 304 | // or indirections), |
aoqi@0 | 305 | // we must check here for termination of the current chunk. |
aoqi@0 | 306 | if (!isChunked) |
aoqi@0 | 307 | return; |
aoqi@0 | 308 | |
aoqi@0 | 309 | // RMI-IIOP stream format version 2 case in which we know |
aoqi@0 | 310 | // that there is no more optional data available. If the |
aoqi@0 | 311 | // Serializable's readObject method tries to read anything, |
aoqi@0 | 312 | // we must throw a MARSHAL exception with the special minor code |
aoqi@0 | 313 | // so that the ValueHandler can give the correct exception |
aoqi@0 | 314 | // to readObject. The state is cleared when the ValueHandler |
aoqi@0 | 315 | // calls end_value after the readObject method exits. |
aoqi@0 | 316 | if (specialNoOptionalDataState) { |
aoqi@0 | 317 | throw omgWrapper.rmiiiopOptionalDataIncompatible1() ; |
aoqi@0 | 318 | } |
aoqi@0 | 319 | |
aoqi@0 | 320 | boolean checkForEndTag = false; |
aoqi@0 | 321 | |
aoqi@0 | 322 | // Are we at the end of the current chunk? If so, |
aoqi@0 | 323 | // try to interpret the next long as a chunk length. |
aoqi@0 | 324 | // (It has to be either a chunk length, end tag, |
aoqi@0 | 325 | // or valuetag.) |
aoqi@0 | 326 | // |
aoqi@0 | 327 | // If it isn't a chunk length, blockLength will |
aoqi@0 | 328 | // remain set to maxBlockLength. |
aoqi@0 | 329 | if (blockLength == get_offset()) { |
aoqi@0 | 330 | |
aoqi@0 | 331 | blockLength = maxBlockLength; |
aoqi@0 | 332 | start_block(); |
aoqi@0 | 333 | |
aoqi@0 | 334 | // What's next is either a valuetag or |
aoqi@0 | 335 | // an end tag. If it's a valuetag, we're |
aoqi@0 | 336 | // probably being called as part of the process |
aoqi@0 | 337 | // to read the valuetag. If it's an end tag, |
aoqi@0 | 338 | // then there isn't enough data left in |
aoqi@0 | 339 | // this valuetype to read! |
aoqi@0 | 340 | if (blockLength == maxBlockLength) |
aoqi@0 | 341 | checkForEndTag = true; |
aoqi@0 | 342 | |
aoqi@0 | 343 | } else |
aoqi@0 | 344 | if (blockLength < get_offset()) { |
aoqi@0 | 345 | // Are we already past the end of the current chunk? |
aoqi@0 | 346 | // This is always an error. |
aoqi@0 | 347 | throw wrapper.chunkOverflow() ; |
aoqi@0 | 348 | } |
aoqi@0 | 349 | |
aoqi@0 | 350 | // If what's next on the wire isn't a chunk length or |
aoqi@0 | 351 | // what we want to read (which can't be split across chunks) |
aoqi@0 | 352 | // won't fit in the current chunk, throw this exception. |
aoqi@0 | 353 | // This probably means that we're in an RMI-IIOP |
aoqi@0 | 354 | // Serializable's readObject method or a custom marshaled |
aoqi@0 | 355 | // IDL type is reading too much/in an incorrect order |
aoqi@0 | 356 | int requiredNumBytes = |
aoqi@0 | 357 | computeAlignment(bbwi.position(), align) + dataSize; |
aoqi@0 | 358 | |
aoqi@0 | 359 | if (blockLength != maxBlockLength && |
aoqi@0 | 360 | blockLength < get_offset() + requiredNumBytes) { |
aoqi@0 | 361 | throw omgWrapper.rmiiiopOptionalDataIncompatible2() ; |
aoqi@0 | 362 | } |
aoqi@0 | 363 | |
aoqi@0 | 364 | // REVISIT - We should look at using the built in advancement |
aoqi@0 | 365 | // of using ByteBuffer.get() rather than explicitly |
aoqi@0 | 366 | // advancing the ByteBuffer's position. |
aoqi@0 | 367 | // This is true for anywhere we are incrementing |
aoqi@0 | 368 | // the ByteBuffer's position. |
aoqi@0 | 369 | if (checkForEndTag) { |
aoqi@0 | 370 | int nextLong = read_long(); |
aoqi@0 | 371 | bbwi.position(bbwi.position() - 4); |
aoqi@0 | 372 | |
aoqi@0 | 373 | // It was an end tag, so there wasn't enough data |
aoqi@0 | 374 | // left in the valuetype's encoding on the wire |
aoqi@0 | 375 | // to read what we wanted |
aoqi@0 | 376 | if (nextLong < 0) |
aoqi@0 | 377 | throw omgWrapper.rmiiiopOptionalDataIncompatible3() ; |
aoqi@0 | 378 | } |
aoqi@0 | 379 | } |
aoqi@0 | 380 | |
aoqi@0 | 381 | protected void alignAndCheck(int align, int n) { |
aoqi@0 | 382 | |
aoqi@0 | 383 | checkBlockLength(align, n); |
aoqi@0 | 384 | |
aoqi@0 | 385 | // WARNING: Must compute real alignment after calling |
aoqi@0 | 386 | // checkBlockLength since it may move the position |
aoqi@0 | 387 | int alignResult = computeAlignment(bbwi.position(), align); |
aoqi@0 | 388 | bbwi.position(bbwi.position() + alignResult); |
aoqi@0 | 389 | |
aoqi@0 | 390 | if (bbwi.position() + n > bbwi.buflen) |
aoqi@0 | 391 | grow(align, n); |
aoqi@0 | 392 | } |
aoqi@0 | 393 | |
aoqi@0 | 394 | // |
aoqi@0 | 395 | // This can be overridden.... |
aoqi@0 | 396 | // |
aoqi@0 | 397 | protected void grow(int align, int n) { |
aoqi@0 | 398 | |
aoqi@0 | 399 | bbwi.needed = n; |
aoqi@0 | 400 | |
aoqi@0 | 401 | bbwi = bufferManagerRead.underflow(bbwi); |
aoqi@0 | 402 | |
aoqi@0 | 403 | } |
aoqi@0 | 404 | |
aoqi@0 | 405 | // |
aoqi@0 | 406 | // Marshal primitives. |
aoqi@0 | 407 | // |
aoqi@0 | 408 | |
aoqi@0 | 409 | public final void consumeEndian() { |
aoqi@0 | 410 | littleEndian = read_boolean(); |
aoqi@0 | 411 | } |
aoqi@0 | 412 | |
aoqi@0 | 413 | // No such type in java |
aoqi@0 | 414 | public final double read_longdouble() { |
aoqi@0 | 415 | throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 416 | } |
aoqi@0 | 417 | |
aoqi@0 | 418 | public final boolean read_boolean() { |
aoqi@0 | 419 | return (read_octet() != 0); |
aoqi@0 | 420 | } |
aoqi@0 | 421 | |
aoqi@0 | 422 | public final char read_char() { |
aoqi@0 | 423 | alignAndCheck(1, 1); |
aoqi@0 | 424 | |
aoqi@0 | 425 | return getConvertedChars(1, getCharConverter())[0]; |
aoqi@0 | 426 | } |
aoqi@0 | 427 | |
aoqi@0 | 428 | public char read_wchar() { |
aoqi@0 | 429 | |
aoqi@0 | 430 | // Don't allow transmission of wchar/wstring data with |
aoqi@0 | 431 | // foreign ORBs since it's against the spec. |
aoqi@0 | 432 | if (ORBUtility.isForeignORB((ORB)orb)) { |
aoqi@0 | 433 | throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 434 | } |
aoqi@0 | 435 | |
aoqi@0 | 436 | // If we're talking to one of our legacy ORBs, do what |
aoqi@0 | 437 | // they did: |
aoqi@0 | 438 | int b1, b2; |
aoqi@0 | 439 | |
aoqi@0 | 440 | alignAndCheck(2, 2); |
aoqi@0 | 441 | |
aoqi@0 | 442 | if (littleEndian) { |
aoqi@0 | 443 | b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; |
aoqi@0 | 444 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 445 | b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; |
aoqi@0 | 446 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 447 | } else { |
aoqi@0 | 448 | b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; |
aoqi@0 | 449 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 450 | b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF; |
aoqi@0 | 451 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 452 | } |
aoqi@0 | 453 | |
aoqi@0 | 454 | return (char)((b1 << 8) + (b2 << 0)); |
aoqi@0 | 455 | } |
aoqi@0 | 456 | |
aoqi@0 | 457 | public final byte read_octet() { |
aoqi@0 | 458 | |
aoqi@0 | 459 | alignAndCheck(1, 1); |
aoqi@0 | 460 | |
aoqi@0 | 461 | byte b = bbwi.byteBuffer.get(bbwi.position()); |
aoqi@0 | 462 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 463 | |
aoqi@0 | 464 | return b; |
aoqi@0 | 465 | } |
aoqi@0 | 466 | |
aoqi@0 | 467 | public final short read_short() { |
aoqi@0 | 468 | int b1, b2; |
aoqi@0 | 469 | |
aoqi@0 | 470 | alignAndCheck(2, 2); |
aoqi@0 | 471 | |
aoqi@0 | 472 | if (littleEndian) { |
aoqi@0 | 473 | b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF; |
aoqi@0 | 474 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 475 | b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00; |
aoqi@0 | 476 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 477 | } else { |
aoqi@0 | 478 | b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00; |
aoqi@0 | 479 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 480 | b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF; |
aoqi@0 | 481 | bbwi.position(bbwi.position() + 1); |
aoqi@0 | 482 | } |
aoqi@0 | 483 | |
aoqi@0 | 484 | return (short)(b1 | b2); |
aoqi@0 | 485 | } |
aoqi@0 | 486 | |
aoqi@0 | 487 | public final short read_ushort() { |
aoqi@0 | 488 | return read_short(); |
aoqi@0 | 489 | } |
aoqi@0 | 490 | |
aoqi@0 | 491 | public final int read_long() { |
aoqi@0 | 492 | int b1, b2, b3, b4; |
aoqi@0 | 493 | |
aoqi@0 | 494 | alignAndCheck(4, 4); |
aoqi@0 | 495 | |
aoqi@0 | 496 | int bufPos = bbwi.position(); |
aoqi@0 | 497 | if (littleEndian) { |
aoqi@0 | 498 | b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 499 | b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 500 | b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 501 | b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 502 | } else { |
aoqi@0 | 503 | b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 504 | b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 505 | b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 506 | b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF; |
aoqi@0 | 507 | } |
aoqi@0 | 508 | bbwi.position(bufPos); |
aoqi@0 | 509 | |
aoqi@0 | 510 | return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; |
aoqi@0 | 511 | } |
aoqi@0 | 512 | |
aoqi@0 | 513 | public final int read_ulong() { |
aoqi@0 | 514 | return read_long(); |
aoqi@0 | 515 | } |
aoqi@0 | 516 | |
aoqi@0 | 517 | public final long read_longlong() { |
aoqi@0 | 518 | long i1, i2; |
aoqi@0 | 519 | |
aoqi@0 | 520 | alignAndCheck(8, 8); |
aoqi@0 | 521 | |
aoqi@0 | 522 | if (littleEndian) { |
aoqi@0 | 523 | i2 = read_long() & 0xFFFFFFFFL; |
aoqi@0 | 524 | i1 = (long)read_long() << 32; |
aoqi@0 | 525 | } else { |
aoqi@0 | 526 | i1 = (long)read_long() << 32; |
aoqi@0 | 527 | i2 = read_long() & 0xFFFFFFFFL; |
aoqi@0 | 528 | } |
aoqi@0 | 529 | |
aoqi@0 | 530 | return (i1 | i2); |
aoqi@0 | 531 | } |
aoqi@0 | 532 | |
aoqi@0 | 533 | public final long read_ulonglong() { |
aoqi@0 | 534 | return read_longlong(); |
aoqi@0 | 535 | } |
aoqi@0 | 536 | |
aoqi@0 | 537 | public final float read_float() { |
aoqi@0 | 538 | return Float.intBitsToFloat(read_long()); |
aoqi@0 | 539 | } |
aoqi@0 | 540 | |
aoqi@0 | 541 | public final double read_double() { |
aoqi@0 | 542 | return Double.longBitsToDouble(read_longlong()); |
aoqi@0 | 543 | } |
aoqi@0 | 544 | |
aoqi@0 | 545 | protected final void checkForNegativeLength(int length) { |
aoqi@0 | 546 | if (length < 0) |
aoqi@0 | 547 | throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 548 | new Integer(length) ) ; |
aoqi@0 | 549 | } |
aoqi@0 | 550 | |
aoqi@0 | 551 | protected final String readStringOrIndirection(boolean allowIndirection) { |
aoqi@0 | 552 | |
aoqi@0 | 553 | int len = read_long(); |
aoqi@0 | 554 | |
aoqi@0 | 555 | // |
aoqi@0 | 556 | // Check for indirection |
aoqi@0 | 557 | // |
aoqi@0 | 558 | if (allowIndirection) { |
aoqi@0 | 559 | if (len == 0xffffffff) |
aoqi@0 | 560 | return null; |
aoqi@0 | 561 | else |
aoqi@0 | 562 | stringIndirection = get_offset() - 4; |
aoqi@0 | 563 | } |
aoqi@0 | 564 | |
aoqi@0 | 565 | checkForNegativeLength(len); |
aoqi@0 | 566 | |
aoqi@0 | 567 | return internalReadString(len); |
aoqi@0 | 568 | } |
aoqi@0 | 569 | |
aoqi@0 | 570 | private final String internalReadString(int len) { |
aoqi@0 | 571 | // Workaround for ORBs which send string lengths of |
aoqi@0 | 572 | // zero to mean empty string. |
aoqi@0 | 573 | // |
aoqi@0 | 574 | // IMPORTANT: Do not replace 'new String("")' with "", it may result |
aoqi@0 | 575 | // in a Serialization bug (See serialization.zerolengthstring) and |
aoqi@0 | 576 | // bug id: 4728756 for details |
aoqi@0 | 577 | if (len == 0) |
aoqi@0 | 578 | return new String(""); |
aoqi@0 | 579 | |
aoqi@0 | 580 | char[] result = getConvertedChars(len - 1, getCharConverter()); |
aoqi@0 | 581 | |
aoqi@0 | 582 | // Skip over the 1 byte null |
aoqi@0 | 583 | read_octet(); |
aoqi@0 | 584 | |
aoqi@0 | 585 | return new String(result, 0, getCharConverter().getNumChars()); |
aoqi@0 | 586 | } |
aoqi@0 | 587 | |
aoqi@0 | 588 | public final String read_string() { |
aoqi@0 | 589 | return readStringOrIndirection(false); |
aoqi@0 | 590 | } |
aoqi@0 | 591 | |
aoqi@0 | 592 | public String read_wstring() { |
aoqi@0 | 593 | // Don't allow transmission of wchar/wstring data with |
aoqi@0 | 594 | // foreign ORBs since it's against the spec. |
aoqi@0 | 595 | if (ORBUtility.isForeignORB((ORB)orb)) { |
aoqi@0 | 596 | throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 597 | } |
aoqi@0 | 598 | |
aoqi@0 | 599 | int len = read_long(); |
aoqi@0 | 600 | |
aoqi@0 | 601 | // |
aoqi@0 | 602 | // Workaround for ORBs which send string lengths of |
aoqi@0 | 603 | // zero to mean empty string. |
aoqi@0 | 604 | // |
aoqi@0 | 605 | // |
aoqi@0 | 606 | // IMPORTANT: Do not replace 'new String("")' with "", it may result |
aoqi@0 | 607 | // in a Serialization bug (See serialization.zerolengthstring) and |
aoqi@0 | 608 | // bug id: 4728756 for details |
aoqi@0 | 609 | if (len == 0) |
aoqi@0 | 610 | return new String(""); |
aoqi@0 | 611 | |
aoqi@0 | 612 | checkForNegativeLength(len); |
aoqi@0 | 613 | |
aoqi@0 | 614 | len--; |
aoqi@0 | 615 | char[] c = new char[len]; |
aoqi@0 | 616 | |
aoqi@0 | 617 | for (int i = 0; i < len; i++) |
aoqi@0 | 618 | c[i] = read_wchar(); |
aoqi@0 | 619 | |
aoqi@0 | 620 | // skip the two null terminator bytes |
aoqi@0 | 621 | read_wchar(); |
aoqi@0 | 622 | // bbwi.position(bbwi.position() + 2); |
aoqi@0 | 623 | |
aoqi@0 | 624 | return new String(c); |
aoqi@0 | 625 | } |
aoqi@0 | 626 | |
aoqi@0 | 627 | public final void read_octet_array(byte[] b, int offset, int length) { |
aoqi@0 | 628 | if ( b == null ) |
aoqi@0 | 629 | throw wrapper.nullParam() ; |
aoqi@0 | 630 | |
aoqi@0 | 631 | // Must call alignAndCheck at least once to ensure |
aoqi@0 | 632 | // we aren't at the end of a chunk. Of course, we |
aoqi@0 | 633 | // should only call it if we actually need to read |
aoqi@0 | 634 | // something, otherwise we might end up with an |
aoqi@0 | 635 | // exception at the end of the stream. |
aoqi@0 | 636 | if (length == 0) |
aoqi@0 | 637 | return; |
aoqi@0 | 638 | |
aoqi@0 | 639 | alignAndCheck(1, 1); |
aoqi@0 | 640 | |
aoqi@0 | 641 | int n = offset; |
aoqi@0 | 642 | while (n < length+offset) { |
aoqi@0 | 643 | int avail; |
aoqi@0 | 644 | int bytes; |
aoqi@0 | 645 | int wanted; |
aoqi@0 | 646 | |
aoqi@0 | 647 | avail = bbwi.buflen - bbwi.position(); |
aoqi@0 | 648 | if (avail <= 0) { |
aoqi@0 | 649 | grow(1, 1); |
aoqi@0 | 650 | avail = bbwi.buflen - bbwi.position(); |
aoqi@0 | 651 | } |
aoqi@0 | 652 | wanted = (length + offset) - n; |
aoqi@0 | 653 | bytes = (wanted < avail) ? wanted : avail; |
aoqi@0 | 654 | // Microbenchmarks are showing a loop of ByteBuffer.get(int) being |
aoqi@0 | 655 | // faster than ByteBuffer.get(byte[], int, int). |
aoqi@0 | 656 | for (int i = 0; i < bytes; i++) { |
aoqi@0 | 657 | b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i); |
aoqi@0 | 658 | } |
aoqi@0 | 659 | |
aoqi@0 | 660 | bbwi.position(bbwi.position() + bytes); |
aoqi@0 | 661 | |
aoqi@0 | 662 | n += bytes; |
aoqi@0 | 663 | } |
aoqi@0 | 664 | } |
aoqi@0 | 665 | |
aoqi@0 | 666 | public Principal read_Principal() { |
aoqi@0 | 667 | int len = read_long(); |
aoqi@0 | 668 | byte[] pvalue = new byte[len]; |
aoqi@0 | 669 | read_octet_array(pvalue,0,len); |
aoqi@0 | 670 | |
aoqi@0 | 671 | Principal p = new PrincipalImpl(); |
aoqi@0 | 672 | p.name(pvalue); |
aoqi@0 | 673 | return p; |
aoqi@0 | 674 | } |
aoqi@0 | 675 | |
aoqi@0 | 676 | public TypeCode read_TypeCode() { |
aoqi@0 | 677 | TypeCodeImpl tc = new TypeCodeImpl(orb); |
aoqi@0 | 678 | tc.read_value(parent); |
aoqi@0 | 679 | return tc; |
aoqi@0 | 680 | } |
aoqi@0 | 681 | |
aoqi@0 | 682 | public Any read_any() { |
aoqi@0 | 683 | Any any = orb.create_any(); |
aoqi@0 | 684 | TypeCodeImpl tc = new TypeCodeImpl(orb); |
aoqi@0 | 685 | |
aoqi@0 | 686 | // read off the typecode |
aoqi@0 | 687 | |
aoqi@0 | 688 | // REVISIT We could avoid this try-catch if we could peek the typecode |
aoqi@0 | 689 | // kind off this stream and see if it is a tk_value. Looking at the |
aoqi@0 | 690 | // code we know that for tk_value the Any.read_value() below |
aoqi@0 | 691 | // ignores the tc argument anyway (except for the kind field). |
aoqi@0 | 692 | // But still we would need to make sure that the whole typecode, |
aoqi@0 | 693 | // including encapsulations, is read off. |
aoqi@0 | 694 | try { |
aoqi@0 | 695 | tc.read_value(parent); |
aoqi@0 | 696 | } catch (MARSHAL ex) { |
aoqi@0 | 697 | if (tc.kind().value() != TCKind._tk_value) |
aoqi@0 | 698 | throw ex; |
aoqi@0 | 699 | // We can be sure that the whole typecode encapsulation has been |
aoqi@0 | 700 | // read off. |
aoqi@0 | 701 | dprintThrowable(ex); |
aoqi@0 | 702 | } |
aoqi@0 | 703 | // read off the value of the any |
aoqi@0 | 704 | any.read_value(parent, tc); |
aoqi@0 | 705 | |
aoqi@0 | 706 | return any; |
aoqi@0 | 707 | } |
aoqi@0 | 708 | |
aoqi@0 | 709 | public org.omg.CORBA.Object read_Object() { |
aoqi@0 | 710 | return read_Object(null); |
aoqi@0 | 711 | } |
aoqi@0 | 712 | |
aoqi@0 | 713 | // ------------ RMI related methods -------------------------- |
aoqi@0 | 714 | |
aoqi@0 | 715 | // IDL to Java ptc-00-01-08 1.21.4.1 |
aoqi@0 | 716 | // |
aoqi@0 | 717 | // The clz argument to read_Object can be either a stub |
aoqi@0 | 718 | // Class or the "Class object for the RMI/IDL interface type |
aoqi@0 | 719 | // that is statically expected." |
aoqi@0 | 720 | // This functions as follows: |
aoqi@0 | 721 | // 1. If clz==null, just use the repository ID from the stub |
aoqi@0 | 722 | // 2. If clz is a stub class, just use it as a static factory. |
aoqi@0 | 723 | // clz is a stub class iff StubAdapter.isStubClass( clz ). |
aoqi@0 | 724 | // In addition, clz is a IDL stub class iff |
aoqi@0 | 725 | // IDLEntity.class.isAssignableFrom( clz ). |
aoqi@0 | 726 | // 3. If clz is an interface, use it to create the appropriate |
aoqi@0 | 727 | // stub factory. |
aoqi@0 | 728 | public org.omg.CORBA.Object read_Object(Class clz) |
aoqi@0 | 729 | { |
aoqi@0 | 730 | // In any case, we must first read the IOR. |
aoqi@0 | 731 | IOR ior = IORFactories.makeIOR(parent) ; |
aoqi@0 | 732 | if (ior.isNil()) |
aoqi@0 | 733 | return null ; |
aoqi@0 | 734 | |
aoqi@0 | 735 | PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ; |
aoqi@0 | 736 | String codeBase = ior.getProfile().getCodebase() ; |
aoqi@0 | 737 | PresentationManager.StubFactory stubFactory = null ; |
aoqi@0 | 738 | |
aoqi@0 | 739 | if (clz == null) { |
aoqi@0 | 740 | RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ; |
aoqi@0 | 741 | String className = rid.getClassName() ; |
aoqi@0 | 742 | boolean isIDLInterface = rid.isIDLType() ; |
aoqi@0 | 743 | |
aoqi@0 | 744 | if (className == null || className.equals( "" )) |
aoqi@0 | 745 | stubFactory = null ; |
aoqi@0 | 746 | else |
aoqi@0 | 747 | try { |
aoqi@0 | 748 | stubFactory = sff.createStubFactory( className, |
aoqi@0 | 749 | isIDLInterface, codeBase, (Class)null, |
aoqi@0 | 750 | (ClassLoader)null ); |
aoqi@0 | 751 | } catch (Exception exc) { |
aoqi@0 | 752 | // Could not create stubFactory, so use null. |
aoqi@0 | 753 | // XXX stubFactory handling is still too complex: |
aoqi@0 | 754 | // Can we resolve the stubFactory question once in |
aoqi@0 | 755 | // a single place? |
aoqi@0 | 756 | stubFactory = null ; |
aoqi@0 | 757 | } |
aoqi@0 | 758 | } else if (StubAdapter.isStubClass( clz )) { |
aoqi@0 | 759 | stubFactory = PresentationDefaults.makeStaticStubFactory( |
aoqi@0 | 760 | clz ) ; |
aoqi@0 | 761 | } else { |
aoqi@0 | 762 | // clz is an interface class |
aoqi@0 | 763 | boolean isIDL = IDLEntity.class.isAssignableFrom( clz ) ; |
aoqi@0 | 764 | |
aoqi@0 | 765 | stubFactory = sff.createStubFactory( clz.getName(), |
aoqi@0 | 766 | isIDL, codeBase, clz, clz.getClassLoader() ) ; |
aoqi@0 | 767 | } |
aoqi@0 | 768 | |
aoqi@0 | 769 | return internalIORToObject( ior, stubFactory, orb ) ; |
aoqi@0 | 770 | } |
aoqi@0 | 771 | |
aoqi@0 | 772 | /* |
aoqi@0 | 773 | * This is used as a general utility (e.g., the PortableInterceptor |
aoqi@0 | 774 | * implementation uses it. If stubFactory is null, the ior's |
aoqi@0 | 775 | * IIOPProfile must support getServant. |
aoqi@0 | 776 | */ |
aoqi@0 | 777 | public static org.omg.CORBA.Object internalIORToObject( |
aoqi@0 | 778 | IOR ior, PresentationManager.StubFactory stubFactory, ORB orb) |
aoqi@0 | 779 | { |
aoqi@0 | 780 | ORBUtilSystemException wrapper = ORBUtilSystemException.get( |
aoqi@0 | 781 | (ORB)orb, CORBALogDomains.RPC_ENCODING ) ; |
aoqi@0 | 782 | |
aoqi@0 | 783 | java.lang.Object servant = ior.getProfile().getServant() ; |
aoqi@0 | 784 | if (servant != null ) { |
aoqi@0 | 785 | if (servant instanceof Tie) { |
aoqi@0 | 786 | String codebase = ior.getProfile().getCodebase(); |
aoqi@0 | 787 | org.omg.CORBA.Object objref = (org.omg.CORBA.Object) |
aoqi@0 | 788 | Utility.loadStub( (Tie)servant, stubFactory, codebase, |
aoqi@0 | 789 | false); |
aoqi@0 | 790 | |
aoqi@0 | 791 | // If we managed to load a stub, return it, otherwise we |
aoqi@0 | 792 | // must fail... |
aoqi@0 | 793 | if (objref != null) { |
aoqi@0 | 794 | return objref; |
aoqi@0 | 795 | } else { |
aoqi@0 | 796 | throw wrapper.readObjectException() ; |
aoqi@0 | 797 | } |
aoqi@0 | 798 | } else if (servant instanceof org.omg.CORBA.Object) { |
aoqi@0 | 799 | if (!(servant instanceof |
aoqi@0 | 800 | org.omg.CORBA.portable.InvokeHandler)) { |
aoqi@0 | 801 | return (org.omg.CORBA.Object) servant; |
aoqi@0 | 802 | } |
aoqi@0 | 803 | } else |
aoqi@0 | 804 | throw wrapper.badServantReadObject() ; |
aoqi@0 | 805 | } |
aoqi@0 | 806 | |
aoqi@0 | 807 | CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ; |
aoqi@0 | 808 | org.omg.CORBA.Object objref = null ; |
aoqi@0 | 809 | try { |
aoqi@0 | 810 | objref = stubFactory.makeStub() ; |
aoqi@0 | 811 | } catch (Throwable e) { |
aoqi@0 | 812 | wrapper.stubCreateError( e ) ; |
aoqi@0 | 813 | |
aoqi@0 | 814 | if (e instanceof ThreadDeath) { |
aoqi@0 | 815 | throw (ThreadDeath) e; |
aoqi@0 | 816 | } |
aoqi@0 | 817 | |
aoqi@0 | 818 | // Return the "default" stub... |
aoqi@0 | 819 | objref = new CORBAObjectImpl() ; |
aoqi@0 | 820 | } |
aoqi@0 | 821 | |
aoqi@0 | 822 | StubAdapter.setDelegate( objref, del ) ; |
aoqi@0 | 823 | return objref; |
aoqi@0 | 824 | } |
aoqi@0 | 825 | |
aoqi@0 | 826 | public java.lang.Object read_abstract_interface() |
aoqi@0 | 827 | { |
aoqi@0 | 828 | return read_abstract_interface(null); |
aoqi@0 | 829 | } |
aoqi@0 | 830 | |
aoqi@0 | 831 | public java.lang.Object read_abstract_interface(java.lang.Class clz) |
aoqi@0 | 832 | { |
aoqi@0 | 833 | boolean object = read_boolean(); |
aoqi@0 | 834 | |
aoqi@0 | 835 | if (object) { |
aoqi@0 | 836 | return read_Object(clz); |
aoqi@0 | 837 | } else { |
aoqi@0 | 838 | return read_value(); |
aoqi@0 | 839 | } |
aoqi@0 | 840 | } |
aoqi@0 | 841 | |
aoqi@0 | 842 | public Serializable read_value() |
aoqi@0 | 843 | { |
aoqi@0 | 844 | return read_value((Class)null); |
aoqi@0 | 845 | } |
aoqi@0 | 846 | |
aoqi@0 | 847 | private Serializable handleIndirection() { |
aoqi@0 | 848 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 849 | if (valueCache != null && valueCache.containsVal(indirection)) { |
aoqi@0 | 850 | |
aoqi@0 | 851 | java.io.Serializable cachedValue |
aoqi@0 | 852 | = (java.io.Serializable)valueCache.getKey(indirection); |
aoqi@0 | 853 | return cachedValue; |
aoqi@0 | 854 | } else { |
aoqi@0 | 855 | // In RMI-IIOP the ValueHandler will recognize this |
aoqi@0 | 856 | // exception and use the provided indirection value |
aoqi@0 | 857 | // to lookup a possible indirection to an object |
aoqi@0 | 858 | // currently on the deserialization stack. |
aoqi@0 | 859 | throw new IndirectionException(indirection); |
aoqi@0 | 860 | } |
aoqi@0 | 861 | } |
aoqi@0 | 862 | |
aoqi@0 | 863 | private String readRepositoryIds(int valueTag, |
aoqi@0 | 864 | Class expectedType, |
aoqi@0 | 865 | String expectedTypeRepId) { |
aoqi@0 | 866 | return readRepositoryIds(valueTag, expectedType, |
aoqi@0 | 867 | expectedTypeRepId, null); |
aoqi@0 | 868 | } |
aoqi@0 | 869 | |
aoqi@0 | 870 | /** |
aoqi@0 | 871 | * Examines the valuetag to see how many (if any) repository IDs |
aoqi@0 | 872 | * are present on the wire. If no repository ID information |
aoqi@0 | 873 | * is on the wire but the expectedType or expectedTypeRepId |
aoqi@0 | 874 | * is known, it will return one of those (favoring the |
aoqi@0 | 875 | * expectedType's repId). Failing that, it uses the supplied |
aoqi@0 | 876 | * BoxedValueHelper to obtain the repository ID, as a last resort. |
aoqi@0 | 877 | */ |
aoqi@0 | 878 | private String readRepositoryIds(int valueTag, |
aoqi@0 | 879 | Class expectedType, |
aoqi@0 | 880 | String expectedTypeRepId, |
aoqi@0 | 881 | BoxedValueHelper factory) { |
aoqi@0 | 882 | switch(repIdUtil.getTypeInfo(valueTag)) { |
aoqi@0 | 883 | case RepositoryIdUtility.NO_TYPE_INFO : |
aoqi@0 | 884 | // Throw an exception if we have no repository ID info and |
aoqi@0 | 885 | // no expectedType to work with. Otherwise, how would we |
aoqi@0 | 886 | // know what to unmarshal? |
aoqi@0 | 887 | if (expectedType == null) { |
aoqi@0 | 888 | if (expectedTypeRepId != null) { |
aoqi@0 | 889 | return expectedTypeRepId; |
aoqi@0 | 890 | } else if (factory != null) { |
aoqi@0 | 891 | return factory.get_id(); |
aoqi@0 | 892 | } else { |
aoqi@0 | 893 | throw wrapper.expectedTypeNullAndNoRepId( |
aoqi@0 | 894 | CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 895 | } |
aoqi@0 | 896 | } |
aoqi@0 | 897 | return repIdStrs.createForAnyType(expectedType); |
aoqi@0 | 898 | case RepositoryIdUtility.SINGLE_REP_TYPE_INFO : |
aoqi@0 | 899 | return read_repositoryId(); |
aoqi@0 | 900 | case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO : |
aoqi@0 | 901 | return read_repositoryIds(); |
aoqi@0 | 902 | default: |
aoqi@0 | 903 | throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 904 | Integer.toHexString(valueTag) ) ; |
aoqi@0 | 905 | } |
aoqi@0 | 906 | } |
aoqi@0 | 907 | |
aoqi@0 | 908 | public Serializable read_value(Class expectedType) { |
aoqi@0 | 909 | |
aoqi@0 | 910 | // Read value tag |
aoqi@0 | 911 | int vType = readValueTag(); |
aoqi@0 | 912 | |
aoqi@0 | 913 | // Is value null? |
aoqi@0 | 914 | if (vType == 0) |
aoqi@0 | 915 | return null; |
aoqi@0 | 916 | |
aoqi@0 | 917 | // Is this an indirection to a previously |
aoqi@0 | 918 | // read valuetype? |
aoqi@0 | 919 | if (vType == 0xffffffff) |
aoqi@0 | 920 | return handleIndirection(); |
aoqi@0 | 921 | |
aoqi@0 | 922 | // Save where this valuetype started so we |
aoqi@0 | 923 | // can put it in the indirection valueCache |
aoqi@0 | 924 | // later |
aoqi@0 | 925 | int indirection = get_offset() - 4; |
aoqi@0 | 926 | |
aoqi@0 | 927 | // Need to save this special marker variable |
aoqi@0 | 928 | // to restore its value during recursion |
aoqi@0 | 929 | boolean saveIsChunked = isChunked; |
aoqi@0 | 930 | |
aoqi@0 | 931 | isChunked = repIdUtil.isChunkedEncoding(vType); |
aoqi@0 | 932 | |
aoqi@0 | 933 | java.lang.Object value = null; |
aoqi@0 | 934 | |
aoqi@0 | 935 | String codebase_URL = null; |
aoqi@0 | 936 | if (repIdUtil.isCodeBasePresent(vType)) { |
aoqi@0 | 937 | codebase_URL = read_codebase_URL(); |
aoqi@0 | 938 | } |
aoqi@0 | 939 | |
aoqi@0 | 940 | // Read repository id(s) |
aoqi@0 | 941 | String repositoryIDString |
aoqi@0 | 942 | = readRepositoryIds(vType, expectedType, null); |
aoqi@0 | 943 | |
aoqi@0 | 944 | // If isChunked was determined to be true based |
aoqi@0 | 945 | // on the valuetag, this will read a chunk length |
aoqi@0 | 946 | start_block(); |
aoqi@0 | 947 | |
aoqi@0 | 948 | // Remember that end_flag keeps track of all nested |
aoqi@0 | 949 | // valuetypes and is used for older ORBs |
aoqi@0 | 950 | end_flag--; |
aoqi@0 | 951 | if (isChunked) |
aoqi@0 | 952 | chunkedValueNestingLevel--; |
aoqi@0 | 953 | |
aoqi@0 | 954 | if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) { |
aoqi@0 | 955 | value = read_wstring(); |
aoqi@0 | 956 | } else |
aoqi@0 | 957 | if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) { |
aoqi@0 | 958 | // read in the class whether with the old ClassDesc or the |
aoqi@0 | 959 | // new one |
aoqi@0 | 960 | value = readClass(); |
aoqi@0 | 961 | } else { |
aoqi@0 | 962 | |
aoqi@0 | 963 | Class valueClass = expectedType; |
aoqi@0 | 964 | |
aoqi@0 | 965 | // By this point, either the expectedType or repositoryIDString |
aoqi@0 | 966 | // is guaranteed to be non-null. |
aoqi@0 | 967 | if (expectedType == null || |
aoqi@0 | 968 | !repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) { |
aoqi@0 | 969 | |
aoqi@0 | 970 | valueClass = getClassFromString(repositoryIDString, |
aoqi@0 | 971 | codebase_URL, |
aoqi@0 | 972 | expectedType); |
aoqi@0 | 973 | } |
aoqi@0 | 974 | |
aoqi@0 | 975 | if (valueClass == null) { |
aoqi@0 | 976 | // No point attempting to use value handler below, since the |
aoqi@0 | 977 | // class information is not available. |
aoqi@0 | 978 | throw wrapper.couldNotFindClass( |
aoqi@0 | 979 | CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 980 | new ClassNotFoundException()); |
aoqi@0 | 981 | } |
aoqi@0 | 982 | |
aoqi@0 | 983 | if (valueClass != null && |
aoqi@0 | 984 | org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) { |
aoqi@0 | 985 | |
aoqi@0 | 986 | value = readIDLValue(indirection, |
aoqi@0 | 987 | repositoryIDString, |
aoqi@0 | 988 | valueClass, |
aoqi@0 | 989 | codebase_URL); |
aoqi@0 | 990 | |
aoqi@0 | 991 | } else { |
aoqi@0 | 992 | |
aoqi@0 | 993 | // Must be some form of RMI-IIOP valuetype |
aoqi@0 | 994 | |
aoqi@0 | 995 | try { |
aoqi@0 | 996 | if (valueHandler == null) |
aoqi@0 | 997 | valueHandler = ORBUtility.createValueHandler(); |
aoqi@0 | 998 | |
aoqi@0 | 999 | value = valueHandler.readValue(parent, |
aoqi@0 | 1000 | indirection, |
aoqi@0 | 1001 | valueClass, |
aoqi@0 | 1002 | repositoryIDString, |
aoqi@0 | 1003 | getCodeBase()); |
aoqi@0 | 1004 | |
aoqi@0 | 1005 | } catch(SystemException sysEx) { |
aoqi@0 | 1006 | // Just rethrow any CORBA system exceptions |
aoqi@0 | 1007 | // that come out of the ValueHandler |
aoqi@0 | 1008 | throw sysEx; |
aoqi@0 | 1009 | } catch(Exception ex) { |
aoqi@0 | 1010 | throw wrapper.valuehandlerReadException( |
aoqi@0 | 1011 | CompletionStatus.COMPLETED_MAYBE, ex ) ; |
aoqi@0 | 1012 | } catch(Error e) { |
aoqi@0 | 1013 | throw wrapper.valuehandlerReadError( |
aoqi@0 | 1014 | CompletionStatus.COMPLETED_MAYBE, e ) ; |
aoqi@0 | 1015 | } |
aoqi@0 | 1016 | } |
aoqi@0 | 1017 | } |
aoqi@0 | 1018 | |
aoqi@0 | 1019 | // Skip any remaining chunks until we get to |
aoqi@0 | 1020 | // an end tag or a valuetag. If we see a valuetag, |
aoqi@0 | 1021 | // that means there was another valuetype in the sender's |
aoqi@0 | 1022 | // version of this class that we need to skip over. |
aoqi@0 | 1023 | handleEndOfValue(); |
aoqi@0 | 1024 | |
aoqi@0 | 1025 | // Read and process the end tag if we're chunking. |
aoqi@0 | 1026 | // Assumes that we're at the position of the end tag |
aoqi@0 | 1027 | // (handleEndOfValue should assure this) |
aoqi@0 | 1028 | readEndTag(); |
aoqi@0 | 1029 | |
aoqi@0 | 1030 | // Cache the valuetype that we read |
aoqi@0 | 1031 | if (valueCache == null) |
aoqi@0 | 1032 | valueCache = new CacheTable(orb,false); |
aoqi@0 | 1033 | valueCache.put(value, indirection); |
aoqi@0 | 1034 | |
aoqi@0 | 1035 | // Allow for possible continuation chunk. |
aoqi@0 | 1036 | // If we're a nested valuetype inside of a chunked |
aoqi@0 | 1037 | // valuetype, and that enclosing valuetype has |
aoqi@0 | 1038 | // more data to write, it will need to have this |
aoqi@0 | 1039 | // new chunk begin after we wrote our end tag. |
aoqi@0 | 1040 | isChunked = saveIsChunked; |
aoqi@0 | 1041 | start_block(); |
aoqi@0 | 1042 | |
aoqi@0 | 1043 | return (java.io.Serializable)value; |
aoqi@0 | 1044 | } |
aoqi@0 | 1045 | |
aoqi@0 | 1046 | public Serializable read_value(BoxedValueHelper factory) { |
aoqi@0 | 1047 | |
aoqi@0 | 1048 | // Read value tag |
aoqi@0 | 1049 | int vType = readValueTag(); |
aoqi@0 | 1050 | |
aoqi@0 | 1051 | if (vType == 0) |
aoqi@0 | 1052 | return null; // value is null |
aoqi@0 | 1053 | else if (vType == 0xffffffff) { // Indirection tag |
aoqi@0 | 1054 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 1055 | if (valueCache != null && valueCache.containsVal(indirection)) |
aoqi@0 | 1056 | { |
aoqi@0 | 1057 | java.io.Serializable cachedValue = |
aoqi@0 | 1058 | (java.io.Serializable)valueCache.getKey(indirection); |
aoqi@0 | 1059 | return cachedValue; |
aoqi@0 | 1060 | } |
aoqi@0 | 1061 | else { |
aoqi@0 | 1062 | throw new IndirectionException(indirection); |
aoqi@0 | 1063 | } |
aoqi@0 | 1064 | } |
aoqi@0 | 1065 | else { |
aoqi@0 | 1066 | int indirection = get_offset() - 4; |
aoqi@0 | 1067 | |
aoqi@0 | 1068 | // end_block(); |
aoqi@0 | 1069 | |
aoqi@0 | 1070 | boolean saveIsChunked = isChunked; |
aoqi@0 | 1071 | isChunked = repIdUtil.isChunkedEncoding(vType); |
aoqi@0 | 1072 | |
aoqi@0 | 1073 | java.lang.Object value = null; |
aoqi@0 | 1074 | |
aoqi@0 | 1075 | String codebase_URL = null; |
aoqi@0 | 1076 | if (repIdUtil.isCodeBasePresent(vType)){ |
aoqi@0 | 1077 | codebase_URL = read_codebase_URL(); |
aoqi@0 | 1078 | } |
aoqi@0 | 1079 | |
aoqi@0 | 1080 | // Read repository id |
aoqi@0 | 1081 | String repositoryIDString |
aoqi@0 | 1082 | = readRepositoryIds(vType, null, null, factory); |
aoqi@0 | 1083 | |
aoqi@0 | 1084 | // Compare rep. ids to see if we should use passed helper |
aoqi@0 | 1085 | if (!repositoryIDString.equals(factory.get_id())) |
aoqi@0 | 1086 | factory = Utility.getHelper(null, codebase_URL, repositoryIDString); |
aoqi@0 | 1087 | |
aoqi@0 | 1088 | start_block(); |
aoqi@0 | 1089 | end_flag--; |
aoqi@0 | 1090 | if (isChunked) |
aoqi@0 | 1091 | chunkedValueNestingLevel--; |
aoqi@0 | 1092 | |
aoqi@0 | 1093 | if (factory instanceof ValueHelper) { |
aoqi@0 | 1094 | value = readIDLValueWithHelper((ValueHelper)factory, indirection); |
aoqi@0 | 1095 | } else { |
aoqi@0 | 1096 | valueIndirection = indirection; // for callback |
aoqi@0 | 1097 | value = factory.read_value(parent); |
aoqi@0 | 1098 | } |
aoqi@0 | 1099 | |
aoqi@0 | 1100 | handleEndOfValue(); |
aoqi@0 | 1101 | readEndTag(); |
aoqi@0 | 1102 | |
aoqi@0 | 1103 | // Put into valueCache |
aoqi@0 | 1104 | if (valueCache == null) |
aoqi@0 | 1105 | valueCache = new CacheTable(orb,false); |
aoqi@0 | 1106 | valueCache.put(value, indirection); |
aoqi@0 | 1107 | |
aoqi@0 | 1108 | // allow for possible continuation chunk |
aoqi@0 | 1109 | isChunked = saveIsChunked; |
aoqi@0 | 1110 | start_block(); |
aoqi@0 | 1111 | |
aoqi@0 | 1112 | return (java.io.Serializable)value; |
aoqi@0 | 1113 | } |
aoqi@0 | 1114 | } |
aoqi@0 | 1115 | |
aoqi@0 | 1116 | private boolean isCustomType(ValueHelper helper) { |
aoqi@0 | 1117 | try{ |
aoqi@0 | 1118 | TypeCode tc = helper.get_type(); |
aoqi@0 | 1119 | int kind = tc.kind().value(); |
aoqi@0 | 1120 | if (kind == TCKind._tk_value) { |
aoqi@0 | 1121 | return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value); |
aoqi@0 | 1122 | } |
aoqi@0 | 1123 | } catch(BadKind ex) { |
aoqi@0 | 1124 | throw wrapper.badKind(ex) ; |
aoqi@0 | 1125 | } |
aoqi@0 | 1126 | |
aoqi@0 | 1127 | return false; |
aoqi@0 | 1128 | } |
aoqi@0 | 1129 | |
aoqi@0 | 1130 | // This method is actually called indirectly by |
aoqi@0 | 1131 | // read_value(String repositoryId). |
aoqi@0 | 1132 | // Therefore, it is not a truly independent read call that handles |
aoqi@0 | 1133 | // header information itself. |
aoqi@0 | 1134 | public java.io.Serializable read_value(java.io.Serializable value) { |
aoqi@0 | 1135 | |
aoqi@0 | 1136 | // Put into valueCache using valueIndirection |
aoqi@0 | 1137 | if (valueCache == null) |
aoqi@0 | 1138 | valueCache = new CacheTable(orb,false); |
aoqi@0 | 1139 | valueCache.put(value, valueIndirection); |
aoqi@0 | 1140 | |
aoqi@0 | 1141 | if (value instanceof StreamableValue) |
aoqi@0 | 1142 | ((StreamableValue)value)._read(parent); |
aoqi@0 | 1143 | else if (value instanceof CustomValue) |
aoqi@0 | 1144 | ((CustomValue)value).unmarshal(parent); |
aoqi@0 | 1145 | |
aoqi@0 | 1146 | return value; |
aoqi@0 | 1147 | } |
aoqi@0 | 1148 | |
aoqi@0 | 1149 | public java.io.Serializable read_value(java.lang.String repositoryId) { |
aoqi@0 | 1150 | |
aoqi@0 | 1151 | // if (inBlock) |
aoqi@0 | 1152 | // end_block(); |
aoqi@0 | 1153 | |
aoqi@0 | 1154 | // Read value tag |
aoqi@0 | 1155 | int vType = readValueTag(); |
aoqi@0 | 1156 | |
aoqi@0 | 1157 | if (vType == 0) |
aoqi@0 | 1158 | return null; // value is null |
aoqi@0 | 1159 | else if (vType == 0xffffffff) { // Indirection tag |
aoqi@0 | 1160 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 1161 | if (valueCache != null && valueCache.containsVal(indirection)) |
aoqi@0 | 1162 | { |
aoqi@0 | 1163 | java.io.Serializable cachedValue = |
aoqi@0 | 1164 | (java.io.Serializable)valueCache.getKey(indirection); |
aoqi@0 | 1165 | return cachedValue; |
aoqi@0 | 1166 | } |
aoqi@0 | 1167 | else { |
aoqi@0 | 1168 | throw new IndirectionException(indirection); |
aoqi@0 | 1169 | } |
aoqi@0 | 1170 | } |
aoqi@0 | 1171 | else { |
aoqi@0 | 1172 | int indirection = get_offset() - 4; |
aoqi@0 | 1173 | |
aoqi@0 | 1174 | // end_block(); |
aoqi@0 | 1175 | |
aoqi@0 | 1176 | boolean saveIsChunked = isChunked; |
aoqi@0 | 1177 | isChunked = repIdUtil.isChunkedEncoding(vType); |
aoqi@0 | 1178 | |
aoqi@0 | 1179 | java.lang.Object value = null; |
aoqi@0 | 1180 | |
aoqi@0 | 1181 | String codebase_URL = null; |
aoqi@0 | 1182 | if (repIdUtil.isCodeBasePresent(vType)){ |
aoqi@0 | 1183 | codebase_URL = read_codebase_URL(); |
aoqi@0 | 1184 | } |
aoqi@0 | 1185 | |
aoqi@0 | 1186 | // Read repository id |
aoqi@0 | 1187 | String repositoryIDString |
aoqi@0 | 1188 | = readRepositoryIds(vType, null, repositoryId); |
aoqi@0 | 1189 | |
aoqi@0 | 1190 | ValueFactory factory = |
aoqi@0 | 1191 | Utility.getFactory(null, codebase_URL, orb, repositoryIDString); |
aoqi@0 | 1192 | |
aoqi@0 | 1193 | start_block(); |
aoqi@0 | 1194 | end_flag--; |
aoqi@0 | 1195 | if (isChunked) |
aoqi@0 | 1196 | chunkedValueNestingLevel--; |
aoqi@0 | 1197 | |
aoqi@0 | 1198 | valueIndirection = indirection; // for callback |
aoqi@0 | 1199 | value = factory.read_value(parent); |
aoqi@0 | 1200 | |
aoqi@0 | 1201 | handleEndOfValue(); |
aoqi@0 | 1202 | readEndTag(); |
aoqi@0 | 1203 | |
aoqi@0 | 1204 | // Put into valueCache |
aoqi@0 | 1205 | if (valueCache == null) |
aoqi@0 | 1206 | valueCache = new CacheTable(orb,false); |
aoqi@0 | 1207 | valueCache.put(value, indirection); |
aoqi@0 | 1208 | |
aoqi@0 | 1209 | // allow for possible continuation chunk |
aoqi@0 | 1210 | isChunked = saveIsChunked; |
aoqi@0 | 1211 | start_block(); |
aoqi@0 | 1212 | |
aoqi@0 | 1213 | return (java.io.Serializable)value; |
aoqi@0 | 1214 | } |
aoqi@0 | 1215 | } |
aoqi@0 | 1216 | |
aoqi@0 | 1217 | private Class readClass() { |
aoqi@0 | 1218 | |
aoqi@0 | 1219 | String codebases = null, classRepId = null; |
aoqi@0 | 1220 | |
aoqi@0 | 1221 | if (orb == null || |
aoqi@0 | 1222 | ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || |
aoqi@0 | 1223 | ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { |
aoqi@0 | 1224 | |
aoqi@0 | 1225 | codebases = (String)read_value(java.lang.String.class); |
aoqi@0 | 1226 | classRepId = (String)read_value(java.lang.String.class); |
aoqi@0 | 1227 | } else { |
aoqi@0 | 1228 | // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID |
aoqi@0 | 1229 | // and codebase strings in the wrong order. |
aoqi@0 | 1230 | classRepId = (String)read_value(java.lang.String.class); |
aoqi@0 | 1231 | codebases = (String)read_value(java.lang.String.class); |
aoqi@0 | 1232 | } |
aoqi@0 | 1233 | |
aoqi@0 | 1234 | if (debug) { |
aoqi@0 | 1235 | dprint("readClass codebases: " |
aoqi@0 | 1236 | + codebases |
aoqi@0 | 1237 | + " rep Id: " |
aoqi@0 | 1238 | + classRepId); |
aoqi@0 | 1239 | } |
aoqi@0 | 1240 | |
aoqi@0 | 1241 | Class cl = null; |
aoqi@0 | 1242 | |
aoqi@0 | 1243 | RepositoryIdInterface repositoryID |
aoqi@0 | 1244 | = repIdStrs.getFromString(classRepId); |
aoqi@0 | 1245 | |
aoqi@0 | 1246 | try { |
aoqi@0 | 1247 | cl = repositoryID.getClassFromType(codebases); |
aoqi@0 | 1248 | } catch(ClassNotFoundException cnfe) { |
aoqi@0 | 1249 | throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1250 | cnfe, repositoryID.getClassName() ) ; |
aoqi@0 | 1251 | } catch(MalformedURLException me) { |
aoqi@0 | 1252 | throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1253 | me, repositoryID.getClassName(), codebases ) ; |
aoqi@0 | 1254 | } |
aoqi@0 | 1255 | |
aoqi@0 | 1256 | return cl; |
aoqi@0 | 1257 | } |
aoqi@0 | 1258 | |
aoqi@0 | 1259 | private java.lang.Object readIDLValueWithHelper(ValueHelper helper, int indirection) |
aoqi@0 | 1260 | { |
aoqi@0 | 1261 | // look for two-argument static read method |
aoqi@0 | 1262 | Method readMethod; |
aoqi@0 | 1263 | try { |
aoqi@0 | 1264 | Class argTypes[] = {org.omg.CORBA.portable.InputStream.class, helper.get_class()}; |
aoqi@0 | 1265 | readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes); |
aoqi@0 | 1266 | } |
aoqi@0 | 1267 | catch(NoSuchMethodException nsme) { // must be boxed value helper |
aoqi@0 | 1268 | java.lang.Object result = helper.read_value(parent); |
aoqi@0 | 1269 | return result; |
aoqi@0 | 1270 | } |
aoqi@0 | 1271 | |
aoqi@0 | 1272 | // found two-argument read method, so must be non-boxed value... |
aoqi@0 | 1273 | // ...create a blank instance |
aoqi@0 | 1274 | java.lang.Object val = null; |
aoqi@0 | 1275 | try { |
aoqi@0 | 1276 | val = helper.get_class().newInstance(); |
aoqi@0 | 1277 | } catch(java.lang.InstantiationException ie) { |
aoqi@0 | 1278 | throw wrapper.couldNotInstantiateHelper( ie, |
aoqi@0 | 1279 | helper.get_class() ) ; |
aoqi@0 | 1280 | } catch(IllegalAccessException iae){ |
aoqi@0 | 1281 | // Value's constructor is protected or private |
aoqi@0 | 1282 | // |
aoqi@0 | 1283 | // So, use the helper to read the value. |
aoqi@0 | 1284 | // |
aoqi@0 | 1285 | // NOTE : This means that in this particular case a recursive ref. |
aoqi@0 | 1286 | // would fail. |
aoqi@0 | 1287 | return helper.read_value(parent); |
aoqi@0 | 1288 | } |
aoqi@0 | 1289 | |
aoqi@0 | 1290 | // add blank instance to cache table |
aoqi@0 | 1291 | if (valueCache == null) |
aoqi@0 | 1292 | valueCache = new CacheTable(orb,false); |
aoqi@0 | 1293 | valueCache.put(val, indirection); |
aoqi@0 | 1294 | |
aoqi@0 | 1295 | // if custom type, call unmarshal method |
aoqi@0 | 1296 | if (val instanceof CustomMarshal && isCustomType(helper)) { |
aoqi@0 | 1297 | ((CustomMarshal)val).unmarshal(parent); |
aoqi@0 | 1298 | return val; |
aoqi@0 | 1299 | } |
aoqi@0 | 1300 | |
aoqi@0 | 1301 | // call two-argument read method using reflection |
aoqi@0 | 1302 | try { |
aoqi@0 | 1303 | java.lang.Object args[] = {parent, val}; |
aoqi@0 | 1304 | readMethod.invoke(helper, args); |
aoqi@0 | 1305 | return val; |
aoqi@0 | 1306 | } catch(IllegalAccessException iae2) { |
aoqi@0 | 1307 | throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ; |
aoqi@0 | 1308 | } catch(InvocationTargetException ite){ |
aoqi@0 | 1309 | throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ; |
aoqi@0 | 1310 | } |
aoqi@0 | 1311 | } |
aoqi@0 | 1312 | |
aoqi@0 | 1313 | private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase) |
aoqi@0 | 1314 | { |
aoqi@0 | 1315 | Class cls = null ; |
aoqi@0 | 1316 | |
aoqi@0 | 1317 | try { |
aoqi@0 | 1318 | ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader()); |
aoqi@0 | 1319 | |
aoqi@0 | 1320 | cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase, |
aoqi@0 | 1321 | clazzLoader, clazz, clazzLoader); |
aoqi@0 | 1322 | final Class helperClass = cls ; |
aoqi@0 | 1323 | |
aoqi@0 | 1324 | final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class}; |
aoqi@0 | 1325 | |
aoqi@0 | 1326 | // getDeclaredMethod requires RuntimePermission accessDeclaredMembers |
aoqi@0 | 1327 | // if a different class loader is used (even though the javadoc says otherwise) |
aoqi@0 | 1328 | Method readMethod = null; |
aoqi@0 | 1329 | try { |
aoqi@0 | 1330 | readMethod = (Method)AccessController.doPrivileged( |
aoqi@0 | 1331 | new PrivilegedExceptionAction() { |
aoqi@0 | 1332 | public java.lang.Object run() throws NoSuchMethodException { |
aoqi@0 | 1333 | return helperClass.getDeclaredMethod(kReadMethod, argTypes); |
aoqi@0 | 1334 | } |
aoqi@0 | 1335 | } |
aoqi@0 | 1336 | ); |
aoqi@0 | 1337 | } catch (PrivilegedActionException pae) { |
aoqi@0 | 1338 | // this gets caught below |
aoqi@0 | 1339 | throw (NoSuchMethodException)pae.getException(); |
aoqi@0 | 1340 | } |
aoqi@0 | 1341 | |
aoqi@0 | 1342 | java.lang.Object args[] = {parent}; |
aoqi@0 | 1343 | return readMethod.invoke(null, args); |
aoqi@0 | 1344 | |
aoqi@0 | 1345 | } catch (ClassNotFoundException cnfe) { |
aoqi@0 | 1346 | throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ; |
aoqi@0 | 1347 | } catch(NoSuchMethodException nsme) { |
aoqi@0 | 1348 | throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ; |
aoqi@0 | 1349 | } catch(IllegalAccessException iae) { |
aoqi@0 | 1350 | throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ; |
aoqi@0 | 1351 | } catch(InvocationTargetException ite) { |
aoqi@0 | 1352 | throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ; |
aoqi@0 | 1353 | } |
aoqi@0 | 1354 | } |
aoqi@0 | 1355 | |
aoqi@0 | 1356 | private java.lang.Object readIDLValue(int indirection, String repId, |
aoqi@0 | 1357 | Class clazz, String codebase) |
aoqi@0 | 1358 | { |
aoqi@0 | 1359 | ValueFactory factory ; |
aoqi@0 | 1360 | |
aoqi@0 | 1361 | // Always try to find a ValueFactory first, as required by the spec. |
aoqi@0 | 1362 | // There are some complications here in the IDL 3.0 mapping (see 1.13.8), |
aoqi@0 | 1363 | // but basically we must always be able to override the DefaultFactory |
aoqi@0 | 1364 | // or Helper mappings that are also used. This appears to be the case |
aoqi@0 | 1365 | // even in the boxed value cases. The original code only did the lookup |
aoqi@0 | 1366 | // in the case of class implementing either StreamableValue or CustomValue, |
aoqi@0 | 1367 | // but abstract valuetypes only implement ValueBase, and really require |
aoqi@0 | 1368 | // the use of the repId to find a factory (including the DefaultFactory). |
aoqi@0 | 1369 | try { |
aoqi@0 | 1370 | // use new-style OBV support (factory object) |
aoqi@0 | 1371 | factory = Utility.getFactory(clazz, codebase, orb, repId); |
aoqi@0 | 1372 | } catch (MARSHAL marshal) { |
aoqi@0 | 1373 | // XXX log marshal at one of the INFO levels |
aoqi@0 | 1374 | |
aoqi@0 | 1375 | // Could not get a factory, so try alternatives |
aoqi@0 | 1376 | if (!StreamableValue.class.isAssignableFrom(clazz) && |
aoqi@0 | 1377 | !CustomValue.class.isAssignableFrom(clazz) && |
aoqi@0 | 1378 | ValueBase.class.isAssignableFrom(clazz)) { |
aoqi@0 | 1379 | // use old-style OBV support (helper object) |
aoqi@0 | 1380 | BoxedValueHelper helper = Utility.getHelper(clazz, codebase, repId); |
aoqi@0 | 1381 | if (helper instanceof ValueHelper) |
aoqi@0 | 1382 | return readIDLValueWithHelper((ValueHelper)helper, indirection); |
aoqi@0 | 1383 | else |
aoqi@0 | 1384 | return helper.read_value(parent); |
aoqi@0 | 1385 | } else { |
aoqi@0 | 1386 | // must be a boxed IDLEntity, so make a reflective call to the |
aoqi@0 | 1387 | // helper's static read method... |
aoqi@0 | 1388 | return readBoxedIDLEntity(clazz, codebase); |
aoqi@0 | 1389 | } |
aoqi@0 | 1390 | } |
aoqi@0 | 1391 | |
aoqi@0 | 1392 | // If there was no error in getting the factory, use it. |
aoqi@0 | 1393 | valueIndirection = indirection; // for callback |
aoqi@0 | 1394 | return factory.read_value(parent); |
aoqi@0 | 1395 | } |
aoqi@0 | 1396 | |
aoqi@0 | 1397 | /** |
aoqi@0 | 1398 | * End tags are only written for chunked valuetypes. |
aoqi@0 | 1399 | * |
aoqi@0 | 1400 | * Before Merlin, our ORBs wrote end tags which took into account |
aoqi@0 | 1401 | * all enclosing valuetypes. This was changed by an interop resolution |
aoqi@0 | 1402 | * (see details around chunkedValueNestingLevel) to only include |
aoqi@0 | 1403 | * enclosing chunked types. |
aoqi@0 | 1404 | * |
aoqi@0 | 1405 | * ORB versioning and end tag compaction are handled here. |
aoqi@0 | 1406 | */ |
aoqi@0 | 1407 | private void readEndTag() { |
aoqi@0 | 1408 | if (isChunked) { |
aoqi@0 | 1409 | |
aoqi@0 | 1410 | // Read the end tag |
aoqi@0 | 1411 | int anEndTag = read_long(); |
aoqi@0 | 1412 | |
aoqi@0 | 1413 | // End tags should always be negative, and the outermost |
aoqi@0 | 1414 | // enclosing chunked valuetype should have a -1 end tag. |
aoqi@0 | 1415 | // |
aoqi@0 | 1416 | // handleEndOfValue should have assured that we were |
aoqi@0 | 1417 | // at the end tag position! |
aoqi@0 | 1418 | if (anEndTag >= 0) { |
aoqi@0 | 1419 | throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1420 | new Integer(anEndTag), new Integer( get_offset() - 4 ) ) ; |
aoqi@0 | 1421 | } |
aoqi@0 | 1422 | |
aoqi@0 | 1423 | // If the ORB is null, or if we're sure we're talking to |
aoqi@0 | 1424 | // a foreign ORB, Merlin, or something more recent, we |
aoqi@0 | 1425 | // use the updated end tag computation, and are more strenuous |
aoqi@0 | 1426 | // about the values. |
aoqi@0 | 1427 | if (orb == null || |
aoqi@0 | 1428 | ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) || |
aoqi@0 | 1429 | ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) { |
aoqi@0 | 1430 | |
aoqi@0 | 1431 | // If the end tag we read was less than what we were expecting, |
aoqi@0 | 1432 | // then the sender must think it's sent more enclosing |
aoqi@0 | 1433 | // chunked valuetypes than we have. Throw an exception. |
aoqi@0 | 1434 | if (anEndTag < chunkedValueNestingLevel) |
aoqi@0 | 1435 | throw wrapper.unexpectedEnclosingValuetype( |
aoqi@0 | 1436 | CompletionStatus.COMPLETED_MAYBE, new Integer( anEndTag ), |
aoqi@0 | 1437 | new Integer( chunkedValueNestingLevel ) ) ; |
aoqi@0 | 1438 | |
aoqi@0 | 1439 | // If the end tag is bigger than what we expected, but |
aoqi@0 | 1440 | // still negative, then the sender has done some end tag |
aoqi@0 | 1441 | // compaction. We back up the stream 4 bytes so that the |
aoqi@0 | 1442 | // next time readEndTag is called, it will get down here |
aoqi@0 | 1443 | // again. Even with fragmentation, we'll always be able |
aoqi@0 | 1444 | // to do this. |
aoqi@0 | 1445 | if (anEndTag != chunkedValueNestingLevel) { |
aoqi@0 | 1446 | bbwi.position(bbwi.position() - 4); |
aoqi@0 | 1447 | } |
aoqi@0 | 1448 | |
aoqi@0 | 1449 | } else { |
aoqi@0 | 1450 | |
aoqi@0 | 1451 | // When talking to Kestrel or Ladybird, we use our old |
aoqi@0 | 1452 | // end tag rules and are less strict. If the end tag |
aoqi@0 | 1453 | // isn't what we expected, we back up, assuming |
aoqi@0 | 1454 | // compaction. |
aoqi@0 | 1455 | if (anEndTag != end_flag) { |
aoqi@0 | 1456 | bbwi.position(bbwi.position() - 4); |
aoqi@0 | 1457 | } |
aoqi@0 | 1458 | } |
aoqi@0 | 1459 | |
aoqi@0 | 1460 | // This only keeps track of the enclosing chunked |
aoqi@0 | 1461 | // valuetypes |
aoqi@0 | 1462 | chunkedValueNestingLevel++; |
aoqi@0 | 1463 | } |
aoqi@0 | 1464 | |
aoqi@0 | 1465 | // This keeps track of all enclosing valuetypes |
aoqi@0 | 1466 | end_flag++; |
aoqi@0 | 1467 | } |
aoqi@0 | 1468 | |
aoqi@0 | 1469 | protected int get_offset() { |
aoqi@0 | 1470 | return bbwi.position(); |
aoqi@0 | 1471 | } |
aoqi@0 | 1472 | |
aoqi@0 | 1473 | private void start_block() { |
aoqi@0 | 1474 | |
aoqi@0 | 1475 | // if (outerValueDone) |
aoqi@0 | 1476 | if (!isChunked) |
aoqi@0 | 1477 | return; |
aoqi@0 | 1478 | |
aoqi@0 | 1479 | // if called from alignAndCheck, need to reset blockLength |
aoqi@0 | 1480 | // to avoid an infinite recursion loop on read_long() call |
aoqi@0 | 1481 | blockLength = maxBlockLength; |
aoqi@0 | 1482 | |
aoqi@0 | 1483 | blockLength = read_long(); |
aoqi@0 | 1484 | |
aoqi@0 | 1485 | // Must remember where we began the chunk to calculate how far |
aoqi@0 | 1486 | // along we are. See notes above about chunkBeginPos. |
aoqi@0 | 1487 | |
aoqi@0 | 1488 | if (blockLength > 0 && blockLength < maxBlockLength) { |
aoqi@0 | 1489 | blockLength += get_offset(); // _REVISIT_ unsafe, should use a Java long |
aoqi@0 | 1490 | |
aoqi@0 | 1491 | // inBlock = true; |
aoqi@0 | 1492 | } else { |
aoqi@0 | 1493 | |
aoqi@0 | 1494 | // System.out.println("start_block snooped a " + Integer.toHexString(blockLength)); |
aoqi@0 | 1495 | |
aoqi@0 | 1496 | // not a chunk length field |
aoqi@0 | 1497 | blockLength = maxBlockLength; |
aoqi@0 | 1498 | |
aoqi@0 | 1499 | bbwi.position(bbwi.position() - 4); |
aoqi@0 | 1500 | } |
aoqi@0 | 1501 | } |
aoqi@0 | 1502 | |
aoqi@0 | 1503 | // Makes sure that if we were reading a chunked value, we end up |
aoqi@0 | 1504 | // at the right place in the stream, no matter how little the |
aoqi@0 | 1505 | // unmarshalling code read. |
aoqi@0 | 1506 | // |
aoqi@0 | 1507 | // After calling this method, if we are chunking, we should be |
aoqi@0 | 1508 | // in position to read the end tag. |
aoqi@0 | 1509 | private void handleEndOfValue() { |
aoqi@0 | 1510 | |
aoqi@0 | 1511 | // If we're not chunking, we don't have to worry about |
aoqi@0 | 1512 | // skipping remaining chunks or finding end tags |
aoqi@0 | 1513 | if (!isChunked) |
aoqi@0 | 1514 | return; |
aoqi@0 | 1515 | |
aoqi@0 | 1516 | // Skip any remaining chunks |
aoqi@0 | 1517 | while (blockLength != maxBlockLength) { |
aoqi@0 | 1518 | end_block(); |
aoqi@0 | 1519 | start_block(); |
aoqi@0 | 1520 | } |
aoqi@0 | 1521 | |
aoqi@0 | 1522 | // Now look for the end tag |
aoqi@0 | 1523 | |
aoqi@0 | 1524 | // This is a little wasteful since we're reading |
aoqi@0 | 1525 | // this long up to 3 times in the worst cases (once |
aoqi@0 | 1526 | // in start_block, once here, and once in readEndTag |
aoqi@0 | 1527 | // |
aoqi@0 | 1528 | // Peek next long |
aoqi@0 | 1529 | int nextLong = read_long(); |
aoqi@0 | 1530 | bbwi.position(bbwi.position() - 4); |
aoqi@0 | 1531 | |
aoqi@0 | 1532 | // We did find an end tag, so we're done. readEndTag |
aoqi@0 | 1533 | // should take care of making sure it's the correct |
aoqi@0 | 1534 | // end tag, etc. Remember that since end tags, |
aoqi@0 | 1535 | // chunk lengths, and valuetags have non overlapping |
aoqi@0 | 1536 | // ranges, we can tell by the value what the longs are. |
aoqi@0 | 1537 | if (nextLong < 0) |
aoqi@0 | 1538 | return; |
aoqi@0 | 1539 | |
aoqi@0 | 1540 | if (nextLong == 0 || nextLong >= maxBlockLength) { |
aoqi@0 | 1541 | |
aoqi@0 | 1542 | // A custom marshaled valuetype left extra data |
aoqi@0 | 1543 | // on the wire, and that data had another |
aoqi@0 | 1544 | // nested value inside of it. We've just |
aoqi@0 | 1545 | // read the value tag or null of that nested value. |
aoqi@0 | 1546 | // |
aoqi@0 | 1547 | // In an attempt to get by it, we'll try to call |
aoqi@0 | 1548 | // read_value() to get the nested value off of |
aoqi@0 | 1549 | // the wire. Afterwards, we must call handleEndOfValue |
aoqi@0 | 1550 | // recursively to read any further chunks that the containing |
aoqi@0 | 1551 | // valuetype might still have after the nested |
aoqi@0 | 1552 | // value. |
aoqi@0 | 1553 | read_value(); |
aoqi@0 | 1554 | handleEndOfValue(); |
aoqi@0 | 1555 | } else { |
aoqi@0 | 1556 | // This probably means that the code to skip chunks has |
aoqi@0 | 1557 | // an error, and ended up setting blockLength to something |
aoqi@0 | 1558 | // other than maxBlockLength even though we weren't |
aoqi@0 | 1559 | // starting a new chunk. |
aoqi@0 | 1560 | throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1561 | new Integer( nextLong ), new Integer( get_offset() ) ) ; |
aoqi@0 | 1562 | } |
aoqi@0 | 1563 | } |
aoqi@0 | 1564 | |
aoqi@0 | 1565 | private void end_block() { |
aoqi@0 | 1566 | |
aoqi@0 | 1567 | // if in a chunk, check for underflow or overflow |
aoqi@0 | 1568 | if (blockLength != maxBlockLength) { |
aoqi@0 | 1569 | if (blockLength == get_offset()) { |
aoqi@0 | 1570 | // Chunk ended correctly |
aoqi@0 | 1571 | blockLength = maxBlockLength; |
aoqi@0 | 1572 | } else { |
aoqi@0 | 1573 | // Skip over anything left by bad unmarshaling code (ex: |
aoqi@0 | 1574 | // a buggy custom unmarshaler). See handleEndOfValue. |
aoqi@0 | 1575 | if (blockLength > get_offset()) { |
aoqi@0 | 1576 | skipToOffset(blockLength); |
aoqi@0 | 1577 | } else { |
aoqi@0 | 1578 | throw wrapper.badChunkLength( new Integer( blockLength ), |
aoqi@0 | 1579 | new Integer( get_offset() ) ) ; |
aoqi@0 | 1580 | } |
aoqi@0 | 1581 | } |
aoqi@0 | 1582 | } |
aoqi@0 | 1583 | } |
aoqi@0 | 1584 | |
aoqi@0 | 1585 | private int readValueTag(){ |
aoqi@0 | 1586 | // outerValueDone = false; |
aoqi@0 | 1587 | return read_long(); |
aoqi@0 | 1588 | } |
aoqi@0 | 1589 | |
aoqi@0 | 1590 | public org.omg.CORBA.ORB orb() { |
aoqi@0 | 1591 | return orb; |
aoqi@0 | 1592 | } |
aoqi@0 | 1593 | |
aoqi@0 | 1594 | // ------------ End RMI related methods -------------------------- |
aoqi@0 | 1595 | |
aoqi@0 | 1596 | public final void read_boolean_array(boolean[] value, int offset, int length) { |
aoqi@0 | 1597 | for(int i=0; i < length; i++) { |
aoqi@0 | 1598 | value[i+offset] = read_boolean(); |
aoqi@0 | 1599 | } |
aoqi@0 | 1600 | } |
aoqi@0 | 1601 | |
aoqi@0 | 1602 | public final void read_char_array(char[] value, int offset, int length) { |
aoqi@0 | 1603 | for(int i=0; i < length; i++) { |
aoqi@0 | 1604 | value[i+offset] = read_char(); |
aoqi@0 | 1605 | } |
aoqi@0 | 1606 | } |
aoqi@0 | 1607 | |
aoqi@0 | 1608 | public final void read_wchar_array(char[] value, int offset, int length) { |
aoqi@0 | 1609 | for(int i=0; i < length; i++) { |
aoqi@0 | 1610 | value[i+offset] = read_wchar(); |
aoqi@0 | 1611 | } |
aoqi@0 | 1612 | } |
aoqi@0 | 1613 | |
aoqi@0 | 1614 | public final void read_short_array(short[] value, int offset, int length) { |
aoqi@0 | 1615 | for(int i=0; i < length; i++) { |
aoqi@0 | 1616 | value[i+offset] = read_short(); |
aoqi@0 | 1617 | } |
aoqi@0 | 1618 | } |
aoqi@0 | 1619 | |
aoqi@0 | 1620 | public final void read_ushort_array(short[] value, int offset, int length) { |
aoqi@0 | 1621 | read_short_array(value, offset, length); |
aoqi@0 | 1622 | } |
aoqi@0 | 1623 | |
aoqi@0 | 1624 | public final void read_long_array(int[] value, int offset, int length) { |
aoqi@0 | 1625 | for(int i=0; i < length; i++) { |
aoqi@0 | 1626 | value[i+offset] = read_long(); |
aoqi@0 | 1627 | } |
aoqi@0 | 1628 | } |
aoqi@0 | 1629 | |
aoqi@0 | 1630 | public final void read_ulong_array(int[] value, int offset, int length) { |
aoqi@0 | 1631 | read_long_array(value, offset, length); |
aoqi@0 | 1632 | } |
aoqi@0 | 1633 | |
aoqi@0 | 1634 | public final void read_longlong_array(long[] value, int offset, int length) { |
aoqi@0 | 1635 | for(int i=0; i < length; i++) { |
aoqi@0 | 1636 | value[i+offset] = read_longlong(); |
aoqi@0 | 1637 | } |
aoqi@0 | 1638 | } |
aoqi@0 | 1639 | |
aoqi@0 | 1640 | public final void read_ulonglong_array(long[] value, int offset, int length) { |
aoqi@0 | 1641 | read_longlong_array(value, offset, length); |
aoqi@0 | 1642 | } |
aoqi@0 | 1643 | |
aoqi@0 | 1644 | public final void read_float_array(float[] value, int offset, int length) { |
aoqi@0 | 1645 | for(int i=0; i < length; i++) { |
aoqi@0 | 1646 | value[i+offset] = read_float(); |
aoqi@0 | 1647 | } |
aoqi@0 | 1648 | } |
aoqi@0 | 1649 | |
aoqi@0 | 1650 | public final void read_double_array(double[] value, int offset, int length) { |
aoqi@0 | 1651 | for(int i=0; i < length; i++) { |
aoqi@0 | 1652 | value[i+offset] = read_double(); |
aoqi@0 | 1653 | } |
aoqi@0 | 1654 | } |
aoqi@0 | 1655 | |
aoqi@0 | 1656 | public final void read_any_array(org.omg.CORBA.Any[] value, int offset, int length) { |
aoqi@0 | 1657 | for(int i=0; i < length; i++) { |
aoqi@0 | 1658 | value[i+offset] = read_any(); |
aoqi@0 | 1659 | } |
aoqi@0 | 1660 | } |
aoqi@0 | 1661 | |
aoqi@0 | 1662 | //--------------------------------------------------------------------// |
aoqi@0 | 1663 | // CDRInputStream state management. |
aoqi@0 | 1664 | // |
aoqi@0 | 1665 | |
aoqi@0 | 1666 | /** |
aoqi@0 | 1667 | * Are we at the end of the input stream? |
aoqi@0 | 1668 | */ |
aoqi@0 | 1669 | // public final boolean isAtEnd() { |
aoqi@0 | 1670 | // return bbwi.position() == bbwi.buflen; |
aoqi@0 | 1671 | // } |
aoqi@0 | 1672 | |
aoqi@0 | 1673 | // public int available() throws IOException { |
aoqi@0 | 1674 | // return bbwi.buflen - bbwi.position(); |
aoqi@0 | 1675 | // } |
aoqi@0 | 1676 | |
aoqi@0 | 1677 | private String read_repositoryIds() { |
aoqi@0 | 1678 | |
aoqi@0 | 1679 | // Read # of repository ids |
aoqi@0 | 1680 | int numRepIds = read_long(); |
aoqi@0 | 1681 | if (numRepIds == 0xffffffff) { |
aoqi@0 | 1682 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 1683 | if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection)) |
aoqi@0 | 1684 | return (String)repositoryIdCache.getKey(indirection); |
aoqi@0 | 1685 | else |
aoqi@0 | 1686 | throw wrapper.unableToLocateRepIdArray( new Integer( indirection ) ) ; |
aoqi@0 | 1687 | } else { |
aoqi@0 | 1688 | |
aoqi@0 | 1689 | // read first array element and store it as an indirection to the whole array |
aoqi@0 | 1690 | int indirection = get_offset(); |
aoqi@0 | 1691 | String repID = read_repositoryId(); |
aoqi@0 | 1692 | if (repositoryIdCache == null) |
aoqi@0 | 1693 | repositoryIdCache = new CacheTable(orb,false); |
aoqi@0 | 1694 | repositoryIdCache.put(repID, indirection); |
aoqi@0 | 1695 | |
aoqi@0 | 1696 | // read and ignore the subsequent array elements, but put them in the |
aoqi@0 | 1697 | // indirection table in case there are later indirections back to them |
aoqi@0 | 1698 | for (int i = 1; i < numRepIds; i++) { |
aoqi@0 | 1699 | read_repositoryId(); |
aoqi@0 | 1700 | } |
aoqi@0 | 1701 | |
aoqi@0 | 1702 | return repID; |
aoqi@0 | 1703 | } |
aoqi@0 | 1704 | } |
aoqi@0 | 1705 | |
aoqi@0 | 1706 | private final String read_repositoryId() |
aoqi@0 | 1707 | { |
aoqi@0 | 1708 | String result = readStringOrIndirection(true); |
aoqi@0 | 1709 | |
aoqi@0 | 1710 | if (result == null) { // Indirection |
aoqi@0 | 1711 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 1712 | |
aoqi@0 | 1713 | if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection)) |
aoqi@0 | 1714 | return (String)repositoryIdCache.getKey(indirection); |
aoqi@0 | 1715 | else |
aoqi@0 | 1716 | throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1717 | new Integer(bbwi.position()) ) ; |
aoqi@0 | 1718 | } else { |
aoqi@0 | 1719 | if (repositoryIdCache == null) |
aoqi@0 | 1720 | repositoryIdCache = new CacheTable(orb,false); |
aoqi@0 | 1721 | repositoryIdCache.put(result, stringIndirection); |
aoqi@0 | 1722 | } |
aoqi@0 | 1723 | |
aoqi@0 | 1724 | return result ; |
aoqi@0 | 1725 | } |
aoqi@0 | 1726 | |
aoqi@0 | 1727 | private final String read_codebase_URL() |
aoqi@0 | 1728 | { |
aoqi@0 | 1729 | String result = readStringOrIndirection(true); |
aoqi@0 | 1730 | |
aoqi@0 | 1731 | if (result == null) { // Indirection |
aoqi@0 | 1732 | int indirection = read_long() + get_offset() - 4; |
aoqi@0 | 1733 | |
aoqi@0 | 1734 | if (codebaseCache != null && codebaseCache.containsVal(indirection)) |
aoqi@0 | 1735 | return (String)codebaseCache.getKey(indirection); |
aoqi@0 | 1736 | else |
aoqi@0 | 1737 | throw wrapper.badCodebaseIndirection( |
aoqi@0 | 1738 | CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 1739 | new Integer(bbwi.position()) ) ; |
aoqi@0 | 1740 | } else { |
aoqi@0 | 1741 | if (codebaseCache == null) |
aoqi@0 | 1742 | codebaseCache = new CacheTable(orb,false); |
aoqi@0 | 1743 | codebaseCache.put(result, stringIndirection); |
aoqi@0 | 1744 | } |
aoqi@0 | 1745 | |
aoqi@0 | 1746 | return result; |
aoqi@0 | 1747 | } |
aoqi@0 | 1748 | |
aoqi@0 | 1749 | /* DataInputStream methods */ |
aoqi@0 | 1750 | |
aoqi@0 | 1751 | public java.lang.Object read_Abstract () { |
aoqi@0 | 1752 | return read_abstract_interface(); |
aoqi@0 | 1753 | } |
aoqi@0 | 1754 | |
aoqi@0 | 1755 | public java.io.Serializable read_Value () { |
aoqi@0 | 1756 | return read_value(); |
aoqi@0 | 1757 | } |
aoqi@0 | 1758 | |
aoqi@0 | 1759 | public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) { |
aoqi@0 | 1760 | read_any_array(seq.value, offset, length); |
aoqi@0 | 1761 | } |
aoqi@0 | 1762 | |
aoqi@0 | 1763 | public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) { |
aoqi@0 | 1764 | read_boolean_array(seq.value, offset, length); |
aoqi@0 | 1765 | } |
aoqi@0 | 1766 | |
aoqi@0 | 1767 | public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) { |
aoqi@0 | 1768 | read_char_array(seq.value, offset, length); |
aoqi@0 | 1769 | } |
aoqi@0 | 1770 | |
aoqi@0 | 1771 | public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) { |
aoqi@0 | 1772 | read_wchar_array(seq.value, offset, length); |
aoqi@0 | 1773 | } |
aoqi@0 | 1774 | |
aoqi@0 | 1775 | public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) { |
aoqi@0 | 1776 | read_octet_array(seq.value, offset, length); |
aoqi@0 | 1777 | } |
aoqi@0 | 1778 | |
aoqi@0 | 1779 | public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) { |
aoqi@0 | 1780 | read_short_array(seq.value, offset, length); |
aoqi@0 | 1781 | } |
aoqi@0 | 1782 | |
aoqi@0 | 1783 | public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) { |
aoqi@0 | 1784 | read_ushort_array(seq.value, offset, length); |
aoqi@0 | 1785 | } |
aoqi@0 | 1786 | |
aoqi@0 | 1787 | public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) { |
aoqi@0 | 1788 | read_long_array(seq.value, offset, length); |
aoqi@0 | 1789 | } |
aoqi@0 | 1790 | |
aoqi@0 | 1791 | public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) { |
aoqi@0 | 1792 | read_ulong_array(seq.value, offset, length); |
aoqi@0 | 1793 | } |
aoqi@0 | 1794 | |
aoqi@0 | 1795 | public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) { |
aoqi@0 | 1796 | read_ulonglong_array(seq.value, offset, length); |
aoqi@0 | 1797 | } |
aoqi@0 | 1798 | |
aoqi@0 | 1799 | public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) { |
aoqi@0 | 1800 | read_longlong_array(seq.value, offset, length); |
aoqi@0 | 1801 | } |
aoqi@0 | 1802 | |
aoqi@0 | 1803 | public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) { |
aoqi@0 | 1804 | read_float_array(seq.value, offset, length); |
aoqi@0 | 1805 | } |
aoqi@0 | 1806 | |
aoqi@0 | 1807 | public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) { |
aoqi@0 | 1808 | read_double_array(seq.value, offset, length); |
aoqi@0 | 1809 | } |
aoqi@0 | 1810 | |
aoqi@0 | 1811 | public java.math.BigDecimal read_fixed(short digits, short scale) { |
aoqi@0 | 1812 | // digits isn't really needed here |
aoqi@0 | 1813 | StringBuffer buffer = read_fixed_buffer(); |
aoqi@0 | 1814 | if (digits != buffer.length()) |
aoqi@0 | 1815 | throw wrapper.badFixed( new Integer(digits), |
aoqi@0 | 1816 | new Integer(buffer.length()) ) ; |
aoqi@0 | 1817 | buffer.insert(digits - scale, '.'); |
aoqi@0 | 1818 | return new BigDecimal(buffer.toString()); |
aoqi@0 | 1819 | } |
aoqi@0 | 1820 | |
aoqi@0 | 1821 | // This method is unable to yield the correct scale. |
aoqi@0 | 1822 | public java.math.BigDecimal read_fixed() { |
aoqi@0 | 1823 | return new BigDecimal(read_fixed_buffer().toString()); |
aoqi@0 | 1824 | } |
aoqi@0 | 1825 | |
aoqi@0 | 1826 | // Each octet contains (up to) two decimal digits. |
aoqi@0 | 1827 | // If the fixed type has an odd number of decimal digits, then the representation |
aoqi@0 | 1828 | // begins with the first (most significant) digit. |
aoqi@0 | 1829 | // Otherwise, this first half-octet is all zero, and the first digit |
aoqi@0 | 1830 | // is in the second half-octet. |
aoqi@0 | 1831 | // The sign configuration, in the last half-octet of the representation, |
aoqi@0 | 1832 | // is 0xD for negative numbers and 0xC for positive and zero values. |
aoqi@0 | 1833 | private StringBuffer read_fixed_buffer() { |
aoqi@0 | 1834 | StringBuffer buffer = new StringBuffer(64); |
aoqi@0 | 1835 | byte doubleDigit; |
aoqi@0 | 1836 | int firstDigit; |
aoqi@0 | 1837 | int secondDigit; |
aoqi@0 | 1838 | boolean wroteFirstDigit = false; |
aoqi@0 | 1839 | boolean more = true; |
aoqi@0 | 1840 | while (more) { |
aoqi@0 | 1841 | doubleDigit = this.read_octet(); |
aoqi@0 | 1842 | firstDigit = (int)((doubleDigit & 0xf0) >> 4); |
aoqi@0 | 1843 | secondDigit = (int)(doubleDigit & 0x0f); |
aoqi@0 | 1844 | if (wroteFirstDigit || firstDigit != 0) { |
aoqi@0 | 1845 | buffer.append(Character.forDigit(firstDigit, 10)); |
aoqi@0 | 1846 | wroteFirstDigit = true; |
aoqi@0 | 1847 | } |
aoqi@0 | 1848 | if (secondDigit == 12) { |
aoqi@0 | 1849 | // positive number or zero |
aoqi@0 | 1850 | if ( ! wroteFirstDigit) { |
aoqi@0 | 1851 | // zero |
aoqi@0 | 1852 | return new StringBuffer("0.0"); |
aoqi@0 | 1853 | } else { |
aoqi@0 | 1854 | // positive number |
aoqi@0 | 1855 | // done |
aoqi@0 | 1856 | } |
aoqi@0 | 1857 | more = false; |
aoqi@0 | 1858 | } else if (secondDigit == 13) { |
aoqi@0 | 1859 | // negative number |
aoqi@0 | 1860 | buffer.insert(0, '-'); |
aoqi@0 | 1861 | more = false; |
aoqi@0 | 1862 | } else { |
aoqi@0 | 1863 | buffer.append(Character.forDigit(secondDigit, 10)); |
aoqi@0 | 1864 | wroteFirstDigit = true; |
aoqi@0 | 1865 | } |
aoqi@0 | 1866 | } |
aoqi@0 | 1867 | return buffer; |
aoqi@0 | 1868 | } |
aoqi@0 | 1869 | |
aoqi@0 | 1870 | private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0"; |
aoqi@0 | 1871 | private final static String[] _ids = { _id }; |
aoqi@0 | 1872 | |
aoqi@0 | 1873 | public String[] _truncatable_ids() { |
aoqi@0 | 1874 | if (_ids == null) |
aoqi@0 | 1875 | return null; |
aoqi@0 | 1876 | |
aoqi@0 | 1877 | return (String[])_ids.clone(); |
aoqi@0 | 1878 | } |
aoqi@0 | 1879 | |
aoqi@0 | 1880 | /* for debugging */ |
aoqi@0 | 1881 | |
aoqi@0 | 1882 | public void printBuffer() { |
aoqi@0 | 1883 | CDRInputStream_1_0.printBuffer(this.bbwi); |
aoqi@0 | 1884 | } |
aoqi@0 | 1885 | |
aoqi@0 | 1886 | public static void printBuffer(ByteBufferWithInfo bbwi) { |
aoqi@0 | 1887 | |
aoqi@0 | 1888 | System.out.println("----- Input Buffer -----"); |
aoqi@0 | 1889 | System.out.println(); |
aoqi@0 | 1890 | System.out.println("Current position: " + bbwi.position()); |
aoqi@0 | 1891 | System.out.println("Total length : " + bbwi.buflen); |
aoqi@0 | 1892 | System.out.println(); |
aoqi@0 | 1893 | |
aoqi@0 | 1894 | try { |
aoqi@0 | 1895 | |
aoqi@0 | 1896 | char[] charBuf = new char[16]; |
aoqi@0 | 1897 | |
aoqi@0 | 1898 | for (int i = 0; i < bbwi.buflen; i += 16) { |
aoqi@0 | 1899 | |
aoqi@0 | 1900 | int j = 0; |
aoqi@0 | 1901 | |
aoqi@0 | 1902 | // For every 16 bytes, there is one line |
aoqi@0 | 1903 | // of output. First, the hex output of |
aoqi@0 | 1904 | // the 16 bytes with each byte separated |
aoqi@0 | 1905 | // by a space. |
aoqi@0 | 1906 | while (j < 16 && j + i < bbwi.buflen) { |
aoqi@0 | 1907 | int k = bbwi.byteBuffer.get(i + j); |
aoqi@0 | 1908 | if (k < 0) |
aoqi@0 | 1909 | k = 256 + k; |
aoqi@0 | 1910 | String hex = Integer.toHexString(k); |
aoqi@0 | 1911 | if (hex.length() == 1) |
aoqi@0 | 1912 | hex = "0" + hex; |
aoqi@0 | 1913 | System.out.print(hex + " "); |
aoqi@0 | 1914 | j++; |
aoqi@0 | 1915 | } |
aoqi@0 | 1916 | |
aoqi@0 | 1917 | // Add any extra spaces to align the |
aoqi@0 | 1918 | // text column in case we didn't end |
aoqi@0 | 1919 | // at 16 |
aoqi@0 | 1920 | while (j < 16) { |
aoqi@0 | 1921 | System.out.print(" "); |
aoqi@0 | 1922 | j++; |
aoqi@0 | 1923 | } |
aoqi@0 | 1924 | |
aoqi@0 | 1925 | // Now output the ASCII equivalents. Non-ASCII |
aoqi@0 | 1926 | // characters are shown as periods. |
aoqi@0 | 1927 | int x = 0; |
aoqi@0 | 1928 | while (x < 16 && x + i < bbwi.buflen) { |
aoqi@0 | 1929 | if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x))) |
aoqi@0 | 1930 | charBuf[x] = (char)bbwi.byteBuffer.get(i + x); |
aoqi@0 | 1931 | else |
aoqi@0 | 1932 | charBuf[x] = '.'; |
aoqi@0 | 1933 | x++; |
aoqi@0 | 1934 | } |
aoqi@0 | 1935 | System.out.println(new String(charBuf, 0, x)); |
aoqi@0 | 1936 | } |
aoqi@0 | 1937 | |
aoqi@0 | 1938 | } catch (Throwable t) { |
aoqi@0 | 1939 | t.printStackTrace(); |
aoqi@0 | 1940 | } |
aoqi@0 | 1941 | |
aoqi@0 | 1942 | System.out.println("------------------------"); |
aoqi@0 | 1943 | } |
aoqi@0 | 1944 | |
aoqi@0 | 1945 | public ByteBuffer getByteBuffer() { |
aoqi@0 | 1946 | ByteBuffer result = null; |
aoqi@0 | 1947 | if (bbwi != null) { |
aoqi@0 | 1948 | result = bbwi.byteBuffer; |
aoqi@0 | 1949 | } |
aoqi@0 | 1950 | return result; |
aoqi@0 | 1951 | } |
aoqi@0 | 1952 | |
aoqi@0 | 1953 | public int getBufferLength() { |
aoqi@0 | 1954 | return bbwi.buflen; |
aoqi@0 | 1955 | } |
aoqi@0 | 1956 | |
aoqi@0 | 1957 | public void setBufferLength(int value) { |
aoqi@0 | 1958 | bbwi.buflen = value; |
aoqi@0 | 1959 | bbwi.byteBuffer.limit(bbwi.buflen); |
aoqi@0 | 1960 | } |
aoqi@0 | 1961 | |
aoqi@0 | 1962 | public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) { |
aoqi@0 | 1963 | this.bbwi = bbwi; |
aoqi@0 | 1964 | } |
aoqi@0 | 1965 | |
aoqi@0 | 1966 | public void setByteBuffer(ByteBuffer byteBuffer) { |
aoqi@0 | 1967 | bbwi.byteBuffer = byteBuffer; |
aoqi@0 | 1968 | } |
aoqi@0 | 1969 | |
aoqi@0 | 1970 | public int getIndex() { |
aoqi@0 | 1971 | return bbwi.position(); |
aoqi@0 | 1972 | } |
aoqi@0 | 1973 | |
aoqi@0 | 1974 | public void setIndex(int value) { |
aoqi@0 | 1975 | bbwi.position(value); |
aoqi@0 | 1976 | } |
aoqi@0 | 1977 | |
aoqi@0 | 1978 | public boolean isLittleEndian() { |
aoqi@0 | 1979 | return littleEndian; |
aoqi@0 | 1980 | } |
aoqi@0 | 1981 | |
aoqi@0 | 1982 | public void orb(org.omg.CORBA.ORB orb) { |
aoqi@0 | 1983 | this.orb = (ORB)orb; |
aoqi@0 | 1984 | } |
aoqi@0 | 1985 | |
aoqi@0 | 1986 | public BufferManagerRead getBufferManager() { |
aoqi@0 | 1987 | return bufferManagerRead; |
aoqi@0 | 1988 | } |
aoqi@0 | 1989 | |
aoqi@0 | 1990 | private void skipToOffset(int offset) { |
aoqi@0 | 1991 | |
aoqi@0 | 1992 | // Number of bytes to skip |
aoqi@0 | 1993 | int len = offset - get_offset(); |
aoqi@0 | 1994 | |
aoqi@0 | 1995 | int n = 0; |
aoqi@0 | 1996 | |
aoqi@0 | 1997 | while (n < len) { |
aoqi@0 | 1998 | int avail; |
aoqi@0 | 1999 | int bytes; |
aoqi@0 | 2000 | int wanted; |
aoqi@0 | 2001 | |
aoqi@0 | 2002 | avail = bbwi.buflen - bbwi.position(); |
aoqi@0 | 2003 | if (avail <= 0) { |
aoqi@0 | 2004 | grow(1, 1); |
aoqi@0 | 2005 | avail = bbwi.buflen - bbwi.position(); |
aoqi@0 | 2006 | } |
aoqi@0 | 2007 | |
aoqi@0 | 2008 | wanted = len - n; |
aoqi@0 | 2009 | bytes = (wanted < avail) ? wanted : avail; |
aoqi@0 | 2010 | bbwi.position(bbwi.position() + bytes); |
aoqi@0 | 2011 | n += bytes; |
aoqi@0 | 2012 | } |
aoqi@0 | 2013 | } |
aoqi@0 | 2014 | |
aoqi@0 | 2015 | |
aoqi@0 | 2016 | // Mark and reset ------------------------------------------------- |
aoqi@0 | 2017 | |
aoqi@0 | 2018 | protected MarkAndResetHandler markAndResetHandler = null; |
aoqi@0 | 2019 | |
aoqi@0 | 2020 | protected class StreamMemento |
aoqi@0 | 2021 | { |
aoqi@0 | 2022 | // These are the fields that may change after marking |
aoqi@0 | 2023 | // the stream position, so we need to save them. |
aoqi@0 | 2024 | private int blockLength_; |
aoqi@0 | 2025 | private int end_flag_; |
aoqi@0 | 2026 | private int chunkedValueNestingLevel_; |
aoqi@0 | 2027 | private int valueIndirection_; |
aoqi@0 | 2028 | private int stringIndirection_; |
aoqi@0 | 2029 | private boolean isChunked_; |
aoqi@0 | 2030 | private javax.rmi.CORBA.ValueHandler valueHandler_; |
aoqi@0 | 2031 | private ByteBufferWithInfo bbwi_; |
aoqi@0 | 2032 | private boolean specialNoOptionalDataState_; |
aoqi@0 | 2033 | |
aoqi@0 | 2034 | public StreamMemento() |
aoqi@0 | 2035 | { |
aoqi@0 | 2036 | blockLength_ = blockLength; |
aoqi@0 | 2037 | end_flag_ = end_flag; |
aoqi@0 | 2038 | chunkedValueNestingLevel_ = chunkedValueNestingLevel; |
aoqi@0 | 2039 | valueIndirection_ = valueIndirection; |
aoqi@0 | 2040 | stringIndirection_ = stringIndirection; |
aoqi@0 | 2041 | isChunked_ = isChunked; |
aoqi@0 | 2042 | valueHandler_ = valueHandler; |
aoqi@0 | 2043 | specialNoOptionalDataState_ = specialNoOptionalDataState; |
aoqi@0 | 2044 | bbwi_ = new ByteBufferWithInfo(bbwi); |
aoqi@0 | 2045 | } |
aoqi@0 | 2046 | } |
aoqi@0 | 2047 | |
aoqi@0 | 2048 | public java.lang.Object createStreamMemento() { |
aoqi@0 | 2049 | return new StreamMemento(); |
aoqi@0 | 2050 | } |
aoqi@0 | 2051 | |
aoqi@0 | 2052 | public void restoreInternalState(java.lang.Object streamMemento) { |
aoqi@0 | 2053 | |
aoqi@0 | 2054 | StreamMemento mem = (StreamMemento)streamMemento; |
aoqi@0 | 2055 | |
aoqi@0 | 2056 | blockLength = mem.blockLength_; |
aoqi@0 | 2057 | end_flag = mem.end_flag_; |
aoqi@0 | 2058 | chunkedValueNestingLevel = mem.chunkedValueNestingLevel_; |
aoqi@0 | 2059 | valueIndirection = mem.valueIndirection_; |
aoqi@0 | 2060 | stringIndirection = mem.stringIndirection_; |
aoqi@0 | 2061 | isChunked = mem.isChunked_; |
aoqi@0 | 2062 | valueHandler = mem.valueHandler_; |
aoqi@0 | 2063 | specialNoOptionalDataState = mem.specialNoOptionalDataState_; |
aoqi@0 | 2064 | bbwi = mem.bbwi_; |
aoqi@0 | 2065 | } |
aoqi@0 | 2066 | |
aoqi@0 | 2067 | public int getPosition() { |
aoqi@0 | 2068 | return get_offset(); |
aoqi@0 | 2069 | } |
aoqi@0 | 2070 | |
aoqi@0 | 2071 | public void mark(int readlimit) { |
aoqi@0 | 2072 | markAndResetHandler.mark(this); |
aoqi@0 | 2073 | } |
aoqi@0 | 2074 | |
aoqi@0 | 2075 | public void reset() { |
aoqi@0 | 2076 | markAndResetHandler.reset(); |
aoqi@0 | 2077 | } |
aoqi@0 | 2078 | |
aoqi@0 | 2079 | // ---------------------------------- end Mark and Reset |
aoqi@0 | 2080 | |
aoqi@0 | 2081 | // Provides a hook so subclasses of CDRInputStream can provide |
aoqi@0 | 2082 | // a CodeBase. This ultimately allows us to grab a Connection |
aoqi@0 | 2083 | // instance in IIOPInputStream, the only subclass where this |
aoqi@0 | 2084 | // is actually used. |
aoqi@0 | 2085 | CodeBase getCodeBase() { |
aoqi@0 | 2086 | return parent.getCodeBase(); |
aoqi@0 | 2087 | } |
aoqi@0 | 2088 | |
aoqi@0 | 2089 | /** |
aoqi@0 | 2090 | * Attempts to find the class described by the given |
aoqi@0 | 2091 | * repository ID string and expected type. The first |
aoqi@0 | 2092 | * attempt is to find the class locally, falling back |
aoqi@0 | 2093 | * on the URL that came with the value. The second |
aoqi@0 | 2094 | * attempt is to use a URL from the remote CodeBase. |
aoqi@0 | 2095 | */ |
aoqi@0 | 2096 | private Class getClassFromString(String repositoryIDString, |
aoqi@0 | 2097 | String codebaseURL, |
aoqi@0 | 2098 | Class expectedType) |
aoqi@0 | 2099 | { |
aoqi@0 | 2100 | RepositoryIdInterface repositoryID |
aoqi@0 | 2101 | = repIdStrs.getFromString(repositoryIDString); |
aoqi@0 | 2102 | |
aoqi@0 | 2103 | try { |
aoqi@0 | 2104 | try { |
aoqi@0 | 2105 | // First try to load the class locally, then use |
aoqi@0 | 2106 | // the provided URL (if it isn't null) |
aoqi@0 | 2107 | return repositoryID.getClassFromType(expectedType, |
aoqi@0 | 2108 | codebaseURL); |
aoqi@0 | 2109 | } catch (ClassNotFoundException cnfeOuter) { |
aoqi@0 | 2110 | |
aoqi@0 | 2111 | try { |
aoqi@0 | 2112 | |
aoqi@0 | 2113 | if (getCodeBase() == null) { |
aoqi@0 | 2114 | return null; // class cannot be loaded remotely. |
aoqi@0 | 2115 | } |
aoqi@0 | 2116 | |
aoqi@0 | 2117 | // Get a URL from the remote CodeBase and retry |
aoqi@0 | 2118 | codebaseURL = getCodeBase().implementation(repositoryIDString); |
aoqi@0 | 2119 | |
aoqi@0 | 2120 | // Don't bother trying to find it locally again if |
aoqi@0 | 2121 | // we got a null URL |
aoqi@0 | 2122 | if (codebaseURL == null) |
aoqi@0 | 2123 | return null; |
aoqi@0 | 2124 | |
aoqi@0 | 2125 | return repositoryID.getClassFromType(expectedType, |
aoqi@0 | 2126 | codebaseURL); |
aoqi@0 | 2127 | } catch (ClassNotFoundException cnfeInner) { |
aoqi@0 | 2128 | dprintThrowable(cnfeInner); |
aoqi@0 | 2129 | // Failed to load the class |
aoqi@0 | 2130 | return null; |
aoqi@0 | 2131 | } |
aoqi@0 | 2132 | } |
aoqi@0 | 2133 | } catch (MalformedURLException mue) { |
aoqi@0 | 2134 | // Always report a bad URL |
aoqi@0 | 2135 | throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 2136 | mue, repositoryIDString, codebaseURL ) ; |
aoqi@0 | 2137 | } |
aoqi@0 | 2138 | } |
aoqi@0 | 2139 | |
aoqi@0 | 2140 | /** |
aoqi@0 | 2141 | * Attempts to find the class described by the given |
aoqi@0 | 2142 | * repository ID string. At most, three attempts are made: |
aoqi@0 | 2143 | * Try to find it locally, through the provided URL, and |
aoqi@0 | 2144 | * finally, via a URL from the remote CodeBase. |
aoqi@0 | 2145 | */ |
aoqi@0 | 2146 | private Class getClassFromString(String repositoryIDString, |
aoqi@0 | 2147 | String codebaseURL) |
aoqi@0 | 2148 | { |
aoqi@0 | 2149 | RepositoryIdInterface repositoryID |
aoqi@0 | 2150 | = repIdStrs.getFromString(repositoryIDString); |
aoqi@0 | 2151 | |
aoqi@0 | 2152 | for (int i = 0; i < 3; i++) { |
aoqi@0 | 2153 | |
aoqi@0 | 2154 | try { |
aoqi@0 | 2155 | |
aoqi@0 | 2156 | switch (i) |
aoqi@0 | 2157 | { |
aoqi@0 | 2158 | case 0: |
aoqi@0 | 2159 | // First try to load the class locally |
aoqi@0 | 2160 | return repositoryID.getClassFromType(); |
aoqi@0 | 2161 | case 1: |
aoqi@0 | 2162 | // Try to load the class using the provided |
aoqi@0 | 2163 | // codebase URL (falls out below) |
aoqi@0 | 2164 | break; |
aoqi@0 | 2165 | case 2: |
aoqi@0 | 2166 | // Try to load the class using a URL from the |
aoqi@0 | 2167 | // remote CodeBase |
aoqi@0 | 2168 | codebaseURL = getCodeBase().implementation(repositoryIDString); |
aoqi@0 | 2169 | break; |
aoqi@0 | 2170 | } |
aoqi@0 | 2171 | |
aoqi@0 | 2172 | // Don't bother if the codebaseURL is null |
aoqi@0 | 2173 | if (codebaseURL == null) |
aoqi@0 | 2174 | continue; |
aoqi@0 | 2175 | |
aoqi@0 | 2176 | return repositoryID.getClassFromType(codebaseURL); |
aoqi@0 | 2177 | |
aoqi@0 | 2178 | } catch(ClassNotFoundException cnfe) { |
aoqi@0 | 2179 | // Will ultimately return null if all three |
aoqi@0 | 2180 | // attempts fail, but don't do anything here. |
aoqi@0 | 2181 | } catch (MalformedURLException mue) { |
aoqi@0 | 2182 | throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE, |
aoqi@0 | 2183 | mue, repositoryIDString, codebaseURL ) ; |
aoqi@0 | 2184 | } |
aoqi@0 | 2185 | } |
aoqi@0 | 2186 | |
aoqi@0 | 2187 | // If we get here, we have failed to load the class |
aoqi@0 | 2188 | dprint("getClassFromString failed with rep id " |
aoqi@0 | 2189 | + repositoryIDString |
aoqi@0 | 2190 | + " and codebase " |
aoqi@0 | 2191 | + codebaseURL); |
aoqi@0 | 2192 | |
aoqi@0 | 2193 | return null; |
aoqi@0 | 2194 | } |
aoqi@0 | 2195 | |
aoqi@0 | 2196 | // Utility method used to get chars from bytes |
aoqi@0 | 2197 | char[] getConvertedChars(int numBytes, |
aoqi@0 | 2198 | CodeSetConversion.BTCConverter converter) { |
aoqi@0 | 2199 | |
aoqi@0 | 2200 | // REVISIT - Look at CodeSetConversion.BTCConverter to see |
aoqi@0 | 2201 | // if it can work with an NIO ByteBuffer. We should |
aoqi@0 | 2202 | // avoid getting the bytes into an array if possible. |
aoqi@0 | 2203 | |
aoqi@0 | 2204 | // To be honest, I doubt this saves much real time |
aoqi@0 | 2205 | if (bbwi.buflen - bbwi.position() >= numBytes) { |
aoqi@0 | 2206 | // If the entire string is in this buffer, |
aoqi@0 | 2207 | // just convert directly from the bbwi rather than |
aoqi@0 | 2208 | // allocating and copying. |
aoqi@0 | 2209 | byte[] tmpBuf; |
aoqi@0 | 2210 | if (bbwi.byteBuffer.hasArray()) |
aoqi@0 | 2211 | { |
aoqi@0 | 2212 | tmpBuf = bbwi.byteBuffer.array(); |
aoqi@0 | 2213 | } |
aoqi@0 | 2214 | else |
aoqi@0 | 2215 | { |
aoqi@0 | 2216 | tmpBuf = new byte[bbwi.buflen]; |
aoqi@0 | 2217 | // Microbenchmarks are showing a loop of ByteBuffer.get(int) |
aoqi@0 | 2218 | // being faster than ByteBuffer.get(byte[], int, int). |
aoqi@0 | 2219 | for (int i = 0; i < bbwi.buflen; i++) |
aoqi@0 | 2220 | tmpBuf[i] = bbwi.byteBuffer.get(i); |
aoqi@0 | 2221 | } |
aoqi@0 | 2222 | char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes); |
aoqi@0 | 2223 | |
aoqi@0 | 2224 | bbwi.position(bbwi.position() + numBytes); |
aoqi@0 | 2225 | return result; |
aoqi@0 | 2226 | } else { |
aoqi@0 | 2227 | // Stretches across buffers. Unless we provide an |
aoqi@0 | 2228 | // incremental conversion interface, allocate and |
aoqi@0 | 2229 | // copy the bytes. |
aoqi@0 | 2230 | byte[] bytes = new byte[numBytes]; |
aoqi@0 | 2231 | read_octet_array(bytes, 0, bytes.length); |
aoqi@0 | 2232 | |
aoqi@0 | 2233 | return converter.getChars(bytes, 0, numBytes); |
aoqi@0 | 2234 | } |
aoqi@0 | 2235 | } |
aoqi@0 | 2236 | |
aoqi@0 | 2237 | protected CodeSetConversion.BTCConverter getCharConverter() { |
aoqi@0 | 2238 | if (charConverter == null) |
aoqi@0 | 2239 | charConverter = parent.createCharBTCConverter(); |
aoqi@0 | 2240 | |
aoqi@0 | 2241 | return charConverter; |
aoqi@0 | 2242 | } |
aoqi@0 | 2243 | |
aoqi@0 | 2244 | protected CodeSetConversion.BTCConverter getWCharConverter() { |
aoqi@0 | 2245 | if (wcharConverter == null) |
aoqi@0 | 2246 | wcharConverter = parent.createWCharBTCConverter(); |
aoqi@0 | 2247 | |
aoqi@0 | 2248 | return wcharConverter; |
aoqi@0 | 2249 | } |
aoqi@0 | 2250 | |
aoqi@0 | 2251 | protected void dprintThrowable(Throwable t) { |
aoqi@0 | 2252 | if (debug && t != null) |
aoqi@0 | 2253 | t.printStackTrace(); |
aoqi@0 | 2254 | } |
aoqi@0 | 2255 | |
aoqi@0 | 2256 | protected void dprint(String msg) { |
aoqi@0 | 2257 | if (debug) { |
aoqi@0 | 2258 | ORBUtility.dprint(this, msg); |
aoqi@0 | 2259 | } |
aoqi@0 | 2260 | } |
aoqi@0 | 2261 | |
aoqi@0 | 2262 | /** |
aoqi@0 | 2263 | * Aligns the current position on the given octet boundary |
aoqi@0 | 2264 | * if there are enough bytes available to do so. Otherwise, |
aoqi@0 | 2265 | * it just returns. This is used for some (but not all) |
aoqi@0 | 2266 | * GIOP 1.2 message headers. |
aoqi@0 | 2267 | */ |
aoqi@0 | 2268 | |
aoqi@0 | 2269 | void alignOnBoundary(int octetBoundary) { |
aoqi@0 | 2270 | int needed = computeAlignment(bbwi.position(), octetBoundary); |
aoqi@0 | 2271 | |
aoqi@0 | 2272 | if (bbwi.position() + needed <= bbwi.buflen) |
aoqi@0 | 2273 | { |
aoqi@0 | 2274 | bbwi.position(bbwi.position() + needed); |
aoqi@0 | 2275 | } |
aoqi@0 | 2276 | } |
aoqi@0 | 2277 | |
aoqi@0 | 2278 | public void resetCodeSetConverters() { |
aoqi@0 | 2279 | charConverter = null; |
aoqi@0 | 2280 | wcharConverter = null; |
aoqi@0 | 2281 | } |
aoqi@0 | 2282 | |
aoqi@0 | 2283 | public void start_value() { |
aoqi@0 | 2284 | // Read value tag |
aoqi@0 | 2285 | int vType = readValueTag(); |
aoqi@0 | 2286 | |
aoqi@0 | 2287 | if (vType == 0) { |
aoqi@0 | 2288 | // Stream needs to go into a state where it |
aoqi@0 | 2289 | // throws standard exception until end_value |
aoqi@0 | 2290 | // is called. This means the sender didn't |
aoqi@0 | 2291 | // send any custom data. If the reader here |
aoqi@0 | 2292 | // tries to read more, we need to throw an |
aoqi@0 | 2293 | // exception before reading beyond where |
aoqi@0 | 2294 | // we're supposed to |
aoqi@0 | 2295 | specialNoOptionalDataState = true; |
aoqi@0 | 2296 | |
aoqi@0 | 2297 | return; |
aoqi@0 | 2298 | } |
aoqi@0 | 2299 | |
aoqi@0 | 2300 | if (vType == 0xffffffff) { |
aoqi@0 | 2301 | // One should never indirect to a custom wrapper |
aoqi@0 | 2302 | throw wrapper.customWrapperIndirection( |
aoqi@0 | 2303 | CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 2304 | } |
aoqi@0 | 2305 | |
aoqi@0 | 2306 | if (repIdUtil.isCodeBasePresent(vType)) { |
aoqi@0 | 2307 | throw wrapper.customWrapperWithCodebase( |
aoqi@0 | 2308 | CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 2309 | } |
aoqi@0 | 2310 | |
aoqi@0 | 2311 | if (repIdUtil.getTypeInfo(vType) |
aoqi@0 | 2312 | != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) { |
aoqi@0 | 2313 | throw wrapper.customWrapperNotSingleRepid( |
aoqi@0 | 2314 | CompletionStatus.COMPLETED_MAYBE); |
aoqi@0 | 2315 | } |
aoqi@0 | 2316 | |
aoqi@0 | 2317 | |
aoqi@0 | 2318 | // REVISIT - Could verify repository ID even though |
aoqi@0 | 2319 | // it isn't used elsewhere |
aoqi@0 | 2320 | read_repositoryId(); |
aoqi@0 | 2321 | |
aoqi@0 | 2322 | // Note: isChunked should be true here. Should have |
aoqi@0 | 2323 | // been set to true in the containing value's read_value |
aoqi@0 | 2324 | // method. |
aoqi@0 | 2325 | |
aoqi@0 | 2326 | start_block(); |
aoqi@0 | 2327 | end_flag--; |
aoqi@0 | 2328 | chunkedValueNestingLevel--; |
aoqi@0 | 2329 | } |
aoqi@0 | 2330 | |
aoqi@0 | 2331 | public void end_value() { |
aoqi@0 | 2332 | |
aoqi@0 | 2333 | if (specialNoOptionalDataState) { |
aoqi@0 | 2334 | specialNoOptionalDataState = false; |
aoqi@0 | 2335 | return; |
aoqi@0 | 2336 | } |
aoqi@0 | 2337 | |
aoqi@0 | 2338 | handleEndOfValue(); |
aoqi@0 | 2339 | readEndTag(); |
aoqi@0 | 2340 | |
aoqi@0 | 2341 | // Note that isChunked should still be true here. |
aoqi@0 | 2342 | // If the containing valuetype is the highest |
aoqi@0 | 2343 | // chunked value, it will get set to false |
aoqi@0 | 2344 | // at the end of read_value. |
aoqi@0 | 2345 | |
aoqi@0 | 2346 | // allow for possible continuation chunk |
aoqi@0 | 2347 | start_block(); |
aoqi@0 | 2348 | } |
aoqi@0 | 2349 | |
aoqi@0 | 2350 | public void close() throws IOException |
aoqi@0 | 2351 | { |
aoqi@0 | 2352 | |
aoqi@0 | 2353 | // tell BufferManagerRead to release any ByteBuffers |
aoqi@0 | 2354 | getBufferManager().close(bbwi); |
aoqi@0 | 2355 | |
aoqi@0 | 2356 | // It's possible bbwi.byteBuffer is shared between |
aoqi@0 | 2357 | // this InputStream and an OutputStream. Thus, we check |
aoqi@0 | 2358 | // if the Input/Output streams are using the same ByteBuffer. |
aoqi@0 | 2359 | // If they sharing the same ByteBuffer we need to ensure only |
aoqi@0 | 2360 | // one of those ByteBuffers are released to the ByteBufferPool. |
aoqi@0 | 2361 | |
aoqi@0 | 2362 | if (bbwi != null && getByteBuffer() != null) |
aoqi@0 | 2363 | { |
aoqi@0 | 2364 | MessageMediator messageMediator = parent.getMessageMediator(); |
aoqi@0 | 2365 | if (messageMediator != null) |
aoqi@0 | 2366 | { |
aoqi@0 | 2367 | CDROutputObject outputObj = |
aoqi@0 | 2368 | (CDROutputObject)messageMediator.getOutputObject(); |
aoqi@0 | 2369 | if (outputObj != null) |
aoqi@0 | 2370 | { |
aoqi@0 | 2371 | if (outputObj.isSharing(getByteBuffer())) |
aoqi@0 | 2372 | { |
aoqi@0 | 2373 | // Set OutputStream's ByteBuffer and bbwi to null |
aoqi@0 | 2374 | // so its ByteBuffer cannot be released to the pool |
aoqi@0 | 2375 | outputObj.setByteBuffer(null); |
aoqi@0 | 2376 | outputObj.setByteBufferWithInfo(null); |
aoqi@0 | 2377 | } |
aoqi@0 | 2378 | } |
aoqi@0 | 2379 | } |
aoqi@0 | 2380 | |
aoqi@0 | 2381 | // release this stream's ByteBuffer to the pool |
aoqi@0 | 2382 | ByteBufferPool byteBufferPool = orb.getByteBufferPool(); |
aoqi@0 | 2383 | if (debug) |
aoqi@0 | 2384 | { |
aoqi@0 | 2385 | // print address of ByteBuffer being released |
aoqi@0 | 2386 | int bbAddress = System.identityHashCode(bbwi.byteBuffer); |
aoqi@0 | 2387 | StringBuffer sb = new StringBuffer(80); |
aoqi@0 | 2388 | sb.append(".close - releasing ByteBuffer id ("); |
aoqi@0 | 2389 | sb.append(bbAddress).append(") to ByteBufferPool."); |
aoqi@0 | 2390 | String msg = sb.toString(); |
aoqi@0 | 2391 | dprint(msg); |
aoqi@0 | 2392 | } |
aoqi@0 | 2393 | byteBufferPool.releaseByteBuffer(bbwi.byteBuffer); |
aoqi@0 | 2394 | bbwi.byteBuffer = null; |
aoqi@0 | 2395 | bbwi = null; |
aoqi@0 | 2396 | } |
aoqi@0 | 2397 | } |
aoqi@0 | 2398 | } |