Source code: org/apache/axis/client/Service.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.axis.client;
18
19 import org.apache.axis.AxisEngine;
20 import org.apache.axis.EngineConfiguration;
21 import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
22 import org.apache.axis.encoding.TypeMappingRegistryImpl;
23 import org.apache.axis.utils.ClassUtils;
24 import org.apache.axis.utils.Messages;
25 import org.apache.axis.utils.WSDLUtils;
26 import org.apache.axis.utils.XMLUtils;
27 import org.apache.axis.wsdl.gen.Parser;
28 import org.apache.axis.wsdl.symbolTable.BindingEntry;
29 import org.apache.axis.wsdl.symbolTable.ServiceEntry;
30 import org.apache.axis.wsdl.symbolTable.SymbolTable;
31 import org.w3c.dom.Document;
32
33 import javax.naming.Reference;
34 import javax.naming.Referenceable;
35 import javax.naming.StringRefAddr;
36 import javax.wsdl.Binding;
37 import javax.wsdl.Operation;
38 import javax.wsdl.Port;
39 import javax.wsdl.PortType;
40 import javax.wsdl.extensions.soap.SOAPAddress;
41 import javax.xml.namespace.QName;
42 import javax.xml.rpc.ServiceException;
43 import javax.xml.rpc.encoding.TypeMappingRegistry;
44 import javax.xml.rpc.handler.HandlerRegistry;
45 import java.io.InputStream;
46 import java.io.Serializable;
47 import java.lang.reflect.Constructor;
48 import java.lang.reflect.Proxy;
49 import java.net.MalformedURLException;
50 import java.net.URL;
51 import java.rmi.Remote;
52 import java.util.HashMap;
53 import java.util.Hashtable;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Vector;
58
59 /**
60 * Axis' JAXRPC Dynamic Invoation Interface implementation of the Service
61 * interface.
62 *
63 * The Service class should be used a the starting point for access
64 * SOAP Web Services. Typically, a Service will be created with a WSDL
65 * document and along with a serviceName you can then ask for a Call
66 * object that will allow you to invoke a Web Service.
67 *
68 * @author Doug Davis (dug@us.ibm.com)
69 */
70
71 public class Service implements javax.xml.rpc.Service, Serializable, Referenceable {
72 private transient AxisEngine engine = null;
73 private transient EngineConfiguration config = null;
74
75 private QName serviceName = null;
76 private String wsdlLocation = null;
77 private javax.wsdl.Service wsdlService = null;
78 private boolean maintainSession = false;
79 private HandlerRegistryImpl registry = new HandlerRegistryImpl();
80 private Parser wsdlParser = null;
81
82 private static HashMap cachedWSDL = new HashMap();
83 private static boolean cachingWSDL = true;
84
85 // The last call object
86 protected Call _call = null;
87
88 /**
89 * A Hashtable mapping addresses (URLs) to Transports (objects)
90 */
91 private Hashtable transportImpls = new Hashtable();
92
93
94 protected javax.wsdl.Service getWSDLService() {
95 return (wsdlService);
96 }
97
98 public Parser getWSDLParser() {
99 return (wsdlParser);
100 }
101
102 protected AxisClient getAxisClient() {
103 return new AxisClient(getEngineConfiguration());
104 }
105
106 /**
107 * Constructs a new Service object - this assumes the caller will set
108 * the appropriate fields by hand rather than getting them from the
109 * WSDL.
110 */
111 public Service() {
112 engine = getAxisClient();
113 }
114
115 /**
116 * Constructs a new Service object - this assumes the caller will set
117 * the appropriate fields by hand rather than getting them from the
118 * WSDL.
119 */
120 public Service(QName serviceName) {
121 this.serviceName = serviceName;
122 engine = getAxisClient();
123 }
124
125 /**
126 * Constructs a Service using the supplied configuration and engine directly.
127 *
128 * @param engineConfiguration
129 * @param axisClient
130 */
131 public Service(EngineConfiguration engineConfiguration, AxisClient axisClient) {
132 this.config = engineConfiguration;
133 this.engine = axisClient;
134 }
135
136 /**
137 * Constructs a new Service object as above, but also passing in
138 * the EngineConfiguration which should be used to set up the
139 * AxisClient.
140 */
141 public Service(EngineConfiguration config) {
142 this.config = config;
143 engine = getAxisClient();
144 }
145
146 /**
147 * Constructs a new Service object for the service in the WSDL document
148 * pointed to by the wsdlDoc URL and serviceName parameters.
149 *
150 * @param wsdlDoc URL of the WSDL document
151 * @param serviceName Qualified name of the desired service
152 * @throws ServiceException If there's an error finding or parsing the WSDL
153 */
154 public Service(URL wsdlDoc, QName serviceName) throws ServiceException {
155 this.serviceName = serviceName;
156 engine = getAxisClient();
157 wsdlLocation = wsdlDoc.toString();
158 Parser parser = null;
159
160 if (cachingWSDL &&
161 (parser = (Parser) cachedWSDL.get(this.wsdlLocation.toString())) != null) {
162 initService(parser, serviceName);
163 } else {
164 initService(wsdlDoc.toString(), serviceName);
165 }
166 }
167
168 /**
169 * Constructs a new Service object for the service in the WSDL document
170 *
171 * @param parser Parser for this service
172 * @param serviceName Qualified name of the desired service
173 * @throws ServiceException If there's an error
174 */
175 public Service(Parser parser, QName serviceName) throws ServiceException {
176 this.serviceName = serviceName;
177 engine = getAxisClient();
178 initService(parser, serviceName);
179 }
180
181 /**
182 * Constructs a new Service object for the service in the WSDL document
183 * pointed to by the wsdlLocation and serviceName parameters. This is
184 * just like the previous constructor but instead of URL the
185 * wsdlLocation parameter points to a file on the filesystem relative
186 * to the current directory.
187 *
188 * @param wsdlLocation Location of the WSDL relative to the current dir
189 * @param serviceName Qualified name of the desired service
190 * @throws ServiceException If there's an error finding or parsing the WSDL
191 */
192 public Service(String wsdlLocation, QName serviceName)
193 throws ServiceException {
194 this.serviceName = serviceName;
195 this.wsdlLocation = wsdlLocation;
196 engine = getAxisClient();
197 // Start by reading in the WSDL using Parser
198 Parser parser = null;
199 if (cachingWSDL &&
200 (parser = (Parser) cachedWSDL.get(wsdlLocation)) != null) {
201 initService(parser, serviceName);
202 } else {
203 initService(wsdlLocation, serviceName);
204 }
205 }
206
207 /**
208 * Constructs a new Service object for the service in the WSDL document
209 * in the wsdlInputStream and serviceName parameters. This is
210 * just like the previous constructor but instead of reading the WSDL
211 * from a file (or from a URL) it is in the passed in InputStream.
212 *
213 * @param wsdlInputStream InputStream containing the WSDL
214 * @param serviceName Qualified name of the desired service
215 * @throws ServiceException If there's an error finding or parsing the WSDL
216 */
217 public Service(InputStream wsdlInputStream, QName serviceName)
218 throws ServiceException {
219 engine = getAxisClient();
220 Document doc = null;
221 try {
222 doc = XMLUtils.newDocument(wsdlInputStream);
223 } catch (Exception exp) {
224 throw new ServiceException(
225 Messages.getMessage("wsdlError00", "" + "", "\n" + exp));
226 }
227 initService(null, doc, serviceName);
228 }
229
230 /**
231 * Common code for building up the Service from a WSDL document
232 *
233 * @param url URL for the WSDL document
234 * @param serviceName Qualified name of the desired service
235 * @throws ServiceException If there's an error finding or parsing the WSDL
236 */
237 private void initService(String url, QName serviceName)
238 throws ServiceException {
239 try {
240 // Start by reading in the WSDL using Parser
241 Parser parser = new Parser();
242 parser.run(url);
243
244 if (cachingWSDL && this.wsdlLocation != null)
245 cachedWSDL.put(url, parser);
246
247 initService(parser, serviceName);
248 } catch (Exception exp) {
249 throw new ServiceException(
250 Messages.getMessage("wsdlError00", "" + "", "\n" + exp),
251 exp);
252 }
253 }
254
255 /**
256 * Common code for building up the Service from a WSDL document
257 *
258 * @param context Context URL
259 * @param doc A DOM document containing WSDL
260 * @param serviceName Qualified name of the desired service
261 * @throws ServiceException If there's an error finding or parsing the WSDL
262 */
263 private void initService(String context, Document doc, QName serviceName)
264 throws ServiceException {
265 try {
266 // Start by reading in the WSDL using Parser
267 Parser parser = new Parser();
268 parser.run(context, doc);
269
270 initService(parser, serviceName);
271 } catch (Exception exp) {
272 throw new ServiceException(
273 Messages.getMessage("wsdlError00", "" + "", "\n" + exp));
274 }
275 }
276
277 /**
278 * Code for building up the Service from a Parser
279 *
280 * @param parser Parser for this service
281 * @param serviceName Qualified name of the desired service
282 * @throws ServiceException If there's an error finding or parsing the WSDL
283 */
284 private void initService(Parser parser, QName serviceName)
285 throws ServiceException {
286 try {
287 this.wsdlParser = parser;
288 ServiceEntry serviceEntry = parser.getSymbolTable().getServiceEntry(serviceName);
289 if (serviceEntry != null)
290 this.wsdlService = serviceEntry.getService();
291 if (this.wsdlService == null)
292 throw new ServiceException(
293 Messages.getMessage("noService00", "" + serviceName));
294 } catch (Exception exp) {
295 throw new ServiceException(
296 Messages.getMessage("wsdlError00", "" + "", "\n" + exp));
297 }
298 }
299
300 /**
301 * Return either an instance of a generated stub, if it can be
302 * found, or a dynamic proxy for the given proxy interface.
303 *
304 * @param portName The name of the service port
305 * @param proxyInterface The Remote object returned by this
306 * method will also implement the given proxyInterface
307 * @return java.rmi.Remote The stub implementation.
308 * @throws ServiceException If there's an error
309 */
310 public Remote getPort(QName portName, Class proxyInterface)
311 throws ServiceException {
312
313 if (wsdlService == null)
314 throw new ServiceException(Messages.getMessage("wsdlMissing00"));
315
316 Port port = wsdlService.getPort(portName.getLocalPart());
317 if (port == null)
318 throw new ServiceException(Messages.getMessage("noPort00", "" + portName));
319
320 // First, try to find a generated stub. If that
321 // returns null, then find a dynamic stub.
322 Remote stub = getGeneratedStub(portName, proxyInterface);
323 return stub != null ? stub : getPort(null, portName, proxyInterface);
324 }
325
326 /**
327 * With the proxyInterface and the service's portName, we have
328 * ALMOST enough info to find a generated stub. The generated
329 * stub is named after the binding, which we can get from the
330 * service's port. This binding is likely in the same namespace
331 * (ie, package) that the proxyInterface is in. So try to find
332 * and instantiate <proxyInterfacePackage>.<bindingName>Stub.
333 * If it doesn't exist, return null.
334 */
335 private Remote getGeneratedStub(QName portName, Class proxyInterface) {
336 try {
337 String pkg = proxyInterface.getName();
338 pkg = pkg.substring(0, pkg.lastIndexOf('.'));
339 Port port = wsdlService.getPort(portName.getLocalPart());
340 String binding = port.getBinding().getQName().getLocalPart();
341 Class stubClass = ClassUtils.forName(
342 pkg + "." + binding + "Stub");
343 if (proxyInterface.isAssignableFrom(stubClass)) {
344 Class[] formalArgs = {javax.xml.rpc.Service.class};
345 Object[] actualArgs = {this};
346 Constructor ctor = stubClass.getConstructor(formalArgs);
347 Stub stub = (Stub) ctor.newInstance(actualArgs);
348 stub._setProperty(
349 Stub.ENDPOINT_ADDRESS_PROPERTY,
350 WSDLUtils.getAddressFromPort(port));
351 stub.setPortName(portName);
352 return (Remote) stub;
353 } else {
354 return null;
355 }
356 } catch (Throwable t) {
357 return null;
358 }
359 } // getGeneratedStub
360
361 /**
362 * Return a dynamic proxy for the given proxy interface.
363 *
364 * @param proxyInterface The Remote object returned by this
365 * method will also implement the given proxyInterface
366 * @return java.rmi.Remote The stub implementation
367 * @throws ServiceException If there's an error
368 */
369 public Remote getPort(Class proxyInterface) throws ServiceException {
370 if (wsdlService == null)
371 throw new ServiceException(Messages.getMessage("wsdlMissing00"));
372
373 Map ports = wsdlService.getPorts();
374 if (ports == null || ports.size() <= 0)
375 throw new ServiceException(Messages.getMessage("noPort00", ""));
376
377 // Get the name of the class (without package name)
378 String clazzName = proxyInterface.getName();
379 if(clazzName.lastIndexOf('.')!=-1) {
380 clazzName = clazzName.substring(clazzName.lastIndexOf('.')+1);
381 }
382
383 // Pick the port with the same name as the class
384 Port port = (Port) ports.get(clazzName);
385 if(port == null) {
386 // If not found, just pick the first port.
387 port = (Port) ports.values().iterator().next();
388 }
389
390 // First, try to find a generated stub. If that
391 // returns null, then find a dynamic stub.
392 Remote stub = getGeneratedStub(new QName(port.getName()), proxyInterface);
393 return stub != null ? stub : getPort(null, new QName(port.getName()), proxyInterface);
394 }
395
396 /**
397 * Return an object which acts as a dynamic proxy for the passed
398 * interface class. This is a more "dynamic" version in that it
399 * doesn't actually require WSDL, simply an endpoint address.
400 *
401 * Note: Not part of the JAX-RPC spec.
402 *
403 * @param endpoint the URL which will be used as the SOAP endpoint
404 * @param proxyInterface the interface class which we wish to mimic
405 * via a dynamic proxy
406 * @throws ServiceException
407 */
408 public Remote getPort(String endpoint, Class proxyInterface)
409 throws ServiceException {
410 return getPort(endpoint, null, proxyInterface);
411 }
412
413 private Remote getPort(String endpoint, QName portName,
414 Class proxyInterface) throws ServiceException {
415 if (!proxyInterface.isInterface()) {
416 throw new ServiceException(Messages.getMessage("mustBeIface00"));
417 }
418
419 if (!(Remote.class.isAssignableFrom(proxyInterface))) {
420 throw new ServiceException(
421 Messages.getMessage("mustExtendRemote00"));
422 }
423
424 // Validate the proxyInterface
425 if (wsdlParser != null) {
426 Port port = wsdlService.getPort(portName.getLocalPart());
427 if (port == null)
428 throw new ServiceException(Messages.getMessage("noPort00", "" + proxyInterface.getName()));
429
430 Binding binding = port.getBinding();
431 SymbolTable symbolTable = wsdlParser.getSymbolTable();
432 BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
433 if(bEntry.getParameters().size() != proxyInterface.getMethods().length) {
434 throw new ServiceException(Messages.getMessage("incompatibleSEI00", "" + proxyInterface.getName()));
435 }
436 // TODO: Check the methods and the parameters as well.
437 }
438
439 try {
440 Call call = null;
441 if (portName == null) {
442 call = (org.apache.axis.client.Call) createCall();
443 if (endpoint != null) {
444 call.setTargetEndpointAddress(new URL(endpoint));
445 }
446 } else {
447 call = (org.apache.axis.client.Call) createCall(portName);
448 }
449 ClassLoader classLoader =
450 Thread.currentThread().getContextClassLoader();
451 javax.xml.rpc.Stub stub = (javax.xml.rpc.Stub) Proxy.newProxyInstance(classLoader,
452 new Class[]{proxyInterface, javax.xml.rpc.Stub.class},
453 new AxisClientProxy(call, portName));
454 if(stub instanceof org.apache.axis.client.Stub){
455 ((org.apache.axis.client.Stub) stub).setPortName(portName);
456 }
457 return (Remote) stub;
458 } catch (Exception e) {
459 throw new ServiceException(
460 Messages.getMessage("wsdlError00", "" + "", "\n" + e));
461 }
462 } // getPort
463
464 /**
465 * Creates a new Call object - will prefill as much info from the WSDL
466 * as it can. Right now it's just the target URL of the Web Service.
467 *
468 * @param portName PortName in the WSDL doc to search for
469 * @return Call Used for invoking the Web Service
470 * @throws ServiceException If there's an error
471 */
472 public javax.xml.rpc.Call createCall(QName portName)
473 throws ServiceException {
474 Call call = (org.apache.axis.client.Call) createCall();
475 call.setPortName(portName);
476
477 // We can't prefill information if WSDL is not specified,
478 // So just return the call that we just created.
479 if (wsdlParser == null)
480 return call;
481
482 Port port = wsdlService.getPort(portName.getLocalPart());
483 if (port == null)
484 throw new ServiceException(Messages.getMessage("noPort00", "" + portName));
485
486 Binding binding = port.getBinding();
487 PortType portType = binding.getPortType();
488 if (portType == null)
489 throw new ServiceException(Messages.getMessage("noPortType00", "" + portName));
490
491 // Get the URL
492 ////////////////////////////////////////////////////////////////////
493 List list = port.getExtensibilityElements();
494 for (int i = 0; list != null && i < list.size(); i++) {
495 Object obj = list.get(i);
496 if (obj instanceof SOAPAddress) {
497 try {
498 SOAPAddress addr = (SOAPAddress) obj;
499 URL url = new URL(addr.getLocationURI());
500 call.setTargetEndpointAddress(url);
501 } catch (Exception exp) {
502 throw new ServiceException(
503 Messages.getMessage("cantSetURI00", "" + exp));
504 }
505 }
506 }
507
508 return (call);
509 }
510
511 /**
512 * Creates a new Call object - will prefill as much info from the WSDL
513 * as it can. Right now it's target URL, SOAPAction, Parameter types,
514 * and return type of the Web Service.
515 *
516 * @param portName PortName in the WSDL doc to search for
517 * @param operationName Operation(method) that's going to be invoked
518 * @return Call Used for invoking the Web Service
519 * @throws ServiceException If there's an error
520 */
521 public javax.xml.rpc.Call createCall(QName portName,
522 String operationName)
523 throws ServiceException {
524
525 Call call = (org.apache.axis.client.Call) createCall();
526 call.setOperation(portName, operationName);
527 return (call);
528 }
529
530 /**
531 * Creates a new Call object - will prefill as much info from the WSDL
532 * as it can. Right now it's target URL, SOAPAction, Parameter types,
533 * and return type of the Web Service.
534 *
535 * @param portName PortName in the WSDL doc to search for
536 * @param operationName Operation(method) that's going to be invoked
537 * @return Call Used for invoking the Web Service
538 * @throws ServiceException If there's an error
539 */
540 public javax.xml.rpc.Call createCall(QName portName,
541 QName operationName)
542 throws ServiceException {
543
544 Call call = (org.apache.axis.client.Call) createCall();
545 call.setOperation(portName, operationName);
546 return (call);
547 }
548
549 /**
550 * Creates a new Call object with no prefilled data. This assumes
551 * that the caller will set everything manually - no checking of
552 * any kind will be done against the WSDL.
553 *
554 * @return Call Used for invoking the Web Service
555 * @throws ServiceException If there's an error
556 */
557 public javax.xml.rpc.Call createCall() throws ServiceException {
558 _call = new org.apache.axis.client.Call(this);
559 return _call;
560 }
561
562 /**
563 * Gets an array of preconfigured Call objects for invoking operations
564 * on the specified port. There is one Call object per operation that
565 * can be invoked on the specified port. Each Call object is
566 * pre-configured and does not need to be configured using the setter
567 * methods on Call interface.
568 *
569 * This method requires the Service implementation class to have access
570 * to the WSDL related metadata.
571 *
572 * @throws ServiceException - If this Service class does not have access
573 * to the required WSDL metadata or if an illegal portName is specified.
574 */
575 public javax.xml.rpc.Call[] getCalls(QName portName) throws ServiceException {
576 if (portName == null)
577 throw new ServiceException(Messages.getMessage("badPort00"));
578
579 if (wsdlService == null)
580 throw new ServiceException(Messages.getMessage("wsdlMissing00"));
581
582 Port port = wsdlService.getPort(portName.getLocalPart());
583 if (port == null)
584 throw new ServiceException(Messages.getMessage("noPort00", "" + portName));
585
586 Binding binding = port.getBinding();
587 SymbolTable symbolTable = wsdlParser.getSymbolTable();
588 BindingEntry bEntry =
589 symbolTable.getBindingEntry(binding.getQName());
590 Iterator i = bEntry.getParameters().keySet().iterator();
591
592 Vector calls = new Vector();
593 while (i.hasNext()) {
594 Operation operation = (Operation) i.next();
595 javax.xml.rpc.Call call = createCall(QName.valueOf(port.getName()),
596 QName.valueOf(operation.getName()));
597 calls.add(call);
598 }
599 javax.xml.rpc.Call[] array = new javax.xml.rpc.Call[calls.size()];
600 calls.toArray(array);
601 return array;
602 }
603
604 /**
605 * Returns the configured HandlerRegistry instance for this Service
606 * instance.
607 *
608 * NOTE: This Service currently does not support the configuration
609 * of a HandlerRegistry! It will throw a
610 * java.lang.UnsupportedOperationException.
611 *
612 * @return HandlerRegistry
613 * @throws java.lang.UnsupportedOperationException - if the Service
614 * class does not support the configuration of a
615 * HandlerRegistry.
616 */
617 public HandlerRegistry getHandlerRegistry() {
618 return registry;
619 }
620
621 /**
622 * Returns the location of the WSDL document used to prefill the data
623 * (if one was used at all).
624 *
625 * @return URL URL pointing to the WSDL doc
626 */
627 public URL getWSDLDocumentLocation() {
628 try {
629 return new URL(wsdlLocation);
630 } catch (MalformedURLException e) {
631 return null;
632 }
633 }
634
635 /**
636 * Returns the qualified name of the service (if one is set).
637 *
638 * @return QName Fully qualified name of this service.
639 */
640 public QName getServiceName() {
641 if (serviceName != null) return serviceName;
642 if (wsdlService == null) return (null);
643 QName qn = wsdlService.getQName();
644 return (new QName(qn.getNamespaceURI(), qn.getLocalPart()));
645 }
646
647 /**
648 * Returns an <code>Iterator</code> for the list of
649 * <code>QName</code>s of service endpoints grouped by this
650 * service
651 *
652 * @return Returns <code>java.util.Iterator</code> with elements
653 * of type <code>javax.xml.namespace.QName</code>
654 * @throws ServiceException If this Service class does not
655 * have access to the required WSDL metadata
656 */
657 public Iterator getPorts() throws ServiceException {
658 if (wsdlService == null)
659 throw new ServiceException(Messages.getMessage("wsdlMissing00"));
660
661 if (wsdlService.getPorts() == null) {
662 // Return an empty iterator;
663 return new Vector().iterator();
664 }
665
666 Map portmap = wsdlService.getPorts();
667 List portlist = new java.util.ArrayList(portmap.size());
668 // we could simply iterate over keys instead and skip
669 // the lookup, but while keys are probably the same as
670 // port names, the documentation does not make any
671 // guarantee on this, so we'll just play it safe
672 // Aaron Hamid
673 Iterator portiterator = portmap.values().iterator();
674 while (portiterator.hasNext()) {
675 Port port = (Port) portiterator.next();
676 // maybe we should use Definition.getTargetNamespace() here,
677 // but this class does not hold a reference to the object,
678 // so we'll just use the namespace of the service's QName
679 // (it should all be the same wsdl targetnamespace value, right?)
680 // Aaron Hamid
681 portlist.add(new QName(wsdlService.getQName().getNamespaceURI(), port.getName()));
682 }
683
684 // ok, return the real list of QNames
685 return portlist.iterator();
686 }
687
688 /**
689 * Defines the current Type Mappig Registry.
690 *
691 * @param registry The TypeMappingRegistry
692 * @throws ServiceException if there's an error
693 */
694 public void setTypeMappingRegistry(TypeMappingRegistry registry)
695 throws ServiceException {
696 }
697
698 /**
699 * Returns the current TypeMappingRegistry or null.
700 *
701 * @return TypeMappingRegistry The registry
702 */
703 public TypeMappingRegistry getTypeMappingRegistry() {
704 return (engine.getTypeMappingRegistry());
705 }
706
707 /**
708 * Returns a reference to this object.
709 *
710 * @return Reference ...
711 */
712 public Reference getReference() {
713 String classname = this.getClass().getName();
714 Reference reference = new Reference(classname,
715 "org.apache.axis.client.ServiceFactory", null);
716 StringRefAddr addr = null;
717 if (!classname.equals("org.apache.axis.client.Service")) {
718 // This is a generated derived class. Don't bother with
719 // all the Service instance variables.
720 addr = new StringRefAddr(
721 ServiceFactory.SERVICE_CLASSNAME, classname);
722 reference.add(addr);
723 } else {
724 if (wsdlLocation != null) {
725 addr = new StringRefAddr(
726 ServiceFactory.WSDL_LOCATION, wsdlLocation.toString());
727 reference.add(addr);
728 }
729 QName serviceName = getServiceName();
730 if (serviceName != null) {
731 addr = new StringRefAddr(ServiceFactory.SERVICE_NAMESPACE,
732 serviceName.getNamespaceURI());
733 reference.add(addr);
734 addr = new StringRefAddr(ServiceFactory.SERVICE_LOCAL_PART,
735 serviceName.getLocalPart());
736 reference.add(addr);
737 }
738 }
739 if (maintainSession) {
740 addr = new StringRefAddr(ServiceFactory.MAINTAIN_SESSION, "true");
741 reference.add(addr);
742 }
743 return reference;
744 }
745
746 /**
747 * Sets this Service's AxisEngine. This engine will be shared by all
748 * Call objects created from this Service object.
749 *
750 * Note: Not part of the JAX-RPC spec.
751 *
752 * @param engine Sets this Service's AxisEngine to the passed in one
753 */
754 public void setEngine(AxisEngine engine) {
755 this.engine = engine;
756 }
757
758 /**
759 * Returns the current AxisEngine used by this Service and all of the
760 * Call objects created from this Service object.
761 *
762 * Note: Not part of the JAX-RPC spec.
763 *
764 * @return AxisEngine the engine
765 */
766 public AxisEngine getEngine() {
767 return (engine);
768 }
769
770 /**
771 * Set this Service's engine configuration.
772 *
773 * Note that since all of the constructors create the AxisClient right
774 * now, this is basically a no-op. Putting it in now so that we can make
775 * lazy engine instantiation work, and not have to duplicate every single
776 * Service constructor with a EngineConfiguration argument.
777 * <p>
778 * If you need to use a non-default <code>EngineConfiguration</code>, do
779 * the following before calling the Service constructor:<p><code>
780 *
781 * AxisProperties.setProperty(EngineConfigurationFactory.SYSTEM_PROPERTY_NAME,
782 * "classname.of.new.EngineConfigurationFactory");
783 * </code><p>
784 * Where the second parameter is the name of your new class that implements
785 * <code>EngineConfigurationFactory</code> and a<code><br>
786 * public static EngineConfigurationFactory newFactory(Object param)
787 * </code>
788 * method. See <code>EngineConfigurationFactoryDefault</code> for an example
789 * of how to do this.<p>
790 *
791 * This way, when the Service class constructor calls<br><code>
792 *
793 * EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig()
794 * </code>
795 * the getClientEngineConfig() of your own EngineConfigurationFactory will be
796 * called, and your configuration will be used in the constructed Service object.<p>
797 *
798 * Another way is to use the "discovery" method of
799 * <code>EngineConfigurationFactoryFinder</code>.
800 *
801 * @param config the EngineConfiguration we want to use.
802 */
803 public void setEngineConfiguration(EngineConfiguration config) {
804 this.config = config;
805 }
806
807 /**
808 * Constructs a EngineConfig if one is not available.
809 */
810 protected EngineConfiguration getEngineConfiguration() {
811 if (this.config == null) {
812 this.config = EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig();
813 }
814 return config;
815 }
816
817 /**
818 * Determine whether we'd like to track sessions or not.
819 * This information is passed to all Call objects created
820 * from this service. Calling setMaintainSession will
821 * only affect future instantiations of the Call object,
822 * not those that already exist.
823 *
824 * Note: Not part of JAX-RPC specification.
825 *
826 * @param yesno true if session state is desired, false if not.
827 */
828 public void setMaintainSession(boolean yesno) {
829 maintainSession = yesno;
830 }
831
832 /**
833 * If true, this service wants to track sessions.
834 */
835 public boolean getMaintainSession() {
836 return maintainSession;
837 }
838
839 /**
840 * Returns last Call object associated with this service. Note that since
841 * the Service is not thread-safe, you may not get the last call object
842 * that you created on this thread. please use Stub._getCall
843 *
844 * @deprecated please use Stub._getCall
845 */
846 public Call getCall() throws ServiceException {
847 return _call;
848 }
849
850 /**
851 * Tells whether or not we're caching WSDL
852 */
853 public boolean getCacheWSDL() {
854 return cachingWSDL;
855 }
856
857 /**
858 * Allows users to turn caching of WSDL documents on or off.
859 * Default is 'true' (on).
860 */
861 public void setCacheWSDL(boolean flag) {
862 cachingWSDL = flag;
863 }
864
865 protected static class HandlerRegistryImpl implements HandlerRegistry {
866 Map map = new HashMap();
867
868 public List getHandlerChain(QName portName) {
869 // namespace is not significant, so use local part directly
870 String key = portName.getLocalPart();
871 List list = (List) map.get(key);
872 if (list == null) {
873 list = new java.util.ArrayList();
874 setHandlerChain(portName, list);
875 }
876 return list;
877 }
878
879 public void setHandlerChain(QName portName, List chain) {
880 // namespace is not significant, so use local part directly
881 map.put(portName.getLocalPart(), chain);
882 }
883 }
884
885 /**
886 * Register a Transport for a particular URL.
887 */
888 void registerTransportForURL(URL url, Transport transport) {
889 transportImpls.put(url.toString(), transport);
890 }
891
892 /**
893 * Get any registered Transport object for a given URL.
894 */
895 Transport getTransportForURL(URL url) {
896 return (Transport) transportImpls.get(url.toString());
897 }
898
899 /**
900 * Set the typemapping version
901 * @param version
902 */
903 public void setTypeMappingVersion(String version) {
904 ((TypeMappingRegistryImpl)getTypeMappingRegistry()).doRegisterFromVersion(version);
905 }
906 }