1. /*
  2. * @(#)InterceptorInvoker.java 1.29 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.internal.Interceptors;
  8. import org.omg.PortableInterceptor.LOCATION_FORWARD;
  9. import org.omg.PortableInterceptor.SUCCESSFUL;
  10. import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
  11. import org.omg.PortableInterceptor.TRANSPORT_RETRY;
  12. import org.omg.PortableInterceptor.USER_EXCEPTION;
  13. import org.omg.PortableInterceptor.ClientRequestInfo;
  14. import org.omg.PortableInterceptor.ClientRequestInterceptor;
  15. import org.omg.PortableInterceptor.ForwardRequest;
  16. import org.omg.PortableInterceptor.IORInterceptor;
  17. import org.omg.PortableInterceptor.ServerRequestInfo;
  18. import org.omg.PortableInterceptor.ServerRequestInterceptor;
  19. import com.sun.corba.se.internal.corba.ClientDelegate;
  20. import com.sun.corba.se.internal.core.ClientSubcontract;
  21. import com.sun.corba.se.internal.core.IOR;
  22. import com.sun.corba.se.internal.POA.POAImpl;
  23. import com.sun.corba.se.internal.ior.IORTemplate;
  24. import org.omg.CORBA.CompletionStatus;
  25. import org.omg.CORBA.INTERNAL;
  26. import org.omg.CORBA.ORB ;
  27. import org.omg.CORBA.SystemException;
  28. import org.omg.CORBA.portable.Delegate;
  29. import org.omg.CORBA.portable.ObjectImpl;
  30. /**
  31. * Handles invocation of interceptors. Has specific knowledge of how to
  32. * invoke IOR, ClientRequest, and ServerRequest interceptors.
  33. * Makes use of the InterceptorList to retrieve the list of interceptors to
  34. * be invoked. Most methods in this class are package scope so that they
  35. * may only be called from the PIORB.
  36. */
  37. public class InterceptorInvoker {
  38. // The ORB
  39. private ORB orb;
  40. // The list of interceptors to be invoked
  41. private InterceptorList interceptorList;
  42. // True if interceptors are to be invoked, or false if not
  43. // Note: This is a global enable/disable flag, whereas the enable flag
  44. // in the RequestInfoStack in PIORB is only for a particular Thread.
  45. private boolean enabled = false;
  46. // PICurrent variable.
  47. private PICurrent current;
  48. // NOTE: Be careful about adding additional attributes to this class.
  49. // Multiple threads may be calling methods on this invoker at the same
  50. // time.
  51. /**
  52. * Creates a new Interceptor Invoker. Constructor is package scope so
  53. * only the ORB can create it. The invoker is initially disabled, and
  54. * must be explicitly enabled using setEnabled().
  55. */
  56. InterceptorInvoker( ORB orb, InterceptorList interceptorList,
  57. PICurrent piCurrent )
  58. {
  59. this.orb = orb;
  60. this.interceptorList = interceptorList;
  61. this.enabled = false;
  62. this.current = piCurrent;
  63. }
  64. /**
  65. * Enables or disables the interceptor invoker
  66. */
  67. void setEnabled( boolean enabled ) {
  68. this.enabled = enabled;
  69. }
  70. /*
  71. **********************************************************************
  72. * IOR Interceptor invocation
  73. **********************************************************************/
  74. /**
  75. * Called when a new POA is created.
  76. *
  77. * @param poaImpl The POA associated with the IOR interceptor.
  78. */
  79. void invokeIORInterceptors( POAImpl poaImpl ) {
  80. // If invocation is not yet enabled, don't do anything.
  81. if( enabled ) {
  82. // Create IORInfo object to pass to IORInterceptors:
  83. IORInfoImpl info = new IORInfoImpl( orb, poaImpl );
  84. // Call each IORInterceptor:
  85. IORInterceptor[] iorInterceptors =
  86. (IORInterceptor[])interceptorList.getInterceptors(
  87. InterceptorList.INTERCEPTOR_TYPE_IOR );
  88. int size = iorInterceptors.length;
  89. // Implementation note:
  90. // This loop counts backwards for greater efficiency.
  91. // Benchmarks have shown that counting down is more efficient
  92. // than counting up in Java for loops, as a compare to zero is
  93. // faster than a subtract and compare to zero. In this case,
  94. // it doesn't really matter much, but it's simply a force of habit.
  95. for( int i = (size - 1); i >= 0; i-- ) {
  96. IORInterceptor interceptor = iorInterceptors[i];
  97. try {
  98. interceptor.establish_components( info );
  99. }
  100. catch( Exception e ) {
  101. // as per PI spec (orbos/99-12-02 sec 7.2.1), if
  102. // establish_components throws an exception, ignore it.
  103. }
  104. }
  105. }
  106. }
  107. /*
  108. **********************************************************************
  109. * Client Interceptor invocation
  110. **********************************************************************/
  111. /**
  112. * Invokes either send_request, or send_poll, depending on the value
  113. * of info.getStartingPointCall()
  114. */
  115. void invokeClientInterceptorStartingPoint( ClientRequestInfoImpl info ) {
  116. // If invocation is not yet enabled, don't do anything.
  117. if( enabled ) {
  118. try {
  119. // Make a a fresh slot table available to TSC in case
  120. // interceptors need to make out calls.
  121. // Client's TSC is now RSC via RequestInfo.
  122. current.pushSlotTable( );
  123. info.setPICurrentPushed( true );
  124. info.setCurrentExecutionPoint( info.EXECUTION_POINT_STARTING );
  125. // Get all ClientRequestInterceptors:
  126. ClientRequestInterceptor[] clientInterceptors =
  127. (ClientRequestInterceptor[])interceptorList.
  128. getInterceptors( InterceptorList.INTERCEPTOR_TYPE_CLIENT );
  129. int size = clientInterceptors.length;
  130. // We will assume that all interceptors returned successfully,
  131. // and adjust the flowStackIndex to the appropriate value if
  132. // we later discover otherwise.
  133. int flowStackIndex = size;
  134. boolean continueProcessing = true;
  135. // Determine whether we are calling send_request or send_poll:
  136. // (This is currently commented out because our ORB does not
  137. // yet support the Messaging specification, so send_poll will
  138. // never occur. Once we have implemented messaging, this may
  139. // be uncommented.)
  140. // int startingPointCall = info.getStartingPointCall();
  141. for( int i = 0; continueProcessing && (i < size); i++ ) {
  142. try {
  143. clientInterceptors[i].send_request( info );
  144. // Again, it is not necessary for a switch here, since
  145. // there is only one starting point call type (see
  146. // above comment).
  147. //switch( startingPointCall ) {
  148. //case ClientRequestInfoImpl.CALL_SEND_REQUEST:
  149. //clientInterceptors[i].send_request( info );
  150. //break;
  151. //case ClientRequestInfoImpl.CALL_SEND_POLL:
  152. //clientInterceptors[i].send_poll( info );
  153. //break;
  154. //}
  155. }
  156. catch( ForwardRequest e ) {
  157. // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
  158. // interception point throws a ForwardRequest,
  159. // no other Interceptors' send_request operations are
  160. // called.
  161. flowStackIndex = i;
  162. info.setForwardRequest( e );
  163. info.setEndingPointCall(
  164. ClientRequestInfoImpl.CALL_RECEIVE_OTHER );
  165. info.setReplyStatus( LOCATION_FORWARD.value );
  166. updateClientDelegateForwardRequest( info );
  167. // For some reason, using break here causes the VM on
  168. // NT to lose track of the value of flowStackIndex
  169. // after exiting the for loop. I changed this to
  170. // check a boolean value instead and it seems to work
  171. // fine.
  172. continueProcessing = false;
  173. }
  174. catch( SystemException e ) {
  175. // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
  176. // interception point throws a SystemException,
  177. // no other Interceptors' send_request operations are
  178. // called.
  179. flowStackIndex = i;
  180. info.setEndingPointCall(
  181. ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION );
  182. info.setReplyStatus( SYSTEM_EXCEPTION.value );
  183. info.setException( e );
  184. // For some reason, using break here causes the VM on
  185. // NT to lose track of the value of flowStackIndex
  186. // after exiting the for loop. I changed this to
  187. // check a boolean value instead and it seems to
  188. // work fine.
  189. continueProcessing = false;
  190. }
  191. }
  192. // Remember where we left off in the flow stack:
  193. info.setFlowStackIndex( flowStackIndex );
  194. }
  195. finally {
  196. // Make the SlotTable fresh for the next interception point.
  197. current.resetSlotTable( );
  198. }
  199. } // end enabled check
  200. }
  201. /**
  202. * Invokes either receive_reply, receive_exception, or receive_other,
  203. * depending on the value of info.getEndingPointCall()
  204. */
  205. void invokeClientInterceptorEndingPoint( ClientRequestInfoImpl info ) {
  206. // If invocation is not yet enabled, don't do anything.
  207. if( enabled ) {
  208. try {
  209. // NOTE: It is assumed someplace else prepared a
  210. // fresh TSC slot table.
  211. info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
  212. // Get all ClientRequestInterceptors:
  213. ClientRequestInterceptor[] clientInterceptors =
  214. (ClientRequestInterceptor[])interceptorList.
  215. getInterceptors( InterceptorList.INTERCEPTOR_TYPE_CLIENT );
  216. int flowStackIndex = info.getFlowStackIndex();
  217. // Determine whether we are calling receive_reply,
  218. // receive_exception, or receive_other:
  219. int endingPointCall = info.getEndingPointCall();
  220. // If we would be calling RECEIVE_REPLY, but this is a
  221. // one-way call, override this and call receive_other:
  222. if( ( endingPointCall ==
  223. ClientRequestInfoImpl.CALL_RECEIVE_REPLY ) &&
  224. info.getIsOneWay() )
  225. {
  226. endingPointCall = ClientRequestInfoImpl.CALL_RECEIVE_OTHER;
  227. info.setEndingPointCall( endingPointCall );
  228. }
  229. // Only step through the interceptors whose starting points
  230. // have successfully returned.
  231. // Unlike the previous loop, this one counts backwards for a
  232. // reason - we must execute these in the reverse order of the
  233. // starting points.
  234. for( int i = (flowStackIndex - 1); i >= 0; i-- ) {
  235. try {
  236. switch( endingPointCall ) {
  237. case ClientRequestInfoImpl.CALL_RECEIVE_REPLY:
  238. clientInterceptors[i].receive_reply( info );
  239. break;
  240. case ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION:
  241. clientInterceptors[i].receive_exception( info );
  242. break;
  243. case ClientRequestInfoImpl.CALL_RECEIVE_OTHER:
  244. clientInterceptors[i].receive_other( info );
  245. break;
  246. }
  247. }
  248. catch( ForwardRequest e ) {
  249. // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
  250. // interception point throws a ForwardException,
  251. // ending point call changes to receive_other.
  252. endingPointCall =
  253. ClientRequestInfoImpl.CALL_RECEIVE_OTHER;
  254. info.setEndingPointCall( endingPointCall );
  255. info.setReplyStatus( LOCATION_FORWARD.value );
  256. info.setForwardRequest( e );
  257. updateClientDelegateForwardRequest( info );
  258. }
  259. catch( SystemException e ) {
  260. // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
  261. // interception point throws a SystemException,
  262. // ending point call changes to receive_exception.
  263. endingPointCall =
  264. ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION;
  265. info.setEndingPointCall( endingPointCall );
  266. info.setReplyStatus( SYSTEM_EXCEPTION.value );
  267. info.setException( e );
  268. }
  269. }
  270. }
  271. finally {
  272. // See doc for setPICurrentPushed as to why this is necessary.
  273. // Check info for null in case errors happen before initiate.
  274. if (info != null && info.isPICurrentPushed()) {
  275. current.popSlotTable( );
  276. // After the pop, original client's TSC slot table
  277. // remains avaiable via PICurrent.
  278. }
  279. }
  280. } // end enabled check
  281. }
  282. /*
  283. **********************************************************************
  284. * Server Interceptor invocation
  285. **********************************************************************/
  286. /**
  287. * Invokes receive_request_service_context interception points.
  288. */
  289. void invokeServerInterceptorStartingPoint( ServerRequestInfoImpl info ) {
  290. // If invocation is not yet enabled, don't do anything.
  291. if( enabled ) {
  292. try {
  293. // Make a fresh slot table for RSC.
  294. current.pushSlotTable();
  295. info.setSlotTable(current.getSlotTable());
  296. // Make a fresh slot table for TSC in case
  297. // interceptors need to make out calls.
  298. current.pushSlotTable( );
  299. info.setCurrentExecutionPoint( info.EXECUTION_POINT_STARTING );
  300. // Get all ServerRequestInterceptors:
  301. ServerRequestInterceptor[] serverInterceptors =
  302. (ServerRequestInterceptor[])interceptorList.
  303. getInterceptors( InterceptorList.INTERCEPTOR_TYPE_SERVER );
  304. int size = serverInterceptors.length;
  305. // We will assume that all interceptors returned successfully,
  306. // and adjust the flowStackIndex to the appropriate value if
  307. // we later discover otherwise.
  308. int flowStackIndex = size;
  309. boolean continueProcessing = true;
  310. // Currently, there is only one server-side starting point
  311. // interceptor called receive_request_service_contexts.
  312. for( int i = 0; continueProcessing && (i < size); i++ ) {
  313. try {
  314. serverInterceptors[i].
  315. receive_request_service_contexts( info );
  316. }
  317. catch( ForwardRequest e ) {
  318. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  319. // interception point throws a ForwardRequest,
  320. // no other Interceptors' starting points are
  321. // called and send_other is called.
  322. flowStackIndex = i;
  323. info.setForwardRequest( e );
  324. info.setIntermediatePointCall(
  325. ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE );
  326. info.setEndingPointCall(
  327. ServerRequestInfoImpl.CALL_SEND_OTHER );
  328. info.setReplyStatus( LOCATION_FORWARD.value );
  329. // For some reason, using break here causes the VM on
  330. // NT to lose track of the value of flowStackIndex
  331. // after exiting the for loop. I changed this to
  332. // check a boolean value instead and it seems to work
  333. // fine.
  334. continueProcessing = false;
  335. }
  336. catch( SystemException e ) {
  337. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  338. // interception point throws a SystemException,
  339. // no other Interceptors' starting points are
  340. // called.
  341. flowStackIndex = i;
  342. info.setException( e );
  343. info.setIntermediatePointCall(
  344. ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE );
  345. info.setEndingPointCall(
  346. ServerRequestInfoImpl.CALL_SEND_EXCEPTION );
  347. info.setReplyStatus( SYSTEM_EXCEPTION.value );
  348. // For some reason, using break here causes the VM on
  349. // NT to lose track of the value of flowStackIndex
  350. // after exiting the for loop. I changed this to
  351. // check a boolean value instead and it seems to
  352. // work fine.
  353. continueProcessing = false;
  354. }
  355. }
  356. // Remember where we left off in the flow stack:
  357. info.setFlowStackIndex( flowStackIndex );
  358. }
  359. finally {
  360. // The remaining points, ServantManager and Servant
  361. // all run in the same logical thread.
  362. current.popSlotTable( );
  363. // Now TSC and RSC are equivalent.
  364. }
  365. } // end enabled check
  366. }
  367. /**
  368. * Invokes receive_request interception points
  369. */
  370. void invokeServerInterceptorIntermediatePoint(
  371. ServerRequestInfoImpl info )
  372. {
  373. int intermediatePointCall = info.getIntermediatePointCall();
  374. // If invocation is not yet enabled, don't do anything.
  375. if( enabled && ( intermediatePointCall !=
  376. ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE ) )
  377. {
  378. // NOTE: do not touch the slotStack. The RSC and TSC are
  379. // equivalent at this point.
  380. info.setCurrentExecutionPoint( info.EXECUTION_POINT_INTERMEDIATE );
  381. // Get all ServerRequestInterceptors:
  382. ServerRequestInterceptor[] serverInterceptors =
  383. (ServerRequestInterceptor[])
  384. interceptorList.getInterceptors(
  385. InterceptorList.INTERCEPTOR_TYPE_SERVER );
  386. int size = serverInterceptors.length;
  387. // Currently, there is only one server-side intermediate point
  388. // interceptor called receive_request.
  389. for( int i = 0; i < size; i++ ) {
  390. try {
  391. serverInterceptors[i].receive_request( info );
  392. }
  393. catch( ForwardRequest e ) {
  394. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  395. // interception point throws a ForwardRequest,
  396. // no other Interceptors' intermediate points are
  397. // called and send_other is called.
  398. info.setForwardRequest( e );
  399. info.setEndingPointCall(
  400. ServerRequestInfoImpl.CALL_SEND_OTHER );
  401. info.setReplyStatus( LOCATION_FORWARD.value );
  402. break;
  403. }
  404. catch( SystemException e ) {
  405. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  406. // interception point throws a SystemException,
  407. // no other Interceptors' starting points are
  408. // called.
  409. info.setException( e );
  410. info.setEndingPointCall(
  411. ServerRequestInfoImpl.CALL_SEND_EXCEPTION );
  412. info.setReplyStatus( SYSTEM_EXCEPTION.value );
  413. break;
  414. }
  415. }
  416. } // end enabled check
  417. }
  418. /**
  419. * Invokes either send_reply, send_exception, or send_other,
  420. * depending on the value of info.getEndingPointCall()
  421. */
  422. void invokeServerInterceptorEndingPoint( ServerRequestInfoImpl info ) {
  423. // If invocation is not yet enabled, don't do anything.
  424. if( enabled ) {
  425. try {
  426. // NOTE: do not touch the slotStack. The RSC and TSC are
  427. // equivalent at this point.
  428. // REVISIT: This is moved out to PIORB until dispatch
  429. // path is rearchitected. It must be there so that
  430. // it always gets executed so if an interceptor raises
  431. // an exception any service contexts added in earlier points
  432. // this point get put in the exception reply (via the SC Q).
  433. //info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
  434. // Get all ServerRequestInterceptors:
  435. ServerRequestInterceptor[] serverInterceptors =
  436. (ServerRequestInterceptor[])interceptorList.
  437. getInterceptors( InterceptorList.INTERCEPTOR_TYPE_SERVER );
  438. int flowStackIndex = info.getFlowStackIndex();
  439. // Determine whether we are calling
  440. // send_exception, or send_other:
  441. int endingPointCall = info.getEndingPointCall();
  442. // Only step through the interceptors whose starting points
  443. // have successfully returned.
  444. for( int i = (flowStackIndex - 1); i >= 0; i-- ) {
  445. try {
  446. switch( endingPointCall ) {
  447. case ServerRequestInfoImpl.CALL_SEND_REPLY:
  448. serverInterceptors[i].send_reply( info );
  449. break;
  450. case ServerRequestInfoImpl.CALL_SEND_EXCEPTION:
  451. serverInterceptors[i].send_exception( info );
  452. break;
  453. case ServerRequestInfoImpl.CALL_SEND_OTHER:
  454. serverInterceptors[i].send_other( info );
  455. break;
  456. }
  457. }
  458. catch( ForwardRequest e ) {
  459. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  460. // interception point throws a ForwardException,
  461. // ending point call changes to receive_other.
  462. endingPointCall =
  463. ServerRequestInfoImpl.CALL_SEND_OTHER;
  464. info.setEndingPointCall( endingPointCall );
  465. info.setForwardRequest( e );
  466. info.setReplyStatus( LOCATION_FORWARD.value );
  467. info.setForwardRequestRaisedInEnding();
  468. }
  469. catch( SystemException e ) {
  470. // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
  471. // interception point throws a SystemException,
  472. // ending point call changes to send_exception.
  473. endingPointCall =
  474. ServerRequestInfoImpl.CALL_SEND_EXCEPTION;
  475. info.setEndingPointCall( endingPointCall );
  476. info.setException( e );
  477. info.setReplyStatus( SYSTEM_EXCEPTION.value );
  478. }
  479. }
  480. // Remember that all interceptors' starting and ending points
  481. // have already been executed so we need not do anything.
  482. info.setAlreadyExecuted( true );
  483. }
  484. finally {
  485. // Get rid of the Server side RSC.
  486. current.popSlotTable();
  487. }
  488. } // end enabled check
  489. }
  490. /*
  491. **********************************************************************
  492. * Private utility methods
  493. **********************************************************************/
  494. /**
  495. * Update the client delegate in the event of a ForwardRequest, given the
  496. * information in the passed-in info object.
  497. */
  498. private void updateClientDelegateForwardRequest(
  499. ClientRequestInfoImpl info )
  500. {
  501. ForwardRequest forwardRequest = info.getForwardRequestException();
  502. // ForwardRequest may be null if the forwarded IOR is set internal
  503. // to the ClientDelegate rather than explicitly through Portable
  504. // Interceptors. In this case, we need not update the client
  505. // delegate ForwardRequest object.
  506. if( forwardRequest != null ) {
  507. ClientDelegate clientDelegate = info.getClientDelegate();
  508. org.omg.CORBA.Object object = forwardRequest.forward;
  509. // Convert the forward object into an IOR:
  510. if( object instanceof ObjectImpl ) {
  511. Delegate delegate = ((ObjectImpl)object)._get_delegate();
  512. if( delegate == null ) {
  513. throw new INTERNAL(
  514. "While converting Forward object into IOR, object " +
  515. "has no delegate.",
  516. MinorCodes.OBJECT_HAS_NO_DELEGATE,
  517. CompletionStatus.COMPLETED_NO );
  518. }
  519. else if( delegate instanceof ClientSubcontract ) {
  520. IOR ior = ((ClientSubcontract)delegate).marshal();
  521. clientDelegate.setLocatedIOR( ior );
  522. }
  523. else {
  524. throw new INTERNAL(
  525. "While converting Forward object into IOR, delegate " +
  526. "is not instanceof ClientSubcontract",
  527. MinorCodes.DELEGATE_NOT_CLIENTSUB,
  528. CompletionStatus.COMPLETED_NO );
  529. }
  530. }
  531. else {
  532. throw new INTERNAL(
  533. "While converting Forward object into IOR, object is not "+
  534. "instanceof ObjectImpl",
  535. MinorCodes.OBJECT_NOT_OBJECTIMPL,
  536. CompletionStatus.COMPLETED_NO );
  537. }
  538. }
  539. }
  540. }