1 /*
2  * Copyright (c) 1998, 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  * Licensed Materials - Property of IBM
27  * RMI-IIOP v1.0
28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
29  *
30  */
31 
32 package com.sun.corba.se.impl.io;
33 
34 import javax.rmi.CORBA.Util;
35 
36 import java.util.Hashtable;
37 import java.io.IOException;
38 
39 import com.sun.corba.se.impl.util.RepositoryId;
40 import com.sun.corba.se.impl.util.Utility;
41 
42 import org.omg.CORBA.TCKind;
43 
44 import org.omg.CORBA.portable.IndirectionException;
45 import com.sun.org.omg.SendingContext.CodeBase;
46 import com.sun.org.omg.SendingContext.CodeBaseHelper;
47 
48 import java.security.AccessController;
49 import java.security.PrivilegedAction;
50 import java.security.PrivilegedExceptionAction;
51 
52 import com.sun.corba.se.spi.logging.CORBALogDomains;
53 import com.sun.corba.se.impl.logging.OMGSystemException;
54 import com.sun.corba.se.impl.logging.UtilSystemException;
55 
56 public final class ValueHandlerImpl implements javax.rmi.CORBA.ValueHandlerMultiFormat {
57 
58     // Property to override our maximum stream format version
59     public static final String FORMAT_VERSION_PROPERTY
60         = "com.sun.CORBA.MaxStreamFormatVersion";
61 
62     private static final byte MAX_SUPPORTED_FORMAT_VERSION = (byte)2;
63     private static final byte STREAM_FORMAT_VERSION_1 = (byte)1;
64 
65     // The ValueHandler's maximum stream format version to advertise,
66     // set in a static initializer.
67     private static final byte MAX_STREAM_FORMAT_VERSION;
68 
69     static {
70         MAX_STREAM_FORMAT_VERSION = getMaxStreamFormatVersion();
71     }
72 
73     // Looks for the FORMAT_VERSION_PROPERTY system property
74     // to allow the user to override our default stream format
75     // version.  Note that this still only allows them to pick
76     // a supported version (1 through MAX_STREAM_FORMAT_VERSION).
getMaxStreamFormatVersion()77     private static byte getMaxStreamFormatVersion() {
78 
79         try {
80 
81             String propValue = (String) AccessController.doPrivileged(
82                                         new PrivilegedAction() {
83                 public java.lang.Object run() {
84                     return System.getProperty(ValueHandlerImpl.FORMAT_VERSION_PROPERTY);
85                 }
86             });
87 
88             // The property wasn't set
89             if (propValue == null)
90                 return MAX_SUPPORTED_FORMAT_VERSION;
91 
92             byte result = Byte.parseByte(propValue);
93 
94             // REVISIT.  Just set to MAX_SUPPORTED_FORMAT_VERSION
95             // or really let the system shutdown with this Error?
96             if (result < 1 || result > MAX_SUPPORTED_FORMAT_VERSION)
97                 // XXX I18N, logging needed.
98                 throw new ExceptionInInitializerError("Invalid stream format version: "
99                                                       + result
100                                                       + ".  Valid range is 1 through "
101                                                       + MAX_SUPPORTED_FORMAT_VERSION);
102 
103             return result;
104 
105         } catch (Exception ex) {
106             // REVISIT.  Swallow this or really let
107             // the system shutdown with this Error?
108 
109             Error err = new ExceptionInInitializerError(ex);
110             err.initCause( ex ) ;
111             throw err ;
112         }
113     }
114 
115     public static final short kRemoteType = 0;
116     public static final short kAbstractType = 1;
117     public static final short kValueType = 2;
118 
119     private Hashtable inputStreamPairs = null;
120     private Hashtable outputStreamPairs = null;
121     private CodeBase codeBase = null;
122     private boolean useHashtables = true;
123     private boolean isInputStream = true;
124     private IIOPOutputStream outputStreamBridge = null;
125     private IIOPInputStream inputStreamBridge = null;
126     private OMGSystemException omgWrapper = OMGSystemException.get(
127         CORBALogDomains.RPC_ENCODING ) ;
128     private UtilSystemException utilWrapper = UtilSystemException.get(
129         CORBALogDomains.RPC_ENCODING ) ;
130 
131     // See javax.rmi.CORBA.ValueHandlerMultiFormat
getMaximumStreamFormatVersion()132     public byte getMaximumStreamFormatVersion() {
133         return MAX_STREAM_FORMAT_VERSION;
134     }
135 
136     // See javax.rmi.CORBA.ValueHandlerMultiFormat
writeValue(org.omg.CORBA.portable.OutputStream out, java.io.Serializable value, byte streamFormatVersion)137     public void writeValue(org.omg.CORBA.portable.OutputStream out,
138                            java.io.Serializable value,
139                            byte streamFormatVersion) {
140 
141         if (streamFormatVersion == 2) {
142             if (!(out instanceof org.omg.CORBA.portable.ValueOutputStream)) {
143                 throw omgWrapper.notAValueoutputstream() ;
144             }
145         } else if (streamFormatVersion != 1) {
146             throw omgWrapper.invalidStreamFormatVersion(
147                 new Integer(streamFormatVersion) ) ;
148         }
149 
150         writeValueWithVersion(out, value, streamFormatVersion);
151     }
152 
ValueHandlerImpl()153     private ValueHandlerImpl(){}
154 
ValueHandlerImpl(boolean isInputStream)155     private ValueHandlerImpl(boolean isInputStream) {
156         this();
157         useHashtables = false;
158         this.isInputStream = isInputStream;
159     }
160 
getInstance()161     static ValueHandlerImpl getInstance() {
162         return new ValueHandlerImpl();
163     }
164 
getInstance(boolean isInputStream)165     static ValueHandlerImpl getInstance(boolean isInputStream) {
166         return new ValueHandlerImpl(isInputStream);
167     }
168 
169     /**
170      * Writes the value to the stream using java semantics.
171      * @param out The stream to write the value to
172      * @param value The value to be written to the stream
173      **/
writeValue(org.omg.CORBA.portable.OutputStream _out, java.io.Serializable value)174     public void writeValue(org.omg.CORBA.portable.OutputStream _out,
175                            java.io.Serializable value) {
176         writeValueWithVersion(_out, value, STREAM_FORMAT_VERSION_1);
177     }
178 
writeValueWithVersion(org.omg.CORBA.portable.OutputStream _out, java.io.Serializable value, byte streamFormatVersion)179     private void writeValueWithVersion(org.omg.CORBA.portable.OutputStream _out,
180                                        java.io.Serializable value,
181                                        byte streamFormatVersion) {
182 
183         org.omg.CORBA_2_3.portable.OutputStream out =
184             (org.omg.CORBA_2_3.portable.OutputStream) _out;
185 
186         if (!useHashtables) {
187             if (outputStreamBridge == null) {
188                 outputStreamBridge = createOutputStream();
189                 outputStreamBridge.setOrbStream(out);
190             }
191 
192             try {
193                 outputStreamBridge.increaseRecursionDepth();
194                 writeValueInternal(outputStreamBridge, out, value, streamFormatVersion);
195             } finally {
196                 outputStreamBridge.decreaseRecursionDepth();
197             }
198 
199             return;
200         }
201 
202         IIOPOutputStream jdkToOrbOutputStreamBridge = null;
203 
204         if (outputStreamPairs == null)
205             outputStreamPairs = new Hashtable();
206 
207         jdkToOrbOutputStreamBridge = (IIOPOutputStream)outputStreamPairs.get(_out);
208 
209         if (jdkToOrbOutputStreamBridge == null) {
210             jdkToOrbOutputStreamBridge = createOutputStream();
211             jdkToOrbOutputStreamBridge.setOrbStream(out);
212             outputStreamPairs.put(_out, jdkToOrbOutputStreamBridge);
213         }
214 
215         try {
216 
217             jdkToOrbOutputStreamBridge.increaseRecursionDepth();
218             writeValueInternal(jdkToOrbOutputStreamBridge, out, value, streamFormatVersion);
219         } finally {
220             if (jdkToOrbOutputStreamBridge.decreaseRecursionDepth() == 0) {
221                 outputStreamPairs.remove(_out);
222             }
223         }
224     }
225 
writeValueInternal(IIOPOutputStream bridge, org.omg.CORBA_2_3.portable.OutputStream out, java.io.Serializable value, byte streamFormatVersion)226     private void writeValueInternal(IIOPOutputStream bridge,
227                                     org.omg.CORBA_2_3.portable.OutputStream out,
228                                     java.io.Serializable value,
229                                     byte streamFormatVersion)
230     {
231         Class clazz = value.getClass();
232 
233         if (clazz.isArray())
234             write_Array(out, value, clazz.getComponentType());
235         else
236             bridge.simpleWriteObject(value, streamFormatVersion);
237     }
238 
239     /**
240      * Reads a value from the stream using java semantics.
241      * @param in The stream to read the value from
242      * @param clazz The type of the value to be read in
243      * @param sender The sending context runtime
244      **/
readValue(org.omg.CORBA.portable.InputStream _in, int offset, java.lang.Class clazz, String repositoryID, org.omg.SendingContext.RunTime _sender)245     public java.io.Serializable readValue(org.omg.CORBA.portable.InputStream _in,
246                                           int offset,
247                                           java.lang.Class clazz,
248                                           String repositoryID,
249                                           org.omg.SendingContext.RunTime _sender)
250     {
251         // Must use narrow rather than a direct cast to a com.sun
252         // class.  Fix for bug 4379539.
253         CodeBase sender = CodeBaseHelper.narrow(_sender);
254 
255         org.omg.CORBA_2_3.portable.InputStream in =
256             (org.omg.CORBA_2_3.portable.InputStream) _in;
257 
258         if (!useHashtables) {
259             if (inputStreamBridge == null) {
260                 inputStreamBridge = createInputStream();
261                 inputStreamBridge.setOrbStream(in);
262                 inputStreamBridge.setSender(sender); //d11638
263                 // backward compatability 4365188
264                 inputStreamBridge.setValueHandler(this);
265             }
266 
267             java.io.Serializable result = null;
268 
269             try {
270 
271                 inputStreamBridge.increaseRecursionDepth();
272                 result = (java.io.Serializable) readValueInternal(inputStreamBridge, in, offset, clazz, repositoryID, sender);
273 
274             } finally {
275 
276                 if (inputStreamBridge.decreaseRecursionDepth() == 0) {
277                     // Indirections are resolved immediately since
278                     // the change to the active recursion manager,
279                     // so this will never happen.
280                 }
281             }
282 
283             return result;
284         }
285 
286         IIOPInputStream jdkToOrbInputStreamBridge = null;
287         if (inputStreamPairs == null)
288             inputStreamPairs = new Hashtable();
289 
290         jdkToOrbInputStreamBridge = (IIOPInputStream)inputStreamPairs.get(_in);
291 
292         if (jdkToOrbInputStreamBridge == null) {
293 
294             jdkToOrbInputStreamBridge = createInputStream();
295             jdkToOrbInputStreamBridge.setOrbStream(in);
296             jdkToOrbInputStreamBridge.setSender(sender); //d11638
297             // backward compatability 4365188
298             jdkToOrbInputStreamBridge.setValueHandler(this);
299             inputStreamPairs.put(_in, jdkToOrbInputStreamBridge);
300         }
301 
302         java.io.Serializable result = null;
303 
304         try {
305 
306             jdkToOrbInputStreamBridge.increaseRecursionDepth();
307             result = (java.io.Serializable) readValueInternal(jdkToOrbInputStreamBridge, in, offset, clazz, repositoryID, sender);
308 
309         } finally {
310 
311             if (jdkToOrbInputStreamBridge.decreaseRecursionDepth() == 0) {
312                 inputStreamPairs.remove(_in);
313             }
314         }
315 
316         return result;
317     }
318 
readValueInternal(IIOPInputStream bridge, org.omg.CORBA_2_3.portable.InputStream in, int offset, java.lang.Class clazz, String repositoryID, com.sun.org.omg.SendingContext.CodeBase sender)319     private java.io.Serializable readValueInternal(IIOPInputStream bridge,
320                                                   org.omg.CORBA_2_3.portable.InputStream in,
321                                                   int offset,
322                                                   java.lang.Class clazz,
323                                                   String repositoryID,
324                                                   com.sun.org.omg.SendingContext.CodeBase sender)
325     {
326         java.io.Serializable result = null;
327 
328         if (clazz == null) {
329             // clazz == null indicates an FVD situation for a nonexistant class
330             if (isArray(repositoryID)){
331                 read_Array(bridge, in, null, sender, offset);
332             } else {
333                 bridge.simpleSkipObject(repositoryID, sender);
334             }
335             return result;
336         }
337 
338         if (clazz.isArray()) {
339             result = (java.io.Serializable)read_Array(bridge, in, clazz, sender, offset);
340         } else {
341             result = (java.io.Serializable)bridge.simpleReadObject(clazz, repositoryID, sender, offset);
342         }
343 
344         return result;
345     }
346 
347     /**
348      * Returns the repository ID for the given RMI value Class.
349      * @param clz The class to return a repository ID for.
350      * @return the repository ID of the Class.
351      **/
getRMIRepositoryID(java.lang.Class clz)352     public java.lang.String getRMIRepositoryID(java.lang.Class clz) {
353         return RepositoryId.createForJavaType(clz);
354     }
355 
356     /**
357      * Indicates whether the given Class performs custom or
358      * default marshaling.
359      * @param clz The class to test for custom marshaling.
360      * @return True if the class performs custom marshaling, false
361      * if it does not.
362      **/
isCustomMarshaled(java.lang.Class clz)363     public boolean isCustomMarshaled(java.lang.Class clz) {
364         return ObjectStreamClass.lookup(clz).isCustomMarshaled();
365     }
366 
367     /**
368      * Returns the CodeBase for this ValueHandler.  This is used by
369      * the ORB runtime.  The server sends the service context containing
370      * the IOR for this CodeBase on the first GIOP reply.  The clients
371      * do the same on the first GIOP request.
372      * @return the SendingContext.CodeBase of this ValueHandler.
373      **/
getRunTimeCodeBase()374     public org.omg.SendingContext.RunTime getRunTimeCodeBase() {
375         if (codeBase != null)
376             return codeBase;
377         else {
378             codeBase = new FVDCodeBaseImpl();
379 
380             // backward compatability 4365188
381             // set the valueHandler so that correct/incorrect RepositoryID
382             // calculations can be done based on the ORB version
383             FVDCodeBaseImpl fvdImpl = (FVDCodeBaseImpl) codeBase;
384             fvdImpl.setValueHandler(this);
385             return codeBase;
386         }
387     }
388 
389 
390     // methods supported for backward compatability so that the appropriate
391     // Rep-id calculations take place based on the ORB version
392 
393     /**
394      *  Returns a boolean of whether or not RepositoryId indicates
395      *  FullValueDescriptor.
396      *  used for backward compatability
397      */
398 
useFullValueDescription(Class clazz, String repositoryID)399      public boolean useFullValueDescription(Class clazz, String repositoryID)
400         throws IOException
401      {
402         return RepositoryId.useFullValueDescription(clazz, repositoryID);
403      }
404 
getClassName(String id)405      public String getClassName(String id)
406      {
407         RepositoryId repID = RepositoryId.cache.getId(id);
408         return repID.getClassName();
409      }
410 
getClassFromType(String id)411      public Class getClassFromType(String id)
412         throws ClassNotFoundException
413      {
414         RepositoryId repId = RepositoryId.cache.getId(id);
415         return repId.getClassFromType();
416      }
417 
getAnyClassFromType(String id)418      public Class getAnyClassFromType(String id)
419         throws ClassNotFoundException
420      {
421         RepositoryId repId = RepositoryId.cache.getId(id);
422         return repId.getAnyClassFromType();
423      }
424 
createForAnyType(Class cl)425      public String createForAnyType(Class cl)
426      {
427         return RepositoryId.createForAnyType(cl);
428      }
429 
getDefinedInId(String id)430      public String getDefinedInId(String id)
431      {
432         RepositoryId repId = RepositoryId.cache.getId(id);
433         return repId.getDefinedInId();
434      }
435 
getUnqualifiedName(String id)436      public String getUnqualifiedName(String id)
437      {
438         RepositoryId repId = RepositoryId.cache.getId(id);
439         return repId.getUnqualifiedName();
440      }
441 
getSerialVersionUID(String id)442      public String getSerialVersionUID(String id)
443      {
444         RepositoryId repId = RepositoryId.cache.getId(id);
445         return repId.getSerialVersionUID();
446      }
447 
448 
isAbstractBase(Class clazz)449      public boolean isAbstractBase(Class clazz)
450      {
451         return RepositoryId.isAbstractBase(clazz);
452      }
453 
isSequence(String id)454      public boolean isSequence(String id)
455      {
456         RepositoryId repId = RepositoryId.cache.getId(id);
457         return repId.isSequence();
458      }
459 
460     /**
461      * If the value contains a writeReplace method then the result
462      * is returned.  Otherwise, the value itself is returned.
463      * @return the true value to marshal on the wire.
464      **/
writeReplace(java.io.Serializable value)465     public java.io.Serializable writeReplace(java.io.Serializable value) {
466         return ObjectStreamClass.lookup(value.getClass()).writeReplace(value);
467     }
468 
writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out, char[] array, int offset, int length)469     private void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out,
470                                 char[] array,
471                                 int offset,
472                                 int length)
473     {
474         out.write_wchar_array(array, offset, length);
475     }
476 
write_Array(org.omg.CORBA_2_3.portable.OutputStream out, java.io.Serializable obj, Class type)477     private void write_Array(org.omg.CORBA_2_3.portable.OutputStream out, java.io.Serializable obj, Class type) {
478 
479         int i, length;
480 
481         if (type.isPrimitive()) {
482             if (type == Integer.TYPE) {
483                 int[] array = (int[])((Object)obj);
484                 length = array.length;
485                 out.write_ulong(length);
486                 out.write_long_array(array, 0, length);
487             } else if (type == Byte.TYPE) {
488                 byte[] array = (byte[])((Object)obj);
489                 length = array.length;
490                 out.write_ulong(length);
491                 out.write_octet_array(array, 0, length);
492             } else if (type == Long.TYPE) {
493                 long[] array = (long[])((Object)obj);
494                 length = array.length;
495                 out.write_ulong(length);
496                 out.write_longlong_array(array, 0, length);
497             } else if (type == Float.TYPE) {
498                 float[] array = (float[])((Object)obj);
499                 length = array.length;
500                 out.write_ulong(length);
501                 out.write_float_array(array, 0, length);
502             } else if (type == Double.TYPE) {
503                 double[] array = (double[])((Object)obj);
504                 length = array.length;
505                 out.write_ulong(length);
506                 out.write_double_array(array, 0, length);
507             } else if (type == Short.TYPE) {
508                 short[] array = (short[])((Object)obj);
509                 length = array.length;
510                 out.write_ulong(length);
511                 out.write_short_array(array, 0, length);
512             } else if (type == Character.TYPE) {
513                 char[] array = (char[])((Object)obj);
514                 length = array.length;
515                 out.write_ulong(length);
516                 writeCharArray(out, array, 0, length);
517             } else if (type == Boolean.TYPE) {
518                 boolean[] array = (boolean[])((Object)obj);
519                 length = array.length;
520                 out.write_ulong(length);
521                 out.write_boolean_array(array, 0, length);
522             } else {
523                 // XXX I18N, logging needed.
524                 throw new Error("Invalid primitive type : " +
525                     obj.getClass().getName());
526             }
527         } else if (type == java.lang.Object.class) {
528             Object[] array = (Object[])((Object)obj);
529             length = array.length;
530             out.write_ulong(length);
531             for (i = 0; i < length; i++) {
532                 Util.writeAny(out, array[i]);
533             }
534         } else {
535             Object[] array = (Object[])((Object)obj);
536             length = array.length;
537             out.write_ulong(length);
538             int callType = kValueType;
539 
540             if (type.isInterface()) {
541                 String className = type.getName();
542 
543                 if (java.rmi.Remote.class.isAssignableFrom(type)) {
544                     // RMI Object reference...
545                     callType = kRemoteType;
546                 } else if (org.omg.CORBA.Object.class.isAssignableFrom(type)){
547                     // IDL Object reference...
548                     callType = kRemoteType;
549                 } else if (RepositoryId.isAbstractBase(type)) {
550                     // IDL Abstract Object reference...
551                     callType = kAbstractType;
552                 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(type)) {
553                     callType = kAbstractType;
554                 }
555             }
556 
557             for (i = 0; i < length; i++) {
558                 switch (callType) {
559                 case kRemoteType:
560                     Util.writeRemoteObject(out, array[i]);
561                     break;
562                 case kAbstractType:
563                     Util.writeAbstractObject(out,array[i]);
564                     break;
565                 case kValueType:
566                     try{
567                         out.write_value((java.io.Serializable)array[i]);
568                     } catch(ClassCastException cce){
569                         if (array[i] instanceof java.io.Serializable)
570                             throw cce;
571                         else {
572                             Utility.throwNotSerializableForCorba(
573                                 array[i].getClass().getName());
574                         }
575                     }
576                     break;
577                 }
578             }
579         }
580     }
581 
readCharArray(org.omg.CORBA_2_3.portable.InputStream in, char[] array, int offset, int length)582     private void readCharArray(org.omg.CORBA_2_3.portable.InputStream in,
583                                  char[] array,
584                                  int offset,
585                                  int length)
586     {
587         in.read_wchar_array(array, offset, length);
588     }
589 
read_Array(IIOPInputStream bridge, org.omg.CORBA_2_3.portable.InputStream in, Class sequence, com.sun.org.omg.SendingContext.CodeBase sender, int offset)590     private java.lang.Object read_Array(IIOPInputStream bridge,
591                                         org.omg.CORBA_2_3.portable.InputStream in,
592                                         Class sequence,
593                                         com.sun.org.omg.SendingContext.CodeBase sender,
594                                         int offset)
595     {
596         try {
597             // Read length of coming array
598             int length = in.read_ulong();
599             int i;
600 
601             if (sequence == null) {
602                 for (i = 0; i < length; i++)
603                     in.read_value();
604 
605                 return null;
606             }
607 
608             Class componentType = sequence.getComponentType();
609             Class actualType = componentType;
610 
611 
612             if (componentType.isPrimitive()) {
613                 if (componentType == Integer.TYPE) {
614                     int[] array = new int[length];
615                     in.read_long_array(array, 0, length);
616                     return ((java.io.Serializable)((Object)array));
617                 } else if (componentType == Byte.TYPE) {
618                     byte[] array = new byte[length];
619                     in.read_octet_array(array, 0, length);
620                     return ((java.io.Serializable)((Object)array));
621                 } else if (componentType == Long.TYPE) {
622                     long[] array = new long[length];
623                     in.read_longlong_array(array, 0, length);
624                     return ((java.io.Serializable)((Object)array));
625                 } else if (componentType == Float.TYPE) {
626                     float[] array = new float[length];
627                     in.read_float_array(array, 0, length);
628                     return ((java.io.Serializable)((Object)array));
629                 } else if (componentType == Double.TYPE) {
630                     double[] array = new double[length];
631                     in.read_double_array(array, 0, length);
632                     return ((java.io.Serializable)((Object)array));
633                 } else if (componentType == Short.TYPE) {
634                     short[] array = new short[length];
635                     in.read_short_array(array, 0, length);
636                     return ((java.io.Serializable)((Object)array));
637                 } else if (componentType == Character.TYPE) {
638                     char[] array = new char[length];
639                     readCharArray(in, array, 0, length);
640                     return ((java.io.Serializable)((Object)array));
641                 } else if (componentType == Boolean.TYPE) {
642                     boolean[] array = new boolean[length];
643                     in.read_boolean_array(array, 0, length);
644                     return ((java.io.Serializable)((Object)array));
645                 } else {
646                     // XXX I18N, logging needed.
647                     throw new Error("Invalid primitive componentType : " + sequence.getName());
648                 }
649             } else if (componentType == java.lang.Object.class) {
650                 Object[] array = (Object[])java.lang.reflect.Array.newInstance(
651                     componentType, length);
652 
653                 // Store this object and its beginning position
654                 // since there might be indirections to it while
655                 // it's been unmarshalled.
656                 bridge.activeRecursionMgr.addObject(offset, array);
657 
658                 for (i = 0; i < length; i++) {
659                     Object objectValue = null;
660                     try {
661                         objectValue = Util.readAny(in);
662                     } catch(IndirectionException cdrie) {
663                         try {
664                             // The CDR stream had never seen the given offset
665                             // before, so check the recursion manager (it will
666                             // throw an IOException if it doesn't have a
667                             // reference, either).
668                             objectValue = bridge.activeRecursionMgr.getObject(
669                                 cdrie.offset);
670                         } catch (IOException ie) {
671                             // Translate to a MARSHAL exception since
672                             // ValueHandlers aren't allowed to throw
673                             // IOExceptions
674                             throw utilWrapper.invalidIndirection( ie,
675                                 new Integer( cdrie.offset ) ) ;
676                         }
677                     }
678 
679                     array[i] = objectValue;
680                 }
681                 return ((java.io.Serializable)((Object)array));
682             } else {
683                 Object[] array = (Object[])java.lang.reflect.Array.newInstance(
684                     componentType, length);
685                 // Store this object and its beginning position
686                 // since there might be indirections to it while
687                 // it's been unmarshalled.
688                 bridge.activeRecursionMgr.addObject(offset, array);
689 
690                 // Decide what method call to make based on the componentType.
691                 // If it is a componentType for which we need to load a stub,
692                 // convert the componentType to the correct stub type.
693 
694                 int callType = kValueType;
695                 boolean narrow = false;
696 
697                 if (componentType.isInterface()) {
698                     boolean loadStubClass = false;
699                     // String className = componentType.getName();
700 
701                     if (java.rmi.Remote.class.isAssignableFrom(componentType)) {
702 
703                         // RMI Object reference...
704                         callType = kRemoteType;
705 
706                         // for better performance, load the stub class once
707                         // instead of for each element of the array
708                         loadStubClass = true;
709                     } else if (org.omg.CORBA.Object.class.isAssignableFrom(componentType)){
710                         // IDL Object reference...
711                         callType = kRemoteType;
712                         loadStubClass = true;
713                     } else if (RepositoryId.isAbstractBase(componentType)) {
714                         // IDL Abstract Object reference...
715                         callType = kAbstractType;
716                         loadStubClass = true;
717                     } else if (ObjectStreamClassCorbaExt.isAbstractInterface(componentType)) {
718 
719                         // RMI Abstract Object reference...
720 
721                         // componentType = null;
722                         callType = kAbstractType;
723                     }
724 
725                     if (loadStubClass) {
726                         try {
727                             String codebase = Util.getCodebase(componentType);
728                             String repID = RepositoryId.createForAnyType(componentType);
729                             Class stubType =
730                                 Utility.loadStubClass(repID, codebase, componentType);
731                             actualType = stubType;
732                         } catch (ClassNotFoundException e) {
733                             narrow = true;
734                         }
735                     } else {
736                         narrow = true;
737                     }
738                 }
739 
740                 for (i = 0; i < length; i++) {
741 
742                     try {
743                         switch (callType) {
744                         case kRemoteType:
745                             if (!narrow)
746                                 array[i] = (Object)in.read_Object(actualType);
747                             else {
748                                 array[i] = Utility.readObjectAndNarrow(in, actualType);
749 
750                             }
751                             break;
752                         case kAbstractType:
753                             if (!narrow)
754                                 array[i] = (Object)in.read_abstract_interface(actualType);
755                             else {
756                                 array[i] = Utility.readAbstractAndNarrow(in, actualType);
757                             }
758                             break;
759                         case kValueType:
760                             array[i] = (Object)in.read_value(actualType);
761                             break;
762                         }
763                     } catch(IndirectionException cdrie) {
764                         // The CDR stream had never seen the given offset before,
765                         // so check the recursion manager (it will throw an
766                         // IOException if it doesn't have a reference, either).
767                         try {
768                             array[i] = bridge.activeRecursionMgr.getObject(
769                                 cdrie.offset);
770                         } catch (IOException ioe) {
771                             // Translate to a MARSHAL exception since
772                             // ValueHandlers aren't allowed to throw
773                             // IOExceptions
774                             throw utilWrapper.invalidIndirection( ioe,
775                                 new Integer( cdrie.offset ) ) ;
776                         }
777                     }
778 
779                 }
780 
781                 return ((java.io.Serializable)((Object)array));
782             }
783         } finally {
784             // We've completed deserializing this object.  Any
785             // future indirections will be handled correctly at the
786             // CDR level.  The ActiveRecursionManager only deals with
787             // objects currently being deserialized.
788             bridge.activeRecursionMgr.removeObject(offset);
789         }
790     }
791 
isArray(String repId)792     private boolean isArray(String repId){
793         return RepositoryId.cache.getId(repId).isSequence();
794     }
795 
getOutputStreamClassName()796     private String getOutputStreamClassName() {
797         return "com.sun.corba.se.impl.io.IIOPOutputStream";
798     }
799 
createOutputStream()800    private IIOPOutputStream createOutputStream() {
801         final String name = getOutputStreamClassName();
802         try {
803              IIOPOutputStream stream = createOutputStreamBuiltIn(name);
804              if (stream != null) {
805                  return stream;
806              }
807              return createCustom(IIOPOutputStream.class, name);
808         } catch (Throwable t) {
809             // Throw exception under the carpet.
810             InternalError ie = new InternalError(
811                 "Error loading " + name
812             );
813                 ie.initCause(t);
814                 throw ie;
815         }
816     }
817 
818     /**
819      * Construct a built in implementation with priveleges.
820      * Returning null indicates a non-built is specified.
821      */
createOutputStreamBuiltIn( final String name )822     private IIOPOutputStream createOutputStreamBuiltIn(
823         final String name
824     ) throws Throwable {
825         try {
826             return AccessController.doPrivileged(
827                 new PrivilegedExceptionAction<IIOPOutputStream>() {
828                     public IIOPOutputStream run() throws IOException {
829                         return createOutputStreamBuiltInNoPriv(name);
830                     }
831                 }
832             );
833         } catch (java.security.PrivilegedActionException exc) {
834             throw exc.getCause();
835         }
836     }
837 
838     /**
839      * Returning null indicates a non-built is specified.
840      */
841     private IIOPOutputStream createOutputStreamBuiltInNoPriv(
842         final String name
843     ) throws IOException {
844         return name.equals(IIOPOutputStream.class.getName()) ?
845                 new IIOPOutputStream() : null;
846     }
847 
848     private String getInputStreamClassName() {
849         return "com.sun.corba.se.impl.io.IIOPInputStream";
850     }
851 
852     private IIOPInputStream createInputStream() {
853         final String name = getInputStreamClassName();
854         try {
855              IIOPInputStream stream = createInputStreamBuiltIn(name);
856              if (stream != null) {
857                  return stream;
858              }
859              return createCustom(IIOPInputStream.class, name);
860         } catch (Throwable t) {
861             // Throw exception under the carpet.
862             InternalError ie = new InternalError(
863                 "Error loading " + name
864             );
865                 ie.initCause(t);
866                 throw ie;
867         }
868     }
869 
870     /**
871      * Construct a built in implementation with priveleges.
872      * Returning null indicates a non-built is specified.
873      */
874      private IIOPInputStream createInputStreamBuiltIn(
875          final String name
876      ) throws Throwable {
877          try {
878              return AccessController.doPrivileged(
879                  new PrivilegedExceptionAction<IIOPInputStream>() {
880                      public IIOPInputStream run() throws IOException {
881                          return createInputStreamBuiltInNoPriv(name);
882                      }
883                  }
884              );
885          } catch (java.security.PrivilegedActionException exc) {
886              throw exc.getCause();
887          }
888      }
889 
890      /**
891       * Returning null indicates a non-built is specified.
892       */
893      private IIOPInputStream createInputStreamBuiltInNoPriv(
894          final String name
895      ) throws IOException {
896          return name.equals(IIOPInputStream.class.getName()) ?
897                 new IIOPInputStream() : null;
898      }
899 
900      /**
901       * Create a custom implementation without privileges.
902       */
903      private <T> T createCustom(
904          final Class<T> type, final String className
905      ) throws Throwable {
906            // Note: We use the thread context or system ClassLoader here
907            // since we want to load classes outside of the
908            // core JDK when running J2EE Pure ORB and
909            // talking to Kestrel.
910                 ClassLoader cl = Thread.currentThread().getContextClassLoader();
911                 if (cl == null)
912                     cl = ClassLoader.getSystemClassLoader();
913 
914                 Class<?> clazz = cl.loadClass(className);
915                 Class<? extends T> streamClass = clazz.asSubclass(type);
916 
917                 // Since the ClassLoader should cache the class, this isn't
918                 // as expensive as it looks.
919                 return streamClass.newInstance();
920 
921     }
922 
923     TCKind getJavaCharTCKind() {
924         return TCKind.tk_wchar;
925     }
926 }
927