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