| /* |
| * 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.client; |
| |
| import org.apache.axiom.om.OMAbstractFactory; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.soap.SOAP12Constants; |
| import org.apache.axiom.soap.SOAPEnvelope; |
| import org.apache.axiom.soap.SOAPFactory; |
| import org.apache.axiom.soap.SOAPHeader; |
| import org.apache.axiom.soap.SOAPHeaderBlock; |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.addressing.EndpointReference; |
| import org.apache.axis2.client.async.AxisCallback; |
| import org.apache.axis2.client.async.Callback; |
| import org.apache.axis2.context.ConfigurationContext; |
| import org.apache.axis2.context.ConfigurationContextFactory; |
| import org.apache.axis2.context.MessageContext; |
| import org.apache.axis2.context.OperationContext; |
| import org.apache.axis2.context.ServiceContext; |
| import org.apache.axis2.context.ServiceGroupContext; |
| import org.apache.axis2.description.AxisModule; |
| import org.apache.axis2.description.AxisOperation; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.description.AxisServiceGroup; |
| import org.apache.axis2.description.OutInAxisOperation; |
| import org.apache.axis2.description.OutOnlyAxisOperation; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.axis2.description.RobustOutOnlyAxisOperation; |
| import org.apache.axis2.description.TransportOutDescription; |
| import org.apache.axis2.engine.AxisConfiguration; |
| import org.apache.axis2.engine.ListenerManager; |
| import org.apache.axis2.i18n.Messages; |
| import org.apache.axis2.namespace.Constants; |
| import org.apache.axis2.util.Counter; |
| import org.apache.axis2.util.JavaUtils; |
| import org.apache.axis2.wsdl.WSDLConstants; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.wsdl.Definition; |
| import javax.xml.namespace.QName; |
| import java.net.URL; |
| import java.util.ArrayList; |
| |
| /** |
| * Client access to a service. Each instance of this class is associated with a particular {@link |
| * org.apache.axis2.description.AxisService}, and the methods support operations using that service. |
| * {@link Options} instances are used to configure various aspects of the service access. |
| */ |
| public class ServiceClient { |
| protected static final Log log = LogFactory.getLog(ServiceClient.class); |
| |
| /** Base name used for a service created without an existing configuration. */ |
| public static final String ANON_SERVICE = "anonService"; |
| |
| /** Option property name for automatically cleaning up old OperationContexts */ |
| public static final String AUTO_OPERATION_CLEANUP = "ServiceClient.autoOperationCleanup"; |
| |
| /** Counter used to generate the anonymous service name. */ |
| private static Counter anonServiceCounter = new Counter(); |
| |
| /** |
| * Operation name used for an anonymous out-only operation (meaning we send a message with no |
| * response allowed from the service, equivalent to a WSDL In-Only operation). |
| */ |
| public static final QName ANON_OUT_ONLY_OP = new QName( |
| Constants.AXIS2_NAMESPACE_URI, "anonOutonlyOp", Constants.AXIS2_NAMESPACE_PREFIX); |
| |
| /** |
| * Operation name used for an anonymous robust-out-only operation (meaning we send a message, |
| * with the only possible response a fault, equivalent to a WSDL Robust-In-Only operation). |
| */ |
| public static final QName ANON_ROBUST_OUT_ONLY_OP = new QName( |
| Constants.AXIS2_NAMESPACE_URI, "anonRobustOp", Constants.AXIS2_NAMESPACE_PREFIX); |
| |
| /** |
| * Operation name used for an anonymous in-out operation (meaning we sent a message and receive |
| * a response, equivalent to a WSDL In-Out operation). |
| */ |
| public static final QName ANON_OUT_IN_OP = new QName(Constants.AXIS2_NAMESPACE_URI, |
| "anonOutInOp", |
| Constants.AXIS2_NAMESPACE_PREFIX); |
| |
| // the meta-data of the service that this client access |
| private AxisService axisService; |
| |
| // the configuration in which my meta-data 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<OMElement> headers; |
| |
| //whether we create configctx or not |
| private boolean createConfigCtx; |
| |
| private int hashCode; |
| |
| private boolean removeAxisService; |
| |
| /** |
| * 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 (may be <code>null</code>, in |
| * which case an anonymous service will be created) |
| * @throws AxisFault if something goes wrong while creating a config context (if needed) |
| */ |
| public ServiceClient(ConfigurationContext configContext, |
| AxisService axisService) throws AxisFault { |
| configureServiceClient(configContext, axisService); |
| } |
| |
| private void configureServiceClient(ConfigurationContext configContext, AxisService axisService) |
| throws AxisFault { |
| if (configContext == null) { |
| if (ListenerManager.defaultConfigurationContext == null) { |
| configContext = ConfigurationContextFactory. |
| createConfigurationContextFromFileSystem(null, null); |
| ListenerManager.defaultConfigurationContext = configContext; |
| createConfigCtx = true; |
| } else { |
| configContext = ListenerManager.defaultConfigurationContext; |
| } |
| } |
| this.configContext = configContext; |
| hashCode = (int)anonServiceCounter.incrementAndGet(); |
| |
| // Initialize transports |
| // TODO : do we need this? |
| configContext.getListenerManager(); |
| |
| // save the axisConfig and service |
| axisConfig = configContext.getAxisConfiguration(); |
| |
| if (axisService == null) { |
| axisService = createAnonymousService(); |
| } |
| this.axisService = axisService; |
| // axis service is removed from the configuration context |
| // only if user has not added it to configuration context. |
| if (axisConfig.getService(axisService.getName()) == null) { |
| axisService.setClientSide(true); |
| axisConfig.addService(axisService); |
| removeAxisService = true; |
| } else { |
| axisService.setClientSide(true); |
| removeAxisService = false; |
| } |
| AxisServiceGroup axisServiceGroup = axisService.getAxisServiceGroup(); |
| ServiceGroupContext sgc = configContext.createServiceGroupContext(axisServiceGroup); |
| serviceContext = sgc.getServiceContext(axisService); |
| } |
| |
| |
| /** |
| * This is WSDL4J based constructor to configure the Service Client/ TODO: make this policy |
| * aware |
| * |
| * @param configContext active ConfigurationContext |
| * @param wsdl4jDefinition the WSDL we're going to be using to configure ourselves |
| * @param wsdlServiceName QName of the WSDL service we'd like to access |
| * @param portName name of the WSDL port we'd like to access |
| * @throws AxisFault in case of error |
| */ |
| |
| public ServiceClient(ConfigurationContext configContext, Definition wsdl4jDefinition, |
| QName wsdlServiceName, String portName) throws AxisFault { |
| configureServiceClient(configContext, AxisService.createClientSideAxisService( |
| wsdl4jDefinition, wsdlServiceName, portName, options)); |
| } |
| |
| /** |
| * 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 |
| * <code>null</code>, 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 { |
| configureServiceClient(configContext, AxisService.createClientSideAxisService(wsdlURL, |
| wsdlServiceName, |
| portName, |
| options)); |
| Parameter transportName = axisService.getParameter("TRANSPORT_NAME"); |
| if (transportName != null) { |
| TransportOutDescription transportOut = |
| configContext.getAxisConfiguration().getTransportOut( |
| transportName.getValue().toString()); |
| if (transportOut == null) { |
| throw new AxisFault( |
| "Cannot load transport from binding, either defin in Axis2.config " + |
| "or set it explicitely in ServiceClinet.Options"); |
| } else { |
| options.setTransportOut(transportOut); |
| } |
| } |
| } |
| |
| /** |
| * Create a service client by assuming an anonymous service and any other necessary |
| * information. |
| * |
| * @throws AxisFault in case of error |
| */ |
| public ServiceClient() throws AxisFault { |
| this(null, null); |
| } |
| |
| /** |
| * Create an anonymous axisService with one (anonymous) operation for each MEP that we 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 + anonServiceCounter.incrementAndGet()); |
| 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; |
| } |
| |
| /** |
| * Get the AxisConfiguration |
| * |
| * @return the AxisConfiguration associated with the client. |
| */ |
| public AxisConfiguration getAxisConfiguration() { |
| synchronized (this.axisConfig) { |
| return axisConfig; |
| } |
| } |
| |
| /** |
| * 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 basic client configuration related to this service interaction. |
| * |
| * @param options (non-<code>null</code>) |
| */ |
| public void setOptions(Options options) { |
| this.options = options; |
| } |
| |
| /** |
| * Get the basic client configuration from this service interaction. |
| * |
| * @return options |
| */ |
| public Options getOptions() { |
| return options; |
| } |
| |
| /** |
| * Set a client configuration to override the normal options used by an operation client. Any |
| * values set in this configuration will be used for each client, with the standard values for |
| * the client still used for any values not set in the override configuration. |
| * |
| * @param overrideOptions the Options to use |
| */ |
| public void setOverrideOptions(Options overrideOptions) { |
| this.overrideOptions = overrideOptions; |
| } |
| |
| /** |
| * Get the client configuration used to override the normal options set by an operation client. |
| * |
| * @return override options |
| */ |
| 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 |
| * @deprecated Please use String version instead |
| */ |
| public void engageModule(QName moduleName) throws AxisFault { |
| engageModule(moduleName.getLocalPart()); |
| } |
| |
| /** |
| * Engage a module for this service client. |
| * |
| * @param moduleName name of the module to engage |
| * @throws AxisFault if something goes wrong |
| */ |
| public void engageModule(String moduleName) throws AxisFault { |
| synchronized (this.axisConfig) { |
| AxisModule module = axisConfig.getModule(moduleName); |
| if (module != null) { |
| axisService.engageModule(module); |
| } else { |
| throw new AxisFault("Unable to engage module : " + moduleName); |
| } |
| } |
| } |
| |
| /** |
| * Disengage a module for this service client |
| * |
| * @param moduleName name of Module to disengage |
| * @deprecated Please use String version instead |
| */ |
| public void disengageModule(QName moduleName) { |
| disengageModule(moduleName.getLocalPart()); |
| } |
| |
| /** |
| * Disengage a module for this service client |
| * |
| * @param moduleName name of Module to disengage |
| */ |
| public void disengageModule(String moduleName) { |
| synchronized (this.axisConfig) { |
| AxisModule module = axisConfig.getModule(moduleName); |
| if (module != null) { |
| try { |
| axisService.disengageModule(module); |
| } catch (AxisFault axisFault) { |
| log.error(axisFault.getMessage(), axisFault); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Add an arbitrary XML element as a header to be sent with outgoing messages. |
| * |
| * @param header header to be sent (non-<code>null</code>) |
| */ |
| public void addHeader(OMElement header) { |
| if (headers == null) { |
| headers = new ArrayList<OMElement>(); |
| } |
| headers.add(header); |
| } |
| |
| /** |
| * Add SOAP Header to be sent with outgoing messages. |
| * |
| * @param header header to be sent (non-<code>null</code>) |
| */ |
| public void addHeader(SOAPHeaderBlock header) { |
| if (headers == null) { |
| headers = new ArrayList<OMElement>(); |
| } |
| headers.add(header); |
| } |
| |
| /** Remove all headers for outgoing message. */ |
| public void removeHeaders() { |
| if (headers != null) { |
| headers.clear(); |
| } |
| } |
| |
| |
| /** |
| * Add a simple header containing some text to be sent with interactions. |
| * |
| * @param headerName name of header to add |
| * @param headerText text content for header |
| * @throws AxisFault in case of error |
| */ |
| public void addStringHeader(QName headerName, String headerText) throws AxisFault { |
| if (headerName.getNamespaceURI() == null || "".equals(headerName.getNamespaceURI())) { |
| throw new AxisFault( |
| "Failed to add string header, you have to have namespaceURI for the QName"); |
| } |
| OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(headerName, null); |
| omElement.setText(headerText); |
| addHeader(omElement); |
| } |
| |
| /** |
| * Directly invoke an anonymous operation with a Robust In-Only MEP. This method just sends your |
| * supplied XML and possibly receives a fault. For more control, you can instead create a client |
| * for the operation and use that client to execute the send. |
| * |
| * @param elem XML to send |
| * @throws AxisFault if something goes wrong while sending, or if a fault is received in |
| * response (per the Robust In-Only MEP). |
| * @see #createClient(QName) |
| */ |
| public void sendRobust(OMElement elem) throws AxisFault { |
| sendRobust(ANON_ROBUST_OUT_ONLY_OP, elem); |
| } |
| |
| /** |
| * Directly invoke a named operation with a Robust In-Only MEP. This method just sends your |
| * supplied XML and possibly receives a fault. For more control, you can instead create a client |
| * for the operation and use that client to execute the send. |
| * |
| * @param operation name of operation to be invoked (non-<code>null</code>) |
| * @param elem 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). |
| * @see #createClient(QName) |
| */ |
| public void sendRobust(QName operation, OMElement elem) throws AxisFault { |
| MessageContext mc = new MessageContext(); |
| fillSOAPEnvelope(mc, elem); |
| OperationClient mepClient = createClient(operation); |
| mepClient.addMessageContext(mc); |
| mepClient.execute(true); |
| } |
| |
| /** |
| * Directly invoke an anonymous operation with an In-Only MEP. This method just sends your |
| * supplied XML without the possibility of any response from the service (even an error - though |
| * you can still get client-side errors such as "Host not found"). For more control, you can |
| * instead create a client for the operation and use that client to execute the send. |
| * |
| * @param elem XML to send |
| * @throws AxisFault ff something goes wrong trying to send the XML |
| * @see #createClient(QName) |
| */ |
| public void fireAndForget(OMElement elem) throws AxisFault { |
| fireAndForget(ANON_OUT_ONLY_OP, elem); |
| } |
| |
| /** |
| * Directly invoke a named operation with an In-Only MEP. This method just sends your supplied |
| * XML without the possibility of any response from the service (even an error - though you can |
| * still get client-side errors such as "Host not found"). For more control, you can instead |
| * create a client for the operation and use that client to execute the send. |
| * |
| * @param operation name of operation to be invoked (non-<code>null</code>) |
| * @param elem XML to send |
| * @throws AxisFault if something goes wrong trying to send the XML |
| * @see #createClient(QName) |
| */ |
| 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); |
| } |
| |
| /** |
| * Directly invoke an anonymous operation with an In-Out MEP. This method sends your supplied |
| * XML and receives a response. For more control, you can instead create a client for the |
| * operation and use that client to execute the exchange. |
| * |
| * @param elem the data to send (becomes the content of SOAP body) |
| * @return response |
| * @throws AxisFault in case of error |
| * @see #createClient(QName) |
| */ |
| public OMElement sendReceive(OMElement elem) throws AxisFault { |
| return sendReceive(ANON_OUT_IN_OP, elem); |
| } |
| |
| /** |
| * Directly invoke a named operationQName with an In-Out MEP. This method sends your supplied |
| * XML and receives a response. For more control, you can instead create a client for the |
| * operationQName and use that client to execute the exchange. |
| * |
| * @param operationQName name of operationQName to be invoked (non-<code>null</code>) |
| * @param xmlPayload the data to send (becomes the content of SOAP body) |
| * @return response OMElement |
| * @throws AxisFault in case of error |
| */ |
| public OMElement sendReceive(QName operationQName, OMElement xmlPayload) |
| throws AxisFault { |
| MessageContext messageContext = new MessageContext(); |
| fillSOAPEnvelope(messageContext, xmlPayload); |
| OperationClient operationClient = createClient(operationQName); |
| operationClient.addMessageContext(messageContext); |
| operationClient.execute(true); |
| MessageContext response = operationClient |
| .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE); |
| if (options.isCallTransportCleanup()) { |
| response.getEnvelope().build(); |
| cleanupTransport(); |
| } |
| return response.getEnvelope().getBody().getFirstElement(); |
| } |
| |
| /** |
| * Directly invoke an anonymous operation with an In-Out MEP without waiting for a response. |
| * This method sends your supplied XML with response notification to your callback handler. For |
| * more control, you can instead create a client for the operation and use that client to |
| * execute the exchange. |
| * |
| * @param elem the data to send (becomes the content of SOAP body) |
| * @param callback a Callback which will be notified upon completion |
| * @throws AxisFault in case of error |
| * @see #createClient(QName) |
| * @deprecated Please use the AxisCallback interface rather than Callback, which has been |
| * deprecated |
| */ |
| public void sendReceiveNonBlocking(OMElement elem, Callback callback) |
| throws AxisFault { |
| sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback); |
| } |
| |
| /** |
| * Directly invoke an anonymous operation with an In-Out MEP without waiting for a response. |
| * This method sends your supplied XML with response notification to your callback handler. For |
| * more control, you can instead create a client for the operation and use that client to |
| * execute the exchange. |
| * |
| * @param elem the data to send (becomes the content of SOAP body) |
| * @param callback a Callback which will be notified upon completion |
| * @throws AxisFault in case of error |
| * @see #createClient(QName) |
| */ |
| public void sendReceiveNonBlocking(OMElement elem, AxisCallback callback) |
| throws AxisFault { |
| sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback); |
| } |
| |
| /** |
| * Directly invoke a named operation with an In-Out MEP without waiting for a response. This |
| * method sends your supplied XML with response notification to your callback handler. For more |
| * control, you can instead create a client for the operation and use that client to execute the |
| * exchange. |
| * |
| * @param operation name of operation to be invoked (non-<code>null</code>) |
| * @param elem the data to send (becomes the content of SOAP body) |
| * @param callback a Callback which will be notified upon completion |
| * @throws AxisFault in case of error |
| * @see #createClient(QName) |
| * @deprecated Please use the AxisCallback interface rather than Callback, which has been |
| * deprecated |
| */ |
| 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); |
| mepClient.execute(false); |
| } |
| |
| /** |
| * Directly invoke a named operation with an In-Out MEP without waiting for a response. This |
| * method sends your supplied XML with response notification to your callback handler. For more |
| * control, you can instead create a client for the operation and use that client to execute the |
| * exchange. |
| * |
| * @param operation name of operation to be invoked (non-<code>null</code>) |
| * @param elem the data to send (becomes the content of SOAP body) |
| * @param callback a Callback which will be notified upon completion |
| * @throws AxisFault in case of error |
| * @see #createClient(QName) |
| */ |
| public void sendReceiveNonBlocking(QName operation, OMElement elem, AxisCallback 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); |
| mepClient.execute(false); |
| } |
| |
| /** |
| * Create an operation client with the appropriate message exchange pattern (MEP). This method |
| * creates a full-function MEP client which can be used to exchange messages for a specific |
| * operation. It configures the constructed operation client to use the current normal and |
| * override options. This method is used internally, and also by generated client stub code. |
| * |
| * @param operationQName qualified name of operation (local name is operation name, namespace |
| * URI is just the empty string) |
| * @return client configured to talk to the given operation |
| * @throws AxisFault if the operation is not found |
| */ |
| public OperationClient createClient(QName operationQName) throws AxisFault { |
| // If we're configured to do so, clean up the last OperationContext (thus |
| // releasing its resources) each time we create a new one. |
| if (JavaUtils.isTrue(getOptions().getProperty(AUTO_OPERATION_CLEANUP), true) && |
| !getOptions().isUseSeparateListener()) { |
| cleanupTransport(); |
| } |
| |
| AxisOperation axisOperation = axisService.getOperation(operationQName); |
| if (axisOperation == null) { |
| throw new AxisFault(Messages |
| .getMessage("operationnotfound", operationQName.getLocalPart())); |
| } |
| |
| // add the option properties to the service context |
| String key; |
| for (Object o : options.getProperties().keySet()) { |
| key = (String)o; |
| serviceContext.setProperty(key, options.getProperties().get(key)); |
| } |
| OperationClient operationClient = axisOperation.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(operationClient.getOptions()); |
| operationClient.setOptions(overrideOptions); |
| } |
| return operationClient; |
| } |
| |
| /** |
| * Return the SOAP factory to use depending on what options have been set. If the SOAP version |
| * can not be seen in the options, version 1.1 is the default. |
| * |
| * @return the SOAP factory |
| * @see Options#setSoapVersionURI(String) |
| */ |
| private SOAPFactory getSOAPFactory() { |
| String soapVersionURI = options.getSoapVersionURI(); |
| if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) { |
| return OMAbstractFactory.getSOAP12Factory(); |
| } else { |
| // make the SOAP 1.1 the default SOAP version |
| return OMAbstractFactory.getSOAP11Factory(); |
| } |
| } |
| |
| /** |
| * Prepare a SOAP envelope with the stuff to be sent. |
| * |
| * @param messageContext the message context to be filled |
| * @param xmlPayload the payload content |
| * @throws AxisFault if something goes wrong |
| */ |
| private void fillSOAPEnvelope(MessageContext messageContext, OMElement xmlPayload) |
| throws AxisFault { |
| messageContext.setServiceContext(serviceContext); |
| SOAPFactory soapFactory = getSOAPFactory(); |
| SOAPEnvelope envelope = soapFactory.getDefaultEnvelope(); |
| if (xmlPayload != null) { |
| envelope.getBody().addChild(xmlPayload); |
| } |
| addHeadersToEnvelope(envelope); |
| messageContext.setEnvelope(envelope); |
| } |
| |
| |
| /** |
| * Add all configured headers to a SOAP envelope. |
| * |
| * @param envelope the SOAPEnvelope in which to write the headers |
| */ |
| public void addHeadersToEnvelope(SOAPEnvelope envelope) { |
| if (headers != null) { |
| SOAPHeader soapHeader = envelope.getHeader(); |
| for (Object header : headers) { |
| soapHeader.addChild((OMElement)header); |
| } |
| } |
| } |
| |
| |
| /** |
| * Get the endpoint reference for this client using a particular transport. |
| * |
| * @param transport transport name (non-<code>null</code>) |
| * @return local endpoint |
| * @throws AxisFault in case of error |
| */ |
| public EndpointReference getMyEPR(String transport) throws AxisFault { |
| return serviceContext.getMyEPR(transport); |
| } |
| |
| /** |
| * Get the endpoint reference for the service. |
| * |
| * @return service endpoint |
| */ |
| public EndpointReference getTargetEPR() { |
| return serviceContext.getTargetEPR(); |
| } |
| |
| /** |
| * Set the endpoint reference for the service. |
| * |
| * @param targetEpr the EPR this ServiceClient should target |
| */ |
| public void setTargetEPR(EndpointReference targetEpr) { |
| serviceContext.setTargetEPR(targetEpr); |
| options.setTo(targetEpr); |
| } |
| |
| /** |
| * Gets the last OperationContext |
| * |
| * @return the last OperationContext that was invoked by this ServiceClient |
| */ |
| public OperationContext getLastOperationContext() { |
| return serviceContext.getLastOperationContext(); |
| } |
| |
| /** |
| * Sets whether or not to cache the last OperationContext |
| * |
| * @param cachingOpContext true if we should hold onto the last active OperationContext |
| * @deprecated |
| */ |
| public void setCachingOperationContext(boolean cachingOpContext) { |
| serviceContext.setCachingOperationContext(cachingOpContext); |
| } |
| |
| |
| /** |
| * Get the service context. |
| * |
| * @return context |
| */ |
| public ServiceContext getServiceContext() { |
| return serviceContext; |
| } |
| |
| protected void finalize() throws Throwable { |
| try { |
| cleanup(); |
| } finally { |
| super.finalize(); |
| } |
| } |
| |
| /** |
| * Clean up configuration created with this client. Call this method when you're done using the |
| * client, in order to discard any associated resources. |
| * |
| * @throws AxisFault in case of error |
| */ |
| public void cleanup() throws AxisFault { |
| // if a configuration context was created for this client there'll also |
| // be a service group, so discard that |
| if (!createConfigCtx) { |
| String serviceGroupName = axisService.getAxisServiceGroup().getServiceGroupName(); |
| AxisConfiguration axisConfiguration = configContext.getAxisConfiguration(); |
| AxisServiceGroup asg = axisConfiguration.getServiceGroup(serviceGroupName); |
| if ((asg != null) && removeAxisService) { |
| axisConfiguration.removeServiceGroup(serviceGroupName); |
| } |
| } else { |
| configContext.terminate(); |
| } |
| } |
| |
| public void cleanupTransport() throws AxisFault { |
| final OperationContext lastOperationContext = getLastOperationContext(); |
| if (lastOperationContext != null) { |
| MessageContext outMessageContext = |
| lastOperationContext |
| .getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE); |
| if (outMessageContext != null) { |
| outMessageContext.getTransportOut().getSender().cleanup(outMessageContext); |
| } |
| } |
| } |
| |
| /** |
| * Configure the ServiceClient to interact with the Web service described by the specified |
| * AxisService object. |
| * |
| * @param axisService the AxisService that represents the new Web service. |
| * @throws AxisFault if an error occurs while configuring the ServiceClient. |
| */ |
| public void setAxisService(AxisService axisService) throws AxisFault { |
| |
| if (axisService == null) { |
| // AxisFault? |
| throw new IllegalArgumentException("AxisService is null"); |
| } |
| |
| synchronized (this.axisConfig) { |
| axisConfig.removeService(this.axisService.getName()); |
| this.axisService = axisService; |
| |
| axisService.setClientSide(true); |
| axisConfig.addService(axisService); |
| } |
| AxisServiceGroup axisServiceGroup = axisService.getAxisServiceGroup(); |
| ServiceGroupContext serviceGroupContext = |
| configContext.createServiceGroupContext(axisServiceGroup); |
| this.serviceContext = serviceGroupContext.getServiceContext(axisService); |
| } |
| |
| /** @see java.lang.Object#hashCode() */ |
| public int hashCode() { |
| return this.hashCode; |
| } |
| |
| /** @see java.lang.Object#equals(java.lang.Object) */ |
| public boolean equals(Object obj) { |
| if (this == obj) |
| return true; |
| if (obj == null) |
| return false; |
| if (!(obj instanceof ServiceClient)) |
| return false; |
| final ServiceClient other = (ServiceClient)obj; |
| return hashCode == other.hashCode; |
| } |
| |
| } |