/*
 * Copyright (c) 1999, 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.iiop;

import org.omg.CORBA.SystemException;

import com.sun.corba.se.impl.core.ServerRequest;
import com.sun.corba.se.impl.core.ServiceContext;
import com.sun.corba.se.impl.core.DuplicateServiceContext;
import com.sun.corba.se.impl.core.UEInfoServiceContext;
import com.sun.corba.se.impl.core.ServiceContexts;
import com.sun.corba.se.impl.core.ServerResponse;
import com.sun.corba.se.impl.corba.IOR;
import com.sun.corba.se.impl.core.ORB;
import com.sun.corba.se.impl.orbutil.ORBUtility;  //d11638
import org.omg.CORBA.portable.UnknownException;
import org.omg.CORBA.UNKNOWN;
import org.omg.CORBA.CompletionStatus;
import com.sun.corba.se.impl.ior.ObjectKey;
import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
import com.sun.corba.se.impl.protocol.giopmsgheaders.RequestMessage;

class LocalServerRequestImpl extends IIOPInputStream implements ServerRequest {
    org.omg.CORBA.portable.OutputStream replyStream;
    org.omg.CORBA.portable.OutputStream exceptionReplyStream;

    LocalServerRequestImpl(ORB orb, byte[] buf, RequestMessage header)
    {
        super(orb, buf, header.getSize(), header.isLittleEndian(), header, null );

        this.request = header;
    }

    public int getRequestId() {
    	return request.getRequestId();
    }

    public boolean isOneWay() {
    	return !request.isResponseExpected();
    }

    public ServiceContexts getServiceContexts() {
    	return request.getServiceContexts();
    }

    public String getOperationName() {
    	return request.getOperation();
    }

    public ObjectKey getObjectKey() {
    	return request.getObjectKey();
    }

    public ServerResponse createResponse(ServiceContexts svc)
    {
    	return new LocalServerResponseImpl(this, svc);
    }

    public org.omg.CORBA.portable.OutputStream createReply() {
        if (replyStream == null) {
            replyStream = (org.omg.CORBA.portable.OutputStream)
                                createResponse(null);
        }
        return replyStream;
    }

    public org.omg.CORBA.portable.OutputStream createExceptionReply() {
        if (exceptionReplyStream == null) {
            exceptionReplyStream = (org.omg.CORBA.portable.OutputStream)
                                        createUserExceptionResponse(null);
        }
        return exceptionReplyStream;
    }

    public ServerResponse createUserExceptionResponse(
	ServiceContexts svc)
    {
    	return new LocalServerResponseImpl(this, svc, true);
    }

    public ServerResponse createUnknownExceptionResponse(
	        UnknownException ex) {
        ServiceContexts contexts = null;
        SystemException sys = new UNKNOWN( 0,
            CompletionStatus.COMPLETED_MAYBE);

            try {
                contexts = new ServiceContexts( (ORB)orb() );
                UEInfoServiceContext uei = new UEInfoServiceContext(sys);
                contexts.put(uei) ;
            } catch (DuplicateServiceContext d) {
            // can't happen
            }

        return createSystemExceptionResponse(sys,contexts);
    }

    public ServerResponse createSystemExceptionResponse(
    	SystemException ex, ServiceContexts svc) {

	// Only do this if interceptors have been initialized on this request
	// and have not completed their lifecycle (otherwise the info stack
	// may be empty or have a different request's entry on top).
	if (executePIInResponseConstructor()) {
	    // Inform Portable Interceptors of the SystemException.  This is
	    // required to be done here because the ending interception point
	    // is called in the ServerResponseImpl constructor called below
	    // but we do not currently write the SystemException into the
	    // response until after the ending point is called.
	    ORB orb = (ORB)orb();
	    orb.getPIHandler().setServerPIInfo( ex );
	}

	if (orb() != null && ((ORB)orb()).subcontractDebugFlag && ex != null)
            ORBUtility.dprint(this, "Sending SystemException:", ex);

        LocalServerResponseImpl response =
            new LocalServerResponseImpl(this, svc, false);
        ORBUtility.writeSystemException(ex, response);
        return response;
    }

    public ServerResponse createLocationForward(
	        IOR ior, ServiceContexts svc) {
        ReplyMessage reply = MessageBase.createReply( (ORB)orb(),
	    request.getGIOPVersion(), request.getRequestId(),
	    ReplyMessage.LOCATION_FORWARD, svc, ior);
        LocalServerResponseImpl response =
            new LocalServerResponseImpl(this, reply, ior);

        return response;
    }

    private RequestMessage request;

    /**
     * Check to see if the request is local.
     */
    public boolean isLocal(){
        return true;
    }

    private boolean _executeReturnServantInResponseConstructor = false;

    public boolean executeReturnServantInResponseConstructor()
    {
	return _executeReturnServantInResponseConstructor;
    }

    public void setExecuteReturnServantInResponseConstructor(boolean b)
    {
	_executeReturnServantInResponseConstructor = b;
    }

    
    private boolean _executeRemoveThreadInfoInResponseConstructor = false;

    public boolean executeRemoveThreadInfoInResponseConstructor()
    {
	return _executeRemoveThreadInfoInResponseConstructor;
    }

    public void setExecuteRemoveThreadInfoInResponseConstructor(boolean b)
    {
	_executeRemoveThreadInfoInResponseConstructor = b;
    }

    
    private boolean _executePIInResponseConstructor = false;
                                                            
    public boolean executePIInResponseConstructor() {
        return _executePIInResponseConstructor;
    }

    public void setExecutePIInResponseConstructor( boolean b ) {
        _executePIInResponseConstructor = b;
    }

    // We know that we're talking to the same ValueHandler, so
    // use the maximum version it supports.
    public byte getStreamFormatVersionForReply() {
        return ORBUtility.getMaxStreamFormatVersion();
    }
}
