Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 }