/*
 * Copyright (c) 1997, 2010, 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.xml.internal.ws.client.dispatch;

import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.xml.internal.ws.api.BindingID;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
import com.sun.xml.internal.ws.api.client.WSPortInfo;
import com.sun.xml.internal.ws.api.message.Attachment;
import com.sun.xml.internal.ws.api.message.AttachmentSet;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Fiber;
import com.sun.xml.internal.ws.api.pipe.Tube;
import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptor;
import com.sun.xml.internal.ws.binding.BindingImpl;
import com.sun.xml.internal.ws.client.*;
import com.sun.xml.internal.ws.encoding.soap.DeserializationException;
import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
import com.sun.xml.internal.ws.message.AttachmentSetImpl;
import com.sun.xml.internal.ws.message.DataHandlerAttachment;
import com.sun.xml.internal.ws.resources.DispatchMessages;

import javax.activation.DataHandler;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Response;
import javax.xml.ws.Service;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.ws.soap.SOAPFaultException;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebEndpoint;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * The <code>DispatchImpl</code> abstract class provides support
 * for the dynamic invocation of a service endpoint operation using XML
 * constructs, JAXB objects or <code>SOAPMessage</code>. The <code>javax.xml.ws.Service</code>
 * interface acts as a factory for the creation of <code>DispatchImpl</code>
 * instances.
 *
 * @author WS Development Team
 * @version 1.0
 */
public abstract class DispatchImpl<T> extends Stub implements Dispatch<T> {

    private static final Logger LOGGER = Logger.getLogger(DispatchImpl.class.getName());

    final Service.Mode mode;
    final SOAPVersion soapVersion;
    final boolean allowFaultResponseMsg;
    static final long AWAIT_TERMINATION_TIME = 800L;

    /**
     *
     * @param port    dispatch instance is associated with this wsdl port qName
     * @param mode    Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
     * @param owner   Service that created the Dispatch
     * @param pipe    Master pipe for the pipeline
     * @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
     */
    @Deprecated
    protected DispatchImpl(QName port, Service.Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr) {
        super(port, owner, pipe, binding, (owner.getWsdlService() != null)? owner.getWsdlService().get(port) : null , owner.getEndpointAddress(port), epr);
        this.mode = mode;
        this.soapVersion = binding.getSOAPVersion();
        this.allowFaultResponseMsg = false;
    }

    /**
     * @param portInfo dispatch instance is associated with this portInfo
     * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
     * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
     */
    protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr) {
        this(portInfo, mode, binding, epr, false);
    }

    /**
     * @param portInfo dispatch instance is associated with this portInfo
     * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
     * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
     * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
     */
    protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
        this(portInfo, mode, binding, null, epr, allowFaultResponseMsg);
    }

    /**
     * @param portInfo dispatch instance is associated with this portInfo
     * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
     * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
     * @param pipe    Master pipe for the pipeline
     * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
     */
    protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, Tube pipe, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
        super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
        this.mode = mode;
        this.soapVersion = binding.getSOAPVersion();
        this.allowFaultResponseMsg = allowFaultResponseMsg;
    }
    /**
     *
     * @param port    dispatch instance is associated with this wsdl port qName
     * @param mode    Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
     * @param owner   Service that created the Dispatch
     * @param pipe    Master pipe for the pipeline
     * @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
     * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
     */
    protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
        super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
        this.mode = mode;
        this.soapVersion = binding.getSOAPVersion();
        this.allowFaultResponseMsg = allowFaultResponseMsg;
    }

    /**
     * Abstract method that is implemented by each concrete Dispatch class
     * @param msg  message passed in from the client program on the invocation
     * @return  The Message created returned as the Interface in actuallity a
     *          concrete Message Type
     */
    abstract Packet createPacket(T msg);

    /**
     * Obtains the value to return from the response message.
     */
    abstract T toReturnValue(Packet response);

    public final Response<T> invokeAsync(T param) {
        if (LOGGER.isLoggable(Level.FINE)) {
          dumpParam(param, "invokeAsync(T)");
        }
        AsyncInvoker invoker = new DispatchAsyncInvoker(param);
        AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,null);
        invoker.setReceiver(ft);
        ft.run();
        return ft;
    }

    private void dumpParam(T param, String method) {
      if (param instanceof Packet) {
        Packet message = (Packet)param;

        String action;
        String msgId;
        if (LOGGER.isLoggable(Level.FINE)) {
          AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
          SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
          action =
            av != null && message.getMessage() != null ?
              message.getMessage().getHeaders().getAction(av, sv) : null;
          msgId =
            av != null && message.getMessage() != null ?
              message.getMessage().getHeaders().getMessageID(av, sv) : null;
          LOGGER.fine("In DispatchImpl." + method + " for message with action: " + action + " and msg ID: " + msgId + " msg: " + message.getMessage());

          if (message.getMessage() == null) {
            LOGGER.fine("Dispatching null message for action: " + action + " and msg ID: " + msgId);
          }
        }
      }
    }
    public final Future<?> invokeAsync(T param, AsyncHandler<T> asyncHandler) {
        if (LOGGER.isLoggable(Level.FINE)) {
          dumpParam(param, "invokeAsync(T, AsyncHandler<T>)");
        }
        AsyncInvoker invoker = new DispatchAsyncInvoker(param);
        AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,asyncHandler);
        invoker.setReceiver(ft);
        invoker.setNonNullAsyncHandlerGiven(asyncHandler != null);

        ft.run();
        return ft;
    }

    /**
     * Synchronously invokes a service.
     *
     * See {@link #process(Packet, RequestContext, ResponseContextReceiver)} on
     * why it takes a {@link RequestContext} and {@link ResponseContextReceiver} as a parameter.
     */
    public final T doInvoke(T in, RequestContext rc, ResponseContextReceiver receiver){
        Packet response = null;
        try {
                try {
                    checkNullAllowed(in, rc, binding, mode);

                    Packet message = createPacket(in);
                    resolveEndpointAddress(message, rc);
                    setProperties(message,true);
                    response = process(message,rc,receiver);
                    Message msg = response.getMessage();

        // REVIEW: eliminate allowFaultResponseMsg, but make that behavior default for MessageDispatch, PacketDispatch
                    if(msg != null && msg.isFault() &&
                 !allowFaultResponseMsg) {
                        SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
                        // passing null means there is no checked excpetion we're looking for all
                        // it will get back to us is a protocol exception
                        throw (SOAPFaultException)faultBuilder.createException(null);
                    }
                } catch (JAXBException e) {
                    //TODO: i18nify
                    throw new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e);
                } catch(WebServiceException e){
                    //it could be a WebServiceException or a ProtocolException
                    throw e;
                } catch(Throwable e){
                    // it could be a RuntimeException resulting due to some internal bug or
                    // its some other exception resulting from user error, wrap it in
                    // WebServiceException
                    throw new WebServiceException(e);
                }

                return toReturnValue(response);
        } finally {
        // REVIEW: Move to AsyncTransportProvider
                if (response != null && response.transportBackChannel != null)
                        response.transportBackChannel.close();
        }
    }

    public final T invoke(T in) {
        if (LOGGER.isLoggable(Level.FINE)) {
          dumpParam(in, "invoke(T)");
        }

        return doInvoke(in,requestContext,this);
    }

    public final void invokeOneWay(T in) {
        if (LOGGER.isLoggable(Level.FINE)) {
          dumpParam(in, "invokeOneWay(T)");
        }

        try {
            checkNullAllowed(in, requestContext, binding, mode);

            Packet request = createPacket(in);
            setProperties(request,false);
            Packet response = process(request,requestContext,this);
        } catch(WebServiceException e){
            //it could be a WebServiceException or a ProtocolException
            throw e;
        } catch(Throwable e){
            // it could be a RuntimeException resulting due to some internal bug or
            // its some other exception resulting from user error, wrap it in
            // WebServiceException
            throw new WebServiceException(e);
        }
    }

    void setProperties(Packet packet, boolean expectReply) {
        packet.expectReply = expectReply;
    }

    static boolean isXMLHttp(@NotNull WSBinding binding) {
        return binding.getBindingId().equals(BindingID.XML_HTTP);
    }

    static boolean isPAYLOADMode(@NotNull Service.Mode mode) {
           return mode == Service.Mode.PAYLOAD;
    }

    static void checkNullAllowed(@Nullable Object in, RequestContext rc, WSBinding binding, Service.Mode mode) {

        if (in != null)
            return;

        //With HTTP Binding a null invocation parameter can not be used
        //with HTTP Request Method == POST
        if (isXMLHttp(binding)){
            if (methodNotOk(rc))
                throw new WebServiceException(DispatchMessages.INVALID_NULLARG_XMLHTTP_REQUEST_METHOD(HTTP_REQUEST_METHOD_POST, HTTP_REQUEST_METHOD_GET));
        } else { //soapBinding
              if (mode == Service.Mode.MESSAGE )
                   throw new WebServiceException(DispatchMessages.INVALID_NULLARG_SOAP_MSGMODE(mode.name(), Service.Mode.PAYLOAD.toString()));
        }
    }

    static boolean methodNotOk(@NotNull RequestContext rc) {
        String requestMethod = (String)rc.get(MessageContext.HTTP_REQUEST_METHOD);
        String request = (requestMethod == null)? HTTP_REQUEST_METHOD_POST: requestMethod;
        // if method == post or put with a null invocation parameter in xml/http binding this is not ok
        return HTTP_REQUEST_METHOD_POST.equalsIgnoreCase(request) || HTTP_REQUEST_METHOD_PUT.equalsIgnoreCase(request);
    }

    public static void checkValidSOAPMessageDispatch(WSBinding binding, Service.Mode mode) {
        // Dispatch<SOAPMessage> is only valid for soap binding and in Service.Mode.MESSAGE
        if (DispatchImpl.isXMLHttp(binding))
            throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_BINDING(HTTPBinding.HTTP_BINDING, SOAPBinding.SOAP11HTTP_BINDING + " or " + SOAPBinding.SOAP12HTTP_BINDING));
        if (DispatchImpl.isPAYLOADMode(mode))
            throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
    }

    public static void checkValidDataSourceDispatch(WSBinding binding, Service.Mode mode) {
        // Dispatch<DataSource> is only valid with xml/http binding and in Service.Mode.MESSAGE
        if (!DispatchImpl.isXMLHttp(binding))
            throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_BINDING("SOAP/HTTP", HTTPBinding.HTTP_BINDING));
        if (DispatchImpl.isPAYLOADMode(mode))
            throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
    }

    public final @NotNull QName getPortName() {
        return portname;
    }

    void resolveEndpointAddress(@NotNull Packet message, @NotNull RequestContext requestContext) {
        //resolve endpoint look for query parameters, pathInfo
        String endpoint = (String) requestContext.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
        if (endpoint == null)
            endpoint = message.endpointAddress.toString();

        String pathInfo = null;
        String queryString = null;
        if (requestContext.get(MessageContext.PATH_INFO) != null)
            pathInfo = (String) requestContext.get(MessageContext.PATH_INFO);

        if (requestContext.get(MessageContext.QUERY_STRING) != null)
            queryString = (String) requestContext.get(MessageContext.QUERY_STRING);


        String resolvedEndpoint = null;
        if (pathInfo != null || queryString != null) {
            pathInfo = checkPath(pathInfo);
            queryString = checkQuery(queryString);
            if (endpoint != null) {
                try {
                    final URI endpointURI = new URI(endpoint);
                    resolvedEndpoint = resolveURI(endpointURI, pathInfo, queryString);
                } catch (URISyntaxException e) {
                    throw new WebServiceException(DispatchMessages.INVALID_URI(endpoint));
                }
            }
            requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, resolvedEndpoint);
            //message.endpointAddress = EndpointAddress.create(resolvedEndpoint);
        }
    }

    protected @NotNull String resolveURI(@NotNull URI endpointURI, @Nullable String pathInfo, @Nullable String queryString) {
        String query = null;
        String fragment = null;
        if (queryString != null) {
            final URI result;
            try {
                URI tp = new URI(null, null, endpointURI.getPath(), queryString, null);
                result = endpointURI.resolve(tp);
            } catch (URISyntaxException e) {
                throw new WebServiceException(DispatchMessages.INVALID_QUERY_STRING(queryString));
            }
            query = result.getQuery();
            fragment = result.getFragment();
        }

        final String path = (pathInfo != null) ? pathInfo : endpointURI.getPath();
        try {
            //final URI temp = new URI(null, null, path, query, fragment);
            //return endpointURI.resolve(temp).toURL().toExternalForm();
            // Using the following HACK instead of the above to avoid double encoding of
            // the query. Application's QUERY_STRING is encoded using URLEncoder.encode().
            // If we use that query in URI's constructor, it is encoded again.
            // URLEncoder's encoding is not the same as URI's encoding of the query.
            // See {@link URL}
            StringBuilder spec = new StringBuilder();
            if (path != null) {
                spec.append(path);
            }
            if (query != null) {
                spec.append("?");
                spec.append(query);
            }
            if (fragment != null) {
                spec.append("#");
                spec.append(fragment);
            }
            return new URL(endpointURI.toURL(), spec.toString()).toExternalForm();
       } catch (MalformedURLException e) {
            throw new WebServiceException(DispatchMessages.INVALID_URI_RESOLUTION(path));
        }
    }

    private static String checkPath(@Nullable String path) {
        //does it begin with /
        return (path == null || path.startsWith("/")) ? path : "/" + path;
    }

    private static String checkQuery(@Nullable String query) {
        if (query == null) return null;

        if (query.indexOf('?') == 0)
           throw new WebServiceException(DispatchMessages.INVALID_QUERY_LEADING_CHAR(query));
        return query;
    }


    protected AttachmentSet setOutboundAttachments() {
        HashMap<String, DataHandler> attachments = (HashMap<String, DataHandler>)
                getRequestContext().get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);

        if (attachments != null) {
            List<Attachment> alist = new ArrayList();
            for (Map.Entry<String, DataHandler> att : attachments.entrySet()) {
                DataHandlerAttachment dha = new DataHandlerAttachment(att.getKey(), att.getValue());
                alist.add(dha);
            }
            return new AttachmentSetImpl(alist);
        }
        return new AttachmentSetImpl();
    }

   /* private void getInboundAttachments(Message msg) {
        AttachmentSet attachments = msg.getAttachments();
        if (!attachments.isEmpty()) {
            Map<String, DataHandler> in = new HashMap<String, DataHandler>();
            for (Attachment attachment : attachments)
                in.put(attachment.getContentId(), attachment.asDataHandler());
            getResponseContext().put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS, in);
        }

    }
    */


    /**
     * Calls {@link DispatchImpl#doInvoke(Object,RequestContext,ResponseContextReceiver)}.
     */
    private class Invoker implements Callable {
        private final T param;
        // snapshot the context now. this is necessary to avoid concurrency issue,
        // and is required by the spec
        private final RequestContext rc = requestContext.copy();

        /**
         * Because of the object instantiation order,
         * we can't take this as a constructor parameter.
         */
        private ResponseContextReceiver receiver;

        Invoker(T param) {
            this.param = param;
        }

        public T call() throws Exception {
            if (LOGGER.isLoggable(Level.FINE)) {
              dumpParam(param, "call()");
            }
            return doInvoke(param,rc,receiver);
        }

        void setReceiver(ResponseContextReceiver receiver) {
            this.receiver = receiver;
        }
    }

    /**
     *
     */
    private class DispatchAsyncInvoker extends AsyncInvoker {
        private final T param;
        // snapshot the context now. this is necessary to avoid concurrency issue,
        // and is required by the spec
        private final RequestContext rc = requestContext.copy();

        DispatchAsyncInvoker(T param) {
            this.param = param;
        }

        public void do_run () {
            checkNullAllowed(param, rc, binding, mode);
            final Packet message = createPacket(param);
            message.nonNullAsyncHandlerGiven = this.nonNullAsyncHandlerGiven;
            resolveEndpointAddress(message, rc);
            setProperties(message,true);

            String action = null;
            String msgId = null;
            if (LOGGER.isLoggable(Level.FINE)) {
              AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
              SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
              action =
                av != null && message.getMessage() != null ?
                  message.getMessage().getHeaders().getAction(av, sv) : null;
              msgId =
                av != null&& message.getMessage() != null ?
                  message.getMessage().getHeaders().getMessageID(av, sv) : null;
              LOGGER.fine("In DispatchAsyncInvoker.do_run for async message with action: " + action + " and msg ID: " + msgId);
            }

            final String actionUse = action;
            final String msgIdUse = msgId;

            Fiber.CompletionCallback callback = new Fiber.CompletionCallback() {
                public void onCompletion(@NotNull Packet response) {

                    if (LOGGER.isLoggable(Level.FINE)) {
                      LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse);
                    }

                    Message msg = response.getMessage();

                    if (LOGGER.isLoggable(Level.FINE)) {
                      LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " msg: " + msg);
                    }

                    try {
                        if(msg != null && msg.isFault() &&
                           !allowFaultResponseMsg) {
                            SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
                            // passing null means there is no checked excpetion we're looking for all
                            // it will get back to us is a protocol exception
                            throw (SOAPFaultException)faultBuilder.createException(null);
                        }
                        responseImpl.setResponseContext(new ResponseContext(response));
                        responseImpl.set(toReturnValue(response), null);
                    } catch (JAXBException e) {
                        //TODO: i18nify
                        responseImpl.set(null, new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e));
                    } catch(WebServiceException e){
                        //it could be a WebServiceException or a ProtocolException
                        responseImpl.set(null, e);
                    } catch(Throwable e){
                        // It could be any RuntimeException resulting due to some internal bug.
                        // or its some other exception resulting from user error, wrap it in
                        // WebServiceException
                        responseImpl.set(null, new WebServiceException(e));
                    }
                }
                public void onCompletion(@NotNull Throwable error) {
                    if (LOGGER.isLoggable(Level.FINE)) {
                      LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " Throwable: " + error.toString());
                    }
                    if (error instanceof WebServiceException) {
                        responseImpl.set(null, error);

                    } else {
                        //its RuntimeException or some other exception resulting from user error, wrap it in
                        // WebServiceException
                        responseImpl.set(null, new WebServiceException(error));
                    }
                }
            };
            processAsync(responseImpl,message,rc, callback);
        }
    }

    public void setOutboundHeaders(Object... headers) {
        throw new UnsupportedOperationException();
    }

    static final String HTTP_REQUEST_METHOD_GET="GET";
    static final String HTTP_REQUEST_METHOD_POST="POST";
    static final String HTTP_REQUEST_METHOD_PUT="PUT";

    @Deprecated
    public static Dispatch<Source> createSourceDispatch(QName port, Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
        if(isXMLHttp(binding))
            return new RESTSourceDispatch(port,mode,owner,pipe,binding,epr);
        else
            return new SOAPSourceDispatch(port,mode,owner,pipe,binding,epr);
    }

    public static Dispatch<Source> createSourceDispatch(WSPortInfo portInfo, Mode mode, BindingImpl binding, WSEndpointReference epr) {
        if (isXMLHttp(binding))
            return new RESTSourceDispatch(portInfo, mode, binding, epr);
        else
            return new SOAPSourceDispatch(portInfo, mode, binding, epr);
    }
}
