/*
 * Copyright (c) 2002, 2013, 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 java.util.*;
import java.io.IOException;

import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.BAD_POLICY;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.NVList;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.UserException;
import org.omg.CORBA.UNKNOWN;

import org.omg.CORBA.portable.ApplicationException;
import org.omg.CORBA.portable.RemarshalException;

import org.omg.IOP.CodecFactory;

import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.Interceptor;
import org.omg.PortableInterceptor.LOCATION_FORWARD;
import org.omg.PortableInterceptor.ORBInitializer;
import org.omg.PortableInterceptor.ORBInitInfo;
import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
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.PolicyFactory;
import org.omg.PortableInterceptor.ObjectReferenceTemplate;

import com.sun.corba.se.pept.encoding.OutputObject;

import com.sun.corba.se.spi.ior.IOR;
import com.sun.corba.se.spi.ior.ObjectKeyTemplate;
import com.sun.corba.se.spi.oa.ObjectAdapter;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.orbutil.closure.ClosureFactory;
import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
import com.sun.corba.se.spi.protocol.ForwardException;
import com.sun.corba.se.spi.protocol.PIHandler;
import com.sun.corba.se.spi.protocol.RetryType;
import com.sun.corba.se.spi.logging.CORBALogDomains;

import com.sun.corba.se.impl.logging.InterceptorsSystemException;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.logging.OMGSystemException;
import com.sun.corba.se.impl.corba.RequestImpl;
import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.sun.corba.se.impl.orbutil.ORBUtility;
import com.sun.corba.se.impl.orbutil.StackImpl;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;

/**
 * Provides portable interceptor functionality.
 */
public class PIHandlerImpl implements PIHandler
{
    // REVISIT - delete these after framework merging.
    boolean printPushPopEnabled = false;
    int pushLevel = 0;
    private void printPush()
    {
        if (! printPushPopEnabled) return;
        printSpaces(pushLevel);
        pushLevel++;
        System.out.println("PUSH");
    }
    private void printPop()
    {
        if (! printPushPopEnabled) return;
        pushLevel--;
        printSpaces(pushLevel);
        System.out.println("POP");
    }
    private void printSpaces(int n)
    {
        for (int i = 0; i < n; i++) {
            System.out.print(" ");
        }
    }

    private ORB orb;
    InterceptorsSystemException wrapper;
    ORBUtilSystemException orbutilWrapper;
    OMGSystemException omgWrapper;

    // A unique id used in ServerRequestInfo.
    // This does not correspond to the GIOP request id.
    private int serverRequestIdCounter = 0;

    // Stores the codec factory for producing codecs
    CodecFactory codecFactory = null;

    // The arguments passed to the application's main method.  May be null.
    // This is used for ORBInitializers and set from set_parameters.
    String[] arguments = null;

    // The list of portable interceptors, organized by type:
    private InterceptorList interceptorList;

    // Cached information for optimization - do we have any interceptors
    // registered of the given types?  Set during ORB initialization.
    private boolean hasIORInterceptors;
    private boolean hasClientInterceptors;  // temp always true
    private boolean hasServerInterceptors;

    // The class responsible for invoking interceptors
    private InterceptorInvoker interceptorInvoker;

    // There will be one PICurrent instantiated for every ORB.
    private PICurrent current;

    // This table contains a list of PolicyFactories registered using
    // ORBInitInfo.registerPolicyFactory() method.
    // Key for the table is PolicyType which is an Integer
    // Value is PolicyFactory.
    private HashMap policyFactoryTable;

    // Table to convert from a ReplyMessage.? to a PI replyStatus short.
    // Note that this table relies on the order and constants of
    // ReplyMessage not to change.
    private final static short REPLY_MESSAGE_TO_PI_REPLY_STATUS[] = {
        SUCCESSFUL.value,       // = ReplyMessage.NO_EXCEPTION
        USER_EXCEPTION.value,   // = ReplyMessage.USER_EXCEPTION
        SYSTEM_EXCEPTION.value, // = ReplyMessage.SYSTEM_EXCEPTION
        LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD
        LOCATION_FORWARD.value, // = ReplyMessage.LOCATION_FORWARD_PERM
        TRANSPORT_RETRY.value   // = ReplyMessage.NEEDS_ADDRESSING_MODE
    };

    // ThreadLocal containing a stack to store client request info objects
    // and a disable count.
    private ThreadLocal threadLocalClientRequestInfoStack =
        new ThreadLocal() {
            protected Object initialValue() {
                return new RequestInfoStack();
            }
        };

    // ThreadLocal containing the current server request info object.
    private ThreadLocal threadLocalServerRequestInfoStack =
        new ThreadLocal() {
            protected Object initialValue() {
                return new RequestInfoStack();
            }
        };

    public void close() {
        orb = null;
        wrapper = null;
        orbutilWrapper = null;
        omgWrapper = null;
        codecFactory = null;
        arguments = null;
        interceptorList = null;
        interceptorInvoker = null;
        current = null;
        policyFactoryTable = null;
        threadLocalClientRequestInfoStack = null;
        threadLocalServerRequestInfoStack = null;
    }

    // Class to contain all ThreadLocal data for ClientRequestInfo
    // maintenance.
    //
    // We use an ArrayList instead since it is not thread-safe.
    // RequestInfoStack is used quite frequently.
    private final class RequestInfoStack extends Stack {
        // Number of times a request has been made to disable interceptors.
        // When this reaches 0, interception hooks are disabled.  Any higher
        // value indicates they are enabled.
        // NOTE: The is only currently used on the client side.
        public int disableCount = 0;
    }

    public PIHandlerImpl( ORB orb, String[] args ) {
        this.orb = orb ;
        wrapper = InterceptorsSystemException.get( orb,
            CORBALogDomains.RPC_PROTOCOL ) ;
        orbutilWrapper = ORBUtilSystemException.get( orb,
            CORBALogDomains.RPC_PROTOCOL ) ;
        omgWrapper = OMGSystemException.get( orb,
            CORBALogDomains.RPC_PROTOCOL ) ;
        arguments = args ;

        // Create codec factory:
        codecFactory = new CodecFactoryImpl( orb );

        // Create new interceptor list:
        interceptorList = new InterceptorList( wrapper );

        // Create a new PICurrent.
        current = new PICurrent( orb );

        // Create new interceptor invoker, initially disabled:
        interceptorInvoker = new InterceptorInvoker( orb, interceptorList,
                                                     current );

        // Register the PI current and Codec factory objects
        orb.getLocalResolver().register( ORBConstants.PI_CURRENT_NAME,
            ClosureFactory.makeConstant( current ) ) ;
        orb.getLocalResolver().register( ORBConstants.CODEC_FACTORY_NAME,
            ClosureFactory.makeConstant( codecFactory ) ) ;
    }

    public void initialize() {
        // If we have any orb initializers, make use of them:
        if( orb.getORBData().getORBInitializers() != null ) {
            // Create the ORBInitInfo object to pass to ORB intializers:
            ORBInitInfoImpl orbInitInfo = createORBInitInfo();

            // Make sure get_slot and set_slot are not called from within
            // ORB initializers:
            current.setORBInitializing( true );

            // Call pre_init on all ORB initializers:
            preInitORBInitializers( orbInitInfo );

            // Call post_init on all ORB initializers:
            postInitORBInitializers( orbInitInfo );

            // Proprietary: sort interceptors:
            interceptorList.sortInterceptors();

            // Re-enable get_slot and set_slot to be called from within
            // ORB initializers:
            current.setORBInitializing( false );

            // Ensure nobody makes any more calls on this object.
            orbInitInfo.setStage( ORBInitInfoImpl.STAGE_CLOSED );

            // Set cached flags indicating whether we have interceptors
            // registered of a given type.
            hasIORInterceptors = interceptorList.hasInterceptorsOfType(
                InterceptorList.INTERCEPTOR_TYPE_IOR );
            // XXX This must always be true, so that using the new generic
            // RPC framework can pass info between the PI stack and the
            // framework invocation stack.  Temporary until Harold fixes
            // this.  Note that this must never be true until after the
            // ORBInitializer instances complete executing.
            //hasClientInterceptors = interceptorList.hasInterceptorsOfType(
                //InterceptorList.INTERCEPTOR_TYPE_CLIENT );
            hasClientInterceptors = true;
            hasServerInterceptors = interceptorList.hasInterceptorsOfType(
                InterceptorList.INTERCEPTOR_TYPE_SERVER );

            // Enable interceptor invoker (not necessary if no interceptors
            // are registered).  This should be the last stage of ORB
            // initialization.
            interceptorInvoker.setEnabled( true );
        }
    }

    /**
     *  ptc/00-08-06 p 205: "When an application calls ORB::destroy, the ORB
     *  1) waits for all requests in progress to complete
     *  2) calls the Interceptor::destroy operation for each interceptor
     *  3) completes destruction of the ORB"
     *
     * This must be called at the end of ORB.destroy.  Note that this is not
     * part of the PIHandler interface, since ORBImpl implements the ORB interface.
     */
    public void destroyInterceptors() {
        interceptorList.destroyAll();
    }

    public void objectAdapterCreated( ObjectAdapter oa )
    {
        if (!hasIORInterceptors)
            return ;

        interceptorInvoker.objectAdapterCreated( oa ) ;
    }

    public void adapterManagerStateChanged( int managerId,
        short newState )
    {
        if (!hasIORInterceptors)
            return ;

        interceptorInvoker.adapterManagerStateChanged( managerId, newState ) ;
    }

    public void adapterStateChanged( ObjectReferenceTemplate[]
        templates, short newState )
    {
        if (!hasIORInterceptors)
            return ;

        interceptorInvoker.adapterStateChanged( templates, newState ) ;
    }

    /*
     *****************
     * Client PI hooks
     *****************/

    public void disableInterceptorsThisThread() {
        if( !hasClientInterceptors ) return;

        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalClientRequestInfoStack.get();
        infoStack.disableCount++;
    }

    public void enableInterceptorsThisThread() {
        if( !hasClientInterceptors ) return;

        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalClientRequestInfoStack.get();
        infoStack.disableCount--;
    }

    public void invokeClientPIStartingPoint()
        throws RemarshalException
    {
        if( !hasClientInterceptors ) return;
        if( !isClientPIEnabledForThisThread() ) return;

        // Invoke the starting interception points and record exception
        // and reply status info in the info object:
        ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
        interceptorInvoker.invokeClientInterceptorStartingPoint( info );

        // Check reply status.  If we will not have another chance later
        // to invoke the client ending points, do it now.
        short replyStatus = info.getReplyStatus();
        if( (replyStatus == SYSTEM_EXCEPTION.value) ||
            (replyStatus == LOCATION_FORWARD.value) )
        {
            // Note: Transport retry cannot happen here since this happens
            // before the request hits the wire.

            Exception exception = invokeClientPIEndingPoint(
                convertPIReplyStatusToReplyMessage( replyStatus ),
                info.getException() );
            if( exception == null ) {
                // Do not throw anything.  Otherwise, it must be a
                // SystemException, UserException or RemarshalException.
            } if( exception instanceof SystemException ) {
                throw (SystemException)exception;
            } else if( exception instanceof RemarshalException ) {
                throw (RemarshalException)exception;
            } else if( (exception instanceof UserException) ||
                     (exception instanceof ApplicationException) ) {
                // It should not be possible for an interceptor to throw
                // a UserException.  By asserting instead of throwing the
                // UserException, we need not declare anything but
                // RemarshalException in the throws clause.
                throw wrapper.exceptionInvalid() ;
            }
        }
        else if( replyStatus != ClientRequestInfoImpl.UNINITIALIZED ) {
            throw wrapper.replyStatusNotInit() ;
        }
    }

    // Needed when an error forces a retry AFTER initiateClientPIRequest
    // but BEFORE invokeClientPIStartingPoint.
    public Exception makeCompletedClientRequest( int replyStatus,
        Exception exception ) {

        // 6763340
        return handleClientPIEndingPoint( replyStatus, exception, false ) ;
    }

    public Exception invokeClientPIEndingPoint( int replyStatus,
        Exception exception ) {

        // 6763340
        return handleClientPIEndingPoint( replyStatus, exception, true ) ;
    }

    public Exception handleClientPIEndingPoint(
        int replyStatus, Exception exception, boolean invokeEndingPoint ) {
        if( !hasClientInterceptors ) return exception;
        if( !isClientPIEnabledForThisThread() ) return exception;

        // Translate ReplyMessage.replyStatus into PI replyStatus:
        // Note: this is also an assertion to make sure a valid replyStatus
        // is passed in (IndexOutOfBoundsException will be thrown otherwise)
        short piReplyStatus = REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];

        // Invoke the ending interception points and record exception
        // and reply status info in the info object:
        ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
        info.setReplyStatus( piReplyStatus );
        info.setException( exception );

        if (invokeEndingPoint) {
            // 6763340
            interceptorInvoker.invokeClientInterceptorEndingPoint( info );
            piReplyStatus = info.getReplyStatus();
        }

        // Check reply status:
        if( (piReplyStatus == LOCATION_FORWARD.value) ||
            (piReplyStatus == TRANSPORT_RETRY.value) ) {
            // If this is a forward or a retry, reset and reuse
            // info object:
            info.reset();

            // fix for 6763340:
            if (invokeEndingPoint) {
                info.setRetryRequest( RetryType.AFTER_RESPONSE ) ;
            } else {
                info.setRetryRequest( RetryType.BEFORE_RESPONSE ) ;
            }

            // ... and return a RemarshalException so the orb internals know
            exception = new RemarshalException();
        } else if( (piReplyStatus == SYSTEM_EXCEPTION.value) ||
                 (piReplyStatus == USER_EXCEPTION.value) ) {
            exception = info.getException();
        }

        return exception;
    }

    public void initiateClientPIRequest( boolean diiRequest ) {
        if( !hasClientInterceptors ) return;
        if( !isClientPIEnabledForThisThread() ) return;

        // Get the most recent info object from the thread local
        // ClientRequestInfoImpl stack:
        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalClientRequestInfoStack.get();
        ClientRequestInfoImpl info = null;

        if (!infoStack.empty() ) {
            info = (ClientRequestInfoImpl)infoStack.peek();
        }

        if (!diiRequest && (info != null) && info.isDIIInitiate() ) {
            // In RequestImpl.doInvocation we already called
            // initiateClientPIRequest( true ), so ignore this initiate.
            info.setDIIInitiate( false );
        } else {
            // If there is no info object or if we are not retrying a request,
            // push a new ClientRequestInfoImpl on the stack:

            // 6763340: don't push unless this is not a retry
            if( (info == null) || !info.getRetryRequest().isRetry() ) {
                info = new ClientRequestInfoImpl( orb );
                infoStack.push( info );
                printPush();
                // Note: the entry count is automatically initialized to 0.
            }

            // Reset the retry request flag so that recursive calls will
            // push a new info object, and bump up entry count so we know
            // when to pop this info object:
            info.setRetryRequest( RetryType.NONE );
            info.incrementEntryCount();

            // KMC 6763340: I don't know why this wasn't set earlier,
            // but we do not want a retry to pick up the previous
            // reply status, so clear it here.  Most likely a new
            // info was pushed before, so that this was not a problem.
            info.setReplyStatus( RequestInfoImpl.UNINITIALIZED ) ;

            // If this is a DII request, make sure we ignore the next initiate.
            if( diiRequest ) {
                info.setDIIInitiate( true );
            }
        }
    }

    public void cleanupClientPIRequest() {
        if( !hasClientInterceptors ) return;
        if( !isClientPIEnabledForThisThread() ) return;

        ClientRequestInfoImpl info = peekClientRequestInfoImplStack();
        RetryType rt = info.getRetryRequest() ;

        // fix for 6763340
        if (!rt.equals( RetryType.BEFORE_RESPONSE )) {

            // If the replyStatus has not yet been set, this is an indication
            // that the ORB threw an exception before we had a chance to
            // invoke the client interceptor ending points.
            //
            // _REVISIT_ We cannot handle any exceptions or ForwardRequests
            // flagged by the ending points here because there is no way
            // to gracefully handle this in any of the calling code.
            // This is a rare corner case, so we will ignore this for now.
            short replyStatus = info.getReplyStatus();
            if (replyStatus == info.UNINITIALIZED ) {
                invokeClientPIEndingPoint( ReplyMessage.SYSTEM_EXCEPTION,
                    wrapper.unknownRequestInvoke(
                        CompletionStatus.COMPLETED_MAYBE ) ) ;
            }
        }

        // Decrement entry count, and if it is zero, pop it from the stack.
        info.decrementEntryCount();

        // fix for 6763340, and probably other cases (non-recursive retry)
        if (info.getEntryCount() == 0 && !info.getRetryRequest().isRetry()) {
            // RequestInfoStack<ClientRequestInfoImpl> infoStack =
            //     threadLocalClientRequestInfoStack.get();
            RequestInfoStack infoStack =
                (RequestInfoStack)threadLocalClientRequestInfoStack.get();
            infoStack.pop();
            printPop();
        }
    }

    public void setClientPIInfo(CorbaMessageMediator messageMediator)
    {
        if( !hasClientInterceptors ) return;
        if( !isClientPIEnabledForThisThread() ) return;

        peekClientRequestInfoImplStack().setInfo(messageMediator);
    }

    public void setClientPIInfo( RequestImpl requestImpl ) {
        if( !hasClientInterceptors ) return;
        if( !isClientPIEnabledForThisThread() ) return;

        peekClientRequestInfoImplStack().setDIIRequest( requestImpl );
    }

    /*
     *****************
     * Server PI hooks
     *****************/

    public void invokeServerPIStartingPoint()
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        interceptorInvoker.invokeServerInterceptorStartingPoint( info );

        // Handle SystemException or ForwardRequest:
        serverPIHandleExceptions( info );
    }

    public void invokeServerPIIntermediatePoint()
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        interceptorInvoker.invokeServerInterceptorIntermediatePoint( info );

        // Clear servant from info object so that the user has control over
        // its lifetime:
        info.releaseServant();

        // Handle SystemException or ForwardRequest:
        serverPIHandleExceptions( info );
    }

    public void invokeServerPIEndingPoint( ReplyMessage replyMessage )
    {
        if( !hasServerInterceptors ) return;
        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();

        // REVISIT: This needs to be done "early" for the following workaround.
        info.setReplyMessage( replyMessage );

        // REVISIT: This was done inside of invokeServerInterceptorEndingPoint
        // but needs to be here for now.  See comment in that method for why.
        info.setCurrentExecutionPoint( info.EXECUTION_POINT_ENDING );

        // It is possible we might have entered this method more than
        // once (e.g. if an ending point threw a SystemException, then
        // a new ServerResponseImpl is created).
        if( !info.getAlreadyExecuted() ) {
            int replyStatus = replyMessage.getReplyStatus();

            // Translate ReplyMessage.replyStatus into PI replyStatus:
            // Note: this is also an assertion to make sure a valid
            // replyStatus is passed in (IndexOutOfBoundsException will be
            // thrown otherwise)
            short piReplyStatus =
                REPLY_MESSAGE_TO_PI_REPLY_STATUS[replyStatus];

            // Make forwarded IOR available to interceptors, if applicable:
            if( ( piReplyStatus == LOCATION_FORWARD.value ) ||
                ( piReplyStatus == TRANSPORT_RETRY.value ) )
            {
                info.setForwardRequest( replyMessage.getIOR() );
            }

            // REVISIT: Do early above for now.
            // Make reply message available to interceptors:
            //info.setReplyMessage( replyMessage );

            // Remember exception so we can tell if an interceptor changed it.
            Exception prevException = info.getException();

            // _REVISIT_ We do not have access to the User Exception at
            // this point, so treat it as an UNKNOWN for now.
            // Note that if this is a DSI call, we do have the user exception.
            if( !info.isDynamic() &&
                (piReplyStatus == USER_EXCEPTION.value) )
            {
                info.setException( omgWrapper.unknownUserException(
                    CompletionStatus.COMPLETED_MAYBE ) ) ;
            }

            // Invoke the ending interception points:
            info.setReplyStatus( piReplyStatus );
            interceptorInvoker.invokeServerInterceptorEndingPoint( info );
            short newPIReplyStatus = info.getReplyStatus();
            Exception newException = info.getException();

            // Check reply status.  If an interceptor threw a SystemException
            // and it is different than the one that we came in with,
            // rethrow it so the proper response can be constructed:
            if( ( newPIReplyStatus == SYSTEM_EXCEPTION.value ) &&
                ( newException != prevException ) )
            {
                throw (SystemException)newException;
            }

            // If we are to forward the location:
            if( newPIReplyStatus == LOCATION_FORWARD.value ) {
                if( piReplyStatus != LOCATION_FORWARD.value ) {
                    // Treat a ForwardRequest as a ForwardException.
                    IOR ior = info.getForwardRequestIOR();
                    throw new ForwardException( orb, ior ) ;
                }
                else if( info.isForwardRequestRaisedInEnding() ) {
                    // Treat a ForwardRequest by changing the IOR.
                    replyMessage.setIOR( info.getForwardRequestIOR() );
                }
            }
        }
    }

    public void setServerPIInfo( Exception exception ) {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        info.setException( exception );
    }

    public void setServerPIInfo( NVList arguments )
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        info.setDSIArguments( arguments );
    }

    public void setServerPIExceptionInfo( Any exception )
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        info.setDSIException( exception );
    }

    public void setServerPIInfo( Any result )
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        info.setDSIResult( result );
    }

    public void initializeServerPIInfo( CorbaMessageMediator request,
        ObjectAdapter oa, byte[] objectId, ObjectKeyTemplate oktemp )
    {
        if( !hasServerInterceptors ) return;

        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalServerRequestInfoStack.get();
        ServerRequestInfoImpl info = new ServerRequestInfoImpl( orb );
        infoStack.push( info );
        printPush();

        // Notify request object that once response is constructed, make
        // sure we execute ending points.
        request.setExecutePIInResponseConstructor( true );

        info.setInfo( request, oa, objectId, oktemp );
    }

    public void setServerPIInfo( java.lang.Object servant,
                                          String targetMostDerivedInterface )
    {
        if( !hasServerInterceptors ) return;

        ServerRequestInfoImpl info = peekServerRequestInfoImplStack();
        info.setInfo( servant, targetMostDerivedInterface );
    }

    public void cleanupServerPIRequest() {
        if( !hasServerInterceptors ) return;

        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalServerRequestInfoStack.get();
        infoStack.pop();
        printPop();
    }

    /*
     **********************************************************************
     *  The following methods are private utility methods.
     ************************************************************************/

    /**
     * Handles exceptions for the starting and intermediate points for
     * server request interceptors.  This is common code that has been
     * factored out into this utility method.
     * <p>
     * This method will NOT work for ending points.
     */
    private void serverPIHandleExceptions( ServerRequestInfoImpl info )
    {
        int endingPointCall = info.getEndingPointCall();
        if(endingPointCall == ServerRequestInfoImpl.CALL_SEND_EXCEPTION) {
            // If a system exception was thrown, throw it to caller:
            throw (SystemException)info.getException();
        }
        else if( (endingPointCall == ServerRequestInfoImpl.CALL_SEND_OTHER) &&
                 (info.getForwardRequestException() != null) )
        {
            // If an interceptor throws a forward request, convert it
            // into a ForwardException for easier handling:
            IOR ior = info.getForwardRequestIOR();
            throw new ForwardException( orb, ior );
        }
    }

    /**
     * Utility method to convert a PI reply status short to a ReplyMessage
     * constant.  This is a reverse lookup on the table defined in
     * REPLY_MESSAGE_TO_PI_REPLY_STATUS.  The reverse lookup need not be
     * performed as quickly since it is only executed in exception
     * conditions.
     */
    private int convertPIReplyStatusToReplyMessage( short replyStatus ) {
        int result = 0;
        for( int i = 0; i < REPLY_MESSAGE_TO_PI_REPLY_STATUS.length; i++ ) {
            if( REPLY_MESSAGE_TO_PI_REPLY_STATUS[i] == replyStatus ) {
                result = i;
                break;
            }
        }
        return result;
    }

    /**
     * Convenience method to get the ClientRequestInfoImpl object off the
     * top of the ThreadLocal stack.  Throws an INTERNAL exception if
     * the Info stack is empty.
     */
    private ClientRequestInfoImpl peekClientRequestInfoImplStack() {
        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalClientRequestInfoStack.get();
        ClientRequestInfoImpl info = null;
        if( !infoStack.empty() ) {
            info = (ClientRequestInfoImpl)infoStack.peek();
        } else {
            throw wrapper.clientInfoStackNull() ;
        }

        return info;
    }

    /**
     * Convenience method to get the ServerRequestInfoImpl object off the
     * top of the ThreadLocal stack.  Returns null if there are none.
     */
    private ServerRequestInfoImpl peekServerRequestInfoImplStack() {
        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalServerRequestInfoStack.get();
        ServerRequestInfoImpl info = null;

        if( !infoStack.empty() ) {
            info = (ServerRequestInfoImpl)infoStack.peek();
        } else {
            throw wrapper.serverInfoStackNull() ;
        }

        return info;
    }

    /**
     * Convenience method to determine whether Client PI is enabled
     * for requests on this thread.
     */
    private boolean isClientPIEnabledForThisThread() {
        RequestInfoStack infoStack =
            (RequestInfoStack)threadLocalClientRequestInfoStack.get();
        return (infoStack.disableCount == 0);
    }

    /**
     * Call pre_init on all ORB initializers
     */
    private void preInitORBInitializers( ORBInitInfoImpl info ) {

        // Inform ORBInitInfo we are in pre_init stage
        info.setStage( ORBInitInfoImpl.STAGE_PRE_INIT );

        // Step through each initializer instantiation and call its
        // pre_init.  Ignore any exceptions.
        for( int i = 0; i < orb.getORBData().getORBInitializers().length;
            i++ ) {
            ORBInitializer init = orb.getORBData().getORBInitializers()[i];
            if( init != null ) {
                try {
                    init.pre_init( info );
                }
                catch( Exception e ) {
                    // As per orbos/99-12-02, section 9.3.1.2, "If there are
                    // any exceptions, the ORB shall ignore them and proceed."
                }
            }
        }
    }

    /**
     * Call post_init on all ORB initializers
     */
    private void postInitORBInitializers( ORBInitInfoImpl info ) {

        // Inform ORBInitInfo we are in post_init stage
        info.setStage( ORBInitInfoImpl.STAGE_POST_INIT );

        // Step through each initializer instantiation and call its post_init.
        // Ignore any exceptions.
        for( int i = 0; i < orb.getORBData().getORBInitializers().length;
            i++ ) {
            ORBInitializer init = orb.getORBData().getORBInitializers()[i];
            if( init != null ) {
                try {
                    init.post_init( info );
                }
                catch( Exception e ) {
                    // As per orbos/99-12-02, section 9.3.1.2, "If there are
                    // any exceptions, the ORB shall ignore them and proceed."
                }
            }
        }
    }

    /**
     * Creates the ORBInitInfo object to be passed to ORB intializers'
     * pre_init and post_init methods
     */
    private ORBInitInfoImpl createORBInitInfo() {
        ORBInitInfoImpl result = null;

        // arguments comes from set_parameters.  May be null.

        // _REVISIT_ The spec does not specify which ID this is to be.
        // We currently get this from the corba.ORB, which reads it from
        // the ORB_ID_PROPERTY property.
        String orbId = orb.getORBData().getORBId() ;

        result = new ORBInitInfoImpl( orb, arguments, orbId, codecFactory );

        return result;
    }

    /**
     * Called by ORBInitInfo when an interceptor needs to be registered.
     * The type is one of:
     * <ul>
     *   <li>INTERCEPTOR_TYPE_CLIENT - ClientRequestInterceptor
     *   <li>INTERCEPTOR_TYPE_SERVER - ServerRequestInterceptor
     *   <li>INTERCEPTOR_TYPE_IOR - IORInterceptor
     * </ul>
     *
     * @exception DuplicateName Thrown if an interceptor of the given
     *     name already exists for the given type.
     */
    public void register_interceptor( Interceptor interceptor, int type )
        throws DuplicateName
    {
        // We will assume interceptor is not null, since it is called
        // internally.
        if( (type >= InterceptorList.NUM_INTERCEPTOR_TYPES) || (type < 0) ) {
            throw wrapper.typeOutOfRange( new Integer( type ) ) ;
        }

        String interceptorName = interceptor.name();

        if( interceptorName == null ) {
            throw wrapper.nameNull() ;
        }

        // Register with interceptor list:
        interceptorList.register_interceptor( interceptor, type );
    }

    public Current getPICurrent( ) {
        return current;
    }

    /**
     * Called when an invalid null parameter was passed.  Throws a
     * BAD_PARAM with a minor code of 1
     */
    private void nullParam()
        throws BAD_PARAM
    {
        throw orbutilWrapper.nullParam() ;
    }

    /** This is the implementation of standard API defined in org.omg.CORBA.ORB
     *  class. This method finds the Policy Factory for the given Policy Type
     *  and instantiates the Policy object from the Factory. It will throw
     *  PolicyError exception, If the PolicyFactory for the given type is
     *  not registered.
     *  _REVISIT_, Once Policy Framework work is completed, Reorganize
     *  this method to com.sun.corba.se.spi.orb.ORB.
     */
    public org.omg.CORBA.Policy create_policy(int type, org.omg.CORBA.Any val)
        throws org.omg.CORBA.PolicyError
    {
        if( val == null ) {
            nullParam( );
        }
        if( policyFactoryTable == null ) {
            throw new org.omg.CORBA.PolicyError(
                "There is no PolicyFactory Registered for type " + type,
                BAD_POLICY.value );
        }
        PolicyFactory factory = (PolicyFactory)policyFactoryTable.get(
            new Integer(type) );
        if( factory == null ) {
            throw new org.omg.CORBA.PolicyError(
                " Could Not Find PolicyFactory for the Type " + type,
                BAD_POLICY.value);
        }
        org.omg.CORBA.Policy policy = factory.create_policy( type, val );
        return policy;
    }

    /** This method registers the Policy Factory in the policyFactoryTable,
     *  which is a HashMap. This method is made package private, because
     *  it is used internally by the  Interceptors.
     */
    public void registerPolicyFactory( int type, PolicyFactory factory ) {
        if( policyFactoryTable == null ) {
            policyFactoryTable = new HashMap();
        }
        Integer key = new Integer( type );
        java.lang.Object val = policyFactoryTable.get( key );
        if( val == null ) {
            policyFactoryTable.put( key, factory );
        }
        else {
            throw omgWrapper.policyFactoryRegFailed( new Integer( type ) ) ;
        }
    }

    public synchronized int allocateServerRequestId ()
    {
        return serverRequestIdCounter++;
    }
}
