KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > encoding > CDRInputStream_1_0


1 /*
2  * @(#)CDRInputStream_1_0.java 1.134 05/01/04
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 /*
9  * Licensed Materials - Property of IBM
10  * RMI-IIOP v1.0
11  * Copyright IBM Corp. 1998 1999 All Rights Reserved
12  *
13  * US Government Users Restricted Rights - Use, duplication or
14  * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
15  */

16
17 package com.sun.corba.se.impl.encoding;
18
19 import java.io.IOException JavaDoc;
20 import java.io.Serializable JavaDoc;
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.ObjectInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.StreamCorruptedException JavaDoc;
25 import java.io.OptionalDataException JavaDoc;
26 import java.io.IOException JavaDoc;
27
28 import java.util.Stack JavaDoc;
29
30 import java.net.URL JavaDoc;
31 import java.net.MalformedURLException JavaDoc;
32
33 import java.nio.ByteBuffer JavaDoc;
34
35 import java.lang.reflect.InvocationTargetException JavaDoc;
36 import java.lang.reflect.Method JavaDoc;
37
38 import java.math.BigDecimal JavaDoc;
39
40 import java.rmi.Remote JavaDoc;
41 import java.rmi.StubNotFoundException JavaDoc;
42
43 import java.security.AccessController JavaDoc;
44 import java.security.PrivilegedExceptionAction JavaDoc;
45 import java.security.PrivilegedActionException JavaDoc;
46
47 import org.omg.CORBA.SystemException JavaDoc;
48 import org.omg.CORBA.Object JavaDoc;
49 import org.omg.CORBA.Principal JavaDoc;
50 import org.omg.CORBA.TypeCode JavaDoc;
51 import org.omg.CORBA.Any JavaDoc;
52 import org.omg.CORBA.portable.Delegate JavaDoc;
53 import org.omg.CORBA.portable.ValueBase JavaDoc;
54 import org.omg.CORBA.portable.IndirectionException JavaDoc;
55 import org.omg.CORBA.CompletionStatus JavaDoc;
56 import org.omg.CORBA.TCKind JavaDoc;
57 import org.omg.CORBA.TypeCodePackage.BadKind JavaDoc;
58 import org.omg.CORBA.CustomMarshal JavaDoc;
59 import org.omg.CORBA.TypeCode JavaDoc;
60 import org.omg.CORBA.Principal JavaDoc;
61 import org.omg.CORBA.Any JavaDoc;
62 import org.omg.CORBA.portable.BoxedValueHelper JavaDoc;
63 import org.omg.CORBA.portable.ValueFactory JavaDoc;
64 import org.omg.CORBA.portable.CustomValue JavaDoc;
65 import org.omg.CORBA.portable.StreamableValue JavaDoc;
66 import org.omg.CORBA.MARSHAL JavaDoc;
67 import org.omg.CORBA.portable.IDLEntity JavaDoc;
68
69 import javax.rmi.PortableRemoteObject JavaDoc;
70 import javax.rmi.CORBA.Tie JavaDoc;
71 import javax.rmi.CORBA.Util JavaDoc;
72 import javax.rmi.CORBA.ValueHandler JavaDoc;
73
74 import com.sun.corba.se.pept.protocol.MessageMediator;
75 import com.sun.corba.se.pept.transport.ByteBufferPool;
76
77 import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
78 import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
79
80 import com.sun.corba.se.spi.ior.IOR;
81 import com.sun.corba.se.spi.ior.IORFactories;
82 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
83
84 import com.sun.corba.se.spi.orb.ORB;
85 import com.sun.corba.se.spi.orb.ORBVersionFactory;
86 import com.sun.corba.se.spi.orb.ORBVersion;
87
88 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
89
90 import com.sun.corba.se.spi.logging.CORBALogDomains;
91 import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
92 import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
93 import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
94
95 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
96 import com.sun.corba.se.impl.logging.OMGSystemException;
97
98 import com.sun.corba.se.impl.corba.PrincipalImpl;
99 import com.sun.corba.se.impl.corba.TypeCodeImpl;
100 import com.sun.corba.se.impl.corba.CORBAObjectImpl;
101
102 import com.sun.corba.se.impl.encoding.CDROutputObject;
103 import com.sun.corba.se.impl.encoding.CodeSetConversion;
104
105 import com.sun.corba.se.impl.util.Utility;
106 import com.sun.corba.se.impl.util.RepositoryId;
107
108 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
109 import com.sun.corba.se.impl.orbutil.RepositoryIdInterface;
110 import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
111 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
112
113 import com.sun.corba.se.impl.orbutil.ORBUtility;
114 import com.sun.corba.se.impl.orbutil.CacheTable;
115
116
117 import com.sun.org.omg.CORBA.portable.ValueHelper;
118
119 import com.sun.org.omg.SendingContext.CodeBase;
120
121 public class CDRInputStream_1_0 extends CDRInputStreamBase
122     implements RestorableInputStream
123 {
124     private static final String JavaDoc kReadMethod = "read";
125     private static final int maxBlockLength = 0x7fffff00;
126
127     protected BufferManagerRead bufferManagerRead;
128     protected ByteBufferWithInfo bbwi;
129
130     // Set to the ORB's transportDebugFlag value. This value is
131
// used if the ORB is null.
132
private boolean debug = false;
133
134     protected boolean littleEndian;
135     protected ORB orb;
136     protected ORBUtilSystemException wrapper ;
137     protected OMGSystemException omgWrapper ;
138     protected ValueHandler JavaDoc valueHandler = null;
139
140     // Value cache
141
private CacheTable valueCache = null;
142     
143     // Repository ID cache
144
private CacheTable repositoryIdCache = null;
145
146     // codebase cache
147
private CacheTable codebaseCache = null;
148
149     // Current Class Stack (repository Ids of current class being read)
150
// private Stack currentStack = null;
151

152     // Length of current chunk, or a large positive number if not in a chunk
153
protected int blockLength = maxBlockLength;
154
155     // Read end flag (value nesting depth)
156
protected int end_flag = 0;
157
158     // Beginning with the resolution to interop issue 3526 (4328?),
159
// only enclosing chunked valuetypes are taken into account
160
// when computing the nesting level. However, we still need
161
// the old computation around for interoperability with our
162
// older ORBs.
163
private int chunkedValueNestingLevel = 0;
164
165     // Flag used to determine whether blocksize was zero
166
// private int checkForNullBlock = -1;
167

168     // In block flag
169
// private boolean inBlock = false;
170

171     // Indicates whether we are inside a value
172
// private boolean outerValueDone = true;
173

174     // Int used by read_value(Serializable) that is set by this class
175
// before calling ValueFactory.read_value
176
protected int valueIndirection = 0;
177
178     // Int set by readStringOrIndirection to communicate the actual
179
// offset of the string length field back to the caller
180
protected int stringIndirection = 0;
181
182     // Flag indicating whether we are unmarshalling a chunked value
183
protected boolean isChunked = false;
184
185     // Repository ID handlers
186
private RepositoryIdUtility repIdUtil;
187     private RepositoryIdStrings repIdStrs;
188
189     // Code set converters (created when first needed)
190
private CodeSetConversion.BTCConverter charConverter;
191     private CodeSetConversion.BTCConverter wcharConverter;
192
193     // RMI-IIOP stream format version 2 case in which we know
194
// that there is no more optional data available. If the
195
// Serializable's readObject method tries to read anything,
196
// we must throw a MARSHAL with the special minor code
197
// so that the ValueHandler can give the correct exception
198
// to readObject. The state is cleared when the ValueHandler
199
// calls end_value after the readObject method exits.
200
private boolean specialNoOptionalDataState = false;
201     
202     // Template method
203
public CDRInputStreamBase dup()
204     {
205         CDRInputStreamBase result = null ;
206
207         try {
208             result = (CDRInputStreamBase)this.getClass().newInstance();
209         } catch (Exception JavaDoc e) {
210         throw wrapper.couldNotDuplicateCdrInputStream( e ) ;
211         }
212         result.init(this.orb,
213                     this.bbwi.byteBuffer,
214                     this.bbwi.buflen,
215                     this.littleEndian,
216                     this.bufferManagerRead);
217
218         ((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position());
219         // To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen.
220
((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen);
221
222         return result;
223     }
224
225     /**
226      * NOTE: size passed to init means buffer size
227      */

228     public void init(org.omg.CORBA.ORB JavaDoc orb,
229                      ByteBuffer JavaDoc byteBuffer,
230                      int size,
231                      boolean littleEndian,
232                      BufferManagerRead bufferManager)
233     {
234         this.orb = (ORB)orb;
235     this.wrapper = ORBUtilSystemException.get( (ORB)orb,
236         CORBALogDomains.RPC_ENCODING ) ;
237     this.omgWrapper = OMGSystemException.get( (ORB)orb,
238         CORBALogDomains.RPC_ENCODING ) ;
239         this.littleEndian = littleEndian;
240         this.bufferManagerRead = bufferManager;
241         this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0);
242         this.bbwi.buflen = size;
243         this.bbwi.byteBuffer.limit(bbwi.buflen);
244         this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler();
245
246     debug = ((ORB)orb).transportDebugFlag;
247     }
248  
249     // See description in CDRInputStream
250
void performORBVersionSpecificInit() {
251         createRepositoryIdHandlers();
252     }
253
254     private final void createRepositoryIdHandlers()
255     {
256     repIdUtil = RepositoryIdFactory.getRepIdUtility(orb);
257     repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(orb);
258     }
259
260     public GIOPVersion getGIOPVersion() {
261         return GIOPVersion.V1_0;
262     }
263     
264     // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
265
// Illegal for GIOP versions < 1.2.
266
void setHeaderPadding(boolean headerPadding) {
267         throw wrapper.giopVersionError();
268     }
269
270     protected final int computeAlignment(int index, int align) {
271         if (align > 1) {
272             int incr = index & (align - 1);
273             if (incr != 0)
274                 return align - incr;
275         }
276
277         return 0;
278     }
279
280     public int getSize()
281     {
282         return bbwi.position();
283     }
284
285     protected void checkBlockLength(int align, int dataSize) {
286     // Since chunks can end at arbitrary points (though not within
287
// primitive CDR types, arrays of primitives, strings, wstrings,
288
// or indirections),
289
// we must check here for termination of the current chunk.
290
if (!isChunked)
291             return;
292
293         // RMI-IIOP stream format version 2 case in which we know
294
// that there is no more optional data available. If the
295
// Serializable's readObject method tries to read anything,
296
// we must throw a MARSHAL exception with the special minor code
297
// so that the ValueHandler can give the correct exception
298
// to readObject. The state is cleared when the ValueHandler
299
// calls end_value after the readObject method exits.
300
if (specialNoOptionalDataState) {
301         throw omgWrapper.rmiiiopOptionalDataIncompatible1() ;
302         }
303
304         boolean checkForEndTag = false;
305
306         // Are we at the end of the current chunk? If so,
307
// try to interpret the next long as a chunk length.
308
// (It has to be either a chunk length, end tag,
309
// or valuetag.)
310
//
311
// If it isn't a chunk length, blockLength will
312
// remain set to maxBlockLength.
313
if (blockLength == get_offset()) {
314
315         blockLength = maxBlockLength;
316         start_block();
317
318             // What's next is either a valuetag or
319
// an end tag. If it's a valuetag, we're
320
// probably being called as part of the process
321
// to read the valuetag. If it's an end tag,
322
// then there isn't enough data left in
323
// this valuetype to read!
324
if (blockLength == maxBlockLength)
325                 checkForEndTag = true;
326
327     } else
328         if (blockLength < get_offset()) {
329         // Are we already past the end of the current chunk?
330
// This is always an error.
331
throw wrapper.chunkOverflow() ;
332     }
333
334         // If what's next on the wire isn't a chunk length or
335
// what we want to read (which can't be split across chunks)
336
// won't fit in the current chunk, throw this exception.
337
// This probably means that we're in an RMI-IIOP
338
// Serializable's readObject method or a custom marshaled
339
// IDL type is reading too much/in an incorrect order
340
int requiredNumBytes =
341                             computeAlignment(bbwi.position(), align) + dataSize;
342
343         if (blockLength != maxBlockLength &&
344             blockLength < get_offset() + requiredNumBytes) {
345         throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
346         }
347
348         // REVISIT - We should look at using the built in advancement
349
// of using ByteBuffer.get() rather than explicitly
350
// advancing the ByteBuffer's position.
351
// This is true for anywhere we are incrementing
352
// the ByteBuffer's position.
353
if (checkForEndTag) {
354             int nextLong = read_long();
355             bbwi.position(bbwi.position() - 4);
356
357             // It was an end tag, so there wasn't enough data
358
// left in the valuetype's encoding on the wire
359
// to read what we wanted
360
if (nextLong < 0)
361         throw omgWrapper.rmiiiopOptionalDataIncompatible3() ;
362         }
363     }
364
365     protected void alignAndCheck(int align, int n) {
366
367         checkBlockLength(align, n);
368
369         // WARNING: Must compute real alignment after calling
370
// checkBlockLength since it may move the position
371
int alignResult = computeAlignment(bbwi.position(), align);
372         bbwi.position(bbwi.position() + alignResult);
373
374         if (bbwi.position() + n > bbwi.buflen)
375             grow(align, n);
376     }
377
378     //
379
// This can be overridden....
380
//
381
protected void grow(int align, int n) {
382                 
383         bbwi.needed = n;
384
385         bbwi = bufferManagerRead.underflow(bbwi);
386
387     }
388
389     //
390
// Marshal primitives.
391
//
392

393     public final void consumeEndian() {
394     littleEndian = read_boolean();
395     }
396
397     // No such type in java
398
public final double read_longdouble() {
399     throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE);
400     }
401
402     public final boolean read_boolean() {
403     return (read_octet() != 0);
404     }
405
406     public final char read_char() {
407         alignAndCheck(1, 1);
408
409         return getConvertedChars(1, getCharConverter())[0];
410     }
411
412     public char read_wchar() {
413
414         // Don't allow transmission of wchar/wstring data with
415
// foreign ORBs since it's against the spec.
416
if (ORBUtility.isForeignORB((ORB)orb)) {
417         throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
418         }
419
420         // If we're talking to one of our legacy ORBs, do what
421
// they did:
422
int b1, b2;
423
424     alignAndCheck(2, 2);
425
426     if (littleEndian) {
427         b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
428             bbwi.position(bbwi.position() + 1);
429         b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
430             bbwi.position(bbwi.position() + 1);
431     } else {
432         b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
433             bbwi.position(bbwi.position() + 1);
434         b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
435             bbwi.position(bbwi.position() + 1);
436     }
437
438     return (char)((b1 << 8) + (b2 << 0));
439     }
440
441     public final byte read_octet() {
442
443         alignAndCheck(1, 1);
444
445         byte b = bbwi.byteBuffer.get(bbwi.position());
446         bbwi.position(bbwi.position() + 1);
447
448         return b;
449     }
450
451     public final short read_short() {
452         int b1, b2;
453
454         alignAndCheck(2, 2);
455
456         if (littleEndian) {
457             b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
458             bbwi.position(bbwi.position() + 1);
459             b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
460             bbwi.position(bbwi.position() + 1);
461         } else {
462             b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
463             bbwi.position(bbwi.position() + 1);
464             b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
465             bbwi.position(bbwi.position() + 1);
466         }
467
468         return (short)(b1 | b2);
469     }
470
471     public final short read_ushort() {
472     return read_short();
473     }
474
475     public final int read_long() {
476         int b1, b2, b3, b4;
477
478         alignAndCheck(4, 4);
479
480         int bufPos = bbwi.position();
481         if (littleEndian) {
482             b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
483             b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
484             b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
485             b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
486         } else {
487             b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
488             b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
489             b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
490             b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
491         }
492         bbwi.position(bufPos);
493
494         return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
495     }
496
497     public final int read_ulong() {
498     return read_long();
499     }
500
501     public final long read_longlong() {
502         long i1, i2;
503
504         alignAndCheck(8, 8);
505
506         if (littleEndian) {
507             i2 = read_long() & 0xFFFFFFFFL;
508             i1 = (long)read_long() << 32;
509         } else {
510             i1 = (long)read_long() << 32;
511             i2 = read_long() & 0xFFFFFFFFL;
512         }
513
514         return (i1 | i2);
515     }
516
517     public final long read_ulonglong() {
518     return read_longlong();
519     }
520
521     public final float read_float() {
522     return Float.intBitsToFloat(read_long());
523     }
524
525     public final double read_double() {
526     return Double.longBitsToDouble(read_longlong());
527     }
528
529     protected final void checkForNegativeLength(int length) {
530         if (length < 0)
531         throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE,
532         new Integer JavaDoc(length) ) ;
533     }
534
535     protected final String JavaDoc readStringOrIndirection(boolean allowIndirection) {
536
537         int len = read_long();
538
539         //
540
// Check for indirection
541
//
542
if (allowIndirection) {
543             if (len == 0xffffffff)
544         return null;
545         else
546         stringIndirection = get_offset() - 4;
547     }
548
549         checkForNegativeLength(len);
550
551         if (orb != null && ORBUtility.isLegacyORB((ORB)orb))
552             return legacyReadString(len);
553         else
554             return internalReadString(len);
555     }
556
557     private final String JavaDoc internalReadString(int len) {
558         // Workaround for ORBs which send string lengths of
559
// zero to mean empty string.
560
//
561
// IMPORTANT: Do not replace 'new String("")' with "", it may result
562
// in a Serialization bug (See serialization.zerolengthstring) and
563
// bug id: 4728756 for details
564
if (len == 0)
565             return new String JavaDoc("");
566
567         char[] result = getConvertedChars(len - 1, getCharConverter());
568
569         // Skip over the 1 byte null
570
read_octet();
571
572         return new String JavaDoc(result, 0, getCharConverter().getNumChars());
573     }
574
575     private final String JavaDoc legacyReadString(int len) {
576
577         //
578
// Workaround for ORBs which send string lengths of
579
// zero to mean empty string.
580
//
581
//
582
// IMPORTANT: Do not replace 'new String("")' with "", it may result
583
// in a Serialization bug (See serialization.zerolengthstring) and
584
// bug id: 4728756 for details
585
if (len == 0)
586             return new String JavaDoc("");
587
588         len--;
589         char[] c = new char[len];
590
591         int n = 0;
592         while (n < len) {
593             int avail;
594             int bytes;
595             int wanted;
596
597             avail = bbwi.buflen - bbwi.position();
598             if (avail <= 0) {
599                 grow(1, 1);
600                 avail = bbwi.buflen - bbwi.position();
601             }
602             wanted = len - n;
603             bytes = (wanted < avail) ? wanted : avail;
604             // Microbenchmarks are showing a loop of ByteBuffer.get(int) being
605
// faster than ByteBuffer.get(byte[], int, int).
606
for (int i=0; i<bytes; i++) {
607             c[n+i] = (char) (bbwi.byteBuffer.get(bbwi.position()+i) & 0xFF);
608             }
609             bbwi.position(bbwi.position() + bytes);
610             n += bytes;
611         }
612
613         //
614
// Skip past terminating null byte
615
//
616
if (bbwi.position() + 1 > bbwi.buflen)
617             alignAndCheck(1, 1);
618         bbwi.position(bbwi.position() + 1);
619
620         return new String JavaDoc(c);
621     }
622
623     public final String JavaDoc read_string() {
624         return readStringOrIndirection(false);
625     }
626
627     public String JavaDoc read_wstring() {
628         // Don't allow transmission of wchar/wstring data with
629
// foreign ORBs since it's against the spec.
630
if (ORBUtility.isForeignORB((ORB)orb)) {
631         throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
632         }
633
634         int len = read_long();
635
636         //
637
// Workaround for ORBs which send string lengths of
638
// zero to mean empty string.
639
//
640
//
641
// IMPORTANT: Do not replace 'new String("")' with "", it may result
642
// in a Serialization bug (See serialization.zerolengthstring) and
643
// bug id: 4728756 for details
644
if (len == 0)
645             return new String JavaDoc("");
646
647         checkForNegativeLength(len);
648
649         len--;
650         char[] c = new char[len];
651
652         for (int i = 0; i < len; i++)
653             c[i] = read_wchar();
654
655         // skip the two null terminator bytes
656
read_wchar();
657         // bbwi.position(bbwi.position() + 2);
658

659         return new String JavaDoc(c);
660     }
661
662     public final void read_octet_array(byte[] b, int offset, int length) {
663         if ( b == null )
664         throw wrapper.nullParam() ;
665
666         // Must call alignAndCheck at least once to ensure
667
// we aren't at the end of a chunk. Of course, we
668
// should only call it if we actually need to read
669
// something, otherwise we might end up with an
670
// exception at the end of the stream.
671
if (length == 0)
672             return;
673
674         alignAndCheck(1, 1);
675
676         int n = offset;
677         while (n < length+offset) {
678             int avail;
679             int bytes;
680             int wanted;
681
682             avail = bbwi.buflen - bbwi.position();
683             if (avail <= 0) {
684                 grow(1, 1);
685                 avail = bbwi.buflen - bbwi.position();
686             }
687             wanted = (length + offset) - n;
688             bytes = (wanted < avail) ? wanted : avail;
689             // Microbenchmarks are showing a loop of ByteBuffer.get(int) being
690
// faster than ByteBuffer.get(byte[], int, int).
691
for (int i = 0; i < bytes; i++) {
692                 b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i);
693             }
694
695             bbwi.position(bbwi.position() + bytes);
696
697             n += bytes;
698         }
699     }
700
701     public Principal JavaDoc read_Principal() {
702         int len = read_long();
703         byte[] pvalue = new byte[len];
704         read_octet_array(pvalue,0,len);
705
706         Principal JavaDoc p = new PrincipalImpl();
707         p.name(pvalue);
708         return p;
709     }
710
711     public TypeCode JavaDoc read_TypeCode() {
712         TypeCodeImpl tc = new TypeCodeImpl(orb);
713         tc.read_value(parent);
714     return tc;
715     }
716   
717     public Any JavaDoc read_any() {
718         Any JavaDoc any = orb.create_any();
719         TypeCodeImpl tc = new TypeCodeImpl(orb);
720
721         // read off the typecode
722

723         // REVISIT We could avoid this try-catch if we could peek the typecode
724
// kind off this stream and see if it is a tk_value. Looking at the
725
// code we know that for tk_value the Any.read_value() below
726
// ignores the tc argument anyway (except for the kind field).
727
// But still we would need to make sure that the whole typecode,
728
// including encapsulations, is read off.
729
try {
730             tc.read_value(parent);
731         } catch (MARSHAL JavaDoc ex) {
732             if (tc.kind().value() != TCKind._tk_value)
733                 throw ex;
734             // We can be sure that the whole typecode encapsulation has been
735
// read off.
736
dprintThrowable(ex);
737         }
738         // read off the value of the any
739
any.read_value(parent, tc);
740
741         return any;
742     }
743
744     public org.omg.CORBA.Object JavaDoc read_Object() {
745         return read_Object(null);
746     }
747
748     // ------------ RMI related methods --------------------------
749

750     // IDL to Java ptc-00-01-08 1.21.4.1
751
//
752
// The clz argument to read_Object can be either a stub
753
// Class or the "Class object for the RMI/IDL interface type
754
// that is statically expected."
755
// This functions as follows:
756
// 1. If clz==null, just use the repository ID from the stub
757
// 2. If clz is a stub class, just use it as a static factory.
758
// clz is a stub class iff StubAdapter.isStubClass( clz ).
759
// In addition, clz is a IDL stub class iff
760
// IDLEntity.class.isAssignableFrom( clz ).
761
// 3. If clz is an interface, use it to create the appropriate
762
// stub factory.
763
public org.omg.CORBA.Object JavaDoc read_Object(Class JavaDoc clz)
764     {
765     // In any case, we must first read the IOR.
766
IOR ior = IORFactories.makeIOR(parent) ;
767     if (ior.isNil())
768         return null ;
769
770     PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ;
771     String JavaDoc codeBase = ior.getProfile().getCodebase() ;
772     PresentationManager.StubFactory stubFactory = null ;
773
774         if (clz == null) {
775         RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ;
776         String JavaDoc className = rid.getClassName() ;
777         boolean isIDLInterface = rid.isIDLType() ;
778
779         if (className == null || className.equals( "" ))
780         stubFactory = null ;
781         else
782         try {
783             stubFactory = sff.createStubFactory( className,
784             isIDLInterface, codeBase, (Class JavaDoc)null,
785             (ClassLoader JavaDoc)null );
786         } catch (Exception JavaDoc exc) {
787             // Could not create stubFactory, so use null.
788
// XXX stubFactory handling is still too complex:
789
// Can we resolve the stubFactory question once in
790
// a single place?
791
stubFactory = null ;
792         }
793         } else if (StubAdapter.isStubClass( clz )) {
794         stubFactory = PresentationDefaults.makeStaticStubFactory(
795         clz ) ;
796     } else {
797         // clz is an interface class
798
boolean isIDL = IDLEntity JavaDoc.class.isAssignableFrom( clz ) ;
799
800         stubFactory = sff.createStubFactory( clz.getName(),
801         isIDL, codeBase, clz, clz.getClassLoader() ) ;
802     }
803
804     return internalIORToObject( ior, stubFactory, orb ) ;
805     }
806
807     /*
808      * This is used as a general utility (e.g., the PortableInterceptor
809      * implementation uses it. If stubFactory is null, the ior's
810      * IIOPProfile must support getServant.
811      */

812     public static org.omg.CORBA.Object JavaDoc internalIORToObject(
813         IOR ior, PresentationManager.StubFactory stubFactory, ORB orb)
814     {
815     ORBUtilSystemException wrapper = ORBUtilSystemException.get(
816         (ORB)orb, CORBALogDomains.RPC_ENCODING ) ;
817
818     java.lang.Object JavaDoc servant = ior.getProfile().getServant() ;
819     if (servant != null ) {
820         if (servant instanceof Tie JavaDoc) {
821         String JavaDoc codebase = ior.getProfile().getCodebase();
822         org.omg.CORBA.Object JavaDoc objref = (org.omg.CORBA.Object JavaDoc)
823             Utility.loadStub( (Tie JavaDoc)servant, stubFactory, codebase,
824             false);
825             
826         // If we managed to load a stub, return it, otherwise we
827
// must fail...
828
if (objref != null) {
829             return objref;
830         } else {
831             throw wrapper.readObjectException() ;
832         }
833         } else if (servant instanceof org.omg.CORBA.Object JavaDoc) {
834         if (!(servant instanceof
835             org.omg.CORBA.portable.InvokeHandler JavaDoc)) {
836             return (org.omg.CORBA.Object JavaDoc) servant;
837         }
838         } else
839         throw wrapper.badServantReadObject() ;
840     }
841
842     CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ;
843     org.omg.CORBA.Object JavaDoc objref = null ;
844     try {
845         objref = stubFactory.makeStub() ;
846     } catch (Throwable JavaDoc e) {
847         wrapper.stubCreateError( e ) ;
848
849         if (e instanceof ThreadDeath JavaDoc) {
850         throw (ThreadDeath JavaDoc) e;
851         }
852
853             // Return the "default" stub...
854
objref = new CORBAObjectImpl() ;
855     }
856         
857     StubAdapter.setDelegate( objref, del ) ;
858     return objref;
859     }
860  
861     public java.lang.Object JavaDoc read_abstract_interface()
862     {
863         return read_abstract_interface(null);
864     }
865
866     public java.lang.Object JavaDoc read_abstract_interface(java.lang.Class JavaDoc clz)
867     {
868         boolean object = read_boolean();
869
870         if (object) {
871             return read_Object(clz);
872         } else {
873             return read_value();
874     }
875     }
876
877     public Serializable JavaDoc read_value()
878     {
879         return read_value((Class JavaDoc)null);
880     }
881
882     private Serializable JavaDoc handleIndirection() {
883         int indirection = read_long() + get_offset() - 4;
884         if (valueCache != null && valueCache.containsVal(indirection)) {
885
886             java.io.Serializable JavaDoc cachedValue
887                 = (java.io.Serializable JavaDoc)valueCache.getKey(indirection);
888             return cachedValue;
889         } else {
890             // In RMI-IIOP the ValueHandler will recognize this
891
// exception and use the provided indirection value
892
// to lookup a possible indirection to an object
893
// currently on the deserialization stack.
894
throw new IndirectionException JavaDoc(indirection);
895         }
896     }
897
898     private String JavaDoc readRepositoryIds(int valueTag,
899                                      Class JavaDoc expectedType,
900                                      String JavaDoc expectedTypeRepId) {
901     return readRepositoryIds(valueTag, expectedType,
902                  expectedTypeRepId, null);
903     }
904
905     /**
906      * Examines the valuetag to see how many (if any) repository IDs
907      * are present on the wire. If no repository ID information
908      * is on the wire but the expectedType or expectedTypeRepId
909      * is known, it will return one of those (favoring the
910      * expectedType's repId). Failing that, it uses the supplied
911      * BoxedValueHelper to obtain the repository ID, as a last resort.
912      */

913     private String JavaDoc readRepositoryIds(int valueTag,
914                                      Class JavaDoc expectedType,
915                                      String JavaDoc expectedTypeRepId,
916                      BoxedValueHelper JavaDoc factory) {
917         switch(repIdUtil.getTypeInfo(valueTag)) {
918             case RepositoryIdUtility.NO_TYPE_INFO :
919                 // Throw an exception if we have no repository ID info and
920
// no expectedType to work with. Otherwise, how would we
921
// know what to unmarshal?
922
if (expectedType == null) {
923                     if (expectedTypeRepId != null) {
924                         return expectedTypeRepId;
925                     } else if (factory != null) {
926             return factory.get_id();
927             } else {
928             throw wrapper.expectedTypeNullAndNoRepId(
929                 CompletionStatus.COMPLETED_MAYBE);
930             }
931                 }
932                 return repIdStrs.createForAnyType(expectedType);
933             case RepositoryIdUtility.SINGLE_REP_TYPE_INFO :
934                 return read_repositoryId();
935             case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO :
936                 return read_repositoryIds();
937             default:
938         throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE,
939             Integer.toHexString(valueTag) ) ;
940         }
941     }
942
943     public Serializable JavaDoc read_value(Class JavaDoc expectedType) {
944
945         // Read value tag
946
int vType = readValueTag();
947
948         // Is value null?
949
if (vType == 0)
950             return null;
951
952         // Is this an indirection to a previously
953
// read valuetype?
954
if (vType == 0xffffffff)
955             return handleIndirection();
956
957         // Save where this valuetype started so we
958
// can put it in the indirection valueCache
959
// later
960
int indirection = get_offset() - 4;
961
962         // Need to save this special marker variable
963
// to restore its value during recursion
964
boolean saveIsChunked = isChunked;
965
966         isChunked = repIdUtil.isChunkedEncoding(vType);
967             
968         java.lang.Object JavaDoc value = null;
969             
970         String JavaDoc codebase_URL = null;
971         if (repIdUtil.isCodeBasePresent(vType)) {
972             codebase_URL = read_codebase_URL();
973         }
974             
975         // Read repository id(s)
976
String JavaDoc repositoryIDString
977             = readRepositoryIds(vType, expectedType, null);
978
979         // If isChunked was determined to be true based
980
// on the valuetag, this will read a chunk length
981
start_block();
982
983         // Remember that end_flag keeps track of all nested
984
// valuetypes and is used for older ORBs
985
end_flag--;
986         if (isChunked)
987             chunkedValueNestingLevel--;
988
989         if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) {
990             value = read_wstring();
991         } else
992         if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) {
993             // read in the class whether with the old ClassDesc or the
994
// new one
995
value = readClass();
996         } else {
997                 
998             Class JavaDoc valueClass = expectedType;
999
1000            // By this point, either the expectedType or repositoryIDString
1001
// is guaranteed to be non-null.
1002
if (expectedType == null ||
1003                !repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) {
1004
1005                valueClass = getClassFromString(repositoryIDString,
1006                                                codebase_URL,
1007                                                expectedType);
1008            }
1009
1010            if (valueClass == null) {
1011                // No point attempting to use value handler below, since the
1012
// class information is not available.
1013
throw wrapper.couldNotFindClass(
1014                    CompletionStatus.COMPLETED_MAYBE,
1015                    new ClassNotFoundException JavaDoc());
1016            }
1017            
1018            if (valueClass != null &&
1019                org.omg.CORBA.portable.IDLEntity JavaDoc.class.isAssignableFrom(valueClass)) {
1020                    
1021                value = readIDLValue(indirection,
1022                                      repositoryIDString,
1023                                      valueClass,
1024                                      codebase_URL);
1025
1026            } else {
1027
1028                // Must be some form of RMI-IIOP valuetype
1029

1030                try {
1031                    if (valueHandler == null)
1032                        valueHandler = ORBUtility.createValueHandler(orb);
1033
1034                    value = valueHandler.readValue(parent,
1035                                                   indirection,
1036                                                   valueClass,
1037                                                   repositoryIDString,
1038                                                   getCodeBase());
1039
1040                } catch(SystemException JavaDoc sysEx) {
1041                    // Just rethrow any CORBA system exceptions
1042
// that come out of the ValueHandler
1043
throw sysEx;
1044                } catch(Exception JavaDoc ex) {
1045            throw wrapper.valuehandlerReadException(
1046            CompletionStatus.COMPLETED_MAYBE, ex ) ;
1047                } catch(Error JavaDoc e) {
1048            throw wrapper.valuehandlerReadError(
1049            CompletionStatus.COMPLETED_MAYBE, e ) ;
1050                }
1051            }
1052        }
1053        
1054        // Skip any remaining chunks until we get to
1055
// an end tag or a valuetag. If we see a valuetag,
1056
// that means there was another valuetype in the sender's
1057
// version of this class that we need to skip over.
1058
handleEndOfValue();
1059        
1060        // Read and process the end tag if we're chunking.
1061
// Assumes that we're at the position of the end tag
1062
// (handleEndOfValue should assure this)
1063
readEndTag();
1064            
1065        // Cache the valuetype that we read
1066
if (valueCache == null)
1067            valueCache = new CacheTable(orb,false);
1068        valueCache.put(value, indirection);
1069        
1070        // Allow for possible continuation chunk.
1071
// If we're a nested valuetype inside of a chunked
1072
// valuetype, and that enclosing valuetype has
1073
// more data to write, it will need to have this
1074
// new chunk begin after we wrote our end tag.
1075
isChunked = saveIsChunked;
1076        start_block();
1077        
1078        return (java.io.Serializable JavaDoc)value;
1079    }
1080
1081    public Serializable JavaDoc read_value(BoxedValueHelper JavaDoc factory) {
1082
1083        // Read value tag
1084
int vType = readValueTag();
1085
1086        if (vType == 0)
1087            return null; // value is null
1088
else if (vType == 0xffffffff) { // Indirection tag
1089
int indirection = read_long() + get_offset() - 4;
1090            if (valueCache != null && valueCache.containsVal(indirection))
1091        {
1092            java.io.Serializable JavaDoc cachedValue =
1093                           (java.io.Serializable JavaDoc)valueCache.getKey(indirection);
1094            return cachedValue;
1095        }
1096            else {
1097        throw new IndirectionException JavaDoc(indirection);
1098        }
1099    }
1100        else {
1101        int indirection = get_offset() - 4;
1102
1103        // end_block();
1104

1105        boolean saveIsChunked = isChunked;
1106        isChunked = repIdUtil.isChunkedEncoding(vType);
1107
1108        java.lang.Object JavaDoc value = null;
1109
1110        String JavaDoc codebase_URL = null;
1111        if (repIdUtil.isCodeBasePresent(vType)){
1112        codebase_URL = read_codebase_URL();
1113        }
1114
1115            // Read repository id
1116
String JavaDoc repositoryIDString
1117                = readRepositoryIds(vType, null, null, factory);
1118
1119            // Compare rep. ids to see if we should use passed helper
1120
if (!repositoryIDString.equals(factory.get_id()))
1121        factory = Utility.getHelper(null, codebase_URL, repositoryIDString);
1122
1123        start_block();
1124        end_flag--;
1125            if (isChunked)
1126                chunkedValueNestingLevel--;
1127        
1128        if (factory instanceof ValueHelper JavaDoc) {
1129        value = readIDLValueWithHelper((ValueHelper JavaDoc)factory, indirection);
1130        } else {
1131        valueIndirection = indirection; // for callback
1132
value = factory.read_value(parent);
1133        }
1134
1135        handleEndOfValue();
1136        readEndTag();
1137
1138        // Put into valueCache
1139
if (valueCache == null)
1140        valueCache = new CacheTable(orb,false);
1141        valueCache.put(value, indirection);
1142    
1143        // allow for possible continuation chunk
1144
isChunked = saveIsChunked;
1145        start_block();
1146
1147            return (java.io.Serializable JavaDoc)value;
1148        }
1149    }
1150
1151    private boolean isCustomType(ValueHelper JavaDoc helper) {
1152    try{
1153        TypeCode JavaDoc tc = helper.get_type();
1154        int kind = tc.kind().value();
1155        if (kind == TCKind._tk_value) {
1156        return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value);
1157        }
1158    } catch(BadKind JavaDoc ex) {
1159        throw wrapper.badKind(ex) ;
1160    }
1161
1162    return false;
1163    }
1164
1165    // This method is actually called indirectly by
1166
// read_value(String repositoryId).
1167
// Therefore, it is not a truly independent read call that handles
1168
// header information itself.
1169
public java.io.Serializable JavaDoc read_value(java.io.Serializable JavaDoc value) {
1170
1171    // Put into valueCache using valueIndirection
1172
if (valueCache == null)
1173        valueCache = new CacheTable(orb,false);
1174    valueCache.put(value, valueIndirection);
1175
1176    if (value instanceof StreamableValue JavaDoc)
1177        ((StreamableValue JavaDoc)value)._read(parent);
1178    else if (value instanceof CustomValue JavaDoc)
1179        ((CustomValue JavaDoc)value).unmarshal(parent);
1180            
1181    return value;
1182    }
1183
1184    public java.io.Serializable JavaDoc read_value(java.lang.String JavaDoc repositoryId) {
1185
1186    // if (inBlock)
1187
// end_block();
1188

1189        // Read value tag
1190
int vType = readValueTag();
1191
1192        if (vType == 0)
1193            return null; // value is null
1194
else if (vType == 0xffffffff) { // Indirection tag
1195
int indirection = read_long() + get_offset() - 4;
1196            if (valueCache != null && valueCache.containsVal(indirection))
1197        {
1198            java.io.Serializable JavaDoc cachedValue =
1199                          (java.io.Serializable JavaDoc)valueCache.getKey(indirection);
1200            return cachedValue;
1201        }
1202            else {
1203        throw new IndirectionException JavaDoc(indirection);
1204        }
1205    }
1206        else {
1207        int indirection = get_offset() - 4;
1208
1209        // end_block();
1210

1211        boolean saveIsChunked = isChunked;
1212        isChunked = repIdUtil.isChunkedEncoding(vType);
1213
1214        java.lang.Object JavaDoc value = null;
1215
1216        String JavaDoc codebase_URL = null;
1217        if (repIdUtil.isCodeBasePresent(vType)){
1218        codebase_URL = read_codebase_URL();
1219        }
1220
1221            // Read repository id
1222
String JavaDoc repositoryIDString
1223                = readRepositoryIds(vType, null, repositoryId);
1224
1225        ValueFactory JavaDoc factory =
1226               Utility.getFactory(null, codebase_URL, orb, repositoryIDString);
1227
1228        start_block();
1229        end_flag--;
1230            if (isChunked)
1231                chunkedValueNestingLevel--;
1232
1233        valueIndirection = indirection; // for callback
1234
value = factory.read_value(parent);
1235
1236        handleEndOfValue();
1237        readEndTag();
1238
1239        // Put into valueCache
1240
if (valueCache == null)
1241        valueCache = new CacheTable(orb,false);
1242        valueCache.put(value, indirection);
1243    
1244        // allow for possible continuation chunk
1245
isChunked = saveIsChunked;
1246        start_block();
1247
1248            return (java.io.Serializable JavaDoc)value;
1249        }
1250    }
1251
1252    private Class JavaDoc readClass() {
1253
1254        String JavaDoc codebases = null, classRepId = null;
1255
1256        if (orb == null ||
1257            ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
1258            ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
1259
1260            codebases = (String JavaDoc)read_value(java.lang.String JavaDoc.class);
1261            classRepId = (String JavaDoc)read_value(java.lang.String JavaDoc.class);
1262        } else {
1263            // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
1264
// and codebase strings in the wrong order.
1265
classRepId = (String JavaDoc)read_value(java.lang.String JavaDoc.class);
1266            codebases = (String JavaDoc)read_value(java.lang.String JavaDoc.class);
1267        }
1268
1269        if (debug) {
1270            dprint("readClass codebases: "
1271           + codebases
1272           + " rep Id: "
1273           + classRepId);
1274        }
1275
1276        Class JavaDoc cl = null;
1277
1278        RepositoryIdInterface repositoryID
1279            = repIdStrs.getFromString(classRepId);
1280        
1281        try {
1282            cl = repositoryID.getClassFromType(codebases);
1283        } catch(ClassNotFoundException JavaDoc cnfe) {
1284            throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE,
1285        cnfe, repositoryID.getClassName() ) ;
1286        } catch(MalformedURLException JavaDoc me) {
1287        throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
1288        me, repositoryID.getClassName(), codebases ) ;
1289        }
1290
1291    return cl;
1292    }
1293
1294    private java.lang.Object JavaDoc readIDLValueWithHelper(ValueHelper JavaDoc helper, int indirection)
1295    {
1296    // look for two-argument static read method
1297
Method JavaDoc readMethod;
1298    try {
1299        Class JavaDoc argTypes[] = {org.omg.CORBA.portable.InputStream JavaDoc.class, helper.get_class()};
1300        readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes);
1301    }
1302    catch(NoSuchMethodException JavaDoc nsme) { // must be boxed value helper
1303
java.lang.Object JavaDoc result = helper.read_value(parent);
1304        return result;
1305    }
1306
1307    // found two-argument read method, so must be non-boxed value...
1308
// ...create a blank instance
1309
java.lang.Object JavaDoc val = null;
1310    try {
1311        val = helper.get_class().newInstance();
1312    } catch(java.lang.InstantiationException JavaDoc ie) {
1313        throw wrapper.couldNotInstantiateHelper( ie,
1314        helper.get_class() ) ;
1315    } catch(IllegalAccessException JavaDoc iae){
1316        // Value's constructor is protected or private
1317
//
1318
// So, use the helper to read the value.
1319
//
1320
// NOTE : This means that in this particular case a recursive ref.
1321
// would fail.
1322
return helper.read_value(parent);
1323    }
1324
1325    // add blank instance to cache table
1326
if (valueCache == null)
1327            valueCache = new CacheTable(orb,false);
1328    valueCache.put(val, indirection);
1329
1330    // if custom type, call unmarshal method
1331
if (val instanceof CustomMarshal JavaDoc && isCustomType(helper)) {
1332            ((CustomMarshal JavaDoc)val).unmarshal(parent);
1333        return val;
1334    }
1335
1336    // call two-argument read method using reflection
1337
try {
1338        java.lang.Object JavaDoc args[] = {parent, val};
1339        readMethod.invoke(helper, args);
1340            return val;
1341    } catch(IllegalAccessException JavaDoc iae2) {
1342        throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ;
1343    } catch(InvocationTargetException JavaDoc ite){
1344        throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ;
1345    }
1346    }
1347
1348    private java.lang.Object JavaDoc readBoxedIDLEntity(Class JavaDoc clazz, String JavaDoc codebase)
1349    {
1350    Class JavaDoc cls = null ;
1351
1352    try {
1353            ClassLoader JavaDoc clazzLoader = (clazz == null ? null : clazz.getClassLoader());
1354
1355        cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
1356                                                   clazzLoader, clazz, clazzLoader);
1357        final Class JavaDoc helperClass = cls ;
1358
1359        final Class JavaDoc argTypes[] = {org.omg.CORBA.portable.InputStream JavaDoc.class};
1360
1361            // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
1362
// if a different class loader is used (even though the javadoc says otherwise)
1363
Method JavaDoc readMethod = null;
1364            try {
1365                readMethod = (Method JavaDoc)AccessController.doPrivileged(
1366                    new PrivilegedExceptionAction JavaDoc() {
1367                        public java.lang.Object JavaDoc run() throws NoSuchMethodException JavaDoc {
1368                            return helperClass.getDeclaredMethod(kReadMethod, argTypes);
1369                        }
1370                    }
1371                );
1372            } catch (PrivilegedActionException JavaDoc pae) {
1373                // this gets caught below
1374
throw (NoSuchMethodException JavaDoc)pae.getException();
1375            }
1376
1377        java.lang.Object JavaDoc args[] = {parent};
1378        return readMethod.invoke(null, args);
1379
1380    } catch (ClassNotFoundException JavaDoc cnfe) {
1381        throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ;
1382    } catch(NoSuchMethodException JavaDoc nsme) {
1383        throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ;
1384    } catch(IllegalAccessException JavaDoc iae) {
1385        throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ;
1386    } catch(InvocationTargetException JavaDoc ite) {
1387        throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ;
1388    }
1389    }
1390
1391    private java.lang.Object JavaDoc readIDLValue(int indirection, String JavaDoc repId,
1392                      Class JavaDoc clazz, String JavaDoc codebase)
1393    {
1394    ValueFactory JavaDoc factory ;
1395
1396    // Always try to find a ValueFactory first, as required by the spec.
1397
// There are some complications here in the IDL 3.0 mapping (see 1.13.8),
1398
// but basically we must always be able to override the DefaultFactory
1399
// or Helper mappings that are also used. This appears to be the case
1400
// even in the boxed value cases. The original code only did the lookup
1401
// in the case of class implementing either StreamableValue or CustomValue,
1402
// but abstract valuetypes only implement ValueBase, and really require
1403
// the use of the repId to find a factory (including the DefaultFactory).
1404
try {
1405        // use new-style OBV support (factory object)
1406
factory = Utility.getFactory(clazz, codebase, orb, repId);
1407    } catch (MARSHAL JavaDoc marshal) {
1408        // XXX log marshal at one of the INFO levels
1409

1410        // Could not get a factory, so try alternatives
1411
if (!StreamableValue JavaDoc.class.isAssignableFrom(clazz) &&
1412        !CustomValue JavaDoc.class.isAssignableFrom(clazz) &&
1413            ValueBase JavaDoc.class.isAssignableFrom(clazz)) {
1414        // use old-style OBV support (helper object)
1415
BoxedValueHelper JavaDoc helper = Utility.getHelper(clazz, codebase, repId);
1416        if (helper instanceof ValueHelper JavaDoc)
1417            return readIDLValueWithHelper((ValueHelper JavaDoc)helper, indirection);
1418        else
1419            return helper.read_value(parent);
1420        } else {
1421        // must be a boxed IDLEntity, so make a reflective call to the
1422
// helper's static read method...
1423
return readBoxedIDLEntity(clazz, codebase);
1424        }
1425    }
1426
1427    // If there was no error in getting the factory, use it.
1428
valueIndirection = indirection; // for callback
1429
return factory.read_value(parent);
1430    }
1431
1432    /**
1433     * End tags are only written for chunked valuetypes.
1434     *
1435     * Before Merlin, our ORBs wrote end tags which took into account
1436     * all enclosing valuetypes. This was changed by an interop resolution
1437     * (see details around chunkedValueNestingLevel) to only include
1438     * enclosing chunked types.
1439     *
1440     * ORB versioning and end tag compaction are handled here.
1441     */

1442    private void readEndTag() {
1443        if (isChunked) {
1444
1445            // Read the end tag
1446
int anEndTag = read_long();
1447
1448            // End tags should always be negative, and the outermost
1449
// enclosing chunked valuetype should have a -1 end tag.
1450
//
1451
// handleEndOfValue should have assured that we were
1452
// at the end tag position!
1453
if (anEndTag >= 0) {
1454        throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE,
1455            new Integer JavaDoc(anEndTag), new Integer JavaDoc( get_offset() - 4 ) ) ;
1456            }
1457
1458            // If the ORB is null, or if we're sure we're talking to
1459
// a foreign ORB, Merlin, or something more recent, we
1460
// use the updated end tag computation, and are more strenuous
1461
// about the values.
1462
if (orb == null ||
1463                ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
1464                ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
1465
1466                // If the end tag we read was less than what we were expecting,
1467
// then the sender must think it's sent more enclosing
1468
// chunked valuetypes than we have. Throw an exception.
1469
if (anEndTag < chunkedValueNestingLevel)
1470            throw wrapper.unexpectedEnclosingValuetype(
1471            CompletionStatus.COMPLETED_MAYBE, new Integer JavaDoc( anEndTag ),
1472            new Integer JavaDoc( chunkedValueNestingLevel ) ) ;
1473
1474                // If the end tag is bigger than what we expected, but
1475
// still negative, then the sender has done some end tag
1476
// compaction. We back up the stream 4 bytes so that the
1477
// next time readEndTag is called, it will get down here
1478
// again. Even with fragmentation, we'll always be able
1479
// to do this.
1480
if (anEndTag != chunkedValueNestingLevel) {
1481                    bbwi.position(bbwi.position() - 4);
1482                 }
1483
1484            } else {
1485                
1486                // When talking to Kestrel or Ladybird, we use our old
1487
// end tag rules and are less strict. If the end tag
1488
// isn't what we expected, we back up, assuming
1489
// compaction.
1490
if (anEndTag != end_flag) {
1491                    bbwi.position(bbwi.position() - 4);
1492                }
1493            }
1494
1495            // This only keeps track of the enclosing chunked
1496
// valuetypes
1497
chunkedValueNestingLevel++;
1498        }
1499
1500        // This keeps track of all enclosing valuetypes
1501
end_flag++;
1502    }
1503
1504    protected int get_offset() {
1505    return bbwi.position();
1506    }
1507
1508    private void start_block() {
1509        
1510    // if (outerValueDone)
1511
if (!isChunked)
1512        return;
1513    
1514    // if called from alignAndCheck, need to reset blockLength
1515
// to avoid an infinite recursion loop on read_long() call
1516
blockLength = maxBlockLength;
1517
1518    blockLength = read_long();
1519
1520        // Must remember where we began the chunk to calculate how far
1521
// along we are. See notes above about chunkBeginPos.
1522

1523    if (blockLength > 0 && blockLength < maxBlockLength) {
1524        blockLength += get_offset(); // _REVISIT_ unsafe, should use a Java long
1525

1526        // inBlock = true;
1527
} else {
1528
1529            // System.out.println("start_block snooped a " + Integer.toHexString(blockLength));
1530

1531        // not a chunk length field
1532
blockLength = maxBlockLength;
1533
1534            bbwi.position(bbwi.position() - 4);
1535    }
1536    }
1537
1538    // Makes sure that if we were reading a chunked value, we end up
1539
// at the right place in the stream, no matter how little the
1540
// unmarshalling code read.
1541
//
1542
// After calling this method, if we are chunking, we should be
1543
// in position to read the end tag.
1544
private void handleEndOfValue() {
1545
1546        // If we're not chunking, we don't have to worry about
1547
// skipping remaining chunks or finding end tags
1548
if (!isChunked)
1549            return;
1550
1551        // Skip any remaining chunks
1552
while (blockLength != maxBlockLength) {
1553            end_block();
1554            start_block();
1555        }
1556
1557        // Now look for the end tag
1558

1559        // This is a little wasteful since we're reading
1560
// this long up to 3 times in the worst cases (once
1561
// in start_block, once here, and once in readEndTag
1562
//
1563
// Peek next long
1564
int nextLong = read_long();
1565        bbwi.position(bbwi.position() - 4);
1566
1567        // We did find an end tag, so we're done. readEndTag
1568
// should take care of making sure it's the correct
1569
// end tag, etc. Remember that since end tags,
1570
// chunk lengths, and valuetags have non overlapping
1571
// ranges, we can tell by the value what the longs are.
1572
if (nextLong < 0)
1573            return;
1574
1575        if (nextLong == 0 || nextLong >= maxBlockLength) {
1576
1577            // A custom marshaled valuetype left extra data
1578
// on the wire, and that data had another
1579
// nested value inside of it. We've just
1580
// read the value tag or null of that nested value.
1581
//
1582
// In an attempt to get by it, we'll try to call
1583
// read_value() to get the nested value off of
1584
// the wire. Afterwards, we must call handleEndOfValue
1585
// recursively to read any further chunks that the containing
1586
// valuetype might still have after the nested
1587
// value.
1588
read_value();
1589            handleEndOfValue();
1590        } else {
1591            // This probably means that the code to skip chunks has
1592
// an error, and ended up setting blockLength to something
1593
// other than maxBlockLength even though we weren't
1594
// starting a new chunk.
1595
throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE,
1596        new Integer JavaDoc( nextLong ), new Integer JavaDoc( get_offset() ) ) ;
1597        }
1598    }
1599
1600    private void end_block() {
1601
1602    // if in a chunk, check for underflow or overflow
1603
if (blockLength != maxBlockLength) {
1604        if (blockLength == get_offset()) {
1605                // Chunk ended correctly
1606
blockLength = maxBlockLength;
1607            } else {
1608                // Skip over anything left by bad unmarshaling code (ex:
1609
// a buggy custom unmarshaler). See handleEndOfValue.
1610
if (blockLength > get_offset()) {
1611                    skipToOffset(blockLength);
1612                } else {
1613            throw wrapper.badChunkLength( new Integer JavaDoc( blockLength ),
1614            new Integer JavaDoc( get_offset() ) ) ;
1615                }
1616            }
1617        }
1618    }
1619    
1620    private int readValueTag(){
1621    // outerValueDone = false;
1622
return read_long();
1623    }
1624
1625    public org.omg.CORBA.ORB JavaDoc orb() {
1626        return orb;
1627    }
1628
1629    // ------------ End RMI related methods --------------------------
1630

1631    public final void read_boolean_array(boolean[] value, int offset, int length) {
1632        for(int i=0; i < length; i++) {
1633            value[i+offset] = read_boolean();
1634        }
1635    }
1636
1637    public final void read_char_array(char[] value, int offset, int length) {
1638        for(int i=0; i < length; i++) {
1639            value[i+offset] = read_char();
1640        }
1641    }
1642
1643    public final void read_wchar_array(char[] value, int offset, int length) {
1644        for(int i=0; i < length; i++) {
1645            value[i+offset] = read_wchar();
1646        }
1647    }
1648
1649    public final void read_short_array(short[] value, int offset, int length) {
1650        for(int i=0; i < length; i++) {
1651            value[i+offset] = read_short();
1652        }
1653    }
1654
1655    public final void read_ushort_array(short[] value, int offset, int length) {
1656        read_short_array(value, offset, length);
1657    }
1658
1659    public final void read_long_array(int[] value, int offset, int length) {
1660        for(int i=0; i < length; i++) {
1661            value[i+offset] = read_long();
1662        }
1663    }
1664
1665    public final void read_ulong_array(int[] value, int offset, int length) {
1666        read_long_array(value, offset, length);
1667    }
1668
1669    public final void read_longlong_array(long[] value, int offset, int length) {
1670        for(int i=0; i < length; i++) {
1671            value[i+offset] = read_longlong();
1672        }
1673    }
1674
1675    public final void read_ulonglong_array(long[] value, int offset, int length) {
1676        read_longlong_array(value, offset, length);
1677    }
1678
1679    public final void read_float_array(float[] value, int offset, int length) {
1680        for(int i=0; i < length; i++) {
1681            value[i+offset] = read_float();
1682        }
1683    }
1684
1685    public final void read_double_array(double[] value, int offset, int length) {
1686        for(int i=0; i < length; i++) {
1687            value[i+offset] = read_double();
1688        }
1689    }
1690
1691    public final void read_any_array(org.omg.CORBA.Any JavaDoc[] value, int offset, int length) {
1692        for(int i=0; i < length; i++) {
1693            value[i+offset] = read_any();
1694        }
1695    }
1696
1697    //--------------------------------------------------------------------//
1698
// CDRInputStream state management.
1699
//
1700

1701    /**
1702     * Are we at the end of the input stream?
1703     */

1704// public final boolean isAtEnd() {
1705
// return bbwi.position() == bbwi.buflen;
1706
// }
1707

1708// public int available() throws IOException {
1709
// return bbwi.buflen - bbwi.position();
1710
// }
1711

1712    private String JavaDoc read_repositoryIds() {
1713        
1714    // Read # of repository ids
1715
int numRepIds = read_long();
1716    if (numRepIds == 0xffffffff) {
1717            int indirection = read_long() + get_offset() - 4;
1718            if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
1719        return (String JavaDoc)repositoryIdCache.getKey(indirection);
1720            else
1721        throw wrapper.unableToLocateRepIdArray( new Integer JavaDoc( indirection ) ) ;
1722    } else {
1723
1724        // read first array element and store it as an indirection to the whole array
1725
int indirection = get_offset();
1726        String JavaDoc repID = read_repositoryId();
1727            if (repositoryIdCache == null)
1728            repositoryIdCache = new CacheTable(orb,false);
1729            repositoryIdCache.put(repID, indirection);
1730
1731        // read and ignore the subsequent array elements, but put them in the
1732
// indirection table in case there are later indirections back to them
1733
for (int i = 1; i < numRepIds; i++) {
1734        read_repositoryId();
1735        }
1736        
1737        return repID;
1738    }
1739    }
1740
1741    private final String JavaDoc read_repositoryId()
1742    {
1743        String JavaDoc result = readStringOrIndirection(true);
1744
1745        if (result == null) { // Indirection
1746
int indirection = read_long() + get_offset() - 4;
1747
1748            if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
1749                return (String JavaDoc)repositoryIdCache.getKey(indirection);
1750            else
1751        throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE,
1752            new Integer JavaDoc(bbwi.position()) ) ;
1753        } else {
1754            if (repositoryIdCache == null)
1755                repositoryIdCache = new CacheTable(orb,false);
1756            repositoryIdCache.put(result, stringIndirection);
1757        }
1758
1759    return result ;
1760    }
1761
1762    private final String JavaDoc read_codebase_URL()
1763    {
1764        String JavaDoc result = readStringOrIndirection(true);
1765
1766        if (result == null) { // Indirection
1767
int indirection = read_long() + get_offset() - 4;
1768
1769            if (codebaseCache != null && codebaseCache.containsVal(indirection))
1770                return (String JavaDoc)codebaseCache.getKey(indirection);
1771            else
1772        throw wrapper.badCodebaseIndirection(
1773            CompletionStatus.COMPLETED_MAYBE,
1774            new Integer JavaDoc(bbwi.position()) ) ;
1775    } else {
1776        if (codebaseCache == null)
1777        codebaseCache = new CacheTable(orb,false);
1778        codebaseCache.put(result, stringIndirection);
1779        }
1780
1781    return result;
1782    }
1783
1784    /* DataInputStream methods */
1785
1786    public java.lang.Object JavaDoc read_Abstract () {
1787        return read_abstract_interface();
1788    }
1789
1790    public java.io.Serializable JavaDoc read_Value () {
1791        return read_value();
1792    }
1793
1794    public void read_any_array (org.omg.CORBA.AnySeqHolder JavaDoc seq, int offset, int length) {
1795        read_any_array(seq.value, offset, length);
1796    }
1797
1798    public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder JavaDoc seq, int offset, int length) {
1799        read_boolean_array(seq.value, offset, length);
1800    }
1801
1802    public void read_char_array (org.omg.CORBA.CharSeqHolder JavaDoc seq, int offset, int length) {
1803        read_char_array(seq.value, offset, length);
1804    }
1805
1806    public void read_wchar_array (org.omg.CORBA.WCharSeqHolder JavaDoc seq, int offset, int length) {
1807        read_wchar_array(seq.value, offset, length);
1808    }
1809
1810    public void read_octet_array (org.omg.CORBA.OctetSeqHolder JavaDoc seq, int offset, int length) {
1811        read_octet_array(seq.value, offset, length);
1812    }
1813
1814    public void read_short_array (org.omg.CORBA.ShortSeqHolder JavaDoc seq, int offset, int length) {
1815        read_short_array(seq.value, offset, length);
1816    }
1817
1818    public void read_ushort_array (org.omg.CORBA.UShortSeqHolder JavaDoc seq, int offset, int length) {
1819        read_ushort_array(seq.value, offset, length);
1820    }
1821
1822    public void read_long_array (org.omg.CORBA.LongSeqHolder JavaDoc seq, int offset, int length) {
1823        read_long_array(seq.value, offset, length);
1824    }
1825
1826    public void read_ulong_array (org.omg.CORBA.ULongSeqHolder JavaDoc seq, int offset, int length) {
1827        read_ulong_array(seq.value, offset, length);
1828    }
1829
1830    public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder JavaDoc seq, int offset, int length) {
1831        read_ulonglong_array(seq.value, offset, length);
1832    }
1833
1834    public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder JavaDoc seq, int offset, int length) {
1835        read_longlong_array(seq.value, offset, length);
1836    }
1837
1838    public void read_float_array (org.omg.CORBA.FloatSeqHolder JavaDoc seq, int offset, int length) {
1839        read_float_array(seq.value, offset, length);
1840    }
1841
1842    public void read_double_array (org.omg.CORBA.DoubleSeqHolder JavaDoc seq, int offset, int length) {
1843        read_double_array(seq.value, offset, length);
1844    }
1845
1846    public java.math.BigDecimal JavaDoc read_fixed(short digits, short scale) {
1847        // digits isn't really needed here
1848
StringBuffer JavaDoc buffer = read_fixed_buffer();
1849        if (digits != buffer.length())
1850        throw wrapper.badFixed( new Integer JavaDoc(digits),
1851        new Integer JavaDoc(buffer.length()) ) ;
1852        buffer.insert(digits - scale, '.');
1853        return new BigDecimal JavaDoc(buffer.toString());
1854    }
1855
1856    // This method is unable to yield the correct scale.
1857
public java.math.BigDecimal JavaDoc read_fixed() {
1858        return new BigDecimal JavaDoc(read_fixed_buffer().toString());
1859    }
1860
1861    // Each octet contains (up to) two decimal digits.
1862
// If the fixed type has an odd number of decimal digits, then the representation
1863
// begins with the first (most significant) digit.
1864
// Otherwise, this first half-octet is all zero, and the first digit
1865
// is in the second half-octet.
1866
// The sign configuration, in the last half-octet of the representation,
1867
// is 0xD for negative numbers and 0xC for positive and zero values.
1868
private StringBuffer JavaDoc read_fixed_buffer() {
1869        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(64);
1870        byte doubleDigit;
1871        int firstDigit;
1872        int secondDigit;
1873        boolean wroteFirstDigit = false;
1874        boolean more = true;
1875        while (more) {
1876            doubleDigit = this.read_octet();
1877            firstDigit = (int)((doubleDigit & 0xf0) >> 4);
1878            secondDigit = (int)(doubleDigit & 0x0f);
1879            if (wroteFirstDigit || firstDigit != 0) {
1880                buffer.append(Character.forDigit(firstDigit, 10));
1881                wroteFirstDigit = true;
1882            }
1883            if (secondDigit == 12) {
1884                // positive number or zero
1885
if ( ! wroteFirstDigit) {
1886                    // zero
1887
return new StringBuffer JavaDoc("0.0");
1888                } else {
1889                    // positive number
1890
// done
1891
}
1892                more = false;
1893            } else if (secondDigit == 13) {
1894                // negative number
1895
buffer.insert(0, '-');
1896                more = false;
1897            } else {
1898                buffer.append(Character.forDigit(secondDigit, 10));
1899                wroteFirstDigit = true;
1900            }
1901        }
1902        return buffer;
1903    }
1904
1905    private final static String JavaDoc _id = "IDL:omg.org/CORBA/DataInputStream:1.0";
1906    private final static String JavaDoc[] _ids = { _id };
1907
1908    public String JavaDoc[] _truncatable_ids() {
1909        if (_ids == null)
1910            return null;
1911
1912        return (String JavaDoc[])_ids.clone();
1913    }
1914
1915    /* for debugging */
1916
1917    public void printBuffer() {
1918        CDRInputStream_1_0.printBuffer(this.bbwi);
1919    }
1920
1921    public static void printBuffer(ByteBufferWithInfo bbwi) {
1922
1923        System.out.println("----- Input Buffer -----");
1924        System.out.println();
1925        System.out.println("Current position: " + bbwi.position());
1926        System.out.println("Total length : " + bbwi.buflen);
1927        System.out.println();
1928
1929        try {
1930
1931            char[] charBuf = new char[16];
1932
1933            for (int i = 0; i < bbwi.buflen; i += 16) {
1934
1935                int j = 0;
1936
1937                // For every 16 bytes, there is one line
1938
// of output. First, the hex output of
1939
// the 16 bytes with each byte separated
1940
// by a space.
1941
while (j < 16 && j + i < bbwi.buflen) {
1942                    int k = bbwi.byteBuffer.get(i + j);
1943                    if (k < 0)
1944                        k = 256 + k;
1945                    String JavaDoc hex = Integer.toHexString(k);
1946                    if (hex.length() == 1)
1947                        hex = "0" + hex;
1948                    System.out.print(hex + " ");
1949                    j++;
1950                }
1951                
1952                // Add any extra spaces to align the
1953
// text column in case we didn't end
1954
// at 16
1955
while (j < 16) {
1956                    System.out.print(" ");
1957                    j++;
1958                }
1959                
1960                // Now output the ASCII equivalents. Non-ASCII
1961
// characters are shown as periods.
1962
int x = 0;
1963                while (x < 16 && x + i < bbwi.buflen) {
1964                    if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
1965                        charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
1966                    else
1967                        charBuf[x] = '.';
1968                    x++;
1969                }
1970                System.out.println(new String JavaDoc(charBuf, 0, x));
1971            }
1972
1973        } catch (Throwable JavaDoc t) {
1974            t.printStackTrace();
1975        }
1976
1977        System.out.println("------------------------");
1978    }
1979
1980    public ByteBuffer JavaDoc getByteBuffer() {
1981        ByteBuffer JavaDoc result = null;
1982        if (bbwi != null) {
1983            result = bbwi.byteBuffer;
1984        }
1985        return result;
1986    }
1987
1988    public int getBufferLength() {
1989        return bbwi.buflen;
1990    }
1991
1992    public void setBufferLength(int value) {
1993        bbwi.buflen = value;
1994        bbwi.byteBuffer.limit(bbwi.buflen);
1995    }
1996
1997    public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
1998        this.bbwi = bbwi;
1999    }
2000
2001    public void setByteBuffer(ByteBuffer JavaDoc byteBuffer) {
2002        bbwi.byteBuffer = byteBuffer;
2003    }
2004
2005    public int getIndex() {
2006        return bbwi.position();
2007    }
2008
2009    public void setIndex(int value) {
2010        bbwi.position(value);
2011    }
2012
2013    public boolean isLittleEndian() {
2014        return littleEndian;
2015    }
2016
2017    public void orb(org.omg.CORBA.ORB JavaDoc orb) {
2018        this.orb = (ORB)orb;
2019    }
2020
2021    public BufferManagerRead getBufferManager() {
2022        return bufferManagerRead;
2023    }
2024
2025    private void skipToOffset(int offset) {
2026
2027        // Number of bytes to skip
2028
int len = offset - get_offset();
2029
2030        int n = 0;
2031
2032        while (n < len) {
2033            int avail;
2034            int bytes;
2035            int wanted;
2036
2037            avail = bbwi.buflen - bbwi.position();
2038            if (avail <= 0) {
2039                grow(1, 1);
2040                avail = bbwi.buflen - bbwi.position();
2041            }
2042
2043            wanted = len - n;
2044            bytes = (wanted < avail) ? wanted : avail;
2045            bbwi.position(bbwi.position() + bytes);
2046            n += bytes;
2047        }
2048    }
2049
2050
2051    // Mark and reset -------------------------------------------------
2052

2053    protected MarkAndResetHandler markAndResetHandler = null;
2054
2055    protected class StreamMemento
2056    {
2057        // These are the fields that may change after marking
2058
// the stream position, so we need to save them.
2059
private int blockLength_;
2060        private int end_flag_;
2061        private int chunkedValueNestingLevel_;
2062        private int valueIndirection_;
2063        private int stringIndirection_;
2064        private boolean isChunked_;
2065        private javax.rmi.CORBA.ValueHandler JavaDoc valueHandler_;
2066        private ByteBufferWithInfo bbwi_;
2067        private boolean specialNoOptionalDataState_;
2068
2069        public StreamMemento()
2070        {
2071            blockLength_ = blockLength;
2072            end_flag_ = end_flag;
2073            chunkedValueNestingLevel_ = chunkedValueNestingLevel;
2074            valueIndirection_ = valueIndirection;
2075            stringIndirection_ = stringIndirection;
2076            isChunked_ = isChunked;
2077            valueHandler_ = valueHandler;
2078            specialNoOptionalDataState_ = specialNoOptionalDataState;
2079            bbwi_ = new ByteBufferWithInfo(bbwi);
2080        }
2081    }
2082
2083    public java.lang.Object JavaDoc createStreamMemento() {
2084        return new StreamMemento();
2085    }
2086
2087    public void restoreInternalState(java.lang.Object JavaDoc streamMemento) {
2088
2089        StreamMemento mem = (StreamMemento)streamMemento;
2090
2091        blockLength = mem.blockLength_;
2092        end_flag = mem.end_flag_;
2093        chunkedValueNestingLevel = mem.chunkedValueNestingLevel_;
2094        valueIndirection = mem.valueIndirection_;
2095        stringIndirection = mem.stringIndirection_;
2096        isChunked = mem.isChunked_;
2097        valueHandler = mem.valueHandler_;
2098        specialNoOptionalDataState = mem.specialNoOptionalDataState_;
2099        bbwi = mem.bbwi_;
2100    }
2101
2102    public int getPosition() {
2103        return get_offset();
2104    }
2105
2106    public void mark(int readlimit) {
2107        markAndResetHandler.mark(this);
2108    }
2109
2110    public void reset() {
2111        markAndResetHandler.reset();
2112    }
2113
2114    // ---------------------------------- end Mark and Reset
2115

2116    // Provides a hook so subclasses of CDRInputStream can provide
2117
// a CodeBase. This ultimately allows us to grab a Connection
2118
// instance in IIOPInputStream, the only subclass where this
2119
// is actually used.
2120
CodeBase getCodeBase() {
2121        return parent.getCodeBase();
2122    }
2123
2124    /**
2125     * Attempts to find the class described by the given
2126     * repository ID string and expected type. The first
2127     * attempt is to find the class locally, falling back
2128     * on the URL that came with the value. The second
2129     * attempt is to use a URL from the remote CodeBase.
2130     */

2131    private Class JavaDoc getClassFromString(String JavaDoc repositoryIDString,
2132                                     String JavaDoc codebaseURL,
2133                                     Class JavaDoc expectedType)
2134    {
2135        RepositoryIdInterface repositoryID
2136            = repIdStrs.getFromString(repositoryIDString);
2137
2138        try {
2139            try {
2140                // First try to load the class locally, then use
2141
// the provided URL (if it isn't null)
2142
return repositoryID.getClassFromType(expectedType,
2143                                                     codebaseURL);
2144            } catch (ClassNotFoundException JavaDoc cnfeOuter) {
2145                
2146                try {
2147                  
2148                    if (getCodeBase() == null) {
2149                        return null; // class cannot be loaded remotely.
2150
}
2151                    
2152                    // Get a URL from the remote CodeBase and retry
2153
codebaseURL = getCodeBase().implementation(repositoryIDString);
2154                    
2155                    // Don't bother trying to find it locally again if
2156
// we got a null URL
2157
if (codebaseURL == null)
2158                        return null;
2159                    
2160                    return repositoryID.getClassFromType(expectedType,
2161                                                         codebaseURL);
2162                } catch (ClassNotFoundException JavaDoc cnfeInner) {
2163                    dprintThrowable(cnfeInner);
2164                    // Failed to load the class
2165
return null;
2166                }
2167            }
2168        } catch (MalformedURLException JavaDoc mue) {
2169            // Always report a bad URL
2170
throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
2171        mue, repositoryIDString, codebaseURL ) ;
2172        }
2173    }
2174
2175    /**
2176     * Attempts to find the class described by the given
2177     * repository ID string. At most, three attempts are made:
2178     * Try to find it locally, through the provided URL, and
2179     * finally, via a URL from the remote CodeBase.
2180     */

2181    private Class JavaDoc getClassFromString(String JavaDoc repositoryIDString,
2182                                     String JavaDoc codebaseURL)
2183    {
2184        RepositoryIdInterface repositoryID
2185            = repIdStrs.getFromString(repositoryIDString);
2186
2187        for (int i = 0; i < 3; i++) {
2188
2189            try {
2190
2191                switch (i)
2192                {
2193                    case 0:
2194                        // First try to load the class locally
2195
return repositoryID.getClassFromType();
2196                    case 1:
2197                        // Try to load the class using the provided
2198
// codebase URL (falls out below)
2199
break;
2200                    case 2:
2201                        // Try to load the class using a URL from the
2202
// remote CodeBase
2203
codebaseURL = getCodeBase().implementation(repositoryIDString);
2204                        break;
2205                }
2206
2207                // Don't bother if the codebaseURL is null
2208
if (codebaseURL == null)
2209                    continue;
2210
2211                return repositoryID.getClassFromType(codebaseURL);
2212
2213            } catch(ClassNotFoundException JavaDoc cnfe) {
2214                // Will ultimately return null if all three
2215
// attempts fail, but don't do anything here.
2216
} catch (MalformedURLException JavaDoc mue) {
2217        throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
2218            mue, repositoryIDString, codebaseURL ) ;
2219            }
2220        }
2221
2222        // If we get here, we have failed to load the class
2223
dprint("getClassFromString failed with rep id "
2224           + repositoryIDString
2225           + " and codebase "
2226           + codebaseURL);
2227        
2228        return null;
2229    }
2230
2231    // Utility method used to get chars from bytes
2232
char[] getConvertedChars(int numBytes,
2233                             CodeSetConversion.BTCConverter converter) {
2234
2235        // REVISIT - Look at CodeSetConversion.BTCConverter to see
2236
// if it can work with an NIO ByteBuffer. We should
2237
// avoid getting the bytes into an array if possible.
2238

2239        // To be honest, I doubt this saves much real time
2240
if (bbwi.buflen - bbwi.position() >= numBytes) {
2241            // If the entire string is in this buffer,
2242
// just convert directly from the bbwi rather than
2243
// allocating and copying.
2244
byte[] tmpBuf;
2245            if (bbwi.byteBuffer.hasArray())
2246            {
2247                tmpBuf = bbwi.byteBuffer.array();
2248            }
2249            else
2250            {
2251                 tmpBuf = new byte[bbwi.buflen];
2252                 // Microbenchmarks are showing a loop of ByteBuffer.get(int)
2253
// being faster than ByteBuffer.get(byte[], int, int).
2254
for (int i = 0; i < bbwi.buflen; i++)
2255                     tmpBuf[i] = bbwi.byteBuffer.get(i);
2256            }
2257            char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes);
2258
2259            bbwi.position(bbwi.position() + numBytes);
2260            return result;
2261        } else {
2262            // Stretches across buffers. Unless we provide an
2263
// incremental conversion interface, allocate and
2264
// copy the bytes.
2265
byte[] bytes = new byte[numBytes];
2266            read_octet_array(bytes, 0, bytes.length);
2267
2268            return converter.getChars(bytes, 0, numBytes);
2269        }
2270    }
2271
2272    protected CodeSetConversion.BTCConverter getCharConverter() {
2273        if (charConverter == null)
2274            charConverter = parent.createCharBTCConverter();
2275        
2276        return charConverter;
2277    }
2278
2279    protected CodeSetConversion.BTCConverter getWCharConverter() {
2280        if (wcharConverter == null)
2281            wcharConverter = parent.createWCharBTCConverter();
2282    
2283        return wcharConverter;
2284    }
2285
2286    protected void dprintThrowable(Throwable JavaDoc t) {
2287        if (debug && t != null)
2288            t.printStackTrace();
2289    }
2290
2291    protected void dprint(String JavaDoc msg) {
2292        if (debug) {
2293            ORBUtility.dprint(this, msg);
2294    }
2295    }
2296
2297    /**
2298     * Aligns the current position on the given octet boundary
2299     * if there are enough bytes available to do so. Otherwise,
2300     * it just returns. This is used for some (but not all)
2301     * GIOP 1.2 message headers.
2302     */

2303
2304    void alignOnBoundary(int octetBoundary) {
2305        int needed = computeAlignment(bbwi.position(), octetBoundary);
2306
2307        if (bbwi.position() + needed <= bbwi.buflen)
2308        {
2309            bbwi.position(bbwi.position() + needed);
2310        }
2311    }
2312
2313    public void resetCodeSetConverters() {
2314        charConverter = null;
2315        wcharConverter = null;
2316    }
2317
2318    public void start_value() {
2319        // Read value tag
2320
int vType = readValueTag();
2321
2322        if (vType == 0) {
2323            // Stream needs to go into a state where it
2324
// throws standard exception until end_value
2325
// is called. This means the sender didn't
2326
// send any custom data. If the reader here
2327
// tries to read more, we need to throw an
2328
// exception before reading beyond where
2329
// we're supposed to
2330
specialNoOptionalDataState = true;
2331
2332            return;
2333        }
2334
2335        if (vType == 0xffffffff) {
2336            // One should never indirect to a custom wrapper
2337
throw wrapper.customWrapperIndirection(
2338        CompletionStatus.COMPLETED_MAYBE);
2339        }
2340
2341        if (repIdUtil.isCodeBasePresent(vType)) {
2342        throw wrapper.customWrapperWithCodebase(
2343        CompletionStatus.COMPLETED_MAYBE);
2344        }
2345            
2346        if (repIdUtil.getTypeInfo(vType)
2347            != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) {
2348        throw wrapper.customWrapperNotSingleRepid(
2349        CompletionStatus.COMPLETED_MAYBE);
2350        }
2351
2352
2353        // REVISIT - Could verify repository ID even though
2354
// it isn't used elsewhere
2355
read_repositoryId();
2356
2357        // Note: isChunked should be true here. Should have
2358
// been set to true in the containing value's read_value
2359
// method.
2360

2361        start_block();
2362        end_flag--;
2363        chunkedValueNestingLevel--;
2364    }
2365
2366    public void end_value() {
2367
2368        if (specialNoOptionalDataState) {
2369            specialNoOptionalDataState = false;
2370            return;
2371        }
2372
2373        handleEndOfValue();
2374        readEndTag();
2375
2376        // Note that isChunked should still be true here.
2377
// If the containing valuetype is the highest
2378
// chunked value, it will get set to false
2379
// at the end of read_value.
2380

2381        // allow for possible continuation chunk
2382
start_block();
2383    }
2384
2385    public void close() throws IOException JavaDoc
2386    {
2387
2388        // tell BufferManagerRead to release any ByteBuffers
2389
getBufferManager().close(bbwi);
2390
2391        // It's possible bbwi.byteBuffer is shared between
2392
// this InputStream and an OutputStream. Thus, we check
2393
// if the Input/Output streams are using the same ByteBuffer.
2394
// If they sharing the same ByteBuffer we need to ensure only
2395
// one of those ByteBuffers are released to the ByteBufferPool.
2396

2397        if (bbwi != null && getByteBuffer() != null)
2398        {
2399            int bbHash = System.identityHashCode(bbwi.byteBuffer);
2400            MessageMediator messageMediator = parent.getMessageMediator();
2401            if (messageMediator != null)
2402            {
2403                CDROutputObject outputObj =
2404                             (CDROutputObject)messageMediator.getOutputObject();
2405                if (outputObj != null)
2406                {
2407                    ByteBuffer JavaDoc outputBb = outputObj.getByteBuffer();
2408
2409                    int oBbHash = 0;
2410                    if (outputBb != null)
2411                    {
2412                        oBbHash = System.identityHashCode(outputBb);
2413                        if (bbHash == oBbHash) // shared?
2414
{
2415                            // Set OutputStream's ByteBuffer and bbwi to null
2416
// so its ByteBuffer cannot be released to the pool
2417
outputObj.setByteBuffer(null);
2418                            outputObj.setByteBufferWithInfo(null);
2419                        }
2420                    }
2421                }
2422            }
2423
2424            // release this stream's ByteBuffer to the pool
2425
ByteBufferPool byteBufferPool = orb.getByteBufferPool();
2426            if (debug)
2427            {
2428                // print address of ByteBuffer being released
2429
int bbAddress = System.identityHashCode(bbwi.byteBuffer);
2430                StringBuffer JavaDoc sb = new StringBuffer JavaDoc(80);
2431                sb.append(".close - releasing ByteBuffer id (");
2432                sb.append(bbAddress).append(") to ByteBufferPool.");
2433                String JavaDoc msg = sb.toString();
2434                dprint(msg);
2435            }
2436            byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
2437            bbwi.byteBuffer = null;
2438            bbwi = null;
2439        }
2440    }
2441}
2442
Popular Tags