001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.client;
021:
022: import org.apache.axiom.om.OMAbstractFactory;
023: import org.apache.axiom.om.OMElement;
024: import org.apache.axiom.soap.SOAP12Constants;
025: import org.apache.axiom.soap.SOAPEnvelope;
026: import org.apache.axiom.soap.SOAPFactory;
027: import org.apache.axiom.soap.SOAPHeader;
028: import org.apache.axiom.soap.SOAPHeaderBlock;
029: import org.apache.axis2.AxisFault;
030: import org.apache.axis2.util.Counter;
031: import org.apache.axis2.addressing.EndpointReference;
032: import org.apache.axis2.client.async.Callback;
033: import org.apache.axis2.client.async.AxisCallback;
034: import org.apache.axis2.context.ConfigurationContext;
035: import org.apache.axis2.context.ConfigurationContextFactory;
036: import org.apache.axis2.context.MessageContext;
037: import org.apache.axis2.context.OperationContext;
038: import org.apache.axis2.context.ServiceContext;
039: import org.apache.axis2.context.ServiceGroupContext;
040: import org.apache.axis2.description.AxisModule;
041: import org.apache.axis2.description.AxisOperation;
042: import org.apache.axis2.description.AxisService;
043: import org.apache.axis2.description.AxisServiceGroup;
044: import org.apache.axis2.description.OutInAxisOperation;
045: import org.apache.axis2.description.OutOnlyAxisOperation;
046: import org.apache.axis2.description.RobustOutOnlyAxisOperation;
047: import org.apache.axis2.engine.AxisConfiguration;
048: import org.apache.axis2.engine.ListenerManager;
049: import org.apache.axis2.i18n.Messages;
050: import org.apache.axis2.wsdl.WSDLConstants;
051: import org.apache.commons.logging.LogFactory;
052: import org.apache.commons.logging.Log;
053:
054: import javax.wsdl.Definition;
055: import javax.xml.namespace.QName;
056: import java.net.URL;
057: import java.util.ArrayList;
058:
059: /**
060: * Client access to a service. Each instance of this class is associated with a
061: * particular {@link org.apache.axis2.description.AxisService}, and the methods
062: * support operations using that service. {@link Options} instances are used to
063: * configure various aspects of the service access.
064: */
065: public class ServiceClient {
066: protected static final Log log = LogFactory
067: .getLog(ServiceClient.class);
068:
069: /**
070: * Base name used for a service created without an existing configuration.
071: */
072: public static final String ANON_SERVICE = "anonService";
073:
074: /** Counter used to generate the anonymous service name. */
075: private static Counter anonServiceCounter = new Counter();
076:
077: /**
078: * Operation name used for an anonymous out-only operation (meaning we send
079: * a message with no response allowed from the service, equivalent to a WSDL
080: * In-Only operation).
081: */
082: public static final QName ANON_OUT_ONLY_OP = new QName(
083: "anonOutonlyOp");
084:
085: /**
086: * Operation name used for an anonymous robust-out-only operation
087: * (meaning we send a message, with the only possible response a fault,
088: * equivalent to a WSDL Robust-In-Only operation).
089: */
090: public static final QName ANON_ROBUST_OUT_ONLY_OP = new QName(
091: "anonRobustOp");
092:
093: /**
094: * Operation name used for an anonymous in-out operation (meaning we sent a
095: * message and receive a response, equivalent to a WSDL In-Out operation).
096: */
097: public static final QName ANON_OUT_IN_OP = new QName("anonOutInOp");
098:
099: // the meta-data of the service that this client access
100: private AxisService axisService;
101:
102: // the configuration in which my meta-data lives
103: private AxisConfiguration axisConfig;
104:
105: // the configuration context in which I live
106: private ConfigurationContext configContext;
107:
108: // service context for this specific service instance
109: private ServiceContext serviceContext;
110:
111: // client options for this service interaction
112: private Options options = new Options();
113:
114: // options that must override those of the child operation client also
115: private Options overrideOptions;
116:
117: // list of headers to be sent with the simple APIs
118: private ArrayList headers;
119:
120: //whether we create configctx or not
121: private boolean createConfigCtx;
122:
123: /**
124: * Create a service client configured to work with a specific AxisService.
125: * If this service is already in the world that's handed in (in the form of
126: * a ConfigurationContext) then I will happily work in it. If not I will
127: * create a small little virtual world and live there.
128: *
129: * @param configContext The configuration context under which this service lives (may
130: * be null, in which case a new local one will be created)
131: * @param axisService The service for which this is the client (may be
132: * <code>null</code>, in which case an anonymous service will be created)
133: * @throws AxisFault if something goes wrong while creating a config context (if
134: * needed)
135: */
136: public ServiceClient(ConfigurationContext configContext,
137: AxisService axisService) throws AxisFault {
138: configureServiceClient(configContext, axisService);
139: }
140:
141: private void configureServiceClient(
142: ConfigurationContext configContext, AxisService axisService)
143: throws AxisFault {
144: if (configContext == null) {
145: if (ListenerManager.defaultConfigurationContext == null) {
146: configContext = ConfigurationContextFactory
147: .createConfigurationContextFromFileSystem(null,
148: null);
149: createConfigCtx = true;
150: } else {
151: configContext = ListenerManager.defaultConfigurationContext;
152: }
153: }
154: this .configContext = configContext;
155:
156: // Initialize transports
157: ListenerManager transportManager = configContext
158: .getListenerManager();
159: if (transportManager == null) {
160: transportManager = new ListenerManager();
161: transportManager.init(this .configContext);
162: }
163:
164: // save the axisConfig and service
165: axisConfig = configContext.getAxisConfiguration();
166: if (axisService == null) {
167: axisService = createAnonymousService();
168: }
169: this .axisService = axisService;
170: if (axisConfig.getService(axisService.getName()) == null) {
171: axisService.setClientSide(true);
172: axisConfig.addService(axisService);
173: } else {
174: throw new AxisFault(Messages.getMessage(
175: "twoservicecannothavesamename", axisService
176: .getName()));
177: }
178: AxisServiceGroup axisServiceGroup = axisService
179: .getAxisServiceGroup();
180: ServiceGroupContext sgc = configContext
181: .createServiceGroupContext(axisServiceGroup);
182: serviceContext = sgc.getServiceContext(axisService);
183: }
184:
185: /**
186: * This is WSDL4J based constructor to configure the Service Client/
187: * TODO: make this policy aware
188: *
189: * @param configContext active ConfigurationContext
190: * @param wsdl4jDefinition the WSDL we're going to be using to configure ourselves
191: * @param wsdlServiceName QName of the WSDL service we'd like to access
192: * @param portName name of the WSDL port we'd like to access
193: * @throws AxisFault in case of error
194: */
195:
196: public ServiceClient(ConfigurationContext configContext,
197: Definition wsdl4jDefinition, QName wsdlServiceName,
198: String portName) throws AxisFault {
199: configureServiceClient(configContext, AxisService
200: .createClientSideAxisService(wsdl4jDefinition,
201: wsdlServiceName, portName, options));
202: }
203:
204: /**
205: * Create a service client for WSDL service identified by the QName of the
206: * wsdl:service element in a WSDL document.
207: *
208: * @param configContext The configuration context under which this service lives (may
209: * be <code>null</code>, in which case a new local one will be created) *
210: * @param wsdlURL The URL of the WSDL document to read
211: * @param wsdlServiceName The QName of the WSDL service in the WSDL document to create a
212: * client for
213: * @param portName The name of the WSDL 1.1 port to create a client for. May be
214: * null (if WSDL 2.0 is used or if only one port is there). .
215: * @throws AxisFault if something goes wrong while creating a config context (if
216: * needed)
217: */
218: public ServiceClient(ConfigurationContext configContext,
219: URL wsdlURL, QName wsdlServiceName, String portName)
220: throws AxisFault {
221: configureServiceClient(configContext, AxisService
222: .createClientSideAxisService(wsdlURL, wsdlServiceName,
223: portName, options));
224: }
225:
226: /**
227: * Create a service client by assuming an anonymous service and any other
228: * necessary information.
229: *
230: * @throws AxisFault in case of error
231: */
232: public ServiceClient() throws AxisFault {
233: this (null, null);
234: }
235:
236: /**
237: * Create an anonymous axisService with one (anonymous) operation for each
238: * MEP that we support dealing with anonymously using the convenience APIs.
239: *
240: * @return the minted anonymous service
241: */
242: private AxisService createAnonymousService() {
243: // now add anonymous operations to the axis2 service for use with the
244: // shortcut client API. NOTE: We only add the ones we know we'll use
245: // later in the convenience API; if you use
246: // this constructor then you can't expect any magic!
247: AxisService axisService = new AxisService(ANON_SERVICE
248: + anonServiceCounter.incrementAndGet());
249: RobustOutOnlyAxisOperation robustoutoonlyOperation = new RobustOutOnlyAxisOperation(
250: ANON_ROBUST_OUT_ONLY_OP);
251: axisService.addOperation(robustoutoonlyOperation);
252:
253: OutOnlyAxisOperation outOnlyOperation = new OutOnlyAxisOperation(
254: ANON_OUT_ONLY_OP);
255: axisService.addOperation(outOnlyOperation);
256:
257: OutInAxisOperation outInOperation = new OutInAxisOperation(
258: ANON_OUT_IN_OP);
259: axisService.addOperation(outInOperation);
260: return axisService;
261: }
262:
263: /**
264: * Returns the AxisConfiguration associated with the client.
265: */
266: public AxisConfiguration getAxisConfiguration() {
267: return axisConfig;
268: }
269:
270: /**
271: * Return the AxisService this is a client for. This is primarily useful
272: * when the AxisService is created anonymously or from WSDL as otherwise the
273: * user had the AxisService to start with.
274: *
275: * @return the axisService
276: */
277: public AxisService getAxisService() {
278: return axisService;
279: }
280:
281: /**
282: * Set the basic client configuration related to this service interaction.
283: *
284: * @param options (non-<code>null</code>)
285: */
286: public void setOptions(Options options) {
287: this .options = options;
288: }
289:
290: /**
291: * Get the basic client configuration from this service interaction.
292: *
293: * @return options
294: */
295: public Options getOptions() {
296: return options;
297: }
298:
299: /**
300: * Set a client configuration to override the normal options used by an
301: * operation client. Any values set in this configuration will be used for
302: * each client, with the standard values for the client still used for any
303: * values not set in the override configuration.
304: *
305: * @param overrideOptions the Options to use
306: */
307: public void setOverrideOptions(Options overrideOptions) {
308: this .overrideOptions = overrideOptions;
309: }
310:
311: /**
312: * Get the client configuration used to override the normal options set by
313: * an operation client.
314: *
315: * @return override options
316: */
317: public Options getOverrideOptions() {
318: return overrideOptions;
319: }
320:
321: /**
322: * Engage a module for this service client.
323: *
324: * @deprecated Please use String version instead
325: * @param moduleName name of the module to engage
326: * @throws AxisFault if something goes wrong
327: */
328: public void engageModule(QName moduleName) throws AxisFault {
329: engageModule(moduleName.getLocalPart());
330: }
331:
332: /**
333: * Engage a module for this service client.
334: *
335: * @param moduleName name of the module to engage
336: * @throws AxisFault if something goes wrong
337: */
338: public void engageModule(String moduleName) throws AxisFault {
339: synchronized (this ) {
340: AxisModule module = axisConfig.getModule(moduleName);
341: if (module != null) {
342: axisService.engageModule(module);
343: } else {
344: throw new AxisFault("Unable to engage module : "
345: + moduleName);
346: }
347: }
348: }
349:
350: /**
351: * Disengage a module for this service client
352: *
353: * @deprecated Please use String version instead
354: * @param moduleName name of Module to disengage
355: */
356: public void disengageModule(QName moduleName) {
357: disengageModule(moduleName.getLocalPart());
358: }
359:
360: /**
361: * Disengage a module for this service client
362: *
363: * @param moduleName name of Module to disengage
364: */
365: public void disengageModule(String moduleName) {
366: AxisModule module = axisConfig.getModule(moduleName);
367: if (module != null) {
368: try {
369: axisService.disengageModule(module);
370: } catch (AxisFault axisFault) {
371: log.error(axisFault.getMessage(), axisFault);
372: }
373: }
374: }
375:
376: /**
377: * Add an arbitrary XML element as a header to be sent with outgoing
378: * messages.
379: *
380: * @param header header to be sent (non-<code>null</code>)
381: */
382: public void addHeader(OMElement header) {
383: if (headers == null) {
384: headers = new ArrayList();
385: }
386: headers.add(header);
387: }
388:
389: /**
390: * Add SOAP Header to be sent with outgoing messages.
391: *
392: * @param header header to be sent (non-<code>null</code>)
393: */
394: public void addHeader(SOAPHeaderBlock header) {
395: if (headers == null) {
396: headers = new ArrayList();
397: }
398: headers.add(header);
399: }
400:
401: /**
402: * Remove all headers for outgoing message.
403: */
404: public void removeHeaders() {
405: if (headers != null) {
406: headers.clear();
407: }
408: }
409:
410: /**
411: * Add a simple header containing some text to be sent with interactions.
412: *
413: * @param headerName name of header to add
414: * @param headerText text content for header
415: * @throws AxisFault in case of error
416: */
417: public void addStringHeader(QName headerName, String headerText)
418: throws AxisFault {
419: if (headerName.getNamespaceURI() == null
420: || "".equals(headerName.getNamespaceURI())) {
421: throw new AxisFault(
422: "Failed to add string header, you have to have namespaceURI for the QName");
423: }
424: OMElement omElement = OMAbstractFactory.getOMFactory()
425: .createOMElement(headerName, null);
426: omElement.setText(headerText);
427: addHeader(omElement);
428: }
429:
430: /**
431: * Directly invoke an anonymous operation with a Robust In-Only MEP. This
432: * method just sends your supplied XML and possibly receives a fault. For
433: * more control, you can instead create a client for the operation and use
434: * that client to execute the send.
435: *
436: * @param elem XML to send
437: * @throws AxisFault if something goes wrong while sending, or if a fault is
438: * received in response (per the Robust In-Only MEP).
439: * @see #createClient(QName)
440: */
441: public void sendRobust(OMElement elem) throws AxisFault {
442: sendRobust(ANON_ROBUST_OUT_ONLY_OP, elem);
443: }
444:
445: /**
446: * Directly invoke a named operation with a Robust In-Only MEP. This method
447: * just sends your supplied XML and possibly receives a fault. For more
448: * control, you can instead create a client for the operation and use that
449: * client to execute the send.
450: *
451: * @param operation name of operation to be invoked (non-<code>null</code>)
452: * @param elem XML to send
453: * @throws AxisFault if something goes wrong while sending it or if a fault is
454: * received in response (per the Robust In-Only MEP).
455: * @see #createClient(QName)
456: */
457: public void sendRobust(QName operation, OMElement elem)
458: throws AxisFault {
459: MessageContext mc = new MessageContext();
460: fillSOAPEnvelope(mc, elem);
461: OperationClient mepClient = createClient(operation);
462: mepClient.addMessageContext(mc);
463: mepClient.execute(true);
464: }
465:
466: /**
467: * Directly invoke an anonymous operation with an In-Only MEP. This method
468: * just sends your supplied XML without the possibility of any response from
469: * the service (even an error - though you can still get client-side errors
470: * such as "Host not found"). For more control, you can instead create a
471: * client for the operation and use that client to execute the send.
472: *
473: * @param elem XML to send
474: * @throws AxisFault ff something goes wrong trying to send the XML
475: * @see #createClient(QName)
476: */
477: public void fireAndForget(OMElement elem) throws AxisFault {
478: fireAndForget(ANON_OUT_ONLY_OP, elem);
479: }
480:
481: /**
482: * Directly invoke a named operation with an In-Only MEP. This method just
483: * sends your supplied XML without the possibility of any response from the
484: * service (even an error - though you can still get client-side errors such
485: * as "Host not found"). For more control, you can instead create a client
486: * for the operation and use that client to execute the send.
487: *
488: * @param operation name of operation to be invoked (non-<code>null</code>)
489: * @param elem XML to send
490: * @throws AxisFault if something goes wrong trying to send the XML
491: * @see #createClient(QName)
492: */
493: public void fireAndForget(QName operation, OMElement elem)
494: throws AxisFault {
495: // look up the appropriate axisop and create the client
496: OperationClient mepClient = createClient(operation);
497: // create a message context and put the payload in there along with any
498: // headers
499: MessageContext mc = new MessageContext();
500: fillSOAPEnvelope(mc, elem);
501: // add the message context there and have it go
502: mepClient.addMessageContext(mc);
503: mepClient.execute(false);
504: }
505:
506: /**
507: * Directly invoke an anonymous operation with an In-Out MEP. This method
508: * sends your supplied XML and receives a response. For more control, you
509: * can instead create a client for the operation and use that client to
510: * execute the exchange.
511: *
512: * @param elem the data to send (becomes the content of SOAP body)
513: * @return response
514: * @throws AxisFault in case of error
515: * @see #createClient(QName)
516: */
517: public OMElement sendReceive(OMElement elem) throws AxisFault {
518: return sendReceive(ANON_OUT_IN_OP, elem);
519: }
520:
521: /**
522: * Directly invoke a named operationQName with an In-Out MEP. This method sends
523: * your supplied XML and receives a response. For more control, you can
524: * instead create a client for the operationQName and use that client to execute
525: * the exchange.
526: *
527: * @param operationQName name of operationQName to be invoked (non-<code>null</code>)
528: * @param xmlPayload the data to send (becomes the content of SOAP body)
529: * @return response OMElement
530: * @throws AxisFault in case of error
531: */
532: public OMElement sendReceive(QName operationQName,
533: OMElement xmlPayload) throws AxisFault {
534: MessageContext messageContext = new MessageContext();
535: fillSOAPEnvelope(messageContext, xmlPayload);
536: OperationClient operationClient = createClient(operationQName);
537: operationClient.addMessageContext(messageContext);
538: operationClient.execute(true);
539: MessageContext response = operationClient
540: .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
541: if (options.isCallTransportCleanup()) {
542: response.getEnvelope().build();
543: cleanupTransport();
544: return response.getEnvelope().getBody().getFirstElement();
545: } else {
546: return response.getEnvelope().getBody().getFirstElement();
547: }
548: }
549:
550: /**
551: * Directly invoke an anonymous operation with an In-Out MEP without waiting
552: * for a response. This method sends your supplied XML with response
553: * notification to your callback handler. For more control, you can instead
554: * create a client for the operation and use that client to execute the
555: * exchange.
556: *
557: * @param elem the data to send (becomes the content of SOAP body)
558: * @param callback a Callback which will be notified upon completion
559: * @throws AxisFault in case of error
560: * @see #createClient(QName)
561: * @deprecated Please use the AxisCallback interface rather than Callback, which has been deprecated
562: */
563: public void sendReceiveNonBlocking(OMElement elem, Callback callback)
564: throws AxisFault {
565: sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
566: }
567:
568: /**
569: * Directly invoke an anonymous operation with an In-Out MEP without waiting
570: * for a response. This method sends your supplied XML with response
571: * notification to your callback handler. For more control, you can instead
572: * create a client for the operation and use that client to execute the
573: * exchange.
574: *
575: * @param elem the data to send (becomes the content of SOAP body)
576: * @param callback a Callback which will be notified upon completion
577: * @throws AxisFault in case of error
578: * @see #createClient(QName)
579: */
580: public void sendReceiveNonBlocking(OMElement elem,
581: AxisCallback callback) throws AxisFault {
582: sendReceiveNonBlocking(ANON_OUT_IN_OP, elem, callback);
583: }
584:
585: /**
586: * Directly invoke a named operation with an In-Out MEP without waiting for
587: * a response. This method sends your supplied XML with response
588: * notification to your callback handler. For more control, you can instead
589: * create a client for the operation and use that client to execute the
590: * exchange.
591: *
592: * @param operation name of operation to be invoked (non-<code>null</code>)
593: * @param elem the data to send (becomes the content of SOAP body)
594: * @param callback a Callback which will be notified upon completion
595: * @throws AxisFault in case of error
596: * @see #createClient(QName)
597: * @deprecated Please use the AxisCallback interface rather than Callback, which has been deprecated
598: */
599: public void sendReceiveNonBlocking(QName operation, OMElement elem,
600: Callback callback) throws AxisFault {
601: MessageContext mc = new MessageContext();
602: fillSOAPEnvelope(mc, elem);
603: OperationClient mepClient = createClient(operation);
604: // here a blocking invocation happens in a new thread, so the
605: // progamming model is non blocking
606: mepClient.setCallback(callback);
607: mepClient.addMessageContext(mc);
608: mepClient.execute(false);
609: }
610:
611: /**
612: * Directly invoke a named operation with an In-Out MEP without waiting for
613: * a response. This method sends your supplied XML with response
614: * notification to your callback handler. For more control, you can instead
615: * create a client for the operation and use that client to execute the
616: * exchange.
617: *
618: * @param operation name of operation to be invoked (non-<code>null</code>)
619: * @param elem the data to send (becomes the content of SOAP body)
620: * @param callback a Callback which will be notified upon completion
621: * @throws AxisFault in case of error
622: * @see #createClient(QName)
623: */
624: public void sendReceiveNonBlocking(QName operation, OMElement elem,
625: AxisCallback callback) throws AxisFault {
626: MessageContext mc = new MessageContext();
627: fillSOAPEnvelope(mc, elem);
628: OperationClient mepClient = createClient(operation);
629: // here a blocking invocation happens in a new thread, so the
630: // progamming model is non blocking
631: mepClient.setCallback(callback);
632: mepClient.addMessageContext(mc);
633: mepClient.execute(false);
634: }
635:
636: /**
637: * Create an operation client with the appropriate message exchange pattern
638: * (MEP). This method creates a full-function MEP client which can be used
639: * to exchange messages for a specific operation. It configures the
640: * constructed operation client to use the current normal and override
641: * options. This method is used internally, and also by generated client
642: * stub code.
643: *
644: * @param operationQName qualified name of operation (local name is operation
645: * name, namespace URI is just the empty string)
646: * @return client configured to talk to the given operation
647: * @throws AxisFault if the operation is not found
648: */
649: public OperationClient createClient(QName operationQName)
650: throws AxisFault {
651: AxisOperation axisOperation = axisService
652: .getOperation(operationQName);
653: if (axisOperation == null) {
654: throw new AxisFault(Messages.getMessage(
655: "operationnotfound", operationQName.getLocalPart()));
656: }
657:
658: OperationClient operationClient = axisOperation.createClient(
659: serviceContext, options);
660:
661: // if overide options have been set, that means we need to make sure
662: // those options override the options of even the operation client. So,
663: // what we do is switch the parents around to make that work.
664: if (overrideOptions != null) {
665: overrideOptions.setParent(operationClient.getOptions());
666: operationClient.setOptions(overrideOptions);
667: }
668: return operationClient;
669: }
670:
671: /**
672: * Return the SOAP factory to use depending on what options have been set.
673: * If the SOAP version can not be seen in the options, version 1.1 is the
674: * default.
675: *
676: * @return the SOAP factory
677: * @see Options#setSoapVersionURI(String)
678: */
679: private SOAPFactory getSOAPFactory() {
680: String soapVersionURI = options.getSoapVersionURI();
681: if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI
682: .equals(soapVersionURI)) {
683: return OMAbstractFactory.getSOAP12Factory();
684: } else {
685: // make the SOAP 1.1 the default SOAP version
686: return OMAbstractFactory.getSOAP11Factory();
687: }
688: }
689:
690: /**
691: * Prepare a SOAP envelope with the stuff to be sent.
692: *
693: * @param messageContext the message context to be filled
694: * @param xmlPayload the payload content
695: * @throws AxisFault if something goes wrong
696: */
697: private void fillSOAPEnvelope(MessageContext messageContext,
698: OMElement xmlPayload) throws AxisFault {
699: messageContext.setServiceContext(serviceContext);
700: SOAPFactory soapFactory = getSOAPFactory();
701: SOAPEnvelope envelope = soapFactory.getDefaultEnvelope();
702: if (xmlPayload != null) {
703: envelope.getBody().addChild(xmlPayload);
704: }
705: addHeadersToEnvelope(envelope);
706: messageContext.setEnvelope(envelope);
707: }
708:
709: /**
710: * Add all configured headers to a SOAP envelope.
711: *
712: * @param envelope the SOAPEnvelope in which to write the headers
713: */
714: public void addHeadersToEnvelope(SOAPEnvelope envelope) {
715: if (headers != null) {
716: SOAPHeader soapHeader = envelope.getHeader();
717: for (int i = 0; i < headers.size(); i++) {
718: soapHeader.addChild((OMElement) headers.get(i));
719: }
720: }
721: }
722:
723: /**
724: * Get the endpoint reference for this client using a particular transport.
725: *
726: * @param transport transport name (non-<code>null</code>)
727: * @return local endpoint
728: * @throws AxisFault in case of error
729: */
730: public EndpointReference getMyEPR(String transport)
731: throws AxisFault {
732: return serviceContext.getMyEPR(transport);
733: }
734:
735: /**
736: * Get the endpoint reference for the service.
737: *
738: * @return service endpoint
739: */
740: public EndpointReference getTargetEPR() {
741: return serviceContext.getTargetEPR();
742: }
743:
744: /**
745: * Set the endpoint reference for the service.
746: *
747: * @param targetEpr the EPR this ServiceClient should target
748: */
749: public void setTargetEPR(EndpointReference targetEpr) {
750: serviceContext.setTargetEPR(targetEpr);
751: options.setTo(targetEpr);
752: }
753:
754: /**
755: * Gets the last OperationContext
756: *
757: * @return the last OperationContext that was invoked by this ServiceClient
758: */
759: public OperationContext getLastOperationContext() {
760: return serviceContext.getLastOperationContext();
761: }
762:
763: /**
764: * Sets whether or not to cache the last OperationContext
765: * @deprecated
766: * @param cachingOpContext true if we should hold onto the last active OperationContext
767: */
768: public void setCachingOperationContext(boolean cachingOpContext) {
769: serviceContext.setCachingOperationContext(cachingOpContext);
770: }
771:
772: /**
773: * Get the service context.
774: *
775: * @return context
776: */
777: public ServiceContext getServiceContext() {
778: return serviceContext;
779: }
780:
781: protected void finalize() throws Throwable {
782: super .finalize();
783: cleanup();
784: }
785:
786: /**
787: * Clean up configuration created with this client. Call this method when
788: * you're done using the client, in order to discard any associated
789: * resources.
790: *
791: * @throws AxisFault in case of error
792: */
793: public void cleanup() throws AxisFault {
794: // if a configuration context was created for this client there'll also
795: // be a service group, so discard that
796: if (!createConfigCtx) {
797: String serviceGroupName = axisService.getAxisServiceGroup()
798: .getServiceGroupName();
799: AxisConfiguration axisConfiguration = configContext
800: .getAxisConfiguration();
801: AxisServiceGroup asg = axisConfiguration
802: .getServiceGroup(serviceGroupName);
803: if (asg != null) {
804: axisConfiguration.removeServiceGroup(serviceGroupName);
805: }
806: } else {
807: configContext.terminate();
808: }
809: }
810:
811: public void cleanupTransport() throws AxisFault {
812: if (getLastOperationContext() != null) {
813: MessageContext outMessageContext = getLastOperationContext()
814: .getMessageContext(
815: WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
816: if (outMessageContext != null) {
817: outMessageContext.getTransportOut().getSender()
818: .cleanup(outMessageContext);
819: }
820: }
821: }
822:
823: /**
824: * Configure the ServiceClient to interact with the Web service described by
825: * the specified AxisService object.
826: *
827: * @param axisService the AxisService that represents the new Web service.
828: * @throws AxisFault if an error occurs while configuring the ServiceClient.
829: */
830: public void setAxisService(AxisService axisService)
831: throws AxisFault {
832:
833: if (axisService == null) {
834: // AxisFault?
835: throw new IllegalArgumentException("AxisService is null");
836: }
837:
838: axisConfig.removeService(this .axisService.getName());
839: this .axisService = axisService;
840:
841: axisService.setClientSide(true);
842: axisConfig.addService(axisService);
843:
844: AxisServiceGroup axisServiceGroup = axisService
845: .getAxisServiceGroup();
846: ServiceGroupContext serviceGroupContext = configContext
847: .createServiceGroupContext(axisServiceGroup);
848: this.serviceContext = serviceGroupContext
849: .getServiceContext(axisService);
850: }
851: }
|