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

Wed, 27 Apr 2016 01:21:28 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:21:28 +0800
changeset 0
7ef37b2cdcad
child 748
6845b95cba6b
permissions
-rw-r--r--

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 }

mercurial