IDLJavaSerializationInputStream.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2004, 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 */
25package com.sun.corba.se.impl.encoding;
26
27import java.io.Serializable;
28import java.io.ObjectInputStream;
29import java.io.ByteArrayInputStream;
30import java.io.IOException;
31import java.nio.ByteBuffer;
32import java.math.BigDecimal;
33import java.util.LinkedList;
34
35import com.sun.corba.se.spi.orb.ORB;
36import com.sun.corba.se.spi.ior.IOR;
37import com.sun.corba.se.spi.ior.IORFactories;
38import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
39import com.sun.corba.se.spi.logging.CORBALogDomains;
40import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
41import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
42import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
43
44import com.sun.corba.se.impl.util.Utility;
45import com.sun.corba.se.impl.orbutil.ORBUtility;
46import com.sun.corba.se.impl.corba.TypeCodeImpl;
47import com.sun.corba.se.impl.util.RepositoryId;
48import com.sun.corba.se.impl.orbutil.ORBConstants;
49import com.sun.corba.se.impl.logging.ORBUtilSystemException;
50import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
51
52import org.omg.CORBA.Any;
53import org.omg.CORBA.TypeCode;
54import org.omg.CORBA.Principal;
55import org.omg.CORBA.portable.IDLEntity;
56
57/**
58 * Implementation class that uses Java serialization for input streams.
59 * This assumes a GIOP version 1.2 message format.
60 *
61 * This class uses a ByteArrayInputStream as the underlying buffer. The
62 * first 16 bytes are directly read out of the underlying buffer. This allows
63 * [GIOPHeader (12 bytes) + requestID (4 bytes)] to be read as bytes.
64 * Subsequent write operations on this output stream object uses
65 * ObjectInputStream class to read into the buffer. This allows unmarshaling
66 * complex types and graphs using the ObjectInputStream implementation.
67 *
68 * Note, this class assumes a GIOP 1.2 style header. Further, the first
69 * 12 bytes, that is, the GIOPHeader is read directly from the received
70 * message, before this stream object is called. So, this class effectively
71 * reads only the requestID (4 bytes) directly, and uses the
72 * ObjectInputStream for further unmarshaling.
73 *
74 * @author Ram Jeyaraman
75 */
76public class IDLJavaSerializationInputStream extends CDRInputStreamBase {
77
78    private ORB orb;
79    private int bufSize;
80    private ByteBuffer buffer;
81    private byte encodingVersion;
82    private ObjectInputStream is;
83    private _ByteArrayInputStream bis;
84    private BufferManagerRead bufferManager;
85
86    // [GIOPHeader(12) + requestID(4)] bytes
87    private final int directReadLength = Message.GIOPMessageHeaderLength + 4;
88
89    // Used for mark / reset operations.
90    private boolean markOn;
91    private int peekIndex, peekCount;
92    private LinkedList markedItemQ = new LinkedList();
93
94    protected ORBUtilSystemException wrapper;
95
96    class _ByteArrayInputStream extends ByteArrayInputStream {
97
98        _ByteArrayInputStream(byte[] buf) {
99            super(buf);
100        }
101
102        int getPosition() {
103            return this.pos;
104        }
105
106        void setPosition(int value) {
107            if (value < 0 || value > count) {
108                throw new IndexOutOfBoundsException();
109            }
110            this.pos = value;
111        }
112    }
113
114    class MarshalObjectInputStream extends ObjectInputStream {
115
116        ORB orb;
117
118        MarshalObjectInputStream(java.io.InputStream out, ORB orb)
119                throws IOException {
120
121            super(out);
122            this.orb = orb;
123
124            java.security.AccessController.doPrivileged(
125                new java.security.PrivilegedAction() {
126                    public Object run() {
127                        // needs SerializablePermission("enableSubstitution")
128                        enableResolveObject(true);
129                        return null;
130                    }
131                }
132            );
133        }
134
135        /**
136         * Connect the Stub to the ORB.
137         */
138        protected final Object resolveObject(Object obj) throws IOException {
139            try {
140                if (StubAdapter.isStub(obj)) {
141                    StubAdapter.connect(obj, orb);
142                }
143            } catch (java.rmi.RemoteException re) {
144                IOException ie = new IOException("resolveObject failed");
145                ie.initCause(re);
146                throw ie;
147            }
148            return obj;
149        }
150    }
151
152    public IDLJavaSerializationInputStream(byte encodingVersion) {
153        super();
154        this.encodingVersion = encodingVersion;
155    }
156
157    public void init(org.omg.CORBA.ORB orb,
158                     ByteBuffer byteBuffer,
159                     int bufSize,
160                     boolean littleEndian,
161                     BufferManagerRead bufferManager) {
162        this.orb = (ORB) orb;
163        this.bufSize = bufSize;
164        this.bufferManager = bufferManager;
165        buffer = byteBuffer;
166        wrapper =
167            ORBUtilSystemException.get((ORB)orb, CORBALogDomains.RPC_ENCODING);
168
169        byte[] buf;
170        if (buffer.hasArray()) {
171            buf = buffer.array();
172        } else {
173            buf = new byte[bufSize];
174            buffer.get(buf);
175        }
176        // Note: at this point, the buffer position is zero. The setIndex()
177        // method call can be used to set a desired read index.
178        bis = new _ByteArrayInputStream(buf);
179    }
180
181    // Called from read_octet or read_long or read_ulong method.
182    private void initObjectInputStream() {
183        //System.out.print(" is ");
184        if (is != null) {
185            throw wrapper.javaStreamInitFailed();
186        }
187        try {
188            is = new MarshalObjectInputStream(bis, orb);
189        } catch (Exception e) {
190            throw wrapper.javaStreamInitFailed(e);
191        }
192    }
193
194    // org.omg.CORBA.portable.InputStream
195
196    // Primitive types.
197
198    public boolean read_boolean() {
199        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
200            return ((Boolean)markedItemQ.removeFirst()).booleanValue();
201        }
202        if (markOn && !(markedItemQ.isEmpty()) &&
203                (peekIndex < peekCount)) { // peek
204            return ((Boolean)markedItemQ.get(peekIndex++)).booleanValue();
205        }
206        try {
207            boolean value = is.readBoolean();
208            if (markOn) { // enqueue
209                markedItemQ.addLast(Boolean.valueOf(value));
210            }
211            return value;
212        } catch (Exception e) {
213            throw wrapper.javaSerializationException(e, "read_boolean");
214        }
215    }
216
217    public char read_char() {
218        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
219            return ((Character)markedItemQ.removeFirst()).charValue();
220        }
221        if (markOn && !(markedItemQ.isEmpty()) &&
222                (peekIndex < peekCount)) { // peek
223            return ((Character)markedItemQ.get(peekIndex++)).charValue();
224        }
225        try {
226            char value = is.readChar();
227            if (markOn) { // enqueue
228                markedItemQ.addLast(new Character(value));
229            }
230            return value;
231        } catch (Exception e) {
232            throw wrapper.javaSerializationException(e, "read_char");
233        }
234    }
235
236    public char read_wchar() {
237        return this.read_char();
238    }
239
240    public byte read_octet() {
241
242        // check if size < [ GIOPHeader(12) + requestID(4)] bytes
243        if (bis.getPosition() < directReadLength) {
244            byte b = (byte) bis.read();
245            if (bis.getPosition() == directReadLength) {
246                initObjectInputStream();
247            }
248            return b;
249        }
250
251        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
252            return ((Byte)markedItemQ.removeFirst()).byteValue();
253        }
254
255        if (markOn && !(markedItemQ.isEmpty()) &&
256                (peekIndex < peekCount)) { // peek
257            return ((Byte)markedItemQ.get(peekIndex++)).byteValue();
258        }
259
260        try {
261            byte value = is.readByte();
262            if (markOn) { // enqueue
263                //markedItemQ.addLast(Byte.valueOf(value)); // only in JDK 1.5
264                markedItemQ.addLast(new Byte(value));
265            }
266            return value;
267        } catch (Exception e) {
268            throw wrapper.javaSerializationException(e, "read_octet");
269        }
270    }
271
272    public short read_short() {
273        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
274            return ((Short)markedItemQ.removeFirst()).shortValue();
275        }
276        if (markOn && !(markedItemQ.isEmpty()) &&
277                (peekIndex < peekCount)) { // peek
278            return ((Short)markedItemQ.get(peekIndex++)).shortValue();
279        }
280
281        try {
282            short value = is.readShort();
283            if (markOn) { // enqueue
284                markedItemQ.addLast(new Short(value));
285            }
286            return value;
287        } catch (Exception e) {
288            throw wrapper.javaSerializationException(e, "read_short");
289        }
290    }
291
292    public short read_ushort() {
293        return this.read_short();
294    }
295
296    public int read_long() {
297
298        // check if size < [ GIOPHeader(12) + requestID(4)] bytes
299        if (bis.getPosition() < directReadLength) {
300
301            // Use big endian (network byte order). This is fixed.
302            // Both the writer and reader use the same byte order.
303            int b1 = (bis.read() << 24) & 0xFF000000;
304            int b2 = (bis.read() << 16) & 0x00FF0000;
305            int b3 = (bis.read() << 8)  & 0x0000FF00;
306            int b4 = (bis.read() << 0)  & 0x000000FF;
307
308            if (bis.getPosition() == directReadLength) {
309                initObjectInputStream();
310            } else if (bis.getPosition() > directReadLength) {
311                // Cannot happen. All direct reads are contained
312                // within the first 16 bytes.
313                wrapper.javaSerializationException("read_long");
314            }
315
316            return (b1 | b2 | b3 | b4);
317        }
318
319        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
320            return ((Integer)markedItemQ.removeFirst()).intValue();
321        }
322
323        if (markOn && !(markedItemQ.isEmpty()) &&
324                (peekIndex < peekCount)) { // peek
325            return ((Integer)markedItemQ.get(peekIndex++)).intValue();
326        }
327
328        try {
329            int value = is.readInt();
330            if (markOn) { // enqueue
331                markedItemQ.addLast(new Integer(value));
332            }
333            return value;
334        } catch (Exception e) {
335            throw wrapper.javaSerializationException(e, "read_long");
336        }
337    }
338
339    public int read_ulong() {
340        return this.read_long();
341    }
342
343    public long read_longlong() {
344        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
345            return ((Long)markedItemQ.removeFirst()).longValue();
346        }
347        if (markOn && !(markedItemQ.isEmpty()) &&
348                (peekIndex < peekCount)) { // peek
349            return ((Long)markedItemQ.get(peekIndex++)).longValue();
350        }
351
352        try {
353            long value = is.readLong();
354            if (markOn) { // enqueue
355                markedItemQ.addLast(new Long(value));
356            }
357            return value;
358        } catch (Exception e) {
359            throw wrapper.javaSerializationException(e, "read_longlong");
360        }
361    }
362
363    public long read_ulonglong() {
364        return read_longlong();
365    }
366
367    public float read_float() {
368        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
369            return ((Float)markedItemQ.removeFirst()).floatValue();
370        }
371        if (markOn && !(markedItemQ.isEmpty()) &&
372                (peekIndex < peekCount)) { // peek
373            return ((Float)markedItemQ.get(peekIndex++)).floatValue();
374        }
375
376        try {
377            float value = is.readFloat();
378            if (markOn) { // enqueue
379                markedItemQ.addLast(new Float(value));
380            }
381            return value;
382        } catch (Exception e) {
383            throw wrapper.javaSerializationException(e, "read_float");
384        }
385    }
386
387    public double read_double() {
388        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
389            return ((Double)markedItemQ.removeFirst()).doubleValue();
390        }
391        if (markOn && !(markedItemQ.isEmpty()) &&
392                (peekIndex < peekCount)) { // peek
393            return ((Double)markedItemQ.get(peekIndex++)).doubleValue();
394        }
395
396        try {
397            double value = is.readDouble();
398            if (markOn) { // enqueue
399                markedItemQ.addLast(new Double(value));
400            }
401            return value;
402        } catch (Exception e) {
403            throw wrapper.javaSerializationException(e, "read_double");
404        }
405    }
406
407    // String types.
408
409    public String read_string() {
410        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
411            return (String) markedItemQ.removeFirst();
412        }
413        if (markOn && !(markedItemQ.isEmpty()) &&
414            (peekIndex < peekCount)) { // peek
415            return (String) markedItemQ.get(peekIndex++);
416        }
417        try {
418            String value = is.readUTF();
419            if (markOn) { // enqueue
420                markedItemQ.addLast(value);
421            }
422            return value;
423        } catch (Exception e) {
424            throw wrapper.javaSerializationException(e, "read_string");
425        }
426    }
427
428    public String read_wstring() {
429        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
430            return (String) markedItemQ.removeFirst();
431        }
432        if (markOn && !(markedItemQ.isEmpty()) &&
433                (peekIndex < peekCount)) { // peek
434            return (String) markedItemQ.get(peekIndex++);
435        }
436        try {
437            String value = (String) is.readObject();
438            if (markOn) { // enqueue
439                markedItemQ.addLast(value);
440            }
441            return value;
442        } catch (Exception e) {
443            throw wrapper.javaSerializationException(e, "read_wstring");
444        }
445    }
446
447    // Array types.
448
449    public void read_boolean_array(boolean[] value, int offset, int length){
450        for(int i = 0; i < length; i++) {
451            value[i+offset] = read_boolean();
452        }
453    }
454
455    public void read_char_array(char[] value, int offset, int length) {
456        for(int i=0; i < length; i++) {
457            value[i+offset] = read_char();
458        }
459    }
460
461    public void read_wchar_array(char[] value, int offset, int length) {
462        read_char_array(value, offset, length);
463    }
464
465    public void read_octet_array(byte[] value, int offset, int length) {
466        for(int i=0; i < length; i++) {
467            value[i+offset] = read_octet();
468        }
469        /* // Cannot use this efficient read due to mark/reset support.
470        try {
471            while (length > 0) {
472                int n = is.read(value, offset, length);
473                offset += n;
474                length -= n;
475            }
476        } catch (Exception e) {
477            throw wrapper.javaSerializationException(e, "read_octet_array");
478        }
479        */
480    }
481
482    public void read_short_array(short[] value, int offset, int length) {
483        for(int i=0; i < length; i++) {
484            value[i+offset] = read_short();
485        }
486    }
487
488    public void read_ushort_array(short[] value, int offset, int length) {
489        read_short_array(value, offset, length);
490    }
491
492    public void read_long_array(int[] value, int offset, int length) {
493        for(int i=0; i < length; i++) {
494            value[i+offset] = read_long();
495        }
496    }
497
498    public void read_ulong_array(int[] value, int offset, int length) {
499        read_long_array(value, offset, length);
500    }
501
502    public void read_longlong_array(long[] value, int offset, int length) {
503        for(int i=0; i < length; i++) {
504            value[i+offset] = read_longlong();
505        }
506    }
507
508    public void read_ulonglong_array(long[] value, int offset, int length) {
509        read_longlong_array(value, offset, length);
510    }
511
512    public void read_float_array(float[] value, int offset, int length) {
513        for(int i=0; i < length; i++) {
514            value[i+offset] = read_float();
515        }
516    }
517
518    public void read_double_array(double[] value, int offset, int length) {
519        for(int i=0; i < length; i++) {
520            value[i+offset] = read_double();
521        }
522    }
523
524    // Complex types.
525
526    public org.omg.CORBA.Object read_Object() {
527        return read_Object(null);
528    }
529
530    public TypeCode read_TypeCode() {
531        TypeCodeImpl tc = new TypeCodeImpl(orb);
532        tc.read_value(parent);
533        return tc;
534    }
535
536    public Any read_any() {
537
538        Any any = orb.create_any();
539        TypeCodeImpl tc = new TypeCodeImpl(orb);
540
541        // read off the typecode
542
543        // REVISIT We could avoid this try-catch if we could peek the typecode
544        // kind off this stream and see if it is a tk_value.
545        // Looking at the code we know that for tk_value the Any.read_value()
546        // below ignores the tc argument anyway (except for the kind field).
547        // But still we would need to make sure that the whole typecode,
548        // including encapsulations, is read off.
549        try {
550            tc.read_value(parent);
551        } catch (org.omg.CORBA.MARSHAL ex) {
552            if (tc.kind().value() != org.omg.CORBA.TCKind._tk_value) {
553                throw ex;
554            }
555            // We can be sure that the whole typecode encapsulation has been
556            // read off.
557            ex.printStackTrace();
558        }
559
560        // read off the value of the any.
561        any.read_value(parent, tc);
562
563        return any;
564    }
565
566    public Principal read_Principal() {
567        // We don't need an implementation for this method, since principal
568        // is absent in GIOP version 1.2 or above.
569        int len = read_long();
570        byte[] pvalue = new byte[len];
571        read_octet_array(pvalue,0,len);
572        Principal p = new com.sun.corba.se.impl.corba.PrincipalImpl();
573        p.name(pvalue);
574        return p;
575    }
576
577    public BigDecimal read_fixed() {
578        return new BigDecimal(read_fixed_buffer().toString());
579    }
580
581    // Each octet contains (up to) two decimal digits. If the fixed type has
582    // an odd number of decimal digits, then the representation
583    // begins with the first (most significant) digit.
584    // Otherwise, this first half-octet is all zero, and the first digit
585    // is in the second half-octet.
586    // The sign configuration, in the last half-octet of the representation,
587    // is 0xD for negative numbers and 0xC for positive and zero values.
588    private StringBuffer read_fixed_buffer() {
589        StringBuffer buffer = new StringBuffer(64);
590        byte doubleDigit;
591        int firstDigit;
592        int secondDigit;
593        boolean wroteFirstDigit = false;
594        boolean more = true;
595        while (more) {
596            doubleDigit = read_octet();
597            firstDigit = (int)((doubleDigit & 0xf0) >> 4);
598            secondDigit = (int)(doubleDigit & 0x0f);
599            if (wroteFirstDigit || firstDigit != 0) {
600                buffer.append(Character.forDigit(firstDigit, 10));
601                wroteFirstDigit = true;
602            }
603            if (secondDigit == 12) {
604                // positive number or zero
605                if ( ! wroteFirstDigit) {
606                    // zero
607                    return new StringBuffer("0.0");
608                } else {
609                    // positive number
610                    // done
611                }
612                more = false;
613            } else if (secondDigit == 13) {
614                // negative number
615                buffer.insert(0, '-');
616                more = false;
617            } else {
618                buffer.append(Character.forDigit(secondDigit, 10));
619                wroteFirstDigit = true;
620            }
621        }
622        return buffer;
623    }
624
625    public org.omg.CORBA.Object read_Object(java.lang.Class clz) {
626
627        // In any case, we must first read the IOR.
628        IOR ior = IORFactories.makeIOR(parent) ;
629        if (ior.isNil()) {
630            return null;
631        }
632
633        PresentationManager.StubFactoryFactory sff =
634            ORB.getStubFactoryFactory();
635        String codeBase = ior.getProfile().getCodebase();
636        PresentationManager.StubFactory stubFactory = null;
637
638        if (clz == null) {
639            RepositoryId rid = RepositoryId.cache.getId(ior.getTypeId() );
640            String className = rid.getClassName();
641            boolean isIDLInterface = rid.isIDLType();
642
643            if (className == null || className.equals( "" )) {
644                stubFactory = null;
645            } else {
646                try {
647                    stubFactory = sff.createStubFactory(className,
648                        isIDLInterface, codeBase, (Class) null,
649                        (ClassLoader) null);
650                } catch (Exception exc) {
651                    // Could not create stubFactory, so use null.
652                    // XXX stubFactory handling is still too complex:
653                    // Can we resolve the stubFactory question once in
654                    // a single place?
655                    stubFactory = null ;
656                }
657            }
658        } else if (StubAdapter.isStubClass(clz)) {
659            stubFactory = PresentationDefaults.makeStaticStubFactory(clz);
660        } else {
661            // clz is an interface class
662            boolean isIDL = IDLEntity.class.isAssignableFrom(clz);
663
664            stubFactory = sff.createStubFactory(
665                 clz.getName(), isIDL, codeBase, clz, clz.getClassLoader());
666        }
667
668        return CDRInputStream_1_0.internalIORToObject(ior, stubFactory, orb);
669    }
670
671    public org.omg.CORBA.ORB orb() {
672        return this.orb;
673    }
674
675    // org.omg.CORBA_2_3.portable.InputStream
676
677    public java.io.Serializable read_value() {
678        if (!markOn && !(markedItemQ.isEmpty())) { // dequeue
679            return (Serializable) markedItemQ.removeFirst();
680        }
681        if (markOn && !(markedItemQ.isEmpty()) &&
682                (peekIndex < peekCount)) { // peek
683            return (Serializable) markedItemQ.get(peekIndex++);
684        }
685        try {
686            Serializable value = (java.io.Serializable) is.readObject();
687            if (markOn) { // enqueue
688                markedItemQ.addLast(value);
689            }
690            return value;
691        } catch (Exception e) {
692            throw wrapper.javaSerializationException(e, "read_value");
693        }
694    }
695
696    public java.io.Serializable read_value(java.lang.Class clz) {
697        return read_value();
698    }
699
700    public java.io.Serializable read_value(
701            org.omg.CORBA.portable.BoxedValueHelper factory) {
702        return read_value();
703    }
704
705    public java.io.Serializable read_value(java.lang.String rep_id) {
706        return read_value();
707    }
708
709    public java.io.Serializable read_value(java.io.Serializable value) {
710        return read_value();
711    }
712
713    public java.lang.Object read_abstract_interface() {
714        return read_abstract_interface(null);
715    }
716
717    public java.lang.Object read_abstract_interface(java.lang.Class clz) {
718        boolean isObject = read_boolean();
719        if (isObject) {
720            return read_Object(clz);
721        } else {
722            return read_value();
723        }
724    }
725
726    // com.sun.corba.se.impl.encoding.MarshalInputStream
727    public void consumeEndian() {
728        throw wrapper.giopVersionError();
729    }
730
731    public int getPosition() {
732        try {
733            return bis.getPosition();
734        } catch (Exception e) {
735            throw wrapper.javaSerializationException(e, "getPosition");
736        }
737    }
738
739    // org.omg.CORBA.DataInputStream
740    public java.lang.Object read_Abstract() {
741        return read_abstract_interface();
742    }
743
744    public java.io.Serializable read_Value() {
745        return read_value();
746    }
747
748    public void read_any_array (org.omg.CORBA.AnySeqHolder seq,
749                                int offset, int length) {
750        read_any_array(seq.value, offset, length);
751    }
752
753    private final void read_any_array(org.omg.CORBA.Any[] value,
754                                     int offset, int length) {
755        for(int i=0; i < length; i++) {
756            value[i+offset] = read_any();
757        }
758    }
759
760    public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq,
761                                    int offset, int length){
762        read_boolean_array(seq.value, offset, length);
763    }
764
765    public void read_char_array (org.omg.CORBA.CharSeqHolder seq,
766                                 int offset, int length){
767        read_char_array(seq.value, offset, length);
768    }
769
770    public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq,
771                                  int offset, int length){
772        read_wchar_array(seq.value, offset, length);
773    }
774
775    public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq,
776                                  int offset, int length){
777        read_octet_array(seq.value, offset, length);
778    }
779
780    public void read_short_array (org.omg.CORBA.ShortSeqHolder seq,
781                                  int offset, int length){
782        read_short_array(seq.value, offset, length);
783    }
784
785    public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq,
786                                   int offset, int length){
787        read_ushort_array(seq.value, offset, length);
788    }
789
790    public void read_long_array (org.omg.CORBA.LongSeqHolder seq,
791                                 int offset, int length){
792        read_long_array(seq.value, offset, length);
793    }
794
795    public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq,
796                                  int offset, int length){
797        read_ulong_array(seq.value, offset, length);
798    }
799
800    public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq,
801                                      int offset, int length){
802        read_ulonglong_array(seq.value, offset, length);
803    }
804
805    public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq,
806                                     int offset, int length){
807        read_longlong_array(seq.value, offset, length);
808    }
809
810    public void read_float_array (org.omg.CORBA.FloatSeqHolder seq,
811                                  int offset, int length){
812        read_float_array(seq.value, offset, length);
813    }
814
815    public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq,
816                                   int offset, int length){
817        read_double_array(seq.value, offset, length);
818    }
819
820    // org.omg.CORBA.portable.ValueBase
821
822    public String[] _truncatable_ids() {
823        throw wrapper.giopVersionError();
824    }
825
826    // java.io.InputStream
827    // REVISIT - should we make these throw UnsupportedOperationExceptions?
828    // Right now, they'll go up to the java.io versions!
829
830    //     public int read(byte b[]) throws IOException;
831    //     public int read(byte b[], int off, int len) throws IOException
832    //     public long skip(long n) throws IOException;
833    //     public int available() throws IOException;
834    //     public void close() throws IOException;
835
836    public void mark(int readLimit) {
837        // Nested mark disallowed.
838        // Further, mark is not supported until first 16 bytes are read.
839        if (markOn || is == null) {
840            throw wrapper.javaSerializationException("mark");
841        }
842        markOn = true;
843        if (!(markedItemQ.isEmpty())) {
844            peekIndex = 0;
845            peekCount = markedItemQ.size();
846        }
847        /*
848        // Note: only ByteArrayInputStream supports mark/reset.
849        if (is == null || is.markSupported() == false) {
850            throw wrapper.javaSerializationException("mark");
851        }
852        is.mark(readLimit);
853        */
854    }
855
856    public void reset() {
857        markOn = false;
858        peekIndex = 0;
859        peekCount = 0;
860        /*
861        // Note: only ByteArrayInputStream supports mark/reset.
862        if (is == null || is.markSupported() == false) {
863            throw wrapper.javaSerializationException("mark");
864        }
865        try {
866            is.reset();
867        } catch (Exception e) {
868            throw wrapper.javaSerializationException(e, "reset");
869        }
870        */
871    }
872
873    // This should return false so that outside users (people using the JDK)
874    // don't have any guarantees that mark/reset will work in their
875    // custom marshaling code.  This is necessary since they could do things
876    // like expect obj1a == obj1b in the following code:
877    //
878    // is.mark(10000);
879    // Object obj1a = is.readObject();
880    // is.reset();
881    // Object obj1b = is.readObject();
882    //
883    public boolean markSupported() {
884        return true;
885    }
886
887    // Needed by AnyImpl and ServiceContexts
888    public CDRInputStreamBase dup() {
889
890        CDRInputStreamBase result = null ;
891
892        try {
893            result = (CDRInputStreamBase) this.getClass().newInstance();
894        } catch (Exception e) {
895            throw wrapper.couldNotDuplicateCdrInputStream(e);
896        }
897
898        result.init(this.orb, this.buffer, this.bufSize, false, null);
899
900        // Set the buffer position.
901        ((IDLJavaSerializationInputStream)result).skipBytes(getPosition());
902
903        // Set mark related data.
904        ((IDLJavaSerializationInputStream)result).
905            setMarkData(markOn, peekIndex, peekCount,
906                        (LinkedList) markedItemQ.clone());
907
908        return result;
909    }
910
911    // Used exclusively by the dup() method.
912    void skipBytes(int len) {
913        try {
914            is.skipBytes(len);
915        } catch (Exception e) {
916            throw wrapper.javaSerializationException(e, "skipBytes");
917        }
918    }
919
920    // Used exclusively by the dup() method.
921    void setMarkData(boolean markOn, int peekIndex, int peekCount,
922                     LinkedList markedItemQ) {
923        this.markOn = markOn;
924        this.peekIndex = peekIndex;
925        this.peekCount = peekCount;
926        this.markedItemQ = markedItemQ;
927    }
928
929    // Needed by TCUtility
930    public java.math.BigDecimal read_fixed(short digits, short scale) {
931        // digits isn't really needed here
932        StringBuffer buffer = read_fixed_buffer();
933        if (digits != buffer.length())
934            throw wrapper.badFixed( new Integer(digits),
935                new Integer(buffer.length()) ) ;
936        buffer.insert(digits - scale, '.');
937        return new BigDecimal(buffer.toString());
938    }
939
940    // Needed by TypeCodeImpl
941    public boolean isLittleEndian() {
942        throw wrapper.giopVersionError();
943    }
944
945    // Needed by request and reply messages for GIOP versions >= 1.2 only.
946    void setHeaderPadding(boolean headerPadding) {
947        // no-op. We don't care about body alignment while using
948        // Java serialization. What the GIOP spec states does not apply here.
949    }
950
951    // Needed by IIOPInputStream and other subclasses
952
953    public ByteBuffer getByteBuffer() {
954        throw wrapper.giopVersionError();
955    }
956
957    public void setByteBuffer(ByteBuffer byteBuffer) {
958        throw wrapper.giopVersionError();
959    }
960
961    public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
962        throw wrapper.giopVersionError();
963    }
964
965    public int getBufferLength() {
966        return bufSize;
967    }
968
969    public void setBufferLength(int value) {
970        // this is redundant, since buffer size was already specified
971        // as part of the init call. So, ignore.
972    }
973
974    public int getIndex() {
975        return bis.getPosition();
976    }
977
978    public void setIndex(int value) {
979        try {
980            bis.setPosition(value);
981        } catch (IndexOutOfBoundsException e) {
982            throw wrapper.javaSerializationException(e, "setIndex");
983        }
984    }
985
986    public void orb(org.omg.CORBA.ORB orb) {
987        this.orb = (ORB) orb;
988    }
989
990    public BufferManagerRead getBufferManager() {
991        return bufferManager;
992    }
993
994    public GIOPVersion getGIOPVersion() {
995        return GIOPVersion.V1_2;
996    }
997
998    com.sun.org.omg.SendingContext.CodeBase getCodeBase() {
999        return parent.getCodeBase();
1000    }
1001
1002    void printBuffer() {
1003        byte[] buf = this.buffer.array();
1004
1005        System.out.println("+++++++ Input Buffer ++++++++");
1006        System.out.println();
1007        System.out.println("Current position: " + getPosition());
1008        System.out.println("Total length : " + this.bufSize);
1009        System.out.println();
1010
1011        char[] charBuf = new char[16];
1012
1013        try {
1014
1015            for (int i = 0; i < buf.length; i += 16) {
1016
1017                int j = 0;
1018
1019                // For every 16 bytes, there is one line
1020                // of output.  First, the hex output of
1021                // the 16 bytes with each byte separated
1022                // by a space.
1023                while (j < 16 && j + i < buf.length) {
1024                    int k = buf[i + j];
1025                    if (k < 0)
1026                        k = 256 + k;
1027                    String hex = Integer.toHexString(k);
1028                    if (hex.length() == 1)
1029                        hex = "0" + hex;
1030                    System.out.print(hex + " ");
1031                    j++;
1032                }
1033
1034                // Add any extra spaces to align the
1035                // text column in case we didn't end
1036                // at 16
1037                while (j < 16) {
1038                    System.out.print("   ");
1039                    j++;
1040                }
1041
1042                // Now output the ASCII equivalents.  Non-ASCII
1043                // characters are shown as periods.
1044                int x = 0;
1045
1046                while (x < 16 && x + i < buf.length) {
1047                    if (ORBUtility.isPrintable((char)buf[i + x])) {
1048                        charBuf[x] = (char) buf[i + x];
1049                    } else {
1050                        charBuf[x] = '.';
1051                    }
1052                    x++;
1053                }
1054                System.out.println(new String(charBuf, 0, x));
1055            }
1056        } catch (Throwable t) {
1057            t.printStackTrace();
1058        }
1059        System.out.println("++++++++++++++++++++++++++++++");
1060    }
1061
1062    void alignOnBoundary(int octetBoundary) {
1063        throw wrapper.giopVersionError();
1064    }
1065
1066    void performORBVersionSpecificInit() {
1067        // No-op.
1068    }
1069
1070    public void resetCodeSetConverters() {
1071        // No-op.
1072    }
1073
1074    // ValueInputStream -------------------------
1075
1076    public void start_value() {
1077        throw wrapper.giopVersionError();
1078    }
1079
1080    public void end_value() {
1081        throw wrapper.giopVersionError();
1082    }
1083}
1084