/*
 * 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.client.proxy;

import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.jaxws.BindingProvider;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.client.async.AsyncResponse;
import org.apache.axis2.jaxws.core.InvocationContext;
import org.apache.axis2.jaxws.core.InvocationContextFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.core.controller.InvocationController;
import org.apache.axis2.jaxws.core.controller.InvocationControllerFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.OperationDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.marshaller.factory.MethodMarshallerFactory;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.axis2.jaxws.spi.Binding;
import org.apache.axis2.jaxws.spi.Constants;
import org.apache.axis2.jaxws.spi.ServiceDelegate;
import org.apache.axis2.jaxws.spi.migrator.ApplicationContextMigratorUtil;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.SOAPBinding;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * ProxyHandler is the java.lang.reflect.InvocationHandler implementation. When a JAX-WS client
 * calls the method on a proxy object, created by calling the ServiceDelegate.getPort(...) method,
 * the inovke method on the ProxyHandler is called.
 * <p/>
 * ProxyHandler uses EndpointInterfaceDescriptor and finds out if 1) The client call is Document
 * Literal or Rpc Literal 2) The WSDL is wrapped or unWrapped.
 * <p/>
 * ProxyHandler then reads OperationDescription using Method name called by Client From
 * OperationDescription it does the following 1) if the wsdl isWrapped() reads RequestWrapper Class
 * and responseWrapperClass 2) then reads the webParams for the Operation.
 * <p/>
 * isWrapped() = true  and DocLiteral then ProxyHandler then uses WrapperTool to create Request that
 * is a Wrapped JAXBObject. Creates JAXBBlock using JAXBBlockFactory Creates MessageContext->Message
 * and sets JAXBBlock to xmlPart as RequestMsgCtx in InvocationContext. Makes call to
 * InvocationController. Reads ResponseMsgCtx ->MessageCtx->Message->XMLPart. Converts that to
 * JAXBlock using JAXBBlockFactory and returns the BO from this JAXBBlock.
 * <p/>
 * isWrapped() != true and DocLiteral then ProxyHandler creates the JAXBBlock for the input request
 * creates a MessageContext that is then used by IbvocationController to invoke. Response is read
 * and return object is derived using @Webresult annotation. A JAXBBlock is created from the
 * Response and the BO from JAXBBlock is returned.
 */

public class JAXWSProxyHandler extends BindingProvider implements
        InvocationHandler {
    private static Log log = LogFactory.getLog(JAXWSProxyHandler.class);

    private Class seiClazz = null;
    private Method method = null;
    
    //Reference to ServiceDelegate instance that was used to create the Proxy
    protected ServiceDescription serviceDesc = null;

    protected InvocationController controller;
    
    public JAXWSProxyHandler(ServiceDelegate delegate,
                             Class seiClazz,
                             EndpointDescription epDesc,
                             WebServiceFeature... features) {
        this(delegate, seiClazz, epDesc, null, null, features);
    }

    public JAXWSProxyHandler(ServiceDelegate delegate,
            Class seiClazz,
            EndpointDescription epDesc,
            EndpointReference epr,
            String addressingNamespace,
            WebServiceFeature... features) {
        super(delegate, epDesc, epr, addressingNamespace, features);
        
        this.seiClazz = seiClazz;
        this.serviceDesc = delegate.getServiceDescription();
    }

    /* (non-Javadoc)
    * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    *
    * Invokes the method that was called on the java.lang.reflect.Proxy instance.
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        boolean debug = log.isDebugEnabled();
        if (debug) {
            log.debug("Attemping to invoke Method: " + method.getName());
        }

        this.method = method;

        if (!isValidMethodCall(method)) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("proxyErr1", method.getName(), seiClazz.getName()));
        }

        if (!isPublic(method)) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("proxyPrivateMethod", method.getName()));
        }

        if (isBindingProviderInvoked(method)) {
            // Since the JAX-WS proxy instance must also implement the javax.xml.ws.BindingProvider
            // interface, this object must handle those invocations as well.  In that case, we'll
            // delegate those calls to the BindingProvider object.
            if (debug) {
                log.debug(
                        "Invoking a public method on the javax.xml.ws.BindingProvider interface.");
            }
            try {
                return method.invoke(this, args);
            }
            catch (Throwable e) {
                if (debug) {
                    log.debug("An error occured while invoking the method: " + e.getMessage());
                }
                throw ExceptionFactory.makeWebServiceException(e);
            }
        } else {
            OperationDescription operationDesc =
                    endpointDesc.getEndpointInterfaceDescription().getOperation(method);
            if (isMethodExcluded(operationDesc)) {
                throw ExceptionFactory.makeWebServiceException(
                        Messages.getMessage("proxyExcludedMethod", method.getName()));
            }
            return invokeSEIMethod(method, args);
        }
    }

    /*
    * Performs the invocation of the method defined on the Service Endpoint
    * Interface.
    */
    private Object invokeSEIMethod(Method method, Object[] args) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("Attempting to invoke SEI Method " + method.getName());
        }

        OperationDescription operationDesc =
                endpointDesc.getEndpointInterfaceDescription().getOperation(method);

        // Create and configure the request MessageContext
        InvocationContext requestIC = InvocationContextFactory.createInvocationContext(null);
        MessageContext request = createRequest(method, args);
        request.setEndpointDescription(getEndpointDescription());
        request.setOperationDescription(operationDesc);

        // Enable MTOM on the Message if the property was set on the SOAPBinding.
        Binding bnd = (Binding) getBinding();
        if (bnd != null && bnd instanceof SOAPBinding) {
            if (((SOAPBinding)bnd).isMTOMEnabled()) {
                Message requestMsg = request.getMessage();
                requestMsg.setMTOMEnabled(true);
            }
        }
        
        /*
         * TODO: review: make sure the handlers are set on the InvocationContext
         * This implementation of the JAXWS runtime does not use Endpoint, which
         * would normally be the place to initialize and store the handler list.
         * In lieu of that, we will have to intialize and store them on the 
         * InvocationContext.  also see the InvocationContextFactory.  On the client
         * side, the binding is not yet set when we call into that factory, so the
         * handler list doesn't get set on the InvocationContext object there.  Thus
         * we gotta do it here.
         */
        
        // be sure to use whatever handlerresolver is registered on the Service
        requestIC.setHandlers(bnd.getHandlerChain());

        requestIC.setRequestMessageContext(request);
        requestIC.setServiceClient(serviceDelegate.getServiceClient(endpointDesc.getPortQName()));
        
        /*
         * if SESSION_MAINTAIN_PROPERTY is true, and the client app has explicitly set a HEADER_COOKIE on the request context, assume the client
         * app is expecting the HEADER_COOKIE to be the session id.  If we were establishing a new session, no cookie would be sent, and the 
         * server would reply with a "Set-Cookie" header, which is copied as a "Cookie"-keyed property to the service context during response.
         * In this case, if we succeed in using an existing server session, no "Set-Cookie" header will be returned, and therefore no
         * "Cookie"-keyed property would be set on the service context.  So, let's copy our request context HEADER_COOKIE key to the service
         * context now to prevent the "no cookie" exception in BindingProvider.setupSessionContext.  It is possible the server does not support
         * sessions, in which case no error occurs, but the client app would assume it is participating in a session.
         */
        if ((requestContext.containsKey(BindingProvider.SESSION_MAINTAIN_PROPERTY)) && ((Boolean)requestContext.get(BindingProvider.SESSION_MAINTAIN_PROPERTY))) {
            if ((requestContext.containsKey(HTTPConstants.HEADER_COOKIE)) && (requestContext.get(HTTPConstants.HEADER_COOKIE) != null)) {
                if (requestIC.getServiceClient().getServiceContext().getProperty(HTTPConstants.HEADER_COOKIE) == null) {
                    requestIC.getServiceClient().getServiceContext().setProperty(HTTPConstants.HEADER_COOKIE, requestContext.get(HTTPConstants.HEADER_COOKIE));
                    if (log.isDebugEnabled()) {
                        log.debug("Client-app defined Cookie property (assume to be session cookie) on request context copied to service context." +
                                "  Caution:  server may or may not support sessions, but client app will not be informed when not supported.");
                    }
                }
            }
        }
        
        // Migrate the properties from the client request context bag to
        // the request MessageContext.
        ApplicationContextMigratorUtil.performMigrationToMessageContext(
                Constants.APPLICATION_CONTEXT_MIGRATOR_LIST_ID, 
                getRequestContext(), request);

        // Perform the WebServiceFeature configuration requested by the user.
        bnd.configure(request, this);

        // We'll need an InvocationController instance to send the request.
        InvocationControllerFactory icf = (InvocationControllerFactory) FactoryRegistry.getFactory(InvocationControllerFactory.class);
        controller = icf.getInvocationController();
        
        if (controller == null) {
            throw new WebServiceException(Messages.getMessage("missingInvocationController"));
        }
        
        // Check if the call is OneWay, Async or Sync
        if (operationDesc.isOneWay()) {
            if (log.isDebugEnabled()) {
                log.debug("OneWay Call");
            }
            controller.invokeOneWay(requestIC);

            // Check to see if we need to maintain session state
            checkMaintainSessionState(request, requestIC);
        }

        if (method.getReturnType() == Future.class) {
            if (log.isDebugEnabled()) {
                log.debug("Async Callback");
            }

            //Get AsyncHandler from Objects and sent that to InvokeAsync
            AsyncHandler asyncHandler = null;
            for (Object obj : args) {
                if (obj != null && AsyncHandler.class.isAssignableFrom(obj.getClass())) {
                    asyncHandler = (AsyncHandler)obj;
                    break;
                }
            }

            // Don't allow the invocation to continue if the invocation requires a callback
            // object, but none was supplied.
            if (asyncHandler == null) {
                throw ExceptionFactory
                        .makeWebServiceException(Messages.getMessage("proxyNullCallback"));
            }
            AsyncResponse listener = createProxyListener(args, operationDesc);
            requestIC.setAsyncResponseListener(listener);

            if ((serviceDelegate.getExecutor() != null) &&
                    (serviceDelegate.getExecutor() instanceof ExecutorService)) {
                ExecutorService es = (ExecutorService)serviceDelegate.getExecutor();
                if (es.isShutdown()) {
                    // the executor service is shutdown and won't accept new tasks
                    // so return an error back to the client
                    throw ExceptionFactory
                            .makeWebServiceException(Messages.getMessage("ExecutorShutdown"));
                }
            }

            requestIC.setExecutor(serviceDelegate.getExecutor());

            Future<?> future = controller.invokeAsync(requestIC, asyncHandler);

            //Check to see if we need to maintain session state
            checkMaintainSessionState(request, requestIC);

            return future;
        }

        if (method.getReturnType() == Response.class) {
            if (log.isDebugEnabled()) {
                log.debug("Async Polling");
            }
            AsyncResponse listener = createProxyListener(args, operationDesc);
            requestIC.setAsyncResponseListener(listener);
            requestIC.setExecutor(serviceDelegate.getExecutor());

            Response response = controller.invokeAsync(requestIC);

            //Check to see if we need to maintain session state
            checkMaintainSessionState(request, requestIC);

            return response;
        }

        if (!operationDesc.isOneWay()) {
            InvocationContext responseIC = controller.invoke(requestIC);

            //Check to see if we need to maintain session state
            checkMaintainSessionState(request, requestIC);

            MessageContext responseContext = responseIC.getResponseMessageContext();
            
            // Migrate the properties from the response MessageContext back
            // to the client response context bag.
            ApplicationContextMigratorUtil.performMigrationFromMessageContext(
                    Constants.APPLICATION_CONTEXT_MIGRATOR_LIST_ID, 
                    getResponseContext(), responseContext);
            
            Object responseObj = createResponse(method, args, responseContext, operationDesc);
            return responseObj;
        }

        return null;
    }
    
    private AsyncResponse createProxyListener(Object[] args, OperationDescription operationDesc) {
        ProxyAsyncListener listener = new ProxyAsyncListener(operationDesc);
        listener.setHandler(this);
        listener.setInputArgs(args);
        return listener;
    }

    protected boolean isAsync() {
        String methodName = method.getName();
        Class returnType = method.getReturnType();
        return methodName.endsWith("Async") && (returnType.isAssignableFrom(Response.class) ||
                returnType.isAssignableFrom(Future.class));
    }

    /**
     * Creates a request MessageContext for the method call. This request context will be used by
     * InvocationController to route the method call to axis engine.
     *
     * @param method - The method invoked on the proxy object.
     * @param args   - The parameter list
     * @return A MessageContext that can be used for the invocation
     */
    protected MessageContext createRequest(Method method, Object[] args) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("Creating a new Message using the request parameters.");
        }

        OperationDescription operationDesc =
                endpointDesc.getEndpointInterfaceDescription().getOperation(method);

        Message message = MethodMarshallerFactory.getMarshaller(operationDesc, true, null)
                .marshalRequest(args, operationDesc);

        if (log.isDebugEnabled()) {
            log.debug("Request Message created successfully.");
        }

        MessageContext request = new MessageContext();
        request.setMessage(message);

        if (log.isDebugEnabled()) {
            log.debug("Request MessageContext created successfully.");
        }

        return request;
    }

    /**
     * Creates a response MessageContext for the method call. This response context will be used to
     * create response result to the client call.
     *
     * @param method          - The method invoked on the proxy object.
     * @param args            - The parameter list.
     * @param responseContext - The MessageContext to be used for the response.
     * @param operationDesc   - The OperationDescription that for the invoked method.
     * @return
     */
    protected Object createResponse(Method method, Object[] args, MessageContext responseContext,
                                    OperationDescription operationDesc) throws Throwable {
        Message responseMsg = responseContext.getMessage();
        try {

            if (log.isDebugEnabled()) {
                log.debug("Processing the response Message to create the return value(s).");
            }

            // Find out if there was a fault on the response and create the appropriate 
            // exception type.
            if (hasFaultResponse(responseContext)) {
                Throwable t = getFaultResponse(responseContext, operationDesc);
                throw t;
            }
            ClassLoader cl = (ClassLoader) responseContext.getProperty(Constants.CACHE_CLASSLOADER);
            Object object =
                    MethodMarshallerFactory.getMarshaller(operationDesc, true, cl)
                                       .demarshalResponse(responseMsg, args, operationDesc);
            if (log.isDebugEnabled()) {
                log.debug("The response was processed and the return value created successfully.");
            }
            return object;
        } finally {
            responseMsg.close();
            // Free incoming stream
            try {
                responseContext.freeInputStream();
            }
            catch (Throwable t) {
                throw ExceptionFactory.makeWebServiceException(t);
            }
        }
    }

    protected static Throwable getFaultResponse(MessageContext msgCtx,
                                                OperationDescription opDesc) {
        Message msg = msgCtx.getMessage();
        //Operation Description for Async method does not store the fault description as Asyc operation 
        //will never have throws clause in the method signature.
        //we will fetch the OperationDescription of the sync method and this should give us the
        //correct fault description so we can throw the right user defined exception.

        try {
            if (opDesc.isJAXWSAsyncClientMethod()) {
                opDesc = opDesc.getSyncOperation();
            }
            if (msg != null && msg.isFault()) {
                ClassLoader cl = (ClassLoader) msgCtx.getProperty(Constants.CACHE_CLASSLOADER);
                Object object = MethodMarshallerFactory.getMarshaller(opDesc, true, cl)
                .demarshalFaultResponse(msg, opDesc);
                if (log.isDebugEnabled() && object != null) {
                    log.debug("A fault was found and processed.");
                    log.debug("Throwing a fault of type: " + object.getClass().getName() +
                    " back to the clent.");
                }

                return (Throwable)object;
            } else if (msgCtx.getLocalException() != null) {
                // use the factory, it'll throw the right thing:
                return ExceptionFactory.makeWebServiceException(msgCtx.getLocalException());
            }
        } finally {
            try {
                msgCtx.freeInputStream();
            }
            catch (Throwable t) {
                throw ExceptionFactory.makeWebServiceException(t);
            }
        }

        return null;
    }

    protected static boolean hasFaultResponse(MessageContext mc) {
        if (mc.getMessage() != null && mc.getMessage().isFault())
            return true;
        else if (mc.getLocalException() != null)
            return true;
        else
            return false;
    }

    private boolean isBindingProviderInvoked(Method method) {
        Class methodsClass = method.getDeclaringClass();
        return (seiClazz == methodsClass) ? false : true;
    }

    private boolean isValidMethodCall(Method method) {
        Class clazz = method.getDeclaringClass();
        if (clazz.isAssignableFrom(seiClazz) ||
                clazz.isAssignableFrom(org.apache.axis2.jaxws.spi.BindingProvider.class) ||
                clazz.isAssignableFrom(javax.xml.ws.BindingProvider.class)) {
            return true;
        }
        return false;
    }

    private boolean isPublic(Method method) {
        return Modifier.isPublic(method.getModifiers());
    }

    private boolean isMethodExcluded(OperationDescription operationDesc) {
        return operationDesc.isExcluded();
    }

    public Class getSeiClazz() {
        return seiClazz;
    }

    public void setSeiClazz(Class seiClazz) {
        this.seiClazz = seiClazz;
    }
}
