src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java

Mon, 28 May 2018 10:29:43 +0800

author
aoqi
date
Mon, 28 May 2018 10:29:43 +0800
changeset 1655
bfd167e38830
parent 1618
4145ba26d9ff
parent 748
6845b95cba6b
permissions
-rw-r--r--

Merge

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

mercurial