1. /*
  2. * @(#)ValueHandlerImpl.java 1.65 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.impl.io;
  16. import javax.rmi.CORBA.Util;
  17. import javax.rmi.PortableRemoteObject;
  18. import java.util.Hashtable;
  19. import java.util.Stack;
  20. import java.io.IOException;
  21. import java.util.EmptyStackException;
  22. import com.sun.corba.se.impl.util.Utility;
  23. import com.sun.corba.se.impl.io.IIOPInputStream;
  24. import com.sun.corba.se.impl.io.IIOPOutputStream;
  25. import com.sun.corba.se.impl.util.RepositoryId;
  26. import com.sun.corba.se.impl.util.Utility;
  27. import org.omg.CORBA.TCKind;
  28. import org.omg.CORBA.MARSHAL;
  29. import org.omg.CORBA.BAD_PARAM;
  30. import org.omg.CORBA.CompletionStatus;
  31. import org.omg.CORBA.portable.IndirectionException;
  32. import com.sun.org.omg.SendingContext.CodeBase;
  33. import com.sun.org.omg.SendingContext.CodeBaseHelper;
  34. import java.security.AccessController;
  35. import java.security.PrivilegedAction;
  36. import com.sun.corba.se.impl.io.IIOPInputStream.ActiveRecursionManager;
  37. import com.sun.corba.se.spi.logging.CORBALogDomains;
  38. import com.sun.corba.se.impl.logging.OMGSystemException;
  39. import com.sun.corba.se.impl.logging.UtilSystemException;
  40. public class ValueHandlerImpl implements javax.rmi.CORBA.ValueHandlerMultiFormat {
  41. // Property to override our maximum stream format version
  42. public static final String FORMAT_VERSION_PROPERTY
  43. = "com.sun.CORBA.MaxStreamFormatVersion";
  44. private static final byte MAX_SUPPORTED_FORMAT_VERSION = (byte)2;
  45. private static final byte STREAM_FORMAT_VERSION_1 = (byte)1;
  46. // The ValueHandler's maximum stream format version to advertise,
  47. // set in a static initializer.
  48. private static final byte MAX_STREAM_FORMAT_VERSION;
  49. static {
  50. MAX_STREAM_FORMAT_VERSION = getMaxStreamFormatVersion();
  51. }
  52. // Looks for the FORMAT_VERSION_PROPERTY system property
  53. // to allow the user to override our default stream format
  54. // version. Note that this still only allows them to pick
  55. // a supported version (1 through MAX_STREAM_FORMAT_VERSION).
  56. private static byte getMaxStreamFormatVersion() {
  57. try {
  58. String propValue = (String) AccessController.doPrivileged(
  59. new PrivilegedAction() {
  60. public java.lang.Object run() {
  61. return System.getProperty(ValueHandlerImpl.FORMAT_VERSION_PROPERTY);
  62. }
  63. });
  64. // The property wasn't set
  65. if (propValue == null)
  66. return MAX_SUPPORTED_FORMAT_VERSION;
  67. byte result = Byte.parseByte(propValue);
  68. // REVISIT. Just set to MAX_SUPPORTED_FORMAT_VERSION
  69. // or really let the system shutdown with this Error?
  70. if (result < 1 || result > MAX_SUPPORTED_FORMAT_VERSION)
  71. // XXX I18N, logging needed.
  72. throw new ExceptionInInitializerError("Invalid stream format version: "
  73. + result
  74. + ". Valid range is 1 through "
  75. + MAX_SUPPORTED_FORMAT_VERSION);
  76. return result;
  77. } catch (Exception ex) {
  78. // REVISIT. Swallow this or really let
  79. // the system shutdown with this Error?
  80. Error err = new ExceptionInInitializerError(ex);
  81. err.initCause( ex ) ;
  82. throw err ;
  83. }
  84. }
  85. public static final short kRemoteType = 0;
  86. public static final short kAbstractType = 1;
  87. public static final short kValueType = 2;
  88. private Hashtable inputStreamPairs = null;
  89. private Hashtable outputStreamPairs = null;
  90. private CodeBase codeBase = null;
  91. private boolean useHashtables = true;
  92. private boolean isInputStream = true;
  93. private IIOPOutputStream outputStreamBridge = null;
  94. private IIOPInputStream inputStreamBridge = null;
  95. private OMGSystemException omgWrapper = OMGSystemException.get(
  96. CORBALogDomains.RPC_ENCODING ) ;
  97. private UtilSystemException utilWrapper = UtilSystemException.get(
  98. CORBALogDomains.RPC_ENCODING ) ;
  99. // See javax.rmi.CORBA.ValueHandlerMultiFormat
  100. public byte getMaximumStreamFormatVersion() {
  101. return MAX_STREAM_FORMAT_VERSION;
  102. }
  103. // See javax.rmi.CORBA.ValueHandlerMultiFormat
  104. public void writeValue(org.omg.CORBA.portable.OutputStream out,
  105. java.io.Serializable value,
  106. byte streamFormatVersion) {
  107. if (streamFormatVersion == 2) {
  108. if (!(out instanceof org.omg.CORBA.portable.ValueOutputStream)) {
  109. throw omgWrapper.notAValueoutputstream() ;
  110. }
  111. } else if (streamFormatVersion != 1) {
  112. throw omgWrapper.invalidStreamFormatVersion(
  113. new Integer(streamFormatVersion) ) ;
  114. }
  115. writeValueWithVersion(out, value, streamFormatVersion);
  116. }
  117. public ValueHandlerImpl(){}
  118. public ValueHandlerImpl(boolean isInputStream) {
  119. this();
  120. useHashtables = false;
  121. this.isInputStream = isInputStream;
  122. }
  123. /**
  124. * Writes the value to the stream using java semantics.
  125. * @param out The stream to write the value to
  126. * @param value The value to be written to the stream
  127. **/
  128. public void writeValue(org.omg.CORBA.portable.OutputStream _out,
  129. java.io.Serializable value) {
  130. writeValueWithVersion(_out, value, STREAM_FORMAT_VERSION_1);
  131. }
  132. private void writeValueWithVersion(org.omg.CORBA.portable.OutputStream _out,
  133. java.io.Serializable value,
  134. byte streamFormatVersion) {
  135. org.omg.CORBA_2_3.portable.OutputStream out =
  136. (org.omg.CORBA_2_3.portable.OutputStream) _out;
  137. if (!useHashtables) {
  138. if (outputStreamBridge == null) {
  139. outputStreamBridge = createOutputStream();
  140. outputStreamBridge.setOrbStream(out);
  141. }
  142. try {
  143. outputStreamBridge.increaseRecursionDepth();
  144. writeValueInternal(outputStreamBridge, out, value, streamFormatVersion);
  145. } finally {
  146. outputStreamBridge.decreaseRecursionDepth();
  147. }
  148. return;
  149. }
  150. IIOPOutputStream jdkToOrbOutputStreamBridge = null;
  151. if (outputStreamPairs == null)
  152. outputStreamPairs = new Hashtable();
  153. jdkToOrbOutputStreamBridge = (IIOPOutputStream)outputStreamPairs.get(_out);
  154. if (jdkToOrbOutputStreamBridge == null) {
  155. jdkToOrbOutputStreamBridge = createOutputStream();
  156. jdkToOrbOutputStreamBridge.setOrbStream(out);
  157. outputStreamPairs.put(_out, jdkToOrbOutputStreamBridge);
  158. }
  159. try {
  160. jdkToOrbOutputStreamBridge.increaseRecursionDepth();
  161. writeValueInternal(jdkToOrbOutputStreamBridge, out, value, streamFormatVersion);
  162. } finally {
  163. if (jdkToOrbOutputStreamBridge.decreaseRecursionDepth() == 0) {
  164. outputStreamPairs.remove(_out);
  165. }
  166. }
  167. }
  168. private void writeValueInternal(IIOPOutputStream bridge,
  169. org.omg.CORBA_2_3.portable.OutputStream out,
  170. java.io.Serializable value,
  171. byte streamFormatVersion)
  172. {
  173. Class clazz = value.getClass();
  174. if (clazz.isArray())
  175. write_Array(out, value, clazz.getComponentType());
  176. else
  177. bridge.simpleWriteObject(value, streamFormatVersion);
  178. }
  179. /**
  180. * Reads a value from the stream using java semantics.
  181. * @param in The stream to read the value from
  182. * @param clazz The type of the value to be read in
  183. * @param sender The sending context runtime
  184. **/
  185. public java.io.Serializable readValue(org.omg.CORBA.portable.InputStream _in,
  186. int offset,
  187. java.lang.Class clazz,
  188. String repositoryID,
  189. org.omg.SendingContext.RunTime _sender)
  190. {
  191. // Must use narrow rather than a direct cast to a com.sun
  192. // class. Fix for bug 4379539.
  193. CodeBase sender = CodeBaseHelper.narrow(_sender);
  194. org.omg.CORBA_2_3.portable.InputStream in =
  195. (org.omg.CORBA_2_3.portable.InputStream) _in;
  196. if (!useHashtables) {
  197. if (inputStreamBridge == null) {
  198. inputStreamBridge = createInputStream();
  199. inputStreamBridge.setOrbStream(in);
  200. inputStreamBridge.setSender(sender); //d11638
  201. // backward compatability 4365188
  202. inputStreamBridge.setValueHandler(this);
  203. }
  204. java.io.Serializable result = null;
  205. try {
  206. inputStreamBridge.increaseRecursionDepth();
  207. result = (java.io.Serializable) readValueInternal(inputStreamBridge, in, offset, clazz, repositoryID, sender);
  208. } finally {
  209. if (inputStreamBridge.decreaseRecursionDepth() == 0) {
  210. // Indirections are resolved immediately since
  211. // the change to the active recursion manager,
  212. // so this will never happen.
  213. }
  214. }
  215. return result;
  216. }
  217. IIOPInputStream jdkToOrbInputStreamBridge = null;
  218. if (inputStreamPairs == null)
  219. inputStreamPairs = new Hashtable();
  220. jdkToOrbInputStreamBridge = (IIOPInputStream)inputStreamPairs.get(_in);
  221. if (jdkToOrbInputStreamBridge == null) {
  222. jdkToOrbInputStreamBridge = createInputStream();
  223. jdkToOrbInputStreamBridge.setOrbStream(in);
  224. jdkToOrbInputStreamBridge.setSender(sender); //d11638
  225. // backward compatability 4365188
  226. jdkToOrbInputStreamBridge.setValueHandler(this);
  227. inputStreamPairs.put(_in, jdkToOrbInputStreamBridge);
  228. }
  229. java.io.Serializable result = null;
  230. try {
  231. jdkToOrbInputStreamBridge.increaseRecursionDepth();
  232. result = (java.io.Serializable) readValueInternal(jdkToOrbInputStreamBridge, in, offset, clazz, repositoryID, sender);
  233. } finally {
  234. if (jdkToOrbInputStreamBridge.decreaseRecursionDepth() == 0) {
  235. inputStreamPairs.remove(_in);
  236. }
  237. }
  238. return result;
  239. }
  240. private java.io.Serializable readValueInternal(IIOPInputStream bridge,
  241. org.omg.CORBA_2_3.portable.InputStream in,
  242. int offset,
  243. java.lang.Class clazz,
  244. String repositoryID,
  245. com.sun.org.omg.SendingContext.CodeBase sender)
  246. {
  247. java.io.Serializable result = null;
  248. if (clazz == null) {
  249. // clazz == null indicates an FVD situation for a nonexistant class
  250. if (isArray(repositoryID)){
  251. read_Array(bridge, in, null, sender, offset);
  252. } else {
  253. bridge.simpleSkipObject(repositoryID, sender);
  254. }
  255. return result;
  256. }
  257. if (clazz.isArray()) {
  258. result = (java.io.Serializable)read_Array(bridge, in, clazz, sender, offset);
  259. } else {
  260. result = (java.io.Serializable)bridge.simpleReadObject(clazz, repositoryID, sender, offset);
  261. }
  262. return result;
  263. }
  264. /**
  265. * Returns the repository ID for the given RMI value Class.
  266. * @param clz The class to return a repository ID for.
  267. * @return the repository ID of the Class.
  268. **/
  269. public java.lang.String getRMIRepositoryID(java.lang.Class clz) {
  270. return RepositoryId.createForJavaType(clz);
  271. }
  272. /**
  273. * Indicates whether the given Class performs custom or
  274. * default marshaling.
  275. * @param clz The class to test for custom marshaling.
  276. * @return True if the class performs custom marshaling, false
  277. * if it does not.
  278. **/
  279. public boolean isCustomMarshaled(java.lang.Class clz) {
  280. return ObjectStreamClass.lookup(clz).isCustomMarshaled();
  281. }
  282. /**
  283. * Returns the CodeBase for this ValueHandler. This is used by
  284. * the ORB runtime. The server sends the service context containing
  285. * the IOR for this CodeBase on the first GIOP reply. The clients
  286. * do the same on the first GIOP request.
  287. * @return the SendingContext.CodeBase of this ValueHandler.
  288. **/
  289. public org.omg.SendingContext.RunTime getRunTimeCodeBase() {
  290. if (codeBase != null)
  291. return codeBase;
  292. else {
  293. codeBase = new FVDCodeBaseImpl();
  294. // backward compatability 4365188
  295. // set the valueHandler so that correct/incorrect RepositoryID
  296. // calculations can be done based on the ORB version
  297. FVDCodeBaseImpl fvdImpl = (FVDCodeBaseImpl) codeBase;
  298. fvdImpl.setValueHandler(this);
  299. return codeBase;
  300. }
  301. }
  302. // methods supported for backward compatability so that the appropriate
  303. // Rep-id calculations take place based on the ORB version
  304. /**
  305. * Returns a boolean of whether or not RepositoryId indicates
  306. * FullValueDescriptor.
  307. * used for backward compatability
  308. */
  309. public boolean useFullValueDescription(Class clazz, String repositoryID)
  310. throws IOException
  311. {
  312. return RepositoryId.useFullValueDescription(clazz, repositoryID);
  313. }
  314. public String getClassName(String id)
  315. {
  316. RepositoryId repID = RepositoryId.cache.getId(id);
  317. return repID.getClassName();
  318. }
  319. public Class getClassFromType(String id)
  320. throws ClassNotFoundException
  321. {
  322. RepositoryId repId = RepositoryId.cache.getId(id);
  323. return repId.getClassFromType();
  324. }
  325. public Class getAnyClassFromType(String id)
  326. throws ClassNotFoundException
  327. {
  328. RepositoryId repId = RepositoryId.cache.getId(id);
  329. return repId.getAnyClassFromType();
  330. }
  331. public String createForAnyType(Class cl)
  332. {
  333. return RepositoryId.createForAnyType(cl);
  334. }
  335. public String getDefinedInId(String id)
  336. {
  337. RepositoryId repId = RepositoryId.cache.getId(id);
  338. return repId.getDefinedInId();
  339. }
  340. public String getUnqualifiedName(String id)
  341. {
  342. RepositoryId repId = RepositoryId.cache.getId(id);
  343. return repId.getUnqualifiedName();
  344. }
  345. public String getSerialVersionUID(String id)
  346. {
  347. RepositoryId repId = RepositoryId.cache.getId(id);
  348. return repId.getSerialVersionUID();
  349. }
  350. public boolean isAbstractBase(Class clazz)
  351. {
  352. return RepositoryId.isAbstractBase(clazz);
  353. }
  354. public boolean isSequence(String id)
  355. {
  356. RepositoryId repId = RepositoryId.cache.getId(id);
  357. return repId.isSequence();
  358. }
  359. /**
  360. * If the value contains a writeReplace method then the result
  361. * is returned. Otherwise, the value itself is returned.
  362. * @return the true value to marshal on the wire.
  363. **/
  364. public java.io.Serializable writeReplace(java.io.Serializable value) {
  365. return ObjectStreamClass.lookup(value.getClass()).writeReplace(value);
  366. }
  367. /**
  368. * Encapsulates writing of Java char arrays so that the 1.3 subclass
  369. * can override it without exposing internals across packages. This
  370. * is a fix for bug 4367783.
  371. */
  372. protected void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out,
  373. char[] array,
  374. int offset,
  375. int length)
  376. {
  377. out.write_wchar_array(array, offset, length);
  378. }
  379. private void write_Array(org.omg.CORBA_2_3.portable.OutputStream out, java.io.Serializable obj, Class type) {
  380. int i, length;
  381. if (type.isPrimitive()) {
  382. if (type == Integer.TYPE) {
  383. int[] array = (int[])((Object)obj);
  384. length = array.length;
  385. out.write_ulong(length);
  386. out.write_long_array(array, 0, length);
  387. } else if (type == Byte.TYPE) {
  388. byte[] array = (byte[])((Object)obj);
  389. length = array.length;
  390. out.write_ulong(length);
  391. out.write_octet_array(array, 0, length);
  392. } else if (type == Long.TYPE) {
  393. long[] array = (long[])((Object)obj);
  394. length = array.length;
  395. out.write_ulong(length);
  396. out.write_longlong_array(array, 0, length);
  397. } else if (type == Float.TYPE) {
  398. float[] array = (float[])((Object)obj);
  399. length = array.length;
  400. out.write_ulong(length);
  401. out.write_float_array(array, 0, length);
  402. } else if (type == Double.TYPE) {
  403. double[] array = (double[])((Object)obj);
  404. length = array.length;
  405. out.write_ulong(length);
  406. out.write_double_array(array, 0, length);
  407. } else if (type == Short.TYPE) {
  408. short[] array = (short[])((Object)obj);
  409. length = array.length;
  410. out.write_ulong(length);
  411. out.write_short_array(array, 0, length);
  412. } else if (type == Character.TYPE) {
  413. char[] array = (char[])((Object)obj);
  414. length = array.length;
  415. out.write_ulong(length);
  416. writeCharArray(out, array, 0, length);
  417. } else if (type == Boolean.TYPE) {
  418. boolean[] array = (boolean[])((Object)obj);
  419. length = array.length;
  420. out.write_ulong(length);
  421. out.write_boolean_array(array, 0, length);
  422. } else {
  423. // XXX I18N, logging needed.
  424. throw new Error("Invalid primitive type : " +
  425. obj.getClass().getName());
  426. }
  427. } else if (type == java.lang.Object.class) {
  428. Object[] array = (Object[])((Object)obj);
  429. length = array.length;
  430. out.write_ulong(length);
  431. for (i = 0; i < length; i++) {
  432. Util.writeAny(out, array[i]);
  433. }
  434. } else {
  435. Object[] array = (Object[])((Object)obj);
  436. length = array.length;
  437. out.write_ulong(length);
  438. int callType = kValueType;
  439. if (type.isInterface()) {
  440. String className = type.getName();
  441. if (java.rmi.Remote.class.isAssignableFrom(type)) {
  442. // RMI Object reference...
  443. callType = kRemoteType;
  444. } else if (org.omg.CORBA.Object.class.isAssignableFrom(type)){
  445. // IDL Object reference...
  446. callType = kRemoteType;
  447. } else if (RepositoryId.isAbstractBase(type)) {
  448. // IDL Abstract Object reference...
  449. callType = kAbstractType;
  450. } else if (ObjectStreamClassCorbaExt.isAbstractInterface(type)) {
  451. callType = kAbstractType;
  452. }
  453. }
  454. for (i = 0; i < length; i++) {
  455. switch (callType) {
  456. case kRemoteType:
  457. Util.writeRemoteObject(out, array[i]);
  458. break;
  459. case kAbstractType:
  460. Util.writeAbstractObject(out,array[i]);
  461. break;
  462. case kValueType:
  463. try{
  464. out.write_value((java.io.Serializable)array[i]);
  465. } catch(ClassCastException cce){
  466. if (array[i] instanceof java.io.Serializable)
  467. throw cce;
  468. else {
  469. Utility.throwNotSerializableForCorba(
  470. array[i].getClass().getName());
  471. }
  472. }
  473. break;
  474. }
  475. }
  476. }
  477. }
  478. /**
  479. * Encapsulates reading of Java char arrays so that the 1.3 subclass
  480. * can override it without exposing internals across packages. This
  481. * is a fix for bug 4367783.
  482. */
  483. protected void readCharArray(org.omg.CORBA_2_3.portable.InputStream in,
  484. char[] array,
  485. int offset,
  486. int length)
  487. {
  488. in.read_wchar_array(array, offset, length);
  489. }
  490. private java.lang.Object read_Array(IIOPInputStream bridge,
  491. org.omg.CORBA_2_3.portable.InputStream in,
  492. Class sequence,
  493. com.sun.org.omg.SendingContext.CodeBase sender,
  494. int offset)
  495. {
  496. try {
  497. // Read length of coming array
  498. int length = in.read_ulong();
  499. int i;
  500. if (sequence == null) {
  501. for (i = 0; i < length; i++)
  502. in.read_value();
  503. return null;
  504. }
  505. Class componentType = sequence.getComponentType();
  506. Class actualType = componentType;
  507. if (componentType.isPrimitive()) {
  508. if (componentType == Integer.TYPE) {
  509. int[] array = new int[length];
  510. in.read_long_array(array, 0, length);
  511. return ((java.io.Serializable)((Object)array));
  512. } else if (componentType == Byte.TYPE) {
  513. byte[] array = new byte[length];
  514. in.read_octet_array(array, 0, length);
  515. return ((java.io.Serializable)((Object)array));
  516. } else if (componentType == Long.TYPE) {
  517. long[] array = new long[length];
  518. in.read_longlong_array(array, 0, length);
  519. return ((java.io.Serializable)((Object)array));
  520. } else if (componentType == Float.TYPE) {
  521. float[] array = new float[length];
  522. in.read_float_array(array, 0, length);
  523. return ((java.io.Serializable)((Object)array));
  524. } else if (componentType == Double.TYPE) {
  525. double[] array = new double[length];
  526. in.read_double_array(array, 0, length);
  527. return ((java.io.Serializable)((Object)array));
  528. } else if (componentType == Short.TYPE) {
  529. short[] array = new short[length];
  530. in.read_short_array(array, 0, length);
  531. return ((java.io.Serializable)((Object)array));
  532. } else if (componentType == Character.TYPE) {
  533. char[] array = new char[length];
  534. readCharArray(in, array, 0, length);
  535. return ((java.io.Serializable)((Object)array));
  536. } else if (componentType == Boolean.TYPE) {
  537. boolean[] array = new boolean[length];
  538. in.read_boolean_array(array, 0, length);
  539. return ((java.io.Serializable)((Object)array));
  540. } else {
  541. // XXX I18N, logging needed.
  542. throw new Error("Invalid primitive componentType : " + sequence.getName());
  543. }
  544. } else if (componentType == java.lang.Object.class) {
  545. Object[] array = (Object[])java.lang.reflect.Array.newInstance(
  546. componentType, length);
  547. // Store this object and its beginning position
  548. // since there might be indirections to it while
  549. // it's been unmarshalled.
  550. bridge.activeRecursionMgr.addObject(offset, array);
  551. for (i = 0; i < length; i++) {
  552. Object objectValue = null;
  553. try {
  554. objectValue = Util.readAny(in);
  555. } catch(IndirectionException cdrie) {
  556. try {
  557. // The CDR stream had never seen the given offset
  558. // before, so check the recursion manager (it will
  559. // throw an IOException if it doesn't have a
  560. // reference, either).
  561. objectValue = bridge.activeRecursionMgr.getObject(
  562. cdrie.offset);
  563. } catch (IOException ie) {
  564. // Translate to a MARSHAL exception since
  565. // ValueHandlers aren't allowed to throw
  566. // IOExceptions
  567. throw utilWrapper.invalidIndirection( ie,
  568. new Integer( cdrie.offset ) ) ;
  569. }
  570. }
  571. array[i] = objectValue;
  572. }
  573. return ((java.io.Serializable)((Object)array));
  574. } else {
  575. Object[] array = (Object[])java.lang.reflect.Array.newInstance(
  576. componentType, length);
  577. // Store this object and its beginning position
  578. // since there might be indirections to it while
  579. // it's been unmarshalled.
  580. bridge.activeRecursionMgr.addObject(offset, array);
  581. // Decide what method call to make based on the componentType.
  582. // If it is a componentType for which we need to load a stub,
  583. // convert the componentType to the correct stub type.
  584. int callType = kValueType;
  585. boolean narrow = false;
  586. if (componentType.isInterface()) {
  587. boolean loadStubClass = false;
  588. // String className = componentType.getName();
  589. if (java.rmi.Remote.class.isAssignableFrom(componentType)) {
  590. // RMI Object reference...
  591. callType = kRemoteType;
  592. // for better performance, load the stub class once
  593. // instead of for each element of the array
  594. loadStubClass = true;
  595. } else if (org.omg.CORBA.Object.class.isAssignableFrom(componentType)){
  596. // IDL Object reference...
  597. callType = kRemoteType;
  598. loadStubClass = true;
  599. } else if (RepositoryId.isAbstractBase(componentType)) {
  600. // IDL Abstract Object reference...
  601. callType = kAbstractType;
  602. loadStubClass = true;
  603. } else if (ObjectStreamClassCorbaExt.isAbstractInterface(componentType)) {
  604. // RMI Abstract Object reference...
  605. // componentType = null;
  606. callType = kAbstractType;
  607. }
  608. if (loadStubClass) {
  609. try {
  610. String codebase = Util.getCodebase(componentType);
  611. String repID = RepositoryId.createForAnyType(componentType);
  612. Class stubType =
  613. Utility.loadStubClass(repID, codebase, componentType);
  614. actualType = stubType;
  615. } catch (ClassNotFoundException e) {
  616. narrow = true;
  617. }
  618. } else {
  619. narrow = true;
  620. }
  621. }
  622. for (i = 0; i < length; i++) {
  623. try {
  624. switch (callType) {
  625. case kRemoteType:
  626. if (!narrow)
  627. array[i] = (Object)in.read_Object(actualType);
  628. else {
  629. array[i] = Utility.readObjectAndNarrow(in, actualType);
  630. }
  631. break;
  632. case kAbstractType:
  633. if (!narrow)
  634. array[i] = (Object)in.read_abstract_interface(actualType);
  635. else {
  636. array[i] = Utility.readAbstractAndNarrow(in, actualType);
  637. }
  638. break;
  639. case kValueType:
  640. array[i] = (Object)in.read_value(actualType);
  641. break;
  642. }
  643. } catch(IndirectionException cdrie) {
  644. // The CDR stream had never seen the given offset before,
  645. // so check the recursion manager (it will throw an
  646. // IOException if it doesn't have a reference, either).
  647. try {
  648. array[i] = bridge.activeRecursionMgr.getObject(
  649. cdrie.offset);
  650. } catch (IOException ioe) {
  651. // Translate to a MARSHAL exception since
  652. // ValueHandlers aren't allowed to throw
  653. // IOExceptions
  654. throw utilWrapper.invalidIndirection( ioe,
  655. new Integer( cdrie.offset ) ) ;
  656. }
  657. }
  658. }
  659. return ((java.io.Serializable)((Object)array));
  660. }
  661. } finally {
  662. // We've completed deserializing this object. Any
  663. // future indirections will be handled correctly at the
  664. // CDR level. The ActiveRecursionManager only deals with
  665. // objects currently being deserialized.
  666. bridge.activeRecursionMgr.removeObject(offset);
  667. }
  668. }
  669. private boolean isArray(String repId){
  670. return RepositoryId.cache.getId(repId).isSequence();
  671. }
  672. protected String getOutputStreamClassName() {
  673. return "com.sun.corba.se.impl.io.IIOPOutputStream";
  674. }
  675. private com.sun.corba.se.impl.io.IIOPOutputStream createOutputStream() {
  676. return (com.sun.corba.se.impl.io.IIOPOutputStream)AccessController.doPrivileged(
  677. new StreamFactory(getOutputStreamClassName()));
  678. }
  679. protected String getInputStreamClassName() {
  680. return "com.sun.corba.se.impl.io.IIOPInputStream";
  681. }
  682. private com.sun.corba.se.impl.io.IIOPInputStream createInputStream() {
  683. return (com.sun.corba.se.impl.io.IIOPInputStream)AccessController.doPrivileged(
  684. new StreamFactory(getInputStreamClassName()));
  685. }
  686. /**
  687. * Instantiates a class of the given name using the system ClassLoader
  688. * as part of a PrivilegedAction.
  689. *
  690. * It's private final so hopefully people can't grab it outside of
  691. * this class.
  692. *
  693. * If you're worried that someone could subclass ValueHandlerImpl,
  694. * install his own streams, and snoop what's on the wire:
  695. * Someone can do that only if he's allowed to use the feature
  696. * of installing his own javax.rmi.CORBA.Util delegate (via a
  697. * JVM property or orb.properties file, read the first time the
  698. * Util class is used). If he can do that, he can snoop
  699. * anything on the wire, anyway, without abusing the
  700. * StreamFactory class.
  701. */
  702. private static final class StreamFactory implements PrivilegedAction {
  703. private String className;
  704. public StreamFactory (String _className) {
  705. className = _className;
  706. }
  707. public Object run() {
  708. try {
  709. // Note: We must use the system ClassLoader here
  710. // since we want to load classes outside of the
  711. // core JDK when running J2EE Pure ORB and
  712. // talking to Kestrel.
  713. ClassLoader cl = Thread.currentThread().getContextClassLoader();
  714. if (cl == null)
  715. cl = ClassLoader.getSystemClassLoader();
  716. Class streamClass = cl.loadClass(className);
  717. // Since the ClassLoader should cache the class, this isn't
  718. // as expensive as it looks.
  719. return streamClass.newInstance();
  720. } catch(Throwable t) {
  721. InternalError ie = new InternalError( "Error loading " + className ) ;
  722. ie.initCause( t ) ;
  723. throw ie ;
  724. }
  725. }
  726. }
  727. /**
  728. * Our JDK 1.3 and JDK 1.3.1 behavior subclasses override this.
  729. * The correct behavior is for a Java char to map to a CORBA wchar,
  730. * but our older code mapped it to a CORBA char.
  731. */
  732. protected TCKind getJavaCharTCKind() {
  733. return TCKind.tk_wchar;
  734. }
  735. }