ValueHandlerImpl.java revision 608:7e06bf1dcb09
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 32package com.sun.corba.se.impl.io; 33 34import javax.rmi.CORBA.Util; 35 36import java.util.Hashtable; 37import java.io.IOException; 38 39import com.sun.corba.se.impl.util.RepositoryId; 40import com.sun.corba.se.impl.util.Utility; 41 42import org.omg.CORBA.TCKind; 43 44import org.omg.CORBA.portable.IndirectionException; 45import com.sun.org.omg.SendingContext.CodeBase; 46import com.sun.org.omg.SendingContext.CodeBaseHelper; 47 48import java.security.AccessController; 49import java.security.PrivilegedAction; 50import java.security.PrivilegedExceptionAction; 51 52import com.sun.corba.se.spi.logging.CORBALogDomains; 53import com.sun.corba.se.impl.logging.OMGSystemException; 54import com.sun.corba.se.impl.logging.UtilSystemException; 55 56public 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). 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 132 public byte getMaximumStreamFormatVersion() { 133 return MAX_STREAM_FORMAT_VERSION; 134 } 135 136 // See javax.rmi.CORBA.ValueHandlerMultiFormat 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 153 private ValueHandlerImpl(){} 154 155 private ValueHandlerImpl(boolean isInputStream) { 156 this(); 157 useHashtables = false; 158 this.isInputStream = isInputStream; 159 } 160 161 static ValueHandlerImpl getInstance() { 162 return new ValueHandlerImpl(); 163 } 164 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 **/ 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 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 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 **/ 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 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 **/ 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 **/ 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 **/ 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 399 public boolean useFullValueDescription(Class clazz, String repositoryID) 400 throws IOException 401 { 402 return RepositoryId.useFullValueDescription(clazz, repositoryID); 403 } 404 405 public String getClassName(String id) 406 { 407 RepositoryId repID = RepositoryId.cache.getId(id); 408 return repID.getClassName(); 409 } 410 411 public Class getClassFromType(String id) 412 throws ClassNotFoundException 413 { 414 RepositoryId repId = RepositoryId.cache.getId(id); 415 return repId.getClassFromType(); 416 } 417 418 public Class getAnyClassFromType(String id) 419 throws ClassNotFoundException 420 { 421 RepositoryId repId = RepositoryId.cache.getId(id); 422 return repId.getAnyClassFromType(); 423 } 424 425 public String createForAnyType(Class cl) 426 { 427 return RepositoryId.createForAnyType(cl); 428 } 429 430 public String getDefinedInId(String id) 431 { 432 RepositoryId repId = RepositoryId.cache.getId(id); 433 return repId.getDefinedInId(); 434 } 435 436 public String getUnqualifiedName(String id) 437 { 438 RepositoryId repId = RepositoryId.cache.getId(id); 439 return repId.getUnqualifiedName(); 440 } 441 442 public String getSerialVersionUID(String id) 443 { 444 RepositoryId repId = RepositoryId.cache.getId(id); 445 return repId.getSerialVersionUID(); 446 } 447 448 449 public boolean isAbstractBase(Class clazz) 450 { 451 return RepositoryId.isAbstractBase(clazz); 452 } 453 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 **/ 465 public java.io.Serializable writeReplace(java.io.Serializable value) { 466 return ObjectStreamClass.lookup(value.getClass()).writeReplace(value); 467 } 468 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 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 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 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 792 private boolean isArray(String repId){ 793 return RepositoryId.cache.getId(repId).isSequence(); 794 } 795 796 private String getOutputStreamClassName() { 797 return "com.sun.corba.se.impl.io.IIOPOutputStream"; 798 } 799 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 */ 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