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  */
25 
26 /*
27  * Licensed Materials - Property of IBM
28  * RMI-IIOP v1.0
29  * Copyright IBM Corp. 1998 1999  All Rights Reserved
30  *
31  */
32 
33 package com.sun.corba.se.impl.encoding;
34 
35 import java.io.Serializable;
36 import java.io.IOException;
37 
38 import java.net.MalformedURLException;
39 
40 import java.nio.ByteBuffer;
41 
42 import java.lang.reflect.InvocationTargetException;
43 import java.lang.reflect.Method;
44 
45 import java.math.BigDecimal;
46 
47 import java.security.AccessController;
48 import java.security.PrivilegedExceptionAction;
49 import java.security.PrivilegedActionException;
50 
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;
67 
68 import javax.rmi.CORBA.Tie;
69 import javax.rmi.CORBA.ValueHandler;
70 
71 import com.sun.corba.se.pept.protocol.MessageMediator;
72 import com.sun.corba.se.pept.transport.ByteBufferPool;
73 
74 import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
75 
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;
79 
80 import com.sun.corba.se.spi.orb.ORB;
81 import com.sun.corba.se.spi.orb.ORBVersionFactory;
82 
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;
87 
88 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
89 import com.sun.corba.se.impl.logging.OMGSystemException;
90 
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;
94 
95 import com.sun.corba.se.impl.encoding.CDROutputObject;
96 import com.sun.corba.se.impl.encoding.CodeSetConversion;
97 
98 import com.sun.corba.se.impl.util.Utility;
99 import com.sun.corba.se.impl.util.RepositoryId;
100 
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;
105 
106 import com.sun.corba.se.impl.orbutil.ORBUtility;
107 import com.sun.corba.se.impl.orbutil.CacheTable;
108 
109 
110 import com.sun.org.omg.CORBA.portable.ValueHelper;
111 
112 import com.sun.org.omg.SendingContext.CodeBase;
113 
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;
119 
120     protected BufferManagerRead bufferManagerRead;
121     protected ByteBufferWithInfo bbwi;
122 
123     // Set to the ORB's transportDebugFlag value.  This value is
124     // used if the ORB is null.
125     private boolean debug = false;
126 
127     protected boolean littleEndian;
128     protected ORB orb;
129     protected ORBUtilSystemException wrapper ;
130     protected OMGSystemException omgWrapper ;
131     protected ValueHandler valueHandler = null;
132 
133     // Value cache
134     private CacheTable valueCache = null;
135 
136     // Repository ID cache
137     private CacheTable repositoryIdCache = null;
138 
139     // codebase cache
140     private CacheTable codebaseCache = null;
141 
142     // Current Class Stack (repository Ids of current class being read)
143     // private Stack currentStack = null;
144 
145     // Length of current chunk, or a large positive number if not in a chunk
146     protected int blockLength = maxBlockLength;
147 
148     // Read end flag (value nesting depth)
149     protected int end_flag = 0;
150 
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;
157 
158     // Flag used to determine whether blocksize was zero
159     // private int checkForNullBlock = -1;
160 
161     // In block flag
162     // private boolean inBlock = false;
163 
164     // Indicates whether we are inside a value
165     // private boolean outerValueDone = true;
166 
167     // Int used by read_value(Serializable) that is set by this class
168     // before calling ValueFactory.read_value
169     protected int valueIndirection = 0;
170 
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;
174 
175     // Flag indicating whether we are unmarshalling a chunked value
176     protected boolean isChunked = false;
177 
178     // Repository ID handlers
179     private RepositoryIdUtility repIdUtil;
180     private RepositoryIdStrings repIdStrs;
181 
182     // Code set converters (created when first needed)
183     private CodeSetConversion.BTCConverter charConverter;
184     private CodeSetConversion.BTCConverter wcharConverter;
185 
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;
194 
195     // Template method
dup()196     public CDRInputStreamBase dup()
197     {
198         CDRInputStreamBase result = null ;
199 
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);
210 
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);
214 
215         return result;
216     }
217 
218     /**
219      * NOTE:  size passed to init means buffer size
220      */
init(org.omg.CORBA.ORB orb, ByteBuffer byteBuffer, int size, boolean littleEndian, BufferManagerRead bufferManager)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();
238 
239         debug = ((ORB)orb).transportDebugFlag;
240     }
241 
242     // See description in CDRInputStream
performORBVersionSpecificInit()243     void performORBVersionSpecificInit() {
244         createRepositoryIdHandlers();
245     }
246 
createRepositoryIdHandlers()247     private final void createRepositoryIdHandlers()
248     {
249         repIdUtil = RepositoryIdFactory.getRepIdUtility();
250         repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
251     }
252 
getGIOPVersion()253     public GIOPVersion getGIOPVersion() {
254         return GIOPVersion.V1_0;
255     }
256 
257     // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
258     // Illegal for GIOP versions < 1.2.
setHeaderPadding(boolean headerPadding)259     void setHeaderPadding(boolean headerPadding) {
260         throw wrapper.giopVersionError();
261     }
262 
computeAlignment(int index, int align)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         }
269 
270         return 0;
271     }
272 
getSize()273     public int getSize()
274     {
275         return bbwi.position();
276     }
277 
checkBlockLength(int align, int dataSize)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;
285 
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         }
296 
297         boolean checkForEndTag = false;
298 
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()) {
307 
308             blockLength = maxBlockLength;
309             start_block();
310 
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;
319 
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         }
326 
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;
335 
336         if (blockLength != maxBlockLength &&
337             blockLength < get_offset() + requiredNumBytes) {
338             throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
339         }
340 
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);
349 
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     }
357 
alignAndCheck(int align, int n)358     protected void alignAndCheck(int align, int n) {
359 
360         checkBlockLength(align, n);
361 
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);
366 
367         if (bbwi.position() + n > bbwi.buflen)
368             grow(align, n);
369     }
370 
371     //
372     // This can be overridden....
373     //
grow(int align, int n)374     protected void grow(int align, int n) {
375 
376         bbwi.needed = n;
377 
378         bbwi = bufferManagerRead.underflow(bbwi);
379 
380     }
381 
382     //
383     // Marshal primitives.
384     //
385 
consumeEndian()386     public final void consumeEndian() {
387         littleEndian = read_boolean();
388     }
389 
390     // No such type in java
read_longdouble()391     public final double read_longdouble() {
392         throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE);
393     }
394 
read_boolean()395     public final boolean read_boolean() {
396         return (read_octet() != 0);
397     }
398 
read_char()399     public final char read_char() {
400         alignAndCheck(1, 1);
401 
402         return getConvertedChars(1, getCharConverter())[0];
403     }
404 
read_wchar()405     public char read_wchar() {
406 
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         }
412 
413         // If we're talking to one of our legacy ORBs, do what
414         // they did:
415         int b1, b2;
416 
417         alignAndCheck(2, 2);
418 
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         }
430 
431         return (char)((b1 << 8) + (b2 << 0));
432     }
433 
read_octet()434     public final byte read_octet() {
435 
436         alignAndCheck(1, 1);
437 
438         byte b = bbwi.byteBuffer.get(bbwi.position());
439         bbwi.position(bbwi.position() + 1);
440 
441         return b;
442     }
443 
read_short()444     public final short read_short() {
445         int b1, b2;
446 
447         alignAndCheck(2, 2);
448 
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         }
460 
461         return (short)(b1 | b2);
462     }
463 
read_ushort()464     public final short read_ushort() {
465         return read_short();
466     }
467 
read_long()468     public final int read_long() {
469         int b1, b2, b3, b4;
470 
471         alignAndCheck(4, 4);
472 
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);
486 
487         return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
488     }
489 
read_ulong()490     public final int read_ulong() {
491         return read_long();
492     }
493 
read_longlong()494     public final long read_longlong() {
495         long i1, i2;
496 
497         alignAndCheck(8, 8);
498 
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         }
506 
507         return (i1 | i2);
508     }
509 
read_ulonglong()510     public final long read_ulonglong() {
511         return read_longlong();
512     }
513 
read_float()514     public final float read_float() {
515         return Float.intBitsToFloat(read_long());
516     }
517 
read_double()518     public final double read_double() {
519         return Double.longBitsToDouble(read_longlong());
520     }
521 
checkForNegativeLength(int length)522     protected final void checkForNegativeLength(int length) {
523         if (length < 0)
524             throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE,
525                 new Integer(length) ) ;
526     }
527 
readStringOrIndirection(boolean allowIndirection)528     protected final String readStringOrIndirection(boolean allowIndirection) {
529 
530         int len = read_long();
531 
532         //
533         // Check for indirection
534         //
535         if (allowIndirection) {
536             if (len == 0xffffffff)
537                 return null;
538             else
539                 stringIndirection = get_offset() - 4;
540         }
541 
542         checkForNegativeLength(len);
543 
544         return internalReadString(len);
545     }
546 
internalReadString(int len)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("");
556 
557         char[] result = getConvertedChars(len - 1, getCharConverter());
558 
559         // Skip over the 1 byte null
560         read_octet();
561 
562         return new String(result, 0, getCharConverter().getNumChars());
563     }
564 
read_string()565     public final String read_string() {
566         return readStringOrIndirection(false);
567     }
568 
read_wstring()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         }
575 
576         int len = read_long();
577 
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("");
588 
589         checkForNegativeLength(len);
590 
591         len--;
592         char[] c = new char[len];
593 
594         for (int i = 0; i < len; i++)
595             c[i] = read_wchar();
596 
597         // skip the two null terminator bytes
598         read_wchar();
599         // bbwi.position(bbwi.position() + 2);
600 
601         return new String(c);
602     }
603 
read_octet_array(byte[] b, int offset, int length)604     public final void read_octet_array(byte[] b, int offset, int length) {
605         if ( b == null )
606             throw wrapper.nullParam() ;
607 
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;
615 
616         alignAndCheck(1, 1);
617 
618         int n = offset;
619         while (n < length+offset) {
620             int avail;
621             int bytes;
622             int wanted;
623 
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             }
636 
637             bbwi.position(bbwi.position() + bytes);
638 
639             n += bytes;
640         }
641     }
642 
read_Principal()643     public Principal read_Principal() {
644         int len = read_long();
645         byte[] pvalue = new byte[len];
646         read_octet_array(pvalue,0,len);
647 
648         Principal p = new PrincipalImpl();
649         p.name(pvalue);
650         return p;
651     }
652 
read_TypeCode()653     public TypeCode read_TypeCode() {
654         TypeCodeImpl tc = new TypeCodeImpl(orb);
655         tc.read_value(parent);
656         return tc;
657     }
658 
read_any()659     public Any read_any() {
660         Any any = orb.create_any();
661         TypeCodeImpl tc = new TypeCodeImpl(orb);
662 
663         // read off the typecode
664 
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);
682 
683         return any;
684     }
685 
read_Object()686     public org.omg.CORBA.Object read_Object() {
687         return read_Object(null);
688     }
689 
690     // ------------ RMI related methods --------------------------
691 
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.
705 
read_Object(Class clz)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         }
713 
714         PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ;
715         String codeBase = ior.getProfile().getCodebase() ;
716         PresentationManager.StubFactory stubFactory = null ;
717 
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() ;
723 
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     }
749 
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      */
internalIORToObject( IOR ior, PresentationManager.StubFactory stubFactory, ORB orb)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 ) ;
760 
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);
768 
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         }
784 
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 ) ;
791 
792             if (e instanceof ThreadDeath) {
793                 throw (ThreadDeath) e;
794             }
795 
796             // Return the "default" stub...
797             objref = new CORBAObjectImpl() ;
798         }
799 
800         StubAdapter.setDelegate( objref, del ) ;
801         return objref;
802     }
803 
read_abstract_interface()804     public java.lang.Object read_abstract_interface()
805     {
806         return read_abstract_interface(null);
807     }
808 
read_abstract_interface(java.lang.Class clz)809     public java.lang.Object read_abstract_interface(java.lang.Class clz)
810     {
811         boolean object = read_boolean();
812 
813         if (object) {
814             return read_Object(clz);
815         } else {
816             return read_value();
817         }
818     }
819 
read_value()820     public Serializable read_value()
821     {
822         return read_value((Class)null);
823     }
824 
handleIndirection()825     private Serializable handleIndirection() {
826         int indirection = read_long() + get_offset() - 4;
827         if (valueCache != null && valueCache.containsVal(indirection)) {
828 
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     }
840 
readRepositoryIds(int valueTag, Class expectedType, String expectedTypeRepId)841     private String readRepositoryIds(int valueTag,
842                                      Class expectedType,
843                                      String expectedTypeRepId) {
844         return readRepositoryIds(valueTag, expectedType,
845                                  expectedTypeRepId, null);
846     }
847 
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      */
readRepositoryIds(int valueTag, Class expectedType, String expectedTypeRepId, BoxedValueHelper factory)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     }
885 
read_value(Class expectedType)886     public Serializable read_value(Class expectedType) {
887 
888         // Read value tag
889         int vType = readValueTag();
890 
891         // Is value null?
892         if (vType == 0)
893             return null;
894 
895         // Is this an indirection to a previously
896         // read valuetype?
897         if (vType == 0xffffffff)
898             return handleIndirection();
899 
900         // Save where this valuetype started so we
901         // can put it in the indirection valueCache
902         // later
903         int indirection = get_offset() - 4;
904 
905         // Need to save this special marker variable
906         // to restore its value during recursion
907         boolean saveIsChunked = isChunked;
908 
909         isChunked = repIdUtil.isChunkedEncoding(vType);
910 
911         java.lang.Object value = null;
912 
913         String codebase_URL = null;
914         if (repIdUtil.isCodeBasePresent(vType)) {
915             codebase_URL = read_codebase_URL();
916         }
917 
918         // Read repository id(s)
919         String repositoryIDString
920             = readRepositoryIds(vType, expectedType, null);
921 
922         // If isChunked was determined to be true based
923         // on the valuetag, this will read a chunk length
924         start_block();
925 
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--;
931 
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 {
940 
941             Class valueClass = expectedType;
942 
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))) {
947 
948                 valueClass = getClassFromString(repositoryIDString,
949                                                 codebase_URL,
950                                                 expectedType);
951             }
952 
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             }
960 
961             if (valueClass != null &&
962                 org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) {
963 
964                 value =  readIDLValue(indirection,
965                                       repositoryIDString,
966                                       valueClass,
967                                       codebase_URL);
968 
969             } else {
970 
971                 // Must be some form of RMI-IIOP valuetype
972 
973                 try {
974                     if (valueHandler == null)
975                         valueHandler = ORBUtility.createValueHandler();
976 
977                     value = valueHandler.readValue(parent,
978                                                    indirection,
979                                                    valueClass,
980                                                    repositoryIDString,
981                                                    getCodeBase());
982 
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         }
996 
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();
1002 
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();
1007 
1008         // Cache the valuetype that we read
1009         if (valueCache == null)
1010             valueCache = new CacheTable(orb,false);
1011         valueCache.put(value, indirection);
1012 
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();
1020 
1021         return (java.io.Serializable)value;
1022     }
1023 
read_value(BoxedValueHelper factory)1024     public Serializable read_value(BoxedValueHelper factory) {
1025 
1026         // Read value tag
1027         int vType = readValueTag();
1028 
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;
1045 
1046             // end_block();
1047 
1048             boolean saveIsChunked = isChunked;
1049             isChunked = repIdUtil.isChunkedEncoding(vType);
1050 
1051             java.lang.Object value = null;
1052 
1053             String codebase_URL = null;
1054             if (repIdUtil.isCodeBasePresent(vType)){
1055                 codebase_URL = read_codebase_URL();
1056             }
1057 
1058             // Read repository id
1059             String repositoryIDString
1060                 = readRepositoryIds(vType, null, null, factory);
1061 
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);
1065 
1066             start_block();
1067             end_flag--;
1068             if (isChunked)
1069                 chunkedValueNestingLevel--;
1070 
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             }
1077 
1078             handleEndOfValue();
1079             readEndTag();
1080 
1081             // Put into valueCache
1082             if (valueCache == null)
1083                 valueCache = new CacheTable(orb,false);
1084             valueCache.put(value, indirection);
1085 
1086             // allow for possible continuation chunk
1087             isChunked = saveIsChunked;
1088             start_block();
1089 
1090             return (java.io.Serializable)value;
1091         }
1092     }
1093 
isCustomType(ValueHelper helper)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         }
1104 
1105         return false;
1106     }
1107 
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.
read_value(java.io.Serializable value)1112     public java.io.Serializable read_value(java.io.Serializable value) {
1113 
1114         // Put into valueCache using valueIndirection
1115         if (valueCache == null)
1116             valueCache = new CacheTable(orb,false);
1117         valueCache.put(value, valueIndirection);
1118 
1119         if (value instanceof StreamableValue)
1120             ((StreamableValue)value)._read(parent);
1121         else if (value instanceof CustomValue)
1122             ((CustomValue)value).unmarshal(parent);
1123 
1124         return value;
1125     }
1126 
read_value(java.lang.String repositoryId)1127     public java.io.Serializable read_value(java.lang.String repositoryId) {
1128 
1129         // if (inBlock)
1130         //    end_block();
1131 
1132         // Read value tag
1133         int vType = readValueTag();
1134 
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;
1151 
1152             // end_block();
1153 
1154             boolean saveIsChunked = isChunked;
1155             isChunked = repIdUtil.isChunkedEncoding(vType);
1156 
1157             java.lang.Object value = null;
1158 
1159             String codebase_URL = null;
1160             if (repIdUtil.isCodeBasePresent(vType)){
1161                 codebase_URL = read_codebase_URL();
1162             }
1163 
1164             // Read repository id
1165             String repositoryIDString
1166                 = readRepositoryIds(vType, null, repositoryId);
1167 
1168             ValueFactory factory =
1169                Utility.getFactory(null, codebase_URL, orb, repositoryIDString);
1170 
1171             start_block();
1172             end_flag--;
1173             if (isChunked)
1174                 chunkedValueNestingLevel--;
1175 
1176             valueIndirection = indirection;  // for callback
1177             value = factory.read_value(parent);
1178 
1179             handleEndOfValue();
1180             readEndTag();
1181 
1182             // Put into valueCache
1183             if (valueCache == null)
1184                 valueCache = new CacheTable(orb,false);
1185             valueCache.put(value, indirection);
1186 
1187             // allow for possible continuation chunk
1188             isChunked = saveIsChunked;
1189             start_block();
1190 
1191             return (java.io.Serializable)value;
1192         }
1193     }
1194 
readClass()1195     private Class readClass() {
1196 
1197         String codebases = null, classRepId = null;
1198 
1199         if (orb == null ||
1200             ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
1201             ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
1202 
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         }
1211 
1212         if (debug) {
1213             dprint("readClass codebases: "
1214                    + codebases
1215                    + " rep Id: "
1216                    + classRepId);
1217         }
1218 
1219         Class cl = null;
1220 
1221         RepositoryIdInterface repositoryID
1222             = repIdStrs.getFromString(classRepId);
1223 
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         }
1233 
1234         return cl;
1235     }
1236 
readIDLValueWithHelper(ValueHelper helper, int indirection)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         }
1249 
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         }
1267 
1268         // add blank instance to cache table
1269         if (valueCache == null)
1270             valueCache = new CacheTable(orb,false);
1271         valueCache.put(val, indirection);
1272 
1273         // if custom type, call unmarshal method
1274         if (val instanceof CustomMarshal && isCustomType(helper)) {
1275             ((CustomMarshal)val).unmarshal(parent);
1276             return val;
1277         }
1278 
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     }
1290 
readBoxedIDLEntity(Class clazz, String codebase)1291     private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase)
1292     {
1293         Class cls = null ;
1294 
1295         try {
1296             ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
1297 
1298             cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
1299                                                    clazzLoader, clazz, clazzLoader);
1300             final Class helperClass = cls ;
1301 
1302             final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class};
1303 
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             }
1319 
1320             java.lang.Object args[] = {parent};
1321             return readMethod.invoke(null, args);
1322 
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     }
1333 
readIDLValue(int indirection, String repId, Class clazz, String codebase)1334     private java.lang.Object readIDLValue(int indirection, String repId,
1335                                           Class clazz, String codebase)
1336     {
1337         ValueFactory factory ;
1338 
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
1352 
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         }
1369 
1370         // If there was no error in getting the factory, use it.
1371         valueIndirection = indirection;  // for callback
1372         return factory.read_value(parent);
1373     }
1374 
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      */
readEndTag()1385     private void readEndTag() {
1386         if (isChunked) {
1387 
1388             // Read the end tag
1389             int anEndTag = read_long();
1390 
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             }
1400 
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) {
1408 
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 ) ) ;
1416 
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                  }
1426 
1427             } else {
1428 
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             }
1437 
1438             // This only keeps track of the enclosing chunked
1439             // valuetypes
1440             chunkedValueNestingLevel++;
1441         }
1442 
1443         // This keeps track of all enclosing valuetypes
1444         end_flag++;
1445     }
1446 
get_offset()1447     protected int get_offset() {
1448         return bbwi.position();
1449     }
1450 
start_block()1451     private void start_block() {
1452 
1453         // if (outerValueDone)
1454         if (!isChunked)
1455             return;
1456 
1457         // if called from alignAndCheck, need to reset blockLength
1458         // to avoid an infinite recursion loop on read_long() call
1459         blockLength = maxBlockLength;
1460 
1461         blockLength = read_long();
1462 
1463         // Must remember where we began the chunk to calculate how far
1464         // along we are.  See notes above about chunkBeginPos.
1465 
1466         if (blockLength > 0 && blockLength < maxBlockLength) {
1467             blockLength += get_offset();  // _REVISIT_ unsafe, should use a Java long
1468 
1469             // inBlock = true;
1470         } else {
1471 
1472             // System.out.println("start_block snooped a " + Integer.toHexString(blockLength));
1473 
1474             // not a chunk length field
1475             blockLength = maxBlockLength;
1476 
1477             bbwi.position(bbwi.position() - 4);
1478         }
1479     }
1480 
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.
handleEndOfValue()1487     private void handleEndOfValue() {
1488 
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;
1493 
1494         // Skip any remaining chunks
1495         while (blockLength != maxBlockLength) {
1496             end_block();
1497             start_block();
1498         }
1499 
1500         // Now look for the end tag
1501 
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);
1509 
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;
1517 
1518         if (nextLong == 0 || nextLong >= maxBlockLength) {
1519 
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     }
1542 
end_block()1543     private void end_block() {
1544 
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     }
1562 
readValueTag()1563     private int readValueTag(){
1564         // outerValueDone = false;
1565         return read_long();
1566     }
1567 
orb()1568     public org.omg.CORBA.ORB orb() {
1569         return orb;
1570     }
1571 
1572     // ------------ End RMI related methods --------------------------
1573 
read_boolean_array(boolean[] value, int offset, int length)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     }
1579 
read_char_array(char[] value, int offset, int length)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     }
1585 
read_wchar_array(char[] value, int offset, int length)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     }
1591 
read_short_array(short[] value, int offset, int length)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     }
1597 
read_ushort_array(short[] value, int offset, int length)1598     public final void read_ushort_array(short[] value, int offset, int length) {
1599         read_short_array(value, offset, length);
1600     }
1601 
read_long_array(int[] value, int offset, int length)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     }
1607 
read_ulong_array(int[] value, int offset, int length)1608     public final void read_ulong_array(int[] value, int offset, int length) {
1609         read_long_array(value, offset, length);
1610     }
1611 
read_longlong_array(long[] value, int offset, int length)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     }
1617 
read_ulonglong_array(long[] value, int offset, int length)1618     public final void read_ulonglong_array(long[] value, int offset, int length) {
1619         read_longlong_array(value, offset, length);
1620     }
1621 
read_float_array(float[] value, int offset, int length)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     }
1627 
read_double_array(double[] value, int offset, int length)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     }
1633 
read_any_array(org.omg.CORBA.Any[] value, int offset, int length)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     }
1639 
1640     //--------------------------------------------------------------------//
1641     // CDRInputStream state management.
1642     //
1643 
1644     /**
1645      * Are we at the end of the input stream?
1646      */
1647 //     public final boolean isAtEnd() {
1648 //      return bbwi.position() == bbwi.buflen;
1649 //     }
1650 
1651 //     public int available() throws IOException {
1652 //         return bbwi.buflen - bbwi.position();
1653 //     }
1654 
read_repositoryIds()1655     private String read_repositoryIds() {
1656 
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 {
1666 
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);
1673 
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             }
1679 
1680             return repID;
1681         }
1682     }
1683 
read_repositoryId()1684     private final String read_repositoryId()
1685     {
1686         String result = readStringOrIndirection(true);
1687 
1688         if (result == null) { // Indirection
1689             int indirection = read_long() + get_offset() - 4;
1690 
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         }
1701 
1702         return result ;
1703     }
1704 
read_codebase_URL()1705     private final String read_codebase_URL()
1706     {
1707         String result = readStringOrIndirection(true);
1708 
1709         if (result == null) { // Indirection
1710             int indirection = read_long() + get_offset() - 4;
1711 
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         }
1723 
1724         return result;
1725     }
1726 
1727     /* DataInputStream methods */
1728 
read_Abstract()1729     public java.lang.Object read_Abstract () {
1730         return read_abstract_interface();
1731     }
1732 
read_Value()1733     public java.io.Serializable read_Value () {
1734         return read_value();
1735     }
1736 
read_any_array(org.omg.CORBA.AnySeqHolder seq, int offset, int length)1737     public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
1738         read_any_array(seq.value, offset, length);
1739     }
1740 
read_boolean_array(org.omg.CORBA.BooleanSeqHolder seq, int offset, int length)1741     public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
1742         read_boolean_array(seq.value, offset, length);
1743     }
1744 
read_char_array(org.omg.CORBA.CharSeqHolder seq, int offset, int length)1745     public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
1746         read_char_array(seq.value, offset, length);
1747     }
1748 
read_wchar_array(org.omg.CORBA.WCharSeqHolder seq, int offset, int length)1749     public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
1750         read_wchar_array(seq.value, offset, length);
1751     }
1752 
read_octet_array(org.omg.CORBA.OctetSeqHolder seq, int offset, int length)1753     public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
1754         read_octet_array(seq.value, offset, length);
1755     }
1756 
read_short_array(org.omg.CORBA.ShortSeqHolder seq, int offset, int length)1757     public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
1758         read_short_array(seq.value, offset, length);
1759     }
1760 
read_ushort_array(org.omg.CORBA.UShortSeqHolder seq, int offset, int length)1761     public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
1762         read_ushort_array(seq.value, offset, length);
1763     }
1764 
read_long_array(org.omg.CORBA.LongSeqHolder seq, int offset, int length)1765     public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
1766         read_long_array(seq.value, offset, length);
1767     }
1768 
read_ulong_array(org.omg.CORBA.ULongSeqHolder seq, int offset, int length)1769     public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
1770         read_ulong_array(seq.value, offset, length);
1771     }
1772 
read_ulonglong_array(org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length)1773     public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
1774         read_ulonglong_array(seq.value, offset, length);
1775     }
1776 
read_longlong_array(org.omg.CORBA.LongLongSeqHolder seq, int offset, int length)1777     public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
1778         read_longlong_array(seq.value, offset, length);
1779     }
1780 
read_float_array(org.omg.CORBA.FloatSeqHolder seq, int offset, int length)1781     public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
1782         read_float_array(seq.value, offset, length);
1783     }
1784 
read_double_array(org.omg.CORBA.DoubleSeqHolder seq, int offset, int length)1785     public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
1786         read_double_array(seq.value, offset, length);
1787     }
1788 
read_fixed(short digits, short scale)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     }
1798 
1799     // This method is unable to yield the correct scale.
read_fixed()1800     public java.math.BigDecimal read_fixed() {
1801         return new BigDecimal(read_fixed_buffer().toString());
1802     }
1803 
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.
read_fixed_buffer()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     }
1847 
1848     private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0";
1849     private final static String[] _ids = { _id };
1850 
_truncatable_ids()1851     public String[] _truncatable_ids() {
1852         if (_ids == null)
1853             return null;
1854 
1855         return (String[])_ids.clone();
1856     }
1857 
1858     /* for debugging */
1859 
printBuffer()1860     public void printBuffer() {
1861         CDRInputStream_1_0.printBuffer(this.bbwi);
1862     }
1863 
printBuffer(ByteBufferWithInfo bbwi)1864     public static void printBuffer(ByteBufferWithInfo bbwi) {
1865 
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();
1871 
1872         try {
1873 
1874             char[] charBuf = new char[16];
1875 
1876             for (int i = 0; i < bbwi.buflen; i += 16) {
1877 
1878                 int j = 0;
1879 
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                 }
1894 
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                 }
1902 
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             }
1915 
1916         } catch (Throwable t) {
1917             t.printStackTrace();
1918         }
1919 
1920         System.out.println("------------------------");
1921     }
1922 
getByteBuffer()1923     public ByteBuffer getByteBuffer() {
1924         ByteBuffer result = null;
1925         if (bbwi != null) {
1926             result = bbwi.byteBuffer;
1927         }
1928         return result;
1929     }
1930 
getBufferLength()1931     public int getBufferLength() {
1932         return bbwi.buflen;
1933     }
1934 
setBufferLength(int value)1935     public void setBufferLength(int value) {
1936         bbwi.buflen = value;
1937         bbwi.byteBuffer.limit(bbwi.buflen);
1938     }
1939 
setByteBufferWithInfo(ByteBufferWithInfo bbwi)1940     public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
1941         this.bbwi = bbwi;
1942     }
1943 
setByteBuffer(ByteBuffer byteBuffer)1944     public void setByteBuffer(ByteBuffer byteBuffer) {
1945         bbwi.byteBuffer = byteBuffer;
1946     }
1947 
getIndex()1948     public int getIndex() {
1949         return bbwi.position();
1950     }
1951 
setIndex(int value)1952     public void setIndex(int value) {
1953         bbwi.position(value);
1954     }
1955 
isLittleEndian()1956     public boolean isLittleEndian() {
1957         return littleEndian;
1958     }
1959 
orb(org.omg.CORBA.ORB orb)1960     public void orb(org.omg.CORBA.ORB orb) {
1961         this.orb = (ORB)orb;
1962     }
1963 
getBufferManager()1964     public BufferManagerRead getBufferManager() {
1965         return bufferManagerRead;
1966     }
1967 
skipToOffset(int offset)1968     private void skipToOffset(int offset) {
1969 
1970         // Number of bytes to skip
1971         int len = offset - get_offset();
1972 
1973         int n = 0;
1974 
1975         while (n < len) {
1976             int avail;
1977             int bytes;
1978             int wanted;
1979 
1980             avail = bbwi.buflen - bbwi.position();
1981             if (avail <= 0) {
1982                 grow(1, 1);
1983                 avail = bbwi.buflen - bbwi.position();
1984             }
1985 
1986             wanted = len - n;
1987             bytes = (wanted < avail) ? wanted : avail;
1988             bbwi.position(bbwi.position() + bytes);
1989             n += bytes;
1990         }
1991     }
1992 
1993 
1994     // Mark and reset -------------------------------------------------
1995 
1996     protected MarkAndResetHandler markAndResetHandler = null;
1997 
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_;
2011 
StreamMemento()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     }
2025 
createStreamMemento()2026     public java.lang.Object createStreamMemento() {
2027         return new StreamMemento();
2028     }
2029 
restoreInternalState(java.lang.Object streamMemento)2030     public void restoreInternalState(java.lang.Object streamMemento) {
2031 
2032         StreamMemento mem = (StreamMemento)streamMemento;
2033 
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     }
2044 
getPosition()2045     public int getPosition() {
2046         return get_offset();
2047     }
2048 
mark(int readlimit)2049     public void mark(int readlimit) {
2050         markAndResetHandler.mark(this);
2051     }
2052 
reset()2053     public void reset() {
2054         markAndResetHandler.reset();
2055     }
2056 
2057     // ---------------------------------- end Mark and Reset
2058 
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.
getCodeBase()2063     CodeBase getCodeBase() {
2064         return parent.getCodeBase();
2065     }
2066 
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      */
getClassFromString(String repositoryIDString, String codebaseURL, Class expectedType)2074     private Class getClassFromString(String repositoryIDString,
2075                                      String codebaseURL,
2076                                      Class expectedType)
2077     {
2078         RepositoryIdInterface repositoryID
2079             = repIdStrs.getFromString(repositoryIDString);
2080 
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) {
2088 
2089                 try {
2090 
2091                     if (getCodeBase() == null) {
2092                         return null; // class cannot be loaded remotely.
2093                     }
2094 
2095                     // Get a URL from the remote CodeBase and retry
2096                     codebaseURL = getCodeBase().implementation(repositoryIDString);
2097 
2098                     // Don't bother trying to find it locally again if
2099                     // we got a null URL
2100                     if (codebaseURL == null)
2101                         return null;
2102 
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     }
2117 
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      */
getClassFromString(String repositoryIDString, String codebaseURL)2124     private Class getClassFromString(String repositoryIDString,
2125                                      String codebaseURL)
2126     {
2127         RepositoryIdInterface repositoryID
2128             = repIdStrs.getFromString(repositoryIDString);
2129 
2130         for (int i = 0; i < 3; i++) {
2131 
2132             try {
2133 
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                 }
2149 
2150                 // Don't bother if the codebaseURL is null
2151                 if (codebaseURL == null)
2152                     continue;
2153 
2154                 return repositoryID.getClassFromType(codebaseURL);
2155 
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         }
2164 
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);
2170 
2171         return null;
2172     }
2173 
2174     // Utility method used to get chars from bytes
getConvertedChars(int numBytes, CodeSetConversion.BTCConverter converter)2175     char[] getConvertedChars(int numBytes,
2176                              CodeSetConversion.BTCConverter converter) {
2177 
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.
2181 
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);
2201 
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);
2210 
2211             return converter.getChars(bytes, 0, numBytes);
2212         }
2213     }
2214 
getCharConverter()2215     protected CodeSetConversion.BTCConverter getCharConverter() {
2216         if (charConverter == null)
2217             charConverter = parent.createCharBTCConverter();
2218 
2219         return charConverter;
2220     }
2221 
getWCharConverter()2222     protected CodeSetConversion.BTCConverter getWCharConverter() {
2223         if (wcharConverter == null)
2224             wcharConverter = parent.createWCharBTCConverter();
2225 
2226         return wcharConverter;
2227     }
2228 
dprintThrowable(Throwable t)2229     protected void dprintThrowable(Throwable t) {
2230         if (debug && t != null)
2231             t.printStackTrace();
2232     }
2233 
dprint(String msg)2234     protected void dprint(String msg) {
2235         if (debug) {
2236             ORBUtility.dprint(this, msg);
2237         }
2238     }
2239 
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      */
2246 
alignOnBoundary(int octetBoundary)2247     void alignOnBoundary(int octetBoundary) {
2248         int needed = computeAlignment(bbwi.position(), octetBoundary);
2249 
2250         if (bbwi.position() + needed <= bbwi.buflen)
2251         {
2252             bbwi.position(bbwi.position() + needed);
2253         }
2254     }
2255 
resetCodeSetConverters()2256     public void resetCodeSetConverters() {
2257         charConverter = null;
2258         wcharConverter = null;
2259     }
2260 
start_value()2261     public void start_value() {
2262         // Read value tag
2263         int vType = readValueTag();
2264 
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;
2274 
2275             return;
2276         }
2277 
2278         if (vType == 0xffffffff) {
2279             // One should never indirect to a custom wrapper
2280             throw wrapper.customWrapperIndirection(
2281                 CompletionStatus.COMPLETED_MAYBE);
2282         }
2283 
2284         if (repIdUtil.isCodeBasePresent(vType)) {
2285             throw wrapper.customWrapperWithCodebase(
2286                 CompletionStatus.COMPLETED_MAYBE);
2287         }
2288 
2289         if (repIdUtil.getTypeInfo(vType)
2290             != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) {
2291             throw wrapper.customWrapperNotSingleRepid(
2292                 CompletionStatus.COMPLETED_MAYBE);
2293         }
2294 
2295 
2296         // REVISIT - Could verify repository ID even though
2297         // it isn't used elsewhere
2298         read_repositoryId();
2299 
2300         // Note: isChunked should be true here.  Should have
2301         // been set to true in the containing value's read_value
2302         // method.
2303 
2304         start_block();
2305         end_flag--;
2306         chunkedValueNestingLevel--;
2307     }
2308 
end_value()2309     public void end_value() {
2310 
2311         if (specialNoOptionalDataState) {
2312             specialNoOptionalDataState = false;
2313             return;
2314         }
2315 
2316         handleEndOfValue();
2317         readEndTag();
2318 
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.
2323 
2324         // allow for possible continuation chunk
2325         start_block();
2326     }
2327 
close()2328     public void close() throws IOException
2329     {
2330 
2331         // tell BufferManagerRead to release any ByteBuffers
2332         getBufferManager().close(bbwi);
2333 
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.
2339 
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             }
2358 
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 }
2377