1. /*
  2. * @(#)CorbaClientRequestDispatcherImpl.java 1.86 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.protocol;
  16. import java.io.IOException;
  17. import java.util.Iterator;
  18. import java.rmi.RemoteException;
  19. import javax.rmi.CORBA.Util;
  20. import javax.rmi.CORBA.Tie;
  21. import org.omg.CORBA.COMM_FAILURE;
  22. import org.omg.CORBA.INTERNAL;
  23. import org.omg.CORBA.SystemException;
  24. import org.omg.CORBA.Request;
  25. import org.omg.CORBA.NamedValue;
  26. import org.omg.CORBA.NVList;
  27. import org.omg.CORBA.Context;
  28. import org.omg.CORBA.ContextList;
  29. import org.omg.CORBA.ExceptionList;
  30. import org.omg.CORBA.TypeCode;
  31. import org.omg.CORBA.portable.RemarshalException;
  32. import org.omg.CORBA_2_3.portable.InputStream;
  33. import org.omg.CORBA_2_3.portable.OutputStream;
  34. import org.omg.CORBA.portable.Delegate;
  35. import org.omg.CORBA.portable.ServantObject;
  36. import org.omg.CORBA.portable.ApplicationException;
  37. import org.omg.CORBA.portable.UnknownException;
  38. import org.omg.IOP.ExceptionDetailMessage;
  39. import org.omg.IOP.TAG_CODE_SETS;
  40. import com.sun.org.omg.SendingContext.CodeBase;
  41. import com.sun.corba.se.pept.broker.Broker;
  42. import com.sun.corba.se.pept.encoding.InputObject;
  43. import com.sun.corba.se.pept.encoding.OutputObject;
  44. import com.sun.corba.se.pept.protocol.ClientRequestDispatcher;
  45. import com.sun.corba.se.pept.protocol.MessageMediator;
  46. import com.sun.corba.se.pept.transport.Connection;
  47. import com.sun.corba.se.pept.transport.OutboundConnectionCache;
  48. import com.sun.corba.se.pept.transport.ContactInfo;
  49. import com.sun.corba.se.spi.ior.IOR;
  50. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  51. import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate;
  52. import com.sun.corba.se.spi.ior.iiop.CodeSetsComponent;
  53. import com.sun.corba.se.spi.oa.OAInvocationInfo;
  54. import com.sun.corba.se.spi.oa.ObjectAdapterFactory;
  55. import com.sun.corba.se.spi.orb.ORB;
  56. import com.sun.corba.se.spi.orb.ORBVersion;
  57. import com.sun.corba.se.spi.orb.ORBVersionFactory;
  58. import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
  59. import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
  60. import com.sun.corba.se.spi.transport.CorbaContactInfo ;
  61. import com.sun.corba.se.spi.transport.CorbaContactInfoList ;
  62. import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator ;
  63. import com.sun.corba.se.spi.transport.CorbaConnection;
  64. import com.sun.corba.se.spi.logging.CORBALogDomains;
  65. import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext;
  66. import com.sun.corba.se.spi.servicecontext.ServiceContext;
  67. import com.sun.corba.se.spi.servicecontext.ServiceContexts;
  68. import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext;
  69. import com.sun.corba.se.spi.servicecontext.CodeSetServiceContext;
  70. import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext;
  71. import com.sun.corba.se.spi.servicecontext.ORBVersionServiceContext;
  72. import com.sun.corba.se.spi.servicecontext.MaxStreamFormatVersionServiceContext;
  73. import com.sun.corba.se.spi.servicecontext.UnknownServiceContext;
  74. import com.sun.corba.se.impl.encoding.CDRInputObject;
  75. import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
  76. import com.sun.corba.se.impl.encoding.CodeSetConversion;
  77. import com.sun.corba.se.impl.encoding.EncapsInputStream;
  78. import com.sun.corba.se.impl.encoding.MarshalOutputStream;
  79. import com.sun.corba.se.impl.encoding.MarshalInputStream;
  80. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  81. import com.sun.corba.se.impl.orbutil.ORBUtility;
  82. import com.sun.corba.se.impl.orbutil.ORBConstants;
  83. import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
  84. import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr;
  85. import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr;
  86. import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr;
  87. import com.sun.corba.se.impl.transport.CorbaContactInfoListIteratorImpl;
  88. import com.sun.corba.se.impl.util.JDKBridge;
  89. /**
  90. * ClientDelegate is the RMI client-side subcontract or representation
  91. * It implements RMI delegate as well as our internal ClientRequestDispatcher
  92. * interface.
  93. */
  94. public class CorbaClientRequestDispatcherImpl
  95. implements
  96. ClientRequestDispatcher
  97. {
  98. // Used for locking
  99. private Object lock = new Object();
  100. public OutputObject beginRequest(Object self, String opName,
  101. boolean isOneWay, ContactInfo contactInfo)
  102. {
  103. ORB orb = null;
  104. try {
  105. CorbaContactInfo corbaContactInfo = (CorbaContactInfo) contactInfo;
  106. orb = (ORB)contactInfo.getBroker();
  107. if (orb.subcontractDebugFlag) {
  108. dprint(".beginRequest->: op/" + opName);
  109. }
  110. //
  111. // Portable Interceptor initialization.
  112. //
  113. orb.getPIHandler().initiateClientPIRequest( false );
  114. //
  115. // Connection.
  116. //
  117. CorbaConnection connection = null;
  118. // This locking is done so that multiple connections are not created
  119. // for the same endpoint
  120. synchronized (lock) {
  121. if (contactInfo.isConnectionBased()) {
  122. if (contactInfo.shouldCacheConnection()) {
  123. connection = (CorbaConnection)
  124. orb.getTransportManager()
  125. .getOutboundConnectionCache(contactInfo).get(contactInfo);
  126. }
  127. if (connection != null) {
  128. if (orb.subcontractDebugFlag) {
  129. dprint(".beginRequest: op/" + opName
  130. + ": Using cached connection: " + connection);
  131. }
  132. } else {
  133. try {
  134. connection = (CorbaConnection)
  135. contactInfo.createConnection();
  136. if (orb.subcontractDebugFlag) {
  137. dprint(".beginRequest: op/" + opName
  138. + ": Using created connection: " + connection);
  139. }
  140. } catch (RuntimeException e) {
  141. if (orb.subcontractDebugFlag) {
  142. dprint(".beginRequest: op/" + opName
  143. + ": failed to create connection: " + e);
  144. }
  145. // REVISIT: this part similar to marshalingComplete below.
  146. boolean retry = getContactInfoListIterator(orb)
  147. .reportException(contactInfo, e);
  148. // REVISIT:
  149. // this part similar to Remarshal in this method below
  150. if (retry) {
  151. if(getContactInfoListIterator(orb).hasNext()) {
  152. contactInfo = (ContactInfo)
  153. getContactInfoListIterator(orb).next();
  154. return beginRequest(self, opName,
  155. isOneWay, contactInfo);
  156. } else {
  157. throw e;
  158. }
  159. } else {
  160. throw e;
  161. }
  162. }
  163. if (connection.shouldRegisterReadEvent()) {
  164. // REVISIT: cast
  165. orb.getTransportManager().getSelector(0)
  166. .registerForEvent(connection.getEventHandler());
  167. connection.setState("ESTABLISHED");
  168. }
  169. // Do not do connection reclaim here since the connections
  170. // are marked in use by registerWaiter() call and since this
  171. // call happens later do it after that.
  172. if (contactInfo.shouldCacheConnection()) {
  173. OutboundConnectionCache connectionCache =
  174. orb.getTransportManager()
  175. .getOutboundConnectionCache(contactInfo);
  176. connectionCache.stampTime(connection);
  177. connectionCache.put(contactInfo, connection);
  178. // connectionCache.reclaim();
  179. }
  180. }
  181. }
  182. }
  183. CorbaMessageMediator messageMediator = (CorbaMessageMediator)
  184. contactInfo.createMessageMediator(
  185. orb, contactInfo, connection, opName, isOneWay);
  186. if (orb.subcontractDebugFlag) {
  187. dprint(".beginRequest: " + opAndId(messageMediator)
  188. + ": created message mediator: " + messageMediator);
  189. }
  190. // NOTE: Thread data so we can get the mediator in release reply
  191. // in order to remove the waiter in CorbaConnection.
  192. // We cannot depend on obtaining information in releaseReply
  193. // via its InputStream argument since, on certain errors
  194. // (e.g., client marshaling errors), the stream may be null.
  195. // Likewise for releaseReply "self".
  196. // NOTE: This must be done before initializing the message since
  197. // that may start sending fragments which may end up in "early"
  198. // replies or client marshaling exceptions.
  199. orb.getInvocationInfo().setMessageMediator(messageMediator);
  200. if (connection != null && connection.getCodeSetContext() == null) {
  201. performCodeSetNegotiation(messageMediator);
  202. }
  203. addServiceContexts(messageMediator);
  204. OutputObject outputObject =
  205. contactInfo.createOutputObject(messageMediator);
  206. if (orb.subcontractDebugFlag) {
  207. dprint(".beginRequest: " + opAndId(messageMediator)
  208. + ": created output object: " + outputObject);
  209. }
  210. // NOTE: Not necessary for oneways, but useful for debugging.
  211. // This must be done BEFORE message initialization since fragments
  212. // may be sent at that time.
  213. registerWaiter(messageMediator);
  214. // Do connection reclaim now
  215. synchronized (lock) {
  216. if (contactInfo.isConnectionBased()) {
  217. if (contactInfo.shouldCacheConnection()) {
  218. OutboundConnectionCache connectionCache =
  219. orb.getTransportManager()
  220. .getOutboundConnectionCache(contactInfo);
  221. connectionCache.reclaim();
  222. }
  223. }
  224. }
  225. orb.getPIHandler().setClientPIInfo(messageMediator);
  226. try {
  227. // This MUST come before message is initialized so
  228. // service contexts may be added by PI because
  229. // initial fragments may be sent during message initialization.
  230. orb.getPIHandler().invokeClientPIStartingPoint();
  231. } catch( RemarshalException e ) {
  232. if (orb.subcontractDebugFlag) {
  233. dprint(".beginRequest: " + opAndId(messageMediator)
  234. + ": Remarshal");
  235. }
  236. // NOTE: We get here because an interceptor raised ForwardRequest
  237. // and updated the IOR/Iterator. Since we have a fresh iterator
  238. // hasNext should succeed.
  239. // REVISIT: We should feed ALL interceptor exceptions to
  240. // iterator.reportException so it can determine if it wants
  241. // to retry. Right now, SystemExceptions will flow to the
  242. // client code.
  243. // REVISIT:
  244. // This assumes that interceptors update
  245. // ContactInfoList outside of subcontract.
  246. // Want to move that update to here.
  247. if (getContactInfoListIterator(orb).hasNext()) {
  248. contactInfo = (ContactInfo)
  249. getContactInfoListIterator(orb).next();
  250. return beginRequest(self, opName, isOneWay, contactInfo);
  251. } else {
  252. ORBUtilSystemException wrapper =
  253. ORBUtilSystemException.get(orb,
  254. CORBALogDomains.RPC_PROTOCOL);
  255. throw wrapper.remarshalWithNowhereToGo();
  256. }
  257. }
  258. messageMediator.initializeMessage();
  259. if (orb.subcontractDebugFlag) {
  260. dprint(".beginRequest: " + opAndId(messageMediator)
  261. + ": initialized message");
  262. }
  263. return outputObject;
  264. } finally {
  265. if (orb.subcontractDebugFlag) {
  266. dprint(".beginRequest<-: op/" + opName);
  267. }
  268. }
  269. }
  270. public InputObject marshalingComplete(java.lang.Object self,
  271. OutputObject outputObject)
  272. throws
  273. ApplicationException,
  274. org.omg.CORBA.portable.RemarshalException
  275. {
  276. ORB orb = null;
  277. CorbaMessageMediator messageMediator = null;
  278. try {
  279. messageMediator = (CorbaMessageMediator)
  280. outputObject.getMessageMediator();
  281. orb = (ORB) messageMediator.getBroker();
  282. if (orb.subcontractDebugFlag) {
  283. dprint(".marshalingComplete->: " + opAndId(messageMediator));
  284. }
  285. InputObject inputObject =
  286. marshalingComplete1(orb, messageMediator);
  287. return processResponse(orb, messageMediator, inputObject);
  288. } finally {
  289. if (orb.subcontractDebugFlag) {
  290. dprint(".marshalingComplete<-: " + opAndId(messageMediator));
  291. }
  292. }
  293. }
  294. public InputObject marshalingComplete1(
  295. ORB orb, CorbaMessageMediator messageMediator)
  296. throws
  297. ApplicationException,
  298. org.omg.CORBA.portable.RemarshalException
  299. {
  300. try {
  301. messageMediator.finishSendingRequest();
  302. if (orb.subcontractDebugFlag) {
  303. dprint(".marshalingComplete: " + opAndId(messageMediator)
  304. + ": finished sending request");
  305. }
  306. return messageMediator.waitForResponse();
  307. } catch (RuntimeException e) {
  308. if (orb.subcontractDebugFlag) {
  309. dprint(".marshalingComplete: " + opAndId(messageMediator)
  310. + ": exception: " + e.toString());
  311. }
  312. boolean retry =
  313. getContactInfoListIterator(orb)
  314. .reportException(messageMediator.getContactInfo(), e);
  315. if (retry) {
  316. // Must run interceptor end point before retrying.
  317. Exception newException =
  318. orb.getPIHandler().invokeClientPIEndingPoint(
  319. ReplyMessage.SYSTEM_EXCEPTION, e);
  320. if (newException == e) {
  321. continueOrThrowSystemOrRemarshal(messageMediator,
  322. new RemarshalException());
  323. } else {
  324. continueOrThrowSystemOrRemarshal(messageMediator,
  325. newException);
  326. }
  327. } else {
  328. // NOTE: Interceptor ending point will run in releaseReply.
  329. throw e;
  330. }
  331. return null; // for compiler
  332. }
  333. }
  334. protected InputObject processResponse(ORB orb,
  335. CorbaMessageMediator messageMediator,
  336. InputObject inputObject)
  337. throws
  338. ApplicationException,
  339. org.omg.CORBA.portable.RemarshalException
  340. {
  341. ORBUtilSystemException wrapper =
  342. ORBUtilSystemException.get( orb,
  343. CORBALogDomains.RPC_PROTOCOL ) ;
  344. if (orb.subcontractDebugFlag) {
  345. dprint(".processResponse: " + opAndId(messageMediator)
  346. + ": response received");
  347. }
  348. // We know for sure now that we've sent a message.
  349. // So OK to not send initial again.
  350. if (messageMediator.getConnection() != null) {
  351. ((CorbaConnection)messageMediator.getConnection())
  352. .setPostInitialContexts();
  353. }
  354. // NOTE: not necessary to set MessageMediator for PI.
  355. // It already has it.
  356. // Process the response.
  357. Exception exception = null;
  358. if (messageMediator.isOneWay()) {
  359. getContactInfoListIterator(orb)
  360. .reportSuccess(messageMediator.getContactInfo());
  361. // Invoke Portable Interceptors with receive_other
  362. exception = orb.getPIHandler().invokeClientPIEndingPoint(
  363. ReplyMessage.NO_EXCEPTION, exception );
  364. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  365. return null;
  366. }
  367. consumeServiceContexts(orb, messageMediator);
  368. // Now that we have the service contexts processed and the
  369. // correct ORBVersion set, we must finish initializing the stream.
  370. // REVISIT - need interface for this operation.
  371. ((CDRInputObject)inputObject).performORBVersionSpecificInit();
  372. if (messageMediator.isSystemExceptionReply()) {
  373. SystemException se = messageMediator.getSystemExceptionReply();
  374. if (orb.subcontractDebugFlag) {
  375. dprint(".processResponse: " + opAndId(messageMediator)
  376. + ": received system exception: " + se);
  377. }
  378. boolean doRemarshal =
  379. getContactInfoListIterator(orb)
  380. .reportException(messageMediator.getContactInfo(), se);
  381. if (doRemarshal) {
  382. // Invoke Portable Interceptors with receive_exception:
  383. exception = orb.getPIHandler().invokeClientPIEndingPoint(
  384. ReplyMessage.SYSTEM_EXCEPTION, se );
  385. // If PI did not change the exception, throw a
  386. // Remarshal.
  387. if( se == exception ) {
  388. // exception = null is to maintain symmetry with
  389. // GenericPOAClientSC.
  390. exception = null;
  391. continueOrThrowSystemOrRemarshal(messageMediator,
  392. new RemarshalException());
  393. throw wrapper.statementNotReachable1() ;
  394. } else {
  395. // Otherwise, throw the exception PI wants thrown.
  396. continueOrThrowSystemOrRemarshal(messageMediator,
  397. exception);
  398. throw wrapper.statementNotReachable2() ;
  399. }
  400. }
  401. // No retry, so see if was unknown.
  402. ServiceContexts contexts =
  403. messageMediator.getReplyServiceContexts();
  404. if (contexts != null) {
  405. UEInfoServiceContext usc =
  406. (UEInfoServiceContext)
  407. contexts.get(UEInfoServiceContext.SERVICE_CONTEXT_ID);
  408. if (usc != null) {
  409. Throwable unknown = usc.getUE() ;
  410. UnknownException ue = new UnknownException(unknown);
  411. // Invoke Portable Interceptors with receive_exception:
  412. exception = orb.getPIHandler().invokeClientPIEndingPoint(
  413. ReplyMessage.SYSTEM_EXCEPTION, ue );
  414. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  415. throw wrapper.statementNotReachable3() ;
  416. }
  417. }
  418. // It was not a comm failure nor unknown.
  419. // This is the general case.
  420. // Invoke Portable Interceptors with receive_exception:
  421. exception = orb.getPIHandler().invokeClientPIEndingPoint(
  422. ReplyMessage.SYSTEM_EXCEPTION, se );
  423. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  424. // Note: We should never need to execute this line, but
  425. // we should assert in case exception is null somehow.
  426. throw wrapper.statementNotReachable4() ;
  427. } else if (messageMediator.isUserExceptionReply()) {
  428. if (orb.subcontractDebugFlag) {
  429. dprint(".processResponse: " + opAndId(messageMediator)
  430. + ": received user exception");
  431. }
  432. getContactInfoListIterator(orb)
  433. .reportSuccess(messageMediator.getContactInfo());
  434. String exceptionRepoId = peekUserExceptionId(inputObject);
  435. Exception newException = null;
  436. if (messageMediator.isDIIRequest()) {
  437. exception = messageMediator.unmarshalDIIUserException(
  438. exceptionRepoId, (InputStream)inputObject);
  439. newException = orb.getPIHandler().invokeClientPIEndingPoint(
  440. ReplyMessage.USER_EXCEPTION, exception );
  441. messageMediator.setDIIException(newException);
  442. } else {
  443. ApplicationException appException =
  444. new ApplicationException(
  445. exceptionRepoId,
  446. (org.omg.CORBA.portable.InputStream)inputObject);
  447. exception = appException;
  448. newException = orb.getPIHandler().invokeClientPIEndingPoint(
  449. ReplyMessage.USER_EXCEPTION, appException );
  450. }
  451. if (newException != exception) {
  452. continueOrThrowSystemOrRemarshal(messageMediator,newException);
  453. }
  454. if (newException instanceof ApplicationException) {
  455. throw (ApplicationException)newException;
  456. }
  457. // For DII:
  458. // This return will be ignored - already unmarshaled above.
  459. return inputObject;
  460. } else if (messageMediator.isLocationForwardReply()) {
  461. if (orb.subcontractDebugFlag) {
  462. dprint(".processResponse: " + opAndId(messageMediator)
  463. + ": received location forward");
  464. }
  465. // NOTE: Expects iterator to update target IOR
  466. getContactInfoListIterator(orb).reportRedirect(
  467. (CorbaContactInfo)messageMediator.getContactInfo(),
  468. messageMediator.getForwardedIOR());
  469. // Invoke Portable Interceptors with receive_other:
  470. Exception newException = orb.getPIHandler().invokeClientPIEndingPoint(
  471. ReplyMessage.LOCATION_FORWARD, null );
  472. if( !(newException instanceof RemarshalException) ) {
  473. exception = newException;
  474. }
  475. // If PI did not change exception, throw Remarshal, else
  476. // throw the exception PI wants thrown.
  477. // KMC: GenericPOAClientSC did not check exception != null
  478. if( exception != null ) {
  479. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  480. }
  481. continueOrThrowSystemOrRemarshal(messageMediator,
  482. new RemarshalException());
  483. throw wrapper.statementNotReachable5() ;
  484. } else if (messageMediator.isDifferentAddrDispositionRequestedReply()){
  485. if (orb.subcontractDebugFlag) {
  486. dprint(".processResponse: " + opAndId(messageMediator)
  487. + ": received different addressing dispostion request");
  488. }
  489. // Set the desired target addressing disposition.
  490. getContactInfoListIterator(orb).reportAddrDispositionRetry(
  491. (CorbaContactInfo)messageMediator.getContactInfo(),
  492. messageMediator.getAddrDispositionReply());
  493. // Invoke Portable Interceptors with receive_other:
  494. Exception newException = orb.getPIHandler().invokeClientPIEndingPoint(
  495. ReplyMessage.NEEDS_ADDRESSING_MODE, null);
  496. // For consistency with corresponding code in GenericPOAClientSC:
  497. if( !(newException instanceof RemarshalException) ) {
  498. exception = newException;
  499. }
  500. // If PI did not change exception, throw Remarshal, else
  501. // throw the exception PI wants thrown.
  502. // KMC: GenericPOAClientSC did not include exception != null check
  503. if( exception != null ) {
  504. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  505. }
  506. continueOrThrowSystemOrRemarshal(messageMediator,
  507. new RemarshalException());
  508. throw wrapper.statementNotReachable6() ;
  509. } else /* normal response */ {
  510. if (orb.subcontractDebugFlag) {
  511. dprint(".processResponse: " + opAndId(messageMediator)
  512. + ": received normal response");
  513. }
  514. getContactInfoListIterator(orb)
  515. .reportSuccess(messageMediator.getContactInfo());
  516. messageMediator.handleDIIReply((InputStream)inputObject);
  517. // Invoke Portable Interceptors with receive_reply:
  518. exception = orb.getPIHandler().invokeClientPIEndingPoint(
  519. ReplyMessage.NO_EXCEPTION, null );
  520. // Remember: not thrown if exception is null.
  521. continueOrThrowSystemOrRemarshal(messageMediator, exception);
  522. return inputObject;
  523. }
  524. }
  525. // Filters the given exception into a SystemException or a
  526. // RemarshalException and throws it. Assumes the given exception is
  527. // of one of these two types. This is a utility method for
  528. // the above invoke code which must do this numerous times.
  529. // If the exception is null, no exception is thrown.
  530. //
  531. // Note that this code is duplicated in GenericPOAClientSC.java
  532. protected void continueOrThrowSystemOrRemarshal(
  533. CorbaMessageMediator messageMediator, Exception exception)
  534. throws
  535. SystemException, RemarshalException
  536. {
  537. ORB orb = (ORB) messageMediator.getBroker();
  538. if( exception == null ) {
  539. // do nothing.
  540. } else if( exception instanceof RemarshalException ) {
  541. // REVISIT - unify with PI handling
  542. orb.getInvocationInfo().setIsRetryInvocation(true);
  543. // NOTE - We must unregister the waiter NOW for this request
  544. // since the retry will result in a new request id. Therefore
  545. // the old request id would be lost and we would have a memory
  546. // leak in the responseWaitingRoom.
  547. unregisterWaiter(orb);
  548. if (orb.subcontractDebugFlag) {
  549. dprint(".continueOrThrowSystemOrRemarshal: "
  550. + opAndId(messageMediator)
  551. + ": throwing Remarshal");
  552. }
  553. throw (RemarshalException)exception;
  554. } else {
  555. if (orb.subcontractDebugFlag) {
  556. dprint(".continueOrThrowSystemOrRemarshal: "
  557. + opAndId(messageMediator)
  558. + ": throwing sex:"
  559. + exception);
  560. }
  561. throw (SystemException)exception;
  562. }
  563. }
  564. protected CorbaContactInfoListIterator getContactInfoListIterator(ORB orb)
  565. {
  566. return (CorbaContactInfoListIterator)
  567. ((CorbaInvocationInfo)orb.getInvocationInfo())
  568. .getContactInfoListIterator();
  569. }
  570. protected void registerWaiter(CorbaMessageMediator messageMediator)
  571. {
  572. if (messageMediator.getConnection() != null) {
  573. messageMediator.getConnection().registerWaiter(messageMediator);
  574. }
  575. }
  576. protected void unregisterWaiter(ORB orb)
  577. {
  578. MessageMediator messageMediator =
  579. orb.getInvocationInfo().getMessageMediator();
  580. if (messageMediator!=null && messageMediator.getConnection() != null) {
  581. // REVISIT:
  582. // The messageMediator may be null if COMM_FAILURE before
  583. // it is created.
  584. messageMediator.getConnection().unregisterWaiter(messageMediator);
  585. }
  586. }
  587. protected void addServiceContexts(CorbaMessageMediator messageMediator)
  588. {
  589. ORB orb = (ORB)messageMediator.getBroker();
  590. CorbaConnection c = (CorbaConnection) messageMediator.getConnection();
  591. GIOPVersion giopVersion = messageMediator.getGIOPVersion();
  592. ServiceContexts contexts = messageMediator.getRequestServiceContexts();
  593. addCodeSetServiceContext(c, contexts, giopVersion);
  594. // Add the RMI-IIOP max stream format version
  595. // service context to every request. Once we have GIOP 1.3,
  596. // we could skip it since we now support version 2, but
  597. // probably safer to always send it.
  598. contexts.put(MaxStreamFormatVersionServiceContext.singleton);
  599. // ORBVersion servicecontext needs to be sent
  600. ORBVersionServiceContext ovsc = new ORBVersionServiceContext(
  601. ORBVersionFactory.getORBVersion() ) ;
  602. contexts.put( ovsc ) ;
  603. // NOTE : We only want to send the runtime context the first time
  604. if ((c != null) && !c.isPostInitialContexts()) {
  605. // Do not do c.setPostInitialContexts() here.
  606. // If a client interceptor send_request does a ForwardRequest
  607. // which ends up using the same connection then the service
  608. // context would not be sent.
  609. SendingContextServiceContext scsc =
  610. new SendingContextServiceContext( orb.getFVDCodeBaseIOR() ) ; //d11638
  611. contexts.put( scsc ) ;
  612. }
  613. }
  614. protected void consumeServiceContexts(ORB orb,
  615. CorbaMessageMediator messageMediator)
  616. {
  617. ServiceContexts ctxts = messageMediator.getReplyServiceContexts();
  618. ServiceContext sc ;
  619. ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb,
  620. CORBALogDomains.RPC_PROTOCOL ) ;
  621. if (ctxts == null) {
  622. return; // no service context available, return gracefully.
  623. }
  624. sc = ctxts.get( SendingContextServiceContext.SERVICE_CONTEXT_ID ) ;
  625. if (sc != null) {
  626. SendingContextServiceContext scsc =
  627. (SendingContextServiceContext)sc ;
  628. IOR ior = scsc.getIOR() ;
  629. try {
  630. // set the codebase returned by the server
  631. if (messageMediator.getConnection() != null) {
  632. ((CorbaConnection)messageMediator.getConnection()).setCodeBaseIOR(ior);
  633. }
  634. } catch (ThreadDeath td) {
  635. throw td ;
  636. } catch (Throwable t) {
  637. throw wrapper.badStringifiedIor( t ) ;
  638. }
  639. }
  640. // see if the version subcontract is present, if yes, then set
  641. // the ORBversion
  642. sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ;
  643. if (sc != null) {
  644. ORBVersionServiceContext ovsc =
  645. (ORBVersionServiceContext) sc;
  646. ORBVersion version = ovsc.getVersion();
  647. orb.setORBVersion( version ) ;
  648. }
  649. getExceptionDetailMessage(messageMediator, wrapper);
  650. }
  651. protected void getExceptionDetailMessage(
  652. CorbaMessageMediator messageMediator,
  653. ORBUtilSystemException wrapper)
  654. {
  655. ServiceContext sc = messageMediator.getReplyServiceContexts()
  656. .get(ExceptionDetailMessage.value);
  657. if (sc == null)
  658. return ;
  659. if (! (sc instanceof UnknownServiceContext)) {
  660. throw wrapper.badExceptionDetailMessageServiceContextType();
  661. }
  662. byte[] data = ((UnknownServiceContext)sc).getData();
  663. EncapsInputStream in =
  664. new EncapsInputStream((ORB)messageMediator.getBroker(),
  665. data, data.length);
  666. in.consumeEndian();
  667. String msg =
  668. "----------BEGIN server-side stack trace----------\n"
  669. + in.read_wstring() + "\n"
  670. + "----------END server-side stack trace----------";
  671. messageMediator.setReplyExceptionDetailMessage(msg);
  672. }
  673. public void endRequest(Broker broker, Object self, InputObject inputObject)
  674. {
  675. ORB orb = (ORB)broker ;
  676. try {
  677. if (orb.subcontractDebugFlag) {
  678. dprint(".endRequest->");
  679. }
  680. // Note: the inputObject may be null if an error occurs
  681. // in request or before _invoke returns.
  682. // Note: self may be null also (e.g., compiler generates null in stub).
  683. MessageMediator messageMediator =
  684. orb.getInvocationInfo().getMessageMediator();
  685. if (messageMediator != null)
  686. {
  687. if (messageMediator.getConnection() != null)
  688. {
  689. ((CorbaMessageMediator)messageMediator)
  690. .sendCancelRequestIfFinalFragmentNotSent();
  691. }
  692. // Release any outstanding NIO ByteBuffers to the ByteBufferPool
  693. InputObject inputObj = messageMediator.getInputObject();
  694. if (inputObj != null) {
  695. inputObj.close();
  696. }
  697. OutputObject outputObj = messageMediator.getOutputObject();
  698. if (outputObj != null) {
  699. outputObj.close();
  700. }
  701. }
  702. // XREVISIT NOTE - Assumes unregistering the waiter for
  703. // location forwards has already happened somewhere else.
  704. // The code below is only going to unregister the final successful
  705. // request.
  706. // NOTE: In the case of a recursive stack of endRequests in a
  707. // finally block (because of Remarshal) only the first call to
  708. // unregisterWaiter will remove the waiter. The rest will be
  709. // noops.
  710. unregisterWaiter(orb);
  711. // Invoke Portable Interceptors cleanup. This is done to handle
  712. // exceptions during stream marshaling. More generally, exceptions
  713. // that occur in the ORB after send_request (which includes
  714. // after returning from _request) before _invoke:
  715. orb.getPIHandler().cleanupClientPIRequest();
  716. // REVISIT: Early replies?
  717. } catch (IOException ex) {
  718. // See CDRInput/OutputObject.close() for more info.
  719. // This won't result in a Corba error if an IOException happens.
  720. if (orb.subcontractDebugFlag)
  721. {
  722. dprint(".endRequest: ignoring IOException - " + ex.toString());
  723. }
  724. } finally {
  725. if (orb.subcontractDebugFlag) {
  726. dprint(".endRequest<-");
  727. }
  728. }
  729. }
  730. protected void performCodeSetNegotiation(CorbaMessageMediator messageMediator)
  731. {
  732. CorbaConnection conn =
  733. (CorbaConnection) messageMediator.getConnection();
  734. IOR ior =
  735. ((CorbaContactInfo)messageMediator.getContactInfo())
  736. .getEffectiveTargetIOR();
  737. GIOPVersion giopVersion = messageMediator.getGIOPVersion();
  738. // XXX This seems to be a broken double checked locking idiom: FIX IT!
  739. // conn.getCodeSetContext() is null when no other requests have
  740. // been made on this connection to trigger code set negotation.
  741. if (conn != null &&
  742. conn.getCodeSetContext() == null &&
  743. !giopVersion.equals(GIOPVersion.V1_0)) {
  744. synchronized(conn) {
  745. // Double checking. Don't let any other
  746. // threads use this connection until the
  747. // code sets are straight.
  748. if (conn.getCodeSetContext() != null)
  749. return;
  750. // This only looks at the first code set component. If
  751. // there can be multiple locations with multiple code sets,
  752. // this requires more work.
  753. IIOPProfileTemplate temp =
  754. (IIOPProfileTemplate)ior.getProfile().
  755. getTaggedProfileTemplate();
  756. Iterator iter = temp.iteratorById(TAG_CODE_SETS.value);
  757. if (!iter.hasNext()) {
  758. // Didn't have a code set component. The default will
  759. // be to use ISO8859-1 for char data and throw an
  760. // exception if wchar data is used.
  761. return;
  762. }
  763. // Get the native and conversion code sets the
  764. // server specified in its IOR
  765. CodeSetComponentInfo serverCodeSets
  766. = ((CodeSetsComponent)iter.next()).getCodeSetComponentInfo();
  767. // Perform the negotiation between this ORB's code sets and
  768. // the ones from the IOR
  769. CodeSetComponentInfo.CodeSetContext result
  770. = CodeSetConversion.impl().negotiate(
  771. conn.getBroker().getORBData().getCodeSetComponentInfo(),
  772. serverCodeSets);
  773. conn.setCodeSetContext(result);
  774. }
  775. }
  776. }
  777. protected void addCodeSetServiceContext(CorbaConnection conn,
  778. ServiceContexts ctxs,
  779. GIOPVersion giopVersion) {
  780. // REVISIT. OMG issue 3318 concerning sending the code set
  781. // service context more than once was deemed too much for the
  782. // RTF. Here's our strategy for the moment:
  783. //
  784. // Send it on every request (necessary in cases of fragmentation
  785. // with multithreaded clients or when the first thing on a
  786. // connection is a LocateRequest). Provide an ORB property
  787. // to disable multiple sends.
  788. //
  789. // Note that the connection is null in the local case and no
  790. // service context is included. We use the ORB provided
  791. // encapsulation streams.
  792. //
  793. // Also, there will be no negotiation or service context
  794. // in GIOP 1.0. ISO8859-1 is used for char/string, and
  795. // wchar/wstring are illegal.
  796. //
  797. if (giopVersion.equals(GIOPVersion.V1_0) || conn == null)
  798. return;
  799. CodeSetComponentInfo.CodeSetContext codeSetCtx = null;
  800. if (conn.getBroker().getORBData().alwaysSendCodeSetServiceContext() ||
  801. !conn.isPostInitialContexts()) {
  802. // Get the negotiated code sets (if any) out of the connection
  803. codeSetCtx = conn.getCodeSetContext();
  804. }
  805. // Either we shouldn't send the code set service context, or
  806. // for some reason, the connection doesn't have its code sets.
  807. // Perhaps the server didn't include them in the IOR. Uses
  808. // ISO8859-1 for char and makes wchar/wstring illegal.
  809. if (codeSetCtx == null)
  810. return;
  811. CodeSetServiceContext cssc = new CodeSetServiceContext(codeSetCtx);
  812. ctxs.put(cssc);
  813. }
  814. protected String peekUserExceptionId(InputObject inputObject)
  815. {
  816. CDRInputObject cdrInputObject = (CDRInputObject) inputObject;
  817. // REVISIT - need interface for mark/reset
  818. cdrInputObject.mark(Integer.MAX_VALUE);
  819. String result = cdrInputObject.read_string();
  820. cdrInputObject.reset();
  821. return result;
  822. }
  823. protected void dprint(String msg)
  824. {
  825. ORBUtility.dprint("CorbaClientRequestDispatcherImpl", msg);
  826. }
  827. protected String opAndId(CorbaMessageMediator mediator)
  828. {
  829. return ORBUtility.operationNameAndRequestId(mediator);
  830. }
  831. }
  832. // End of file.