Package org.apache.axis2.client

Source Code of org.apache.axis2.client.ServiceClient$SyncCallBack

package org.apache.axis2.client;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.async.AsyncResult;
import org.apache.axis2.client.async.Callback;
import org.apache.axis2.context.*;
import org.apache.axis2.description.*;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.ListenerManager;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.util.CallbackReceiver;
import org.apache.ws.commons.om.OMAbstractFactory;
import org.apache.ws.commons.om.OMElement;
import org.apache.ws.commons.soap.SOAP12Constants;
import org.apache.ws.commons.soap.SOAPEnvelope;
import org.apache.ws.commons.soap.SOAPFactory;
import org.apache.ws.commons.soap.SOAPHeader;
import org.apache.wsdl.WSDLConstants;
import org.apache.wsdl.WSDLDescription;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;

/**
* A ServiceClient class is used to create a client for a service. More details
* need to be explained here.
*/
public class ServiceClient {

    // service and operation names used for anonymously stuff
    public static final String ANON_SERVICE = "__ANONYMOUS_SERVICE__";

    public static final QName ANON_OUT_ONLY_OP = new QName(
            "__OPERATION_OUT_ONLY__");

    public static final QName ANON_ROBUST_OUT_ONLY_OP = new QName(
            "__OPERATION_ROBUST_OUT_ONLY__");

    public static final QName ANON_OUT_IN_OP = new QName("__OPERATION_OUT_IN__");

    // the metadata for the service that I'm clienting for
    private AxisService axisService;

    // the configuration in which my metadata lives
    private AxisConfiguration axisConfig;

    // the configuration context in which I live
    private ConfigurationContext configContext;

    // service context for this specific service instance
    private ServiceContext serviceContext;

    // client options for this service interaction
    private Options options = new Options();

    // options that must override those of the child operation client also
    private Options overrideOptions;

    // list of headers to be sent with the simple APIs
    private ArrayList headers;

    private CallbackReceiver callbackReceiver;

    /**
     * Create a service client configured to work with a specific AxisService.
     * If this service is already in the world that's handed in (in the form of
     * a ConfigurationContext) then I will happily work in it. If not I will
     * create a small little virtual world and live there.
     *
     * @param configContext The configuration context under which this service lives (may
     *                      be null, in which case a new local one will be created)
     * @param axisService   The service for which this is the client.
     * @throws AxisFault if something goes wrong while creating a config context (if
     *                   needed)
     */
    public ServiceClient(ConfigurationContext configContext,
                         AxisService axisService) throws AxisFault {
        // create a config context if needed

        initializeTransports(configContext);
        // save the axisConfig and service
        this.axisConfig = this.configContext.getAxisConfiguration();
        this.axisService = (axisService != null) ? axisService
                : createAnonymousService();
        // add the service to the config context if it isn't in there already
        if (this.axisConfig.getService(this.axisService.getName()) == null) {
            this.axisConfig.addService(this.axisService);
        }
        // create a service context for myself: create a new service group
        // context and then get the service context for myself as I'll need that
        // later for stuff that I gotta do
        ServiceGroupContext sgc = new ServiceGroupContext(this.configContext,
                (AxisServiceGroup) this.axisService.getParent());
        this.serviceContext = sgc.getServiceContext(this.axisService);
    }


    /**
     * This is WOM based constructor to configure the Service Client/
     * We are going to make this policy aware
     *
     * @param configContext
     * @param wsdldesc
     * @param wsdlServiceName
     * @param portName
     * @throws AxisFault
     */

    public ServiceClient(ConfigurationContext configContext, WSDLDescription wsdldesc,
                         QName wsdlServiceName, String portName) throws AxisFault {
        // create a config context if needed
        initializeTransports(configContext);
        try {
            this.axisConfig = this.configContext.getAxisConfiguration();
            WSDLBasedServiceConfigurationBuilder scb =
                    new WSDLBasedServiceConfigurationBuilder(wsdldesc, configContext);
            axisService = scb.buildAxisService(wsdlServiceName, portName, options);
            // add the service to the config context if it isn't in there
            // already
            if (this.axisConfig.getService(this.axisService.getName()) == null) {
                this.axisConfig.addService(this.axisService);
            }
            ServiceGroupContext sgc = new ServiceGroupContext(this.configContext,
                    (AxisServiceGroup) this.axisService.getParent());
            this.serviceContext = sgc.getServiceContext(this.axisService);
        } catch (IOException e) {
            throw new AxisFault(e);
        }
    }

    /**
     * Create a service client for WSDL service identified by the QName of the
     * wsdl:service element in a WSDL document.
     *
     * @param configContext   The configuration context under which this service lives (may
     *                        be null, in which case a new local one will be created) *
     * @param wsdlURL         The URL of the WSDL document to read
     * @param wsdlServiceName The QName of the WSDL service in the WSDL document to create a
     *                        client for
     * @param portName        The name of the WSDL 1.1 port to create a client for. May be
     *                        null (if WSDL 2.0 is used or if only one port is there). .
     * @throws AxisFault if something goes wrong while creating a config context (if
     *                   needed)
     */
    public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
                         QName wsdlServiceName, String portName) throws AxisFault {
        // create a config context if needed
        initializeTransports(configContext);
        try {
            this.axisConfig = this.configContext.getAxisConfiguration();
            axisService = AxisService.createClientSideAxisService(wsdlURL,
                    wsdlServiceName, portName, options);
            // add the service to the config context if it isn't in there
            // already
            if (this.axisConfig.getService(this.axisService.getName()) == null) {
                this.axisConfig.addService(this.axisService);
            }
            ServiceGroupContext sgc = new ServiceGroupContext(this.configContext,
                    (AxisServiceGroup) this.axisService.getParent());
            this.serviceContext = sgc.getServiceContext(this.axisService);
        } catch (IOException e) {
            throw new AxisFault(e);
        }
    }

    private void initializeTransports(ConfigurationContext configContext) throws AxisFault {
        ListenerManager trsManager;
        if (configContext != null) {
            this.configContext = configContext;
            trsManager = configContext.getListenerManager();
            if (trsManager == null) {
                trsManager = new ListenerManager();
                trsManager.init(this.configContext);
            }
        } else {
            this.configContext = ConfigurationContextFactory.
                    createConfigurationContextFromFileSystem(null, null);
            trsManager = new ListenerManager();
            trsManager.init(this.configContext);
        }
    }

    /**
     * Create a service client by assuming an anonymous service and any other
     * necessary information.
     */
    public ServiceClient() throws AxisFault {
        this(null, null);
    }

    /**
     * Create an anonymous axisService with one (anonymous) operation each for
     * each MEP that I support dealing with anonymously using the convenience
     * APIs.
     *
     * @return the minted anonymous service
     */
    private AxisService createAnonymousService() {
        // now add anonymous operations to the axis2 service for use with the
        // shortcut client API. NOTE: We only add the ones we know we'll use
        // later in the convenience API; if you use
        // this constructor then you can't expect any magic!
        AxisService axisService = new AxisService(ANON_SERVICE);
        RobustOutOnlyAxisOperation robustoutoonlyOperation = new RobustOutOnlyAxisOperation(
                ANON_ROBUST_OUT_ONLY_OP);
        axisService.addOperation(robustoutoonlyOperation);

        OutOnlyAxisOperation outOnlyOperation = new OutOnlyAxisOperation(
                ANON_OUT_ONLY_OP);
        axisService.addOperation(outOnlyOperation);

        OutInAxisOperation outInOperation = new OutInAxisOperation(
                ANON_OUT_IN_OP);
        axisService.addOperation(outInOperation);
        return axisService;
    }

    /**
     * Return the AxisService this is a client for. This is primarily useful
     * when the AxisService is created anonymously or from WSDL as otherwise the
     * user had the AxisService to start with.
     *
     * @return the axisService
     */
    public AxisService getAxisService() {
        return axisService;
    }

    /**
     * Set the client configuration related to this service interaction.
     */
    public void setOptions(Options options) {
        this.options = options;
    }

    /**
     * Get the client configuration from this service interaction.
     *
     * @return set of options set earlier.
     */
    public Options getOptions() {
        return options;
    }

    /**
     * Set the client configuration related to this service interaction to
     * override any options that the underlying operation client may have.
     */
    public void setOverrideOptions(Options overrideOptions) {
        this.overrideOptions = overrideOptions;
    }

    /**
     * Get the client configuration from this service interaction which have
     * been used to overide operation client options as well.
     *
     * @return set of options set earlier.
     */
    public Options getOverrideOptions() {
        return overrideOptions;
    }

    /**
     * Engage a module for this service client.
     *
     * @param moduleName Name of the module to engage
     * @throws AxisFault if something goes wrong
     */
    public void engageModule(QName moduleName) throws AxisFault {
        axisService.engageModule(axisConfig.getModule(moduleName), axisConfig);
    }

    public void disEngageModule(QName moduleName) {
        AxisModule module = axisConfig.getModule(moduleName);
        if (module != null) {
            axisService.disEngageModule(module);
        }
    }

    /**
     * Add an XML element as a header to be sent with interactions. This allows
     * users to go a bit beyond the dirt simple XML in/out pattern using this
     * simplified API. A header
     *
     * @param header The header to be added for interactions. Must not be null.
     */
    public void addHeader(OMElement header) {
        if (headers == null) {
            headers = new ArrayList();
        }
        headers.add(header);
    }

    /**
     * To remove all the headers in ServiceClient
     */
    public void removeHeaders() {
        headers.clear();
    }


    /**
     * Add a simple header consisting of some text (and a header name; duh) to
     * be sent with interactions.
     *
     * @param headerName
     * @param headerText
     */
    public void addStringHeader(QName headerName, String headerText) {
        OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(
                headerName, null);
        omElement.setText(headerText);
        addHeader(omElement);
    }

    /**
     * This is a simple client API to invoke a service operation who's MEP is
     * Robust In-Only. This API can be used to simply send a bit of XML and
     * possibly receive a fault. If you need more control over this interaction
     * then you need to create a client (@see createClient()) for the operation
     * and use that instead.
     *
     * @param elem The XML to send
     * @throws AxisFault if something goes wrong while sending it or if a fault is
     *                   received in response (per the Robust In-Only MEP).
     */
    public void sendRobust(OMElement elem) throws AxisFault {
        sendRobust(ANON_ROBUST_OUT_ONLY_OP, elem);
    }

    /**
     * This is a simple client API to invoke a service operation who's MEP is
     * Robust In-Only. This API can be used to simply send a bit of XML and
     * possibly receive a fault under the guise of a specific operation. If you
     * need more control over this interaction then you need to create a client
     * (@see createClient()) for the operation and use that instead.
     *
     * @param operation The name of the operation to use. Must NOT be null.
     * @param elem      The XML to send
     * @throws AxisFault if something goes wrong while sending it or if a fault is
     *                   received in response (per the Robust In-Only MEP).
     */
    public void sendRobust(QName operation, OMElement elem) throws AxisFault {
        // look up the appropriate axisop and create the client
        // OperationClient mepClient = createClient(operation);

        // create a message context with elem as the payload
        /*
         * MessageContext mc = new MessageContext(); SOAPEnvelope se =
         * createEmptySOAPEnvelope(); se.getBody().addChild(se);
         * mc.setEnvelope(se); // create a client and have it do the work of
         * sending this out InOnlyMEPClient mepClient = new
         * InOnlyMEPClient(serviceContext); mepClient.send("foo", mc);
         */
        throw new UnsupportedOperationException(
                "ServiceClient.sendRobust is not yet implemented");

    }

    /**
     * Send a bit of XML and forget about it. This API is used to interact with
     * a service operation who's MEP is In-Only. That is, there is no
     * opportunity to get an error from the service via this API; one may still
     * get client-side errors, such as host unknown etc.
     *
     * @param elem The XML element to send to the service
     * @throws AxisFault If something goes wrong trying to send the XML
     */
    public void fireAndForget(OMElement elem) throws AxisFault {
        fireAndForget(ANON_OUT_ONLY_OP, elem);
    }

    /**
     * Send a bit of XML and forget about it under the guise of a specific
     * operation. This API is used to interact with a service operation who's
     * MEP is In-Only. That is, there is no opportunity to get an error from the
     * service via this API; one may still get client-side errors, such as host
     * unknown etc.
     *
     * @param operation The operation to send fire the message under
     * @param elem      The XML element to send to the service
     * @throws AxisFault If something goes wrong trying to send the XML
     */
    public void fireAndForget(QName operation, OMElement elem) throws AxisFault {
        // look up the appropriate axisop and create the client
        OperationClient mepClient = createClient(operation);
        // create a message context and put the payload in there along with any
        // headers
        MessageContext mc = new MessageContext();
        fillSoapEnvelope(mc, elem);
        // add the message context there and have it go
        mepClient.addMessageContext(mc);
        mepClient.execute(false);
    }

    public OMElement sendReceive(OMElement elem) throws AxisFault {
        return sendReceive(ANON_OUT_IN_OP, elem);
    }

    public OMElement sendReceive(QName operation, OMElement elem)
            throws AxisFault {
        if (options.isUseSeparateListener()) {

            // This mean doing a Request-Response invocation using two channel.
            // If the
            // transport is two way transport (e.g. http) Only one channel is
            // used (e.g. in http cases
            // 202 OK is sent to say no respsone avalible). Axis2 get blocked
            // return when the response is avalible.
            SyncCallBack callback = new SyncCallBack();

            // this method call two channel non blocking method to do the work
            // and wait on the callbck
            sendReceiveNonBlocking(operation, elem, callback);
            long timeout = options.getTimeOutInMilliSeconds();
            synchronized (callback) {
                try {
                    callback.wait(timeout);
                } catch (InterruptedException e) {
                    throw new AxisFault(Messages
                            .getMessage("responseTimeOut"));
                }
            }
            // process the resule of the invocation
            if (callback.envelope != null) {
                // building soap enevlop
                callback.envelope.build();
                // closing tranport
                return callback.envelope.getBody().getFirstElement();
            } else {
                if (callback.error instanceof AxisFault) {
                    throw (AxisFault) callback.error;
                } else {
                    throw new AxisFault(callback.error);
                }
            }
        } else {
            MessageContext mc = new MessageContext();
            fillSoapEnvelope(mc, elem);
            OperationClient mepClient = createClient(operation);
            mepClient.addMessageContext(mc);
            mepClient.execute(true);
            MessageContext response = mepClient
                    .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
            return response.getEnvelope().getBody().getFirstElement();
        }
    }

    public void sendReceiveNonBlocking(OMElement elem, Callback callback)
            throws AxisFault {
        sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
    }

    public void sendReceiveNonBlocking(QName operation, OMElement elem,
                                       Callback callback) throws AxisFault {
        MessageContext mc = new MessageContext();
        fillSoapEnvelope(mc, elem);
        OperationClient mepClient = createClient(operation);
        // here a blocking invocation happens in a new thread, so the
        // progamming model is non blocking
        mepClient.setCallback(callback);
        mepClient.addMessageContext(mc);
        if (options.isUseSeparateListener()) {
            if (callbackReceiver == null) {
                callbackReceiver = new CallbackReceiver();
            }
            axisService.getOperation(operation).setMessageReceiver(
                    callbackReceiver);
        }
        mepClient.execute(false);
    }

    /**
     * Create a MEP client for a specific operation. This is the way one can
     * create a full function MEP client which can be used to exchange messages
     * for this specific operation. If you're using this then you must know what
     * you're doing and need the full capabilities of Axis2's client
     * architecture. This is meant for people with deep skin and not the light
     * user.
     *
     * @param operation The QName of the operation to create a client for.
     * @return a MEP client configured to talk to the given operation or null if
     *         the operation name is not found.
     * @throws AxisFault if the operation is not found or something else goes wrong
     */
    public OperationClient createClient(QName operation) throws AxisFault {
        AxisOperation axisOp = axisService.getOperation(operation);
        if (axisOp == null) {
            throw new AxisFault(Messages
                    .getMessage("operationnotfound", operation.getLocalPart()));
        }

        OperationClient oc = axisOp.createClient(serviceContext, options);

        // if overide options have been set, that means we need to make sure
        // those options override the options of even the operation client. So,
        // what we do is switch the parents around to make that work.
        if (overrideOptions != null) {
            overrideOptions.setParent(oc.getOptions());
            oc.setOptions(overrideOptions);
        }
        return oc;
    }

    /**
     * This will close the out put stream or , and remove entry from waiting
     * queue of the transport Listener queue
     *
     * @throws AxisFault
     */
    public void finalizeInvoke() throws AxisFault {
        configContext.getListenerManager().stop();
    }

    /**
     * Return the SOAP factory to use depending on what options have been set
     * (or default to SOAP 1.1)
     *
     * @return the SOAP factory
     */
    private SOAPFactory getSOAPFactory() {
        String soapVersionURI = options.getSoapVersionURI();
        if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) {
            return OMAbstractFactory.getSOAP12Factory();
        } else {
            // if its not SOAP 1.2 just assume SOAP 1.1
            return OMAbstractFactory.getSOAP11Factory();
        }
    }

    /**
     * Prepare a SOAP envelope with the stuff to be sent.
     *
     * @param mc   the message context to be filled
     * @param elem the payload content
     * @throws AxisFault if something goes wrong
     */
    private void fillSoapEnvelope(MessageContext mc, OMElement elem)
            throws AxisFault {
        mc.setServiceContext(serviceContext);
        SOAPFactory sf = getSOAPFactory();
        SOAPEnvelope se = sf.getDefaultEnvelope();
        if (elem != null) {
            se.getBody().addChild(elem);
        }
        if (headers != null) {
            SOAPHeader sh = se.getHeader();
            for (int i = 0; i < headers.size(); i++) {
                sh.addChild((OMElement) headers.get(i));
            }
        }
        mc.setEnvelope(se);
    }


    /**
     * To get the EPR that the service is running
     * transport : can be null , if it is null then epr will be craetd using any available
     * transports
     */
    public EndpointReference getMyEPR(String transport) throws AxisFault {
        return serviceContext.getMyEPR(transport);
    }

    /**
     * To get the Targert EPR if any in service conetext
     * and reference paramters in TEPR can send back , in the same time this epr can use to manage
     * session across mutiple ServiceClient
     *
     * @return <code>EndpointReference</code>
     */
    public EndpointReference getTargetEPR() {
        return serviceContext.getTargetEPR();
    }

    public void setTargetEPR(EndpointReference targetEpr) {
        serviceContext.setTargetEPR(targetEpr);
    }


    /**
     * This class acts as a callback that allows users to wait on the result.
     */
    private class SyncCallBack extends Callback {
        private SOAPEnvelope envelope;

        private MessageContext msgctx;

        private Exception error;

        public void onComplete(AsyncResult result) {
            this.envelope = result.getResponseEnvelope();
            this.msgctx = result.getResponseMessageContext();
            synchronized (this) {
                notify();
            }
        }

        public void onError(Exception e) {
            error = e;
        }

        public MessageContext getMsgctx() {
            return msgctx;
        }
    }
}
TOP

Related Classes of org.apache.axis2.client.ServiceClient$SyncCallBack

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.