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

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

mercurial