/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axis2.jaxws.server;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.engine.AxisEngine;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.core.InvocationContextFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.description.DescriptionFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.handler.AttachmentsAdapter;
import org.apache.axis2.jaxws.handler.MEPContext;
import org.apache.axis2.jaxws.handler.SOAPHeadersAdapter;
import org.apache.axis2.jaxws.handler.TransportHeadersAdapter;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.message.util.MessageUtils;
import org.apache.axis2.jaxws.registry.InvocationListenerRegistry;
import org.apache.axis2.jaxws.util.Constants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.ThreadContextMigratorUtil;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants;
import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2006Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.ws.Binding;
import javax.xml.ws.WebServiceException;

/**
 * The JAXWSMessageReceiver is the entry point, from the server's perspective, to the JAX-WS code.
 * This will be called by the Axis Engine and is the end of the chain from an Axis2 perspective.
 */
public class JAXWSMessageReceiver implements MessageReceiver {

    private static final Log log = LogFactory.getLog(JAXWSMessageReceiver.class);

    private static String PARAM_SERVICE_CLASS = "ServiceClass";
    public static String PARAM_BINDING = "Binding";

    /**
     * We should have already determined which AxisService we're targetting at this point.  So now,
     * just get the service implementation and invoke the appropriate method.
     * @param axisRequestMsgCtx
     * @throws org.apache.axis2.AxisFault
     */
    public void receive(org.apache.axis2.context.MessageContext axisRequestMsgCtx)
            throws AxisFault {
        AxisFault faultToReturn = null;

        if (log.isDebugEnabled()) {
            log.debug("new request received");
        }

        //Get the name of the service impl that was stored as a parameter
        // inside of the services.xml.
        AxisService service = axisRequestMsgCtx.getAxisService();
        
        org.apache.axis2.description.Parameter svcClassParam =
                service.getParameter(PARAM_SERVICE_CLASS);

        if (svcClassParam == null) {
            throw new RuntimeException(
                    Messages.getMessage("JAXWSMessageReceiverNoServiceClass"));
        }

        Parameter endpointDescParam =
                service.getParameter(EndpointDescription.AXIS_SERVICE_PARAMETER);
        if (endpointDescParam == null) {
            throw new RuntimeException(Messages.getMessage("JAXWSMessageReceiverNoServiceClass"));
        }
        AxisOperation operation = axisRequestMsgCtx.getAxisOperation();
        String mep = operation.getMessageExchangePattern();
        if (log.isDebugEnabled()) {
            log.debug("MEP: " + mep);
        }

        try {

            //This assumes that we are on the ultimate execution thread
            ThreadContextMigratorUtil.performMigrationToThread(
                    Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);

            //We'll need an instance of the EndpointController to actually
            //drive the invocation.
            //TODO: More work needed to determine the lifecycle of this thing
            EndpointController endpointCtlr = new EndpointController();

            MessageContext requestMsgCtx = new MessageContext(axisRequestMsgCtx);
            requestMsgCtx.setServer(true);
            requestMsgCtx.setMEPContext(new MEPContext(requestMsgCtx));
            ClassLoader loader = getCachedClassLoader(axisRequestMsgCtx);
            if (loader != null) {
                requestMsgCtx.setProperty(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER,
                        loader);
            }
            // The adapters need to be installed on the new request Message Context
            AttachmentsAdapter.install(requestMsgCtx);
            TransportHeadersAdapter.install(requestMsgCtx);
            SOAPHeadersAdapter.install(requestMsgCtx);
            
            Binding binding = (Binding)axisRequestMsgCtx.getProperty(PARAM_BINDING);
            EndpointInvocationContext eic = InvocationContextFactory.createEndpointInvocationContext(binding);
            addInvocationListenerFactories(eic);
            eic.setRequestMessageContext(requestMsgCtx);

            // WARNING: This should be left disabled for now.  This locks the server side
            // into a single threaded invocation.
            eic.getRequestMessageContext().setProperty(ServerConstants.SERVER_DISABLE_THREAD_SWITCH, true);

            if (isMepInOnly(mep)) {
                if (log.isDebugEnabled()) {
                    log.debug("Detected a one way invocation.");
                }
                eic.setIsOneWay(true);
                endpointCtlr.invokeOneWay(eic);
            } else if (JavaUtils.isTrueExplicitly(axisRequestMsgCtx.getProperty(
                AddressingConstants.IS_ADDR_INFO_ALREADY_PROCESSED))
                && (axisRequestMsgCtx.getReplyTo() != null
                && !axisRequestMsgCtx.getReplyTo().hasAnonymousAddress())) {
                
                if (log.isDebugEnabled()) {
                    log.debug("Detected an async invocation.");
                }
                
                EndpointCallback ecb = new EndpointCallback();
                eic.setCallback(ecb);
                
                endpointCtlr.invokeAsync(eic);
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Detected a sync invocation.");
                }
                eic = endpointCtlr.invoke(eic);

                // If this is a two-way exchange, there should already be a 
                // JAX-WS MessageContext for the response.  We need to pull 
                // the Message data out of there and set it on the Axis2 
                // MessageContext.
                MessageContext responseMsgCtx = eic.getResponseMessageContext();
                org.apache.axis2.context.MessageContext axisResponseMsgCtx =
                        responseMsgCtx.getAxisMessageContext();
                if (loader != null) {
                    responseMsgCtx.setProperty(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER,
                            loader);
                }
                MessageUtils.putMessageOnMessageContext(responseMsgCtx.getMessage(),
                                                        axisResponseMsgCtx);

                OperationContext opCtx = axisResponseMsgCtx.getOperationContext();
                opCtx.addMessageContext(axisResponseMsgCtx);

                // If this is a fault message, we want to throw it as an
                // exception so that the transport can do the appropriate things
                if (responseMsgCtx.getMessage().isFault()) {
                    
                    //Rather than create a new AxisFault, we should use the AxisFault that was
                    //created at the causedBy
                    if (responseMsgCtx.getCausedByException() != null)
                        faultToReturn = responseMsgCtx.getCausedByException();
                    else {
                        faultToReturn = new AxisFault("An error was detected during JAXWS processing",
                                                          axisResponseMsgCtx);
                    }
                } else {
                    //This assumes that we are on the ultimate execution thread
                    ThreadContextMigratorUtil.performMigrationToContext(
                            Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisResponseMsgCtx);

                    //Create the AxisEngine for the reponse and send it.
                    AxisEngine.send(axisResponseMsgCtx);
                    //This assumes that we are on the ultimate execution thread
                    ThreadContextMigratorUtil.performContextCleanup(
                            Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisResponseMsgCtx);
                }
            }

        } catch (AxisFault af) {
            throw af;
        } catch (Exception e) {
            ThreadContextMigratorUtil.performThreadCleanup(
                    Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);

            //e.printStackTrace();

            // TODO.  This is throwing a client exception ?
            // TODO Why are we preserving the stack information  ?  
            
            // Make a webservice exception (which will strip out a unnecessary stuff)
            WebServiceException wse = ExceptionFactory.makeWebServiceException(e);

            // The AxisEngine expects an AxisFault
            throw AxisFault.makeFault(wse);

        }

        //This assumes that we are on the ultimate execution thread
        ThreadContextMigratorUtil
                .performThreadCleanup(Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, axisRequestMsgCtx);

        if (faultToReturn != null) {
            throw faultToReturn;
        }
    }


    private boolean isMepInOnly(String mep) {
        boolean inOnly = mep.equals(WSDL20_2004_Constants.MEP_URI_ROBUST_IN_ONLY) ||
                mep.equals(WSDL20_2004_Constants.MEP_URI_IN_ONLY) ||
                mep.equals(WSDL2Constants.MEP_URI_IN_ONLY) ||
                mep.equals(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY) ||
                mep.equals(WSDL20_2006Constants.MEP_URI_ROBUST_IN_ONLY) ||
                mep.equals(WSDL20_2006Constants.MEP_URI_IN_ONLY);
        return inOnly;
    }
    
    /**
     * Retrieves the registered InvocationListenerFactory instances and sets them
     * on the current EndpointInvocationContext.
     * @param eic
     */
    void addInvocationListenerFactories(EndpointInvocationContext eic) {
        eic.setInvocationListenerFactories(InvocationListenerRegistry.getFactories());
    }

    public ClassLoader getCachedClassLoader(org.apache.axis2.context.MessageContext msgContext) {
        return (ClassLoader) msgContext.getAxisService().getParameterValue(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER);
    }
}
