- /*
- * @(#)InterceptorInvoker.java 1.29 03/01/23
- *
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package com.sun.corba.se.internal.Interceptors;
-
- import org.omg.PortableInterceptor.LOCATION_FORWARD;
- import org.omg.PortableInterceptor.SUCCESSFUL;
- import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
- import org.omg.PortableInterceptor.TRANSPORT_RETRY;
- import org.omg.PortableInterceptor.USER_EXCEPTION;
-
- import org.omg.PortableInterceptor.ClientRequestInfo;
- import org.omg.PortableInterceptor.ClientRequestInterceptor;
- import org.omg.PortableInterceptor.ForwardRequest;
- import org.omg.PortableInterceptor.IORInterceptor;
- import org.omg.PortableInterceptor.ServerRequestInfo;
- import org.omg.PortableInterceptor.ServerRequestInterceptor;
-
- import com.sun.corba.se.internal.corba.ClientDelegate;
- import com.sun.corba.se.internal.core.ClientSubcontract;
- import com.sun.corba.se.internal.core.IOR;
- import com.sun.corba.se.internal.POA.POAImpl;
- import com.sun.corba.se.internal.ior.IORTemplate;
-
- import org.omg.CORBA.CompletionStatus;
- import org.omg.CORBA.INTERNAL;
- import org.omg.CORBA.ORB ;
- import org.omg.CORBA.SystemException;
- import org.omg.CORBA.portable.Delegate;
- import org.omg.CORBA.portable.ObjectImpl;
-
- /**
- * Handles invocation of interceptors. Has specific knowledge of how to
- * invoke IOR, ClientRequest, and ServerRequest interceptors.
- * Makes use of the InterceptorList to retrieve the list of interceptors to
- * be invoked. Most methods in this class are package scope so that they
- * may only be called from the PIORB.
- */
- public class InterceptorInvoker {
-
- // The ORB
- private ORB orb;
-
- // The list of interceptors to be invoked
- private InterceptorList interceptorList;
-
- // True if interceptors are to be invoked, or false if not
- // Note: This is a global enable/disable flag, whereas the enable flag
- // in the RequestInfoStack in PIORB is only for a particular Thread.
- private boolean enabled = false;
-
- // PICurrent variable.
- private PICurrent current;
-
- // NOTE: Be careful about adding additional attributes to this class.
- // Multiple threads may be calling methods on this invoker at the same
- // time.
-
- /**
- * Creates a new Interceptor Invoker. Constructor is package scope so
- * only the ORB can create it. The invoker is initially disabled, and
- * must be explicitly enabled using setEnabled().
- */
- InterceptorInvoker( ORB orb, InterceptorList interceptorList,
- PICurrent piCurrent )
- {
- this.orb = orb;
- this.interceptorList = interceptorList;
- this.enabled = false;
- this.current = piCurrent;
- }
-
- /**
- * Enables or disables the interceptor invoker
- */
- void setEnabled( boolean enabled ) {
- this.enabled = enabled;
- }
-
- /*
- **********************************************************************
- * IOR Interceptor invocation
- **********************************************************************/
-
- /**
- * Called when a new POA is created.
- *
- * @param poaImpl The POA associated with the IOR interceptor.
- */
- void invokeIORInterceptors( POAImpl poaImpl ) {
- // If invocation is not yet enabled, don't do anything.
- if( enabled ) {
- // Create IORInfo object to pass to IORInterceptors:
- IORInfoImpl info = new IORInfoImpl( orb, poaImpl );
-
- // Call each IORInterceptor:
- IORInterceptor[] iorInterceptors =
- (IORInterceptor[])interceptorList.getInterceptors(
- InterceptorList.INTERCEPTOR_TYPE_IOR );
- int size = iorInterceptors.length;
-
- // Implementation note:
- // This loop counts backwards for greater efficiency.
- // Benchmarks have shown that counting down is more efficient
- // than counting up in Java for loops, as a compare to zero is
- // faster than a subtract and compare to zero. In this case,
- // it doesn't really matter much, but it's simply a force of habit.
-
- for( int i = (size - 1); i >= 0; i-- ) {
- IORInterceptor interceptor = iorInterceptors[i];
- try {
- interceptor.establish_components( info );
- }
- catch( Exception e ) {
- // as per PI spec (orbos/99-12-02 sec 7.2.1), if
- // establish_components throws an exception, ignore it.
- }
- }
- }
- }
-
- /*
- **********************************************************************
- * Client Interceptor invocation
- **********************************************************************/
-
- /**
- * Invokes either send_request, or send_poll, depending on the value
- * of info.getStartingPointCall()
- */
- void invokeClientInterceptorStartingPoint( ClientRequestInfoImpl info ) {
- // If invocation is not yet enabled, don't do anything.
- if( enabled ) {
- try {
- // Make a a fresh slot table available to TSC in case
- // interceptors need to make out calls.
- // Client's TSC is now RSC via RequestInfo.
- current.pushSlotTable( );
- info.setPICurrentPushed( true );
- info.setCurrentExecutionPoint( info.EXECUTION_POINT_STARTING );
-
- // Get all ClientRequestInterceptors:
- ClientRequestInterceptor[] clientInterceptors =
- (ClientRequestInterceptor[])interceptorList.
- getInterceptors( InterceptorList.INTERCEPTOR_TYPE_CLIENT );
- int size = clientInterceptors.length;
-
- // We will assume that all interceptors returned successfully,
- // and adjust the flowStackIndex to the appropriate value if
- // we later discover otherwise.
- int flowStackIndex = size;
- boolean continueProcessing = true;
-
- // Determine whether we are calling send_request or send_poll:
- // (This is currently commented out because our ORB does not
- // yet support the Messaging specification, so send_poll will
- // never occur. Once we have implemented messaging, this may
- // be uncommented.)
- // int startingPointCall = info.getStartingPointCall();
- for( int i = 0; continueProcessing && (i < size); i++ ) {
- try {
- clientInterceptors[i].send_request( info );
-
- // Again, it is not necessary for a switch here, since
- // there is only one starting point call type (see
- // above comment).
-
- //switch( startingPointCall ) {
- //case ClientRequestInfoImpl.CALL_SEND_REQUEST:
- //clientInterceptors[i].send_request( info );
- //break;
- //case ClientRequestInfoImpl.CALL_SEND_POLL:
- //clientInterceptors[i].send_poll( info );
- //break;
- //}
-
- }
- catch( ForwardRequest e ) {
- // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
- // interception point throws a ForwardRequest,
- // no other Interceptors' send_request operations are
- // called.
- flowStackIndex = i;
- info.setForwardRequest( e );
- info.setEndingPointCall(
- ClientRequestInfoImpl.CALL_RECEIVE_OTHER );
- info.setReplyStatus( LOCATION_FORWARD.value );
-
- updateClientDelegateForwardRequest( info );
-
- // For some reason, using break here causes the VM on
- // NT to lose track of the value of flowStackIndex
- // after exiting the for loop. I changed this to
- // check a boolean value instead and it seems to work
- // fine.
- continueProcessing = false;
- }
- catch( SystemException e ) {
- // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
- // interception point throws a SystemException,
- // no other Interceptors' send_request operations are
- // called.
- flowStackIndex = i;
- info.setEndingPointCall(
- ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION );
- info.setReplyStatus( SYSTEM_EXCEPTION.value );
- info.setException( e );
-
- // For some reason, using break here causes the VM on
- // NT to lose track of the value of flowStackIndex
- // after exiting the for loop. I changed this to
- // check a boolean value instead and it seems to
- // work fine.
- continueProcessing = false;
- }
- }
-
- // Remember where we left off in the flow stack:
- info.setFlowStackIndex( flowStackIndex );
- }
- finally {
- // Make the SlotTable fresh for the next interception point.
- current.resetSlotTable( );
- }
- } // end enabled check
- }
-
- /**
- * Invokes either receive_reply, receive_exception, or receive_other,
- * depending on the value of info.getEndingPointCall()
- */
- void invokeClientInterceptorEndingPoint( ClientRequestInfoImpl info ) {
- // If invocation is not yet enabled, don't do anything.
- if( enabled ) {
- try {
- // NOTE: It is assumed someplace else prepared a
- // fresh TSC slot table.
-
- info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
-
- // Get all ClientRequestInterceptors:
- ClientRequestInterceptor[] clientInterceptors =
- (ClientRequestInterceptor[])interceptorList.
- getInterceptors( InterceptorList.INTERCEPTOR_TYPE_CLIENT );
- int flowStackIndex = info.getFlowStackIndex();
-
- // Determine whether we are calling receive_reply,
- // receive_exception, or receive_other:
- int endingPointCall = info.getEndingPointCall();
-
- // If we would be calling RECEIVE_REPLY, but this is a
- // one-way call, override this and call receive_other:
- if( ( endingPointCall ==
- ClientRequestInfoImpl.CALL_RECEIVE_REPLY ) &&
- info.getIsOneWay() )
- {
- endingPointCall = ClientRequestInfoImpl.CALL_RECEIVE_OTHER;
- info.setEndingPointCall( endingPointCall );
- }
-
- // Only step through the interceptors whose starting points
- // have successfully returned.
- // Unlike the previous loop, this one counts backwards for a
- // reason - we must execute these in the reverse order of the
- // starting points.
- for( int i = (flowStackIndex - 1); i >= 0; i-- ) {
-
- try {
- switch( endingPointCall ) {
- case ClientRequestInfoImpl.CALL_RECEIVE_REPLY:
- clientInterceptors[i].receive_reply( info );
- break;
- case ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION:
- clientInterceptors[i].receive_exception( info );
- break;
- case ClientRequestInfoImpl.CALL_RECEIVE_OTHER:
- clientInterceptors[i].receive_other( info );
- break;
- }
- }
- catch( ForwardRequest e ) {
-
- // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
- // interception point throws a ForwardException,
- // ending point call changes to receive_other.
- endingPointCall =
- ClientRequestInfoImpl.CALL_RECEIVE_OTHER;
- info.setEndingPointCall( endingPointCall );
- info.setReplyStatus( LOCATION_FORWARD.value );
- info.setForwardRequest( e );
- updateClientDelegateForwardRequest( info );
- }
- catch( SystemException e ) {
-
- // as per PI spec (orbos/99-12-02 sec 5.2.1.), if
- // interception point throws a SystemException,
- // ending point call changes to receive_exception.
- endingPointCall =
- ClientRequestInfoImpl.CALL_RECEIVE_EXCEPTION;
- info.setEndingPointCall( endingPointCall );
- info.setReplyStatus( SYSTEM_EXCEPTION.value );
- info.setException( e );
- }
- }
- }
- finally {
- // See doc for setPICurrentPushed as to why this is necessary.
- // Check info for null in case errors happen before initiate.
- if (info != null && info.isPICurrentPushed()) {
- current.popSlotTable( );
- // After the pop, original client's TSC slot table
- // remains avaiable via PICurrent.
- }
- }
- } // end enabled check
- }
-
- /*
- **********************************************************************
- * Server Interceptor invocation
- **********************************************************************/
-
- /**
- * Invokes receive_request_service_context interception points.
- */
- void invokeServerInterceptorStartingPoint( ServerRequestInfoImpl info ) {
- // If invocation is not yet enabled, don't do anything.
- if( enabled ) {
- try {
- // Make a fresh slot table for RSC.
- current.pushSlotTable();
- info.setSlotTable(current.getSlotTable());
-
- // Make a fresh slot table for TSC in case
- // interceptors need to make out calls.
- current.pushSlotTable( );
-
- info.setCurrentExecutionPoint( info.EXECUTION_POINT_STARTING );
-
- // Get all ServerRequestInterceptors:
- ServerRequestInterceptor[] serverInterceptors =
- (ServerRequestInterceptor[])interceptorList.
- getInterceptors( InterceptorList.INTERCEPTOR_TYPE_SERVER );
- int size = serverInterceptors.length;
-
- // We will assume that all interceptors returned successfully,
- // and adjust the flowStackIndex to the appropriate value if
- // we later discover otherwise.
- int flowStackIndex = size;
- boolean continueProcessing = true;
-
- // Currently, there is only one server-side starting point
- // interceptor called receive_request_service_contexts.
- for( int i = 0; continueProcessing && (i < size); i++ ) {
-
- try {
- serverInterceptors[i].
- receive_request_service_contexts( info );
- }
- catch( ForwardRequest e ) {
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a ForwardRequest,
- // no other Interceptors' starting points are
- // called and send_other is called.
- flowStackIndex = i;
- info.setForwardRequest( e );
- info.setIntermediatePointCall(
- ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE );
- info.setEndingPointCall(
- ServerRequestInfoImpl.CALL_SEND_OTHER );
- info.setReplyStatus( LOCATION_FORWARD.value );
-
- // For some reason, using break here causes the VM on
- // NT to lose track of the value of flowStackIndex
- // after exiting the for loop. I changed this to
- // check a boolean value instead and it seems to work
- // fine.
- continueProcessing = false;
- }
- catch( SystemException e ) {
-
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a SystemException,
- // no other Interceptors' starting points are
- // called.
- flowStackIndex = i;
- info.setException( e );
- info.setIntermediatePointCall(
- ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE );
- info.setEndingPointCall(
- ServerRequestInfoImpl.CALL_SEND_EXCEPTION );
- info.setReplyStatus( SYSTEM_EXCEPTION.value );
-
- // For some reason, using break here causes the VM on
- // NT to lose track of the value of flowStackIndex
- // after exiting the for loop. I changed this to
- // check a boolean value instead and it seems to
- // work fine.
- continueProcessing = false;
- }
-
- }
-
- // Remember where we left off in the flow stack:
- info.setFlowStackIndex( flowStackIndex );
- }
- finally {
- // The remaining points, ServantManager and Servant
- // all run in the same logical thread.
- current.popSlotTable( );
- // Now TSC and RSC are equivalent.
- }
- } // end enabled check
- }
-
- /**
- * Invokes receive_request interception points
- */
- void invokeServerInterceptorIntermediatePoint(
- ServerRequestInfoImpl info )
- {
- int intermediatePointCall = info.getIntermediatePointCall();
- // If invocation is not yet enabled, don't do anything.
- if( enabled && ( intermediatePointCall !=
- ServerRequestInfoImpl.CALL_INTERMEDIATE_NONE ) )
- {
- // NOTE: do not touch the slotStack. The RSC and TSC are
- // equivalent at this point.
-
- info.setCurrentExecutionPoint( info.EXECUTION_POINT_INTERMEDIATE );
-
- // Get all ServerRequestInterceptors:
- ServerRequestInterceptor[] serverInterceptors =
- (ServerRequestInterceptor[])
- interceptorList.getInterceptors(
- InterceptorList.INTERCEPTOR_TYPE_SERVER );
- int size = serverInterceptors.length;
-
- // Currently, there is only one server-side intermediate point
- // interceptor called receive_request.
- for( int i = 0; i < size; i++ ) {
-
- try {
- serverInterceptors[i].receive_request( info );
- }
- catch( ForwardRequest e ) {
-
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a ForwardRequest,
- // no other Interceptors' intermediate points are
- // called and send_other is called.
- info.setForwardRequest( e );
- info.setEndingPointCall(
- ServerRequestInfoImpl.CALL_SEND_OTHER );
- info.setReplyStatus( LOCATION_FORWARD.value );
- break;
- }
- catch( SystemException e ) {
-
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a SystemException,
- // no other Interceptors' starting points are
- // called.
- info.setException( e );
- info.setEndingPointCall(
- ServerRequestInfoImpl.CALL_SEND_EXCEPTION );
- info.setReplyStatus( SYSTEM_EXCEPTION.value );
- break;
- }
- }
- } // end enabled check
- }
-
- /**
- * Invokes either send_reply, send_exception, or send_other,
- * depending on the value of info.getEndingPointCall()
- */
- void invokeServerInterceptorEndingPoint( ServerRequestInfoImpl info ) {
- // If invocation is not yet enabled, don't do anything.
- if( enabled ) {
- try {
- // NOTE: do not touch the slotStack. The RSC and TSC are
- // equivalent at this point.
-
- // REVISIT: This is moved out to PIORB until dispatch
- // path is rearchitected. It must be there so that
- // it always gets executed so if an interceptor raises
- // an exception any service contexts added in earlier points
- // this point get put in the exception reply (via the SC Q).
- //info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );
-
- // Get all ServerRequestInterceptors:
- ServerRequestInterceptor[] serverInterceptors =
- (ServerRequestInterceptor[])interceptorList.
- getInterceptors( InterceptorList.INTERCEPTOR_TYPE_SERVER );
- int flowStackIndex = info.getFlowStackIndex();
-
- // Determine whether we are calling
- // send_exception, or send_other:
- int endingPointCall = info.getEndingPointCall();
-
- // Only step through the interceptors whose starting points
- // have successfully returned.
- for( int i = (flowStackIndex - 1); i >= 0; i-- ) {
- try {
- switch( endingPointCall ) {
- case ServerRequestInfoImpl.CALL_SEND_REPLY:
- serverInterceptors[i].send_reply( info );
- break;
- case ServerRequestInfoImpl.CALL_SEND_EXCEPTION:
- serverInterceptors[i].send_exception( info );
- break;
- case ServerRequestInfoImpl.CALL_SEND_OTHER:
- serverInterceptors[i].send_other( info );
- break;
- }
- }
- catch( ForwardRequest e ) {
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a ForwardException,
- // ending point call changes to receive_other.
- endingPointCall =
- ServerRequestInfoImpl.CALL_SEND_OTHER;
- info.setEndingPointCall( endingPointCall );
- info.setForwardRequest( e );
- info.setReplyStatus( LOCATION_FORWARD.value );
- info.setForwardRequestRaisedInEnding();
- }
- catch( SystemException e ) {
- // as per PI spec (orbos/99-12-02 sec 5.3.1.), if
- // interception point throws a SystemException,
- // ending point call changes to send_exception.
- endingPointCall =
- ServerRequestInfoImpl.CALL_SEND_EXCEPTION;
- info.setEndingPointCall( endingPointCall );
- info.setException( e );
- info.setReplyStatus( SYSTEM_EXCEPTION.value );
- }
- }
-
- // Remember that all interceptors' starting and ending points
- // have already been executed so we need not do anything.
- info.setAlreadyExecuted( true );
- }
- finally {
- // Get rid of the Server side RSC.
- current.popSlotTable();
- }
- } // end enabled check
- }
-
- /*
- **********************************************************************
- * Private utility methods
- **********************************************************************/
-
- /**
- * Update the client delegate in the event of a ForwardRequest, given the
- * information in the passed-in info object.
- */
- private void updateClientDelegateForwardRequest(
- ClientRequestInfoImpl info )
- {
- ForwardRequest forwardRequest = info.getForwardRequestException();
-
- // ForwardRequest may be null if the forwarded IOR is set internal
- // to the ClientDelegate rather than explicitly through Portable
- // Interceptors. In this case, we need not update the client
- // delegate ForwardRequest object.
- if( forwardRequest != null ) {
- ClientDelegate clientDelegate = info.getClientDelegate();
- org.omg.CORBA.Object object = forwardRequest.forward;
-
- // Convert the forward object into an IOR:
- if( object instanceof ObjectImpl ) {
- Delegate delegate = ((ObjectImpl)object)._get_delegate();
- if( delegate == null ) {
- throw new INTERNAL(
- "While converting Forward object into IOR, object " +
- "has no delegate.",
- MinorCodes.OBJECT_HAS_NO_DELEGATE,
- CompletionStatus.COMPLETED_NO );
- }
- else if( delegate instanceof ClientSubcontract ) {
- IOR ior = ((ClientSubcontract)delegate).marshal();
- clientDelegate.setLocatedIOR( ior );
- }
- else {
- throw new INTERNAL(
- "While converting Forward object into IOR, delegate " +
- "is not instanceof ClientSubcontract",
- MinorCodes.DELEGATE_NOT_CLIENTSUB,
- CompletionStatus.COMPLETED_NO );
- }
- }
- else {
- throw new INTERNAL(
- "While converting Forward object into IOR, object is not "+
- "instanceof ObjectImpl",
- MinorCodes.OBJECT_NOT_OBJECTIMPL,
- CompletionStatus.COMPLETED_NO );
- }
- }
- }
-
- }