blob: 367ed231900843158669c9204e28cfed8c17173c [file] [log] [blame]
/*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.corba.se.impl.interceptors;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.portable.Delegate;
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.IORInterceptor_3_0;
import org.omg.PortableInterceptor.ServerRequestInfo;
import org.omg.PortableInterceptor.ServerRequestInterceptor;
import org.omg.PortableInterceptor.ObjectReferenceTemplate;
import com.sun.corba.se.spi.ior.IOR;
import com.sun.corba.se.spi.oa.ObjectAdapter;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.impl.orbutil.ORBUtility;
/**
* 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 PIHandlerImpl.
*/
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 PIHandlerImpl 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 oa The Object Adapter associated with the IOR interceptor.
*/
void objectAdapterCreated( ObjectAdapter oa ) {
// If invocation is not yet enabled, don't do anything.
if( enabled ) {
// Create IORInfo object to pass to IORInterceptors:
IORInfoImpl info = new IORInfoImpl( oa );
// 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.
}
}
// Change the state so that only template operations are valid
info.makeStateEstablished() ;
for( int i = (size - 1); i >= 0; i-- ) {
IORInterceptor interceptor = iorInterceptors[i];
if (interceptor instanceof IORInterceptor_3_0) {
IORInterceptor_3_0 interceptor30 = (IORInterceptor_3_0)interceptor ;
// Note that exceptions here are NOT ignored, as per the
// ORT spec (orbos/01-01-04)
interceptor30.components_established( info );
}
}
// Change the state so that no operations are valid,
// in case a reference to info escapes this scope.
// This also completes the actions associated with the
// template interceptors on this POA.
info.makeStateDone() ;
}
}
void adapterManagerStateChanged( int managerId, short newState )
{
if (enabled) {
IORInterceptor[] interceptors =
(IORInterceptor[])interceptorList.getInterceptors(
InterceptorList.INTERCEPTOR_TYPE_IOR );
int size = interceptors.length;
for( int i = (size - 1); i >= 0; i-- ) {
try {
IORInterceptor interceptor = interceptors[i];
if (interceptor instanceof IORInterceptor_3_0) {
IORInterceptor_3_0 interceptor30 = (IORInterceptor_3_0)interceptor ;
interceptor30.adapter_manager_state_changed( managerId,
newState );
}
} catch (Exception exc) {
// No-op: ignore exception in this case
}
}
}
}
void adapterStateChanged( ObjectReferenceTemplate[] templates,
short newState )
{
if (enabled) {
IORInterceptor[] interceptors =
(IORInterceptor[])interceptorList.getInterceptors(
InterceptorList.INTERCEPTOR_TYPE_IOR );
int size = interceptors.length;
for( int i = (size - 1); i >= 0; i-- ) {
try {
IORInterceptor interceptor = interceptors[i];
if (interceptor instanceof IORInterceptor_3_0) {
IORInterceptor_3_0 interceptor30 = (IORInterceptor_3_0)interceptor ;
interceptor30.adapter_state_changed( templates, newState );
}
} catch (Exception exc) {
// No-op: ignore exception in this case
}
}
}
}
/*
**********************************************************************
* 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 );
updateClientRequestDispatcherForward( 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 );
updateClientRequestDispatcherForward( 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 PIHandlerImpl 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 updateClientRequestDispatcherForward(
ClientRequestInfoImpl info )
{
ForwardRequest forwardRequest = info.getForwardRequestException();
// ForwardRequest may be null if the forwarded IOR is set internal
// to the ClientRequestDispatcher rather than explicitly through Portable
// Interceptors. In this case, we need not update the client
// delegate ForwardRequest object.
if( forwardRequest != null ) {
org.omg.CORBA.Object object = forwardRequest.forward;
// Convert the forward object into an IOR:
IOR ior = ORBUtility.getIOR( object ) ;
info.setLocatedIOR( ior );
}
}
}