src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java

Fri, 24 Sep 2010 22:42:14 -0700

author
skoppar
date
Fri, 24 Sep 2010 22:42:14 -0700
changeset 205
b2fff4b7e8cd
parent 158
91006f157c46
child 443
3c73273667ae
permissions
-rw-r--r--

6891766: Vulnerabilities in use of reflection in CORBA
Reviewed-by: hawtin

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

mercurial