/*
 * Copyright (c) 2000, 2012, 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.Any;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.NO_RESOURCES;
import org.omg.CORBA.NVList;
import org.omg.CORBA.Object;
import org.omg.CORBA.Policy;
import org.omg.CORBA.TypeCode;

import org.omg.PortableServer.Servant;

import org.omg.IOP.TaggedProfile;
import org.omg.IOP.ServiceContext;

import org.omg.Dynamic.Parameter;

import org.omg.PortableInterceptor.InvalidSlot;
import org.omg.PortableInterceptor.ServerRequestInfo;
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 com.sun.corba.se.spi.oa.ObjectAdapter;
import com.sun.corba.se.spi.presentation.rmi.StubAdapter;

import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;

import com.sun.corba.se.spi.servicecontext.ServiceContexts;
import com.sun.corba.se.spi.orb.ORB;

import com.sun.corba.se.spi.ior.ObjectKeyTemplate;
import com.sun.corba.se.spi.ior.ObjectAdapterId ;

import com.sun.corba.se.spi.protocol.CorbaMessageMediator;

import java.util.*;

/**
 * Implementation of the ServerRequestInfo interface as specified in
 * orbos/99-12-02 section 5.4.3.
 */
public final class ServerRequestInfoImpl
    extends RequestInfoImpl
    implements ServerRequestInfo
{
    // The available constants for startingPointCall
    static final int CALL_RECEIVE_REQUEST_SERVICE_CONTEXT = 0;

    // The available constants for intermediatePointCall.  The default (0)
    // is receive_request, but can be set to none on demand.
    static final int CALL_RECEIVE_REQUEST = 0;
    static final int CALL_INTERMEDIATE_NONE = 1;

    // The available constants for endingPointCall
    static final int CALL_SEND_REPLY = 0;
    static final int CALL_SEND_EXCEPTION = 1;
    static final int CALL_SEND_OTHER = 2;

    //////////////////////////////////////////////////////////////////////
    //
    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
    //
    //////////////////////////////////////////////////////////////////////

    // Set to true if the server ending point raised ForwardRequest at some
    // point in the ending point.
    private boolean forwardRequestRaisedInEnding;

    // Sources of server request information:
    private CorbaMessageMediator request;
    private java.lang.Object servant;
    private byte[] objectId;
    private ObjectKeyTemplate oktemp ;

    // Information cached from calls to oktemp
    private byte[] adapterId;
    private String[] adapterName;

    private ArrayList addReplyServiceContextQueue;
    private ReplyMessage replyMessage;
    private String targetMostDerivedInterface;
    private NVList dsiArguments;
    private Any dsiResult;
    private Any dsiException;
    private boolean isDynamic;
    private ObjectAdapter objectAdapter;
    private int serverRequestId;

    // Cached information:
    private Parameter[] cachedArguments;
    private Any cachedSendingException;
    // key = Integer, value = IOP.ServiceContext.
    private HashMap cachedRequestServiceContexts;
    // key = Integer, value = IOP.ServiceContext.
    private HashMap cachedReplyServiceContexts;

    //////////////////////////////////////////////////////////////////////
    //
    // NOTE: IF AN ATTRIBUTE IS ADDED, PLEASE UPDATE RESET();
    //
    //////////////////////////////////////////////////////////////////////


    /**
     * Reset the info object so that it can be reused for a retry,
     * for example.
     */
    void reset() {
        super.reset();

        // Please keep these in the same order as declared above.

        forwardRequestRaisedInEnding = false;

        request = null;
        servant = null;
        objectId = null;
        oktemp = null;

        adapterId = null;
        adapterName = null;

        addReplyServiceContextQueue = null;
        replyMessage = null;
        targetMostDerivedInterface = null;
        dsiArguments = null;
        dsiResult = null;
        dsiException = null;
        isDynamic = false;
        objectAdapter = null;
        serverRequestId = myORB.getPIHandler().allocateServerRequestId();

        // reset cached attributes:
        cachedArguments = null;
        cachedSendingException = null;
        cachedRequestServiceContexts = null;
        cachedReplyServiceContexts = null;

        startingPointCall = CALL_RECEIVE_REQUEST_SERVICE_CONTEXT;
        intermediatePointCall = CALL_RECEIVE_REQUEST;
        endingPointCall = CALL_SEND_REPLY;
    }

    /*
     **********************************************************************
     * Access protection
     **********************************************************************/

    // Method IDs for all methods in ServerRequestInfo.  This allows for a
    // convenient O(1) lookup for checkAccess().
    protected static final int MID_SENDING_EXCEPTION       = MID_RI_LAST +  1;
    protected static final int MID_OBJECT_ID               = MID_RI_LAST +  2;
    protected static final int MID_ADAPTER_ID              = MID_RI_LAST +  3;
    protected static final int MID_TARGET_MOST_DERIVED_INTERFACE
                                                           = MID_RI_LAST +  4;
    protected static final int MID_GET_SERVER_POLICY       = MID_RI_LAST +  5;
    protected static final int MID_SET_SLOT                = MID_RI_LAST +  6;
    protected static final int MID_TARGET_IS_A             = MID_RI_LAST +  7;
    protected static final int MID_ADD_REPLY_SERVICE_CONTEXT
                                                           = MID_RI_LAST +  8;
    protected static final int MID_SERVER_ID               = MID_RI_LAST +  9;
    protected static final int MID_ORB_ID                  = MID_RI_LAST +  10;
    protected static final int MID_ADAPTER_NAME            = MID_RI_LAST +  11;

    // ServerRequestInfo validity table (see ptc/00-08-06 table 21-2).
    // Note: These must be in the same order as specified in contants.
    private static final boolean validCall[][] = {
        // LEGEND:
        // r_rsc = receive_request_service_contexts
        // r_req = receive_request
        // s_rep = send_reply
        // s_exc = send_exception
        // s_oth = send_other
        //
        // A true value indicates call is valid at specified point.
        // A false value indicates the call is invalid.
        //
        // NOTE: If the order or number of columns change, update
        // checkAccess() accordingly.
        //
        //                              { r_rsc, r_req, s_rep, s_exc, s_oth }
        // RequestInfo methods:
        /*request_id*/                  { true , true , true , true , true  },
        /*operation*/                   { true , true , true , true , true  },
        /*arguments*/                   { false, true , true , false, false },
        /*exceptions*/                  { false, true , true , true , true  },
        /*contexts*/                    { false, true , true , true , true  },
        /*operation_context*/           { false, true , true , false, false },
        /*result*/                      { false, false, true , false, false },
        /*response_expected*/           { true , true , true , true , true  },
        /*sync_scope*/                  { true , true , true , true , true  },
        /*reply_status*/                { false, false, true , true , true  },
        /*forward_reference*/           { false, false, false, false, true  },
        /*get_slot*/                    { true , true , true , true , true  },
        /*get_request_service_context*/ { true , true , true , true , true  },
        /*get_reply_service_context*/   { false, false, true , true , true  },
        //
        // ServerRequestInfo methods::
        /*sending_exception*/           { false, false, false, true , false },
        /*object_id*/                   { false, true , true , true , true  },
        /*adapter_id*/                  { false, true , true , true , true  },
        /*target_most_derived_inte...*/ { false, true , false, false, false },
        /*get_server_policy*/           { true , true , true , true , true  },
        /*set_slot*/                    { true , true , true , true , true  },
        /*target_is_a*/                 { false, true , false, false, false },
        /*add_reply_service_context*/   { true , true , true , true , true  },
        /*orb_id*/                      { false, true , true , true , true  },
        /*server_id*/                   { false, true , true , true , true  },
        /*adapter_name*/                { false, true , true , true , true  }
    };

    /*
     **********************************************************************
     * Public interfaces
     **********************************************************************/

    /**
     * Creates a new ServerRequestInfo implementation.
     * The constructor is package scope since no other package need create
     * an instance of this class.
     */
    ServerRequestInfoImpl( ORB myORB ) {
        super( myORB );
        startingPointCall = CALL_RECEIVE_REQUEST_SERVICE_CONTEXT;
        intermediatePointCall = CALL_RECEIVE_REQUEST;
        endingPointCall = CALL_SEND_REPLY;
        serverRequestId = myORB.getPIHandler().allocateServerRequestId();
    }

    /**
     * Any containing the exception to be returned to the client.
     */
    public Any sending_exception () {
        checkAccess( MID_SENDING_EXCEPTION );

        if( cachedSendingException == null ) {
            Any result = null ;

            if( dsiException != null ) {
                result = dsiException;
            } else if( exception != null ) {
                result = exceptionToAny( exception );
            } else {
                // sending_exception should not be callable if both dsiException
                // and exception are null.
                throw wrapper.exceptionUnavailable() ;
            }

            cachedSendingException = result;
        }

        return cachedSendingException;
    }

    /**
     * The opaque object_id describing the target of the operation invocation.
     */
    public byte[] object_id () {
        checkAccess( MID_OBJECT_ID );

        if( objectId == null ) {
            // For some reason, we never set object id.  This could be
            // because a servant locator caused a location forward or
            // raised an exception.  As per ptc/00-08-06, section 21.3.14,
            // we throw NO_RESOURCES
            throw stdWrapper.piOperationNotSupported6() ;
        }

        // Good citizen: In the interest of efficiency, we will assume
        // interceptors will not change the resulting byte[] array.
        // Otherwise, we would need to make a clone of this array.

        return objectId;
    }

    private void checkForNullTemplate()
    {
        if (oktemp == null) {
            // For some reason, we never set the ObjectKeyTemplate
            // because a servant locator caused a location forward or
            // raised an exception.  As per ptc/00-08-06, section 21.3.14,
            // we throw NO_RESOURCES
            throw stdWrapper.piOperationNotSupported7() ;
        }
    }

    public String server_id()
    {
        checkAccess( MID_SERVER_ID ) ;
        checkForNullTemplate() ;

        // Good citizen: In the interest of efficiency, we will assume
        // interceptors will not change the resulting byte[] array.
        // Otherwise, we would need to make a clone of this array.

        return Integer.toString( oktemp.getServerId() ) ;
    }

    public String orb_id()
    {
        checkAccess( MID_ORB_ID ) ;

        return myORB.getORBData().getORBId() ;
    }

    synchronized public String[] adapter_name()
    {
        checkAccess( MID_ADAPTER_NAME ) ;

        if (adapterName == null) {
            checkForNullTemplate() ;

            ObjectAdapterId oaid = oktemp.getObjectAdapterId() ;
            adapterName = oaid.getAdapterName() ;
        }

        return adapterName ;
    }

    /**
     * The opaque identifier for the object adapter.
     */
    synchronized public byte[] adapter_id ()
    {
        checkAccess( MID_ADAPTER_ID );

        if( adapterId == null ) {
            checkForNullTemplate() ;
            adapterId = oktemp.getAdapterId() ;
        }

        return adapterId;
    }

    /**
     * The RepositoryID for the most derived interface of the servant.
     */
    public String target_most_derived_interface () {
        checkAccess( MID_TARGET_MOST_DERIVED_INTERFACE );
        return targetMostDerivedInterface;
    }

    /**
     * Returns the policy in effect for this operation for the given policy
     * type.
     */
    public Policy get_server_policy (int type) {
        // access is currently valid for all states:
        //checkAccess( MID_GET_SERVER_POLICY );

        Policy result = null;

        if( objectAdapter != null ) {
            result = objectAdapter.getEffectivePolicy( type );
        }

        // _REVISIT_ RTF Issue: get_server_policy spec not in sync with
        // get_effective_policy spec.

        return result;
    }

    /**
     * Allows an Interceptor to set a slot in the Current that is in the scope
     * of the request.  If data already exists in that slot, it will be
     * overwritten.  If the ID does not define an allocated slot, InvalidSlot
     * is raised.
     */
    public void set_slot (int id, Any data) throws InvalidSlot {
        // access is currently valid for all states:
        //checkAccess( MID_SET_SLOT );

        slotTable.set_slot( id, data );
    }

    /**
     * Returns true if the servant is the given RepositoryId, false if it is
     * not.
     */
    public boolean target_is_a (String id) {
        checkAccess( MID_TARGET_IS_A );

        boolean result = false ;
        if( servant instanceof Servant ) {
            result = ((Servant)servant)._is_a( id );
        } else if (StubAdapter.isStub( servant )) {
            result = ((org.omg.CORBA.Object)servant)._is_a( id );
        } else {
            throw wrapper.servantInvalid() ;
        }

        return result;
    }

    /**
     * Allows Interceptors to add service contexts to the request.
     */
    public void add_reply_service_context ( ServiceContext service_context,
                                            boolean replace )
    {
        // access is currently valid for all states:
        //checkAccess( MID_ADD_REPLY_SERVICE_CONTEXT );

        if( currentExecutionPoint == EXECUTION_POINT_ENDING ) {
            ServiceContexts scs = replyMessage.getServiceContexts();

            // May be null.  If this is null, create a new one in its place.
            if( scs == null ) {
                scs = new ServiceContexts( myORB );
                replyMessage.setServiceContexts( scs );
            }

            if( cachedReplyServiceContexts == null ) {
                cachedReplyServiceContexts = new HashMap();
            }

            // This is during and ending point, so we now have enough
            // information to add the reply service context.
            addServiceContext( cachedReplyServiceContexts, scs,
                               service_context, replace );
        }

        // We enqueue all adds for the following reasons:
        //
        // If we are not in the ending point then we do not yet have a
        // pointer to the ServiceContexts object so we cannot access the
        // service contexts until we get to the ending point.
        // So we enqueue this add reply service context request.
        // It is added when we do have a handle on the service contexts object.
        //
        // If we are in the ending point and we just add directly to the
        // SC container but then an interceptor raises a SystemException
        // then that add will be lost since a new container is created
        // for the SystemException response.
        //
        // Therefore we always enqueue and never dequeue (per request) so
        // that all adds will be completed.

        AddReplyServiceContextCommand addReply =
            new AddReplyServiceContextCommand();
        addReply.service_context = service_context;
        addReply.replace = replace;

        if( addReplyServiceContextQueue == null ) {
            addReplyServiceContextQueue = new ArrayList();
        }

        // REVISIT: this does not add to the cache.
        enqueue( addReply );
    }

    // NOTE: When adding a method, be sure to:
    // 1. Add a MID_* constant for that method
    // 2. Call checkAccess at the start of the method
    // 3. Define entries in the validCall[][] table for interception points.

    /*
     **********************************************************************
     * Public RequestInfo interfaces
     *
     * These are implemented here because they have differing
     * implementations depending on whether this is a client or a server
     * request info object.
     **********************************************************************/

    /**
     * See ServerRequestInfo for javadocs.
     */
    public int request_id (){
        // access is currently valid for all states:
        //checkAccess( MID_REQUEST_ID );
        /*
         * NOTE: The request id in server interceptors is NOT the
         * same as the GIOP request id.  The ORB may be servicing several
         * connections, each with possibly overlapping sets of request ids.
         * Therefore we create a request id specific to interceptors.
         */
        return serverRequestId;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public String operation (){
        // access is currently valid for all states:
        //checkAccess( MID_OPERATION );
        return request.getOperationName();
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public Parameter[] arguments (){
        checkAccess( MID_ARGUMENTS );

        if( cachedArguments == null ) {
            if( !isDynamic ) {
                throw stdWrapper.piOperationNotSupported1() ;
            }

            if( dsiArguments == null ) {
                throw stdWrapper.piOperationNotSupported8() ;
            }

            // If it is a DSI request then get the arguments from the DSI req
            // and convert that into parameters.
            cachedArguments = nvListToParameterArray( dsiArguments );
        }

        // Good citizen: In the interest of efficiency, we assume
        // interceptors will be "good citizens" in that they will not
        // modify the contents of the Parameter[] array.  We also assume
        // they will not change the values of the containing Anys.

        return cachedArguments;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public TypeCode[] exceptions (){
        checkAccess( MID_EXCEPTIONS );

        // _REVISIT_ PI RTF Issue: No exception list on server side.

        throw stdWrapper.piOperationNotSupported2() ;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public String[] contexts (){
        checkAccess( MID_CONTEXTS );

        // We do not support this because our ORB does not send contexts.

        throw stdWrapper.piOperationNotSupported3() ;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public String[] operation_context (){
        checkAccess( MID_OPERATION_CONTEXT );

        // We do not support this because our ORB does not send
        // operation_context.

        throw stdWrapper.piOperationNotSupported4() ;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public Any result (){
        checkAccess( MID_RESULT );

        if( !isDynamic ) {
            throw stdWrapper.piOperationNotSupported5() ;
        }

        if( dsiResult == null ) {
            throw wrapper.piDsiResultIsNull() ;
        }

        // Good citizen: In the interest of efficiency, we assume that
        // interceptors will not modify the contents of the result Any.
        // Otherwise, we would need to create a deep copy of the Any.

        return dsiResult;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public boolean response_expected (){
        // access is currently valid for all states:
        //checkAccess( MID_RESPONSE_EXPECTED );
        return !request.isOneWay();
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public Object forward_reference (){
        checkAccess( MID_FORWARD_REFERENCE );
        // Check to make sure we are in LOCATION_FORWARD
        // state as per ptc/00-08-06, table 21-2
        // footnote 2.
        if( replyStatus != LOCATION_FORWARD.value ) {
            throw stdWrapper.invalidPiCall1() ;
        }

        return getForwardRequestException().forward;
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public org.omg.IOP.ServiceContext get_request_service_context( int id ) {
        checkAccess( MID_GET_REQUEST_SERVICE_CONTEXT );

        if( cachedRequestServiceContexts == null ) {
            cachedRequestServiceContexts = new HashMap();
        }

        return getServiceContext( cachedRequestServiceContexts,
                                  request.getRequestServiceContexts(), id );
    }

    /**
     * See ServerRequestInfo for javadocs.
     */
    public org.omg.IOP.ServiceContext get_reply_service_context( int id ) {
        checkAccess( MID_GET_REPLY_SERVICE_CONTEXT );

        if( cachedReplyServiceContexts == null ) {
            cachedReplyServiceContexts = new HashMap();
        }

        return getServiceContext( cachedReplyServiceContexts,
                                  replyMessage.getServiceContexts(), id );
    }

    /*
     **********************************************************************
     * Private-scope classes and methods
     **********************************************************************/

    // A command encapsulating a request to add a reply service context.
    // These commands are enqueued until we have a handle on the actual
    // reply service context, at which point they are executed.
    private class AddReplyServiceContextCommand {
        ServiceContext service_context;
        boolean replace;
    }

    // Adds the given add reply service context command to the queue of
    // such commands.  If a command is detected to have the same id as
    // the service context in this command, and replace is false,
    // BAD_INV_ORDER is thrown.  If replace is true, the original command
    // in the queue is replaced by this command.
    private void enqueue( AddReplyServiceContextCommand addReply ) {
        int size = addReplyServiceContextQueue.size();
        boolean found = false;

        for( int i = 0; i < size; i++ ) {
            AddReplyServiceContextCommand cmd =
                (AddReplyServiceContextCommand)
                addReplyServiceContextQueue.get( i );

            if( cmd.service_context.context_id ==
                addReply.service_context.context_id )
            {
                found = true;
                if( addReply.replace ) {
                    addReplyServiceContextQueue.set( i, addReply );
                } else {
                    throw stdWrapper.serviceContextAddFailed(
                        new Integer( cmd.service_context.context_id ) ) ;
                }
                break;
            }
        }

        if( !found ) {
            addReplyServiceContextQueue.add( addReply );
        }
    }

    /*
     **********************************************************************
     * Package and protected-scope methods
     **********************************************************************/

    /**
     * Overridden from RequestInfoImpl.  This version calls the super
     * and then, if we are changing to ending points, executes all
     * enqueued AddReplyServiceContextCommands.
     */
    protected void setCurrentExecutionPoint( int executionPoint ) {
        super.setCurrentExecutionPoint( executionPoint );

        // If we are transitioning to ending point, we will now have a pointer
        // to the reply service contexts, so we can execute all queued
        // add reply service context requests.
        if( (executionPoint == EXECUTION_POINT_ENDING) &&
            (addReplyServiceContextQueue != null) )
        {
            int size = addReplyServiceContextQueue.size();
            for( int i = 0; i < size; i++ ) {
                AddReplyServiceContextCommand addReply =
                    (AddReplyServiceContextCommand)
                    addReplyServiceContextQueue.get( i );
                try {
                    add_reply_service_context( addReply.service_context,
                                               addReply.replace );
                }
                catch( BAD_INV_ORDER e ) {
                    // _REVISIT_  The only way this can happen is if during
                    // rrsc or rr, the interceptor tried to add with
                    // replace=false to a service context that is present in
                    // the reply message.  At that time there was no way for
                    // us to check for this, so the best we can do is ignore
                    // the original request.
                }
            }

            // We specifically do not empty the SC queue so that if
            // the interceptor raises an exception the queued service contexts
            // will be put in the exception response.
        }
    }

    /**
     * Stores the various sources of information used for this info object.
     */
    protected void setInfo( CorbaMessageMediator request, ObjectAdapter oa,
        byte[] objectId, ObjectKeyTemplate oktemp )
    {
        this.request = request;
        this.objectId = objectId;
        this.oktemp = oktemp;
        this.objectAdapter = oa ;
        this.connection = (com.sun.corba.se.spi.legacy.connection.Connection)
            request.getConnection();
    }

    /**
     * Stores the various sources of information used for this info object.
     */
    protected void setDSIArguments( NVList arguments ) {
        this.dsiArguments = arguments;
    }

    /**
     * Stores the various sources of information used for this info object.
     */
    protected void setDSIException( Any exception ) {
        this.dsiException = exception;

        // Clear cached exception value:
        cachedSendingException = null;
    }

    /**
     * Stores the various sources of information used for this info object.
     */
    protected void setDSIResult( Any result ) {
        this.dsiResult = result;
    }

    /**
     * Sets the exception to be returned by received_exception and
     * received_exception_id.
     */
    protected void setException( Exception exception ) {
        super.setException( exception );

        // Make sure DSIException is null because this is the more recent one.
        this.dsiException = null;

        // Clear cached exception value:
        cachedSendingException = null;
    }

    /**
     * Stores the various sources of information used for this info object.
     */
    protected void setInfo( java.lang.Object servant,
                            String targetMostDerivedInterface )
    {
        this.servant = servant;
        this.targetMostDerivedInterface = targetMostDerivedInterface;
        this.isDynamic =
            (servant instanceof
            org.omg.PortableServer.DynamicImplementation) ||
            (servant instanceof org.omg.CORBA.DynamicImplementation);
    }

    /**
     * Set reply message
     */
    void setReplyMessage( ReplyMessage replyMessage ) {
        this.replyMessage = replyMessage;
    }

    /**
     * Overridden from RequestInfoImpl.  Calls the super class, then
     * sets the ending point call depending on the reply status.
     */
    protected void setReplyStatus( short replyStatus ) {
        super.setReplyStatus( replyStatus );
        switch( replyStatus ) {
        case SUCCESSFUL.value:
            endingPointCall = CALL_SEND_REPLY;
            break;
        case SYSTEM_EXCEPTION.value:
        case USER_EXCEPTION.value:
            endingPointCall = CALL_SEND_EXCEPTION;
            break;
        case LOCATION_FORWARD.value:
        case TRANSPORT_RETRY.value:
            endingPointCall = CALL_SEND_OTHER;
            break;
        }
    }

    /**
     * Release the servant object so the user has control over its lifetime.
     * Called after receive_request is finished executing.
     */
    void releaseServant() {
        this.servant = null;
    }

    /**
     * Sets the forwardRequestRaisedInEnding flag to true, indicating that
     * a server ending point has raised location forward at some point.
     */
    void setForwardRequestRaisedInEnding() {
        this.forwardRequestRaisedInEnding = true;
    }

    /**
     * Returns true if ForwardRequest was raised by a server ending point
     * or false otherwise.
     */
    boolean isForwardRequestRaisedInEnding() {
        return this.forwardRequestRaisedInEnding;
    }

    /**
     * Returns true if this is a dynamic invocation, or false if not
     */
    boolean isDynamic() {
      return this.isDynamic;
    }

    /**
     * See description for RequestInfoImpl.checkAccess
     */
    protected void checkAccess( int methodID )
    {
        // Make sure currentPoint matches the appropriate index in the
        // validCall table:
        int validCallIndex = 0;
        switch( currentExecutionPoint ) {
        case EXECUTION_POINT_STARTING:
            validCallIndex = 0;
            break;
        case EXECUTION_POINT_INTERMEDIATE:
            validCallIndex = 1;
            break;
        case EXECUTION_POINT_ENDING:
            switch( endingPointCall ) {
            case CALL_SEND_REPLY:
                validCallIndex = 2;
                break;
            case CALL_SEND_EXCEPTION:
                validCallIndex = 3;
                break;
            case CALL_SEND_OTHER:
                validCallIndex = 4;
                break;
            }
            break;
        }

        // Check the validCall table:
        if( !validCall[methodID][validCallIndex] ) {
            throw stdWrapper.invalidPiCall2() ;
        }
    }

}
