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