View Javadoc

1   /*
2    * $Id: AxisConnector.java 22370 2011-07-11 08:31:38Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.soap.axis;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleRuntimeException;
16  import org.mule.api.construct.FlowConstruct;
17  import org.mule.api.context.notification.MuleContextNotificationListener;
18  import org.mule.api.endpoint.EndpointBuilder;
19  import org.mule.api.endpoint.EndpointURI;
20  import org.mule.api.endpoint.ImmutableEndpoint;
21  import org.mule.api.endpoint.InboundEndpoint;
22  import org.mule.api.lifecycle.InitialisationException;
23  import org.mule.api.processor.MessageProcessor;
24  import org.mule.api.security.SecurityFilter;
25  import org.mule.api.service.Service;
26  import org.mule.api.source.CompositeMessageSource;
27  import org.mule.api.transport.MessageReceiver;
28  import org.mule.component.DefaultJavaComponent;
29  import org.mule.config.ExceptionHelper;
30  import org.mule.config.i18n.CoreMessages;
31  import org.mule.context.notification.MuleContextNotification;
32  import org.mule.endpoint.AbstractEndpointBuilder;
33  import org.mule.endpoint.EndpointURIEndpointBuilder;
34  import org.mule.model.seda.SedaService;
35  import org.mule.object.SingletonObjectFactory;
36  import org.mule.processor.SecurityFilterMessageProcessor;
37  import org.mule.routing.MessageFilter;
38  import org.mule.service.ServiceCompositeMessageSource;
39  import org.mule.transport.AbstractConnector;
40  import org.mule.transport.service.TransportFactory;
41  import org.mule.transport.servlet.ServletConnector;
42  import org.mule.transport.soap.axis.extensions.MuleConfigProvider;
43  import org.mule.transport.soap.axis.extensions.MuleTransport;
44  import org.mule.transport.soap.axis.extensions.WSDDFileProvider;
45  import org.mule.transport.soap.axis.extensions.WSDDJavaMuleProvider;
46  import org.mule.transport.soap.axis.i18n.AxisMessages;
47  import org.mule.util.ClassUtils;
48  import org.mule.util.CollectionUtils;
49  import org.mule.util.MuleUrlStreamHandlerFactory;
50  
51  import java.lang.reflect.Field;
52  import java.util.ArrayList;
53  import java.util.HashMap;
54  import java.util.Iterator;
55  import java.util.List;
56  import java.util.Map;
57  
58  import javax.xml.namespace.QName;
59  
60  import org.apache.axis.AxisProperties;
61  import org.apache.axis.client.Call;
62  import org.apache.axis.configuration.SimpleProvider;
63  import org.apache.axis.deployment.wsdd.WSDDConstants;
64  import org.apache.axis.deployment.wsdd.WSDDProvider;
65  import org.apache.axis.encoding.TypeMappingRegistryImpl;
66  import org.apache.axis.encoding.ser.BeanDeserializerFactory;
67  import org.apache.axis.encoding.ser.BeanSerializerFactory;
68  import org.apache.axis.handlers.soap.SOAPService;
69  import org.apache.axis.server.AxisServer;
70  import org.apache.axis.wsdl.fromJava.Namespaces;
71  import org.apache.axis.wsdl.fromJava.Types;
72  
73  /**
74   * <code>AxisConnector</code> is used to maintain one or more Services for Axis
75   * server instance.
76   * <p/>
77   * Some of the Axis specific service initialisation code was adapted from the Ivory
78   * project (http://ivory.codehaus.org). Thanks guys :)
79   */
80  public class AxisConnector extends AbstractConnector implements MuleContextNotificationListener<MuleContextNotification>
81  {
82      /* Register the AxisFault Exception reader if this class gets loaded */
83      static
84      {
85          ExceptionHelper.registerExceptionReader(new AxisFaultExceptionReader());
86      }
87  
88      public static final QName QNAME_MULE_PROVIDER = new QName(WSDDConstants.URI_WSDD_JAVA, "Mule");
89      public static final QName QNAME_MULE_TYPE_MAPPINGS = new QName("http://www.muleumo.org/ws/mappings",
90              "Mule");
91      public static final String DEFAULT_MULE_NAMESPACE_URI = "http://www.muleumo.org";
92  
93      public static final String DEFAULT_MULE_AXIS_SERVER_CONFIG = "mule-axis-server-config.wsdd";
94      public static final String DEFAULT_MULE_AXIS_CLIENT_CONFIG = "mule-axis-client-config.wsdd";
95      public static final String AXIS_SERVICE_COMPONENT_NAME = "_axisServiceComponent";
96      public static final String AXIS_SERVICE_PROPERTY = "_axisService";
97      public static final String AXIS_CLIENT_CONFIG_PROPERTY = "clientConfig";
98  
99      public static final String SERVICE_PROPERTY_COMPONENT_NAME = "componentName";
100     public static final String SERVICE_PROPERTY_SERVCE_PATH = "servicePath";
101 
102     public static final String AXIS = "axis";
103 
104     // used by dispatcher and receiver
105     public static final String SOAP_METHODS = "soapMethods";
106     public static final String STYLE = "style";
107     public static final String USE = "use";
108 
109     private String serverConfig = DEFAULT_MULE_AXIS_SERVER_CONFIG;
110 
111     private AxisServer axis = null;
112     private SimpleProvider serverProvider = null;
113     private String clientConfig = DEFAULT_MULE_AXIS_CLIENT_CONFIG;
114     private SimpleProvider clientProvider = null;
115 
116     private List beanTypes;
117     private Service axisComponent;
118 
119     //this will store the name of the descriptor of the current connector's AxisServiceComponent
120     //private String specificAxisServiceComponentName;
121 
122     /**
123      * These protocols will be set on client invocations. By default Mule uses it's
124      * own transports rather that Axis's. This is only because it gives us more
125      * flexibility inside Mule and simplifies the code
126      */
127     private Map axisTransportProtocols = null;
128 
129     /**
130      * A store of registered servlet services that need to have their endpoints
131      * re-written with the 'real' http url instead of the servlet:// one. This is
132      * only required to ensure wsdl is generated correctly. I would like a clearer
133      * way of doing this so I can remove this workaround
134      */
135     private List servletServices = new ArrayList();
136 
137     private List supportedSchemes = null;
138 
139     private boolean doAutoTypes = true;
140 
141     private boolean treatMapAsNamedParams = true;
142 
143     public AxisConnector(MuleContext context)
144     {
145         super(context);
146         this.registerProtocols();
147     }
148 
149     protected void registerProtocols()
150     {
151         if (supportedSchemes == null)
152         {
153             // Default supported schemes, these can be restricted
154             // through configuration
155             supportedSchemes = new ArrayList();
156             supportedSchemes.add("http");
157             supportedSchemes.add("https");
158             supportedSchemes.add("servlet");
159             supportedSchemes.add("vm");
160             supportedSchemes.add("jms");
161             supportedSchemes.add("xmpp");
162             supportedSchemes.add("ssl");
163             supportedSchemes.add("tcp");
164             supportedSchemes.add("smtp");
165             supportedSchemes.add("smtps");
166             supportedSchemes.add("pop3");
167             supportedSchemes.add("pop3s");
168             supportedSchemes.add("imap");
169             supportedSchemes.add("imaps");
170         }
171 
172         for (Iterator iterator = supportedSchemes.iterator(); iterator.hasNext();)
173         {
174             String s = (String) iterator.next();
175             registerSupportedProtocol(s);
176         }
177     }
178 
179     @Override
180     protected void doInitialise() throws InitialisationException
181     {
182         axisTransportProtocols = new HashMap();
183         //specificAxisServiceComponentName = AXIS_SERVICE_COMPONENT_NAME + "_" + name;
184 
185         axisTransportProtocols = new HashMap();
186         try
187         {
188             for (Iterator iterator = supportedSchemes.iterator(); iterator.hasNext();)
189             {
190                 String s = (String) iterator.next();
191                 axisTransportProtocols.put(s, MuleTransport.getTransportClass(s));
192                 registerSupportedProtocol(s);
193             }
194             muleContext.registerListener(this);
195         }
196         catch (Exception e)
197         {
198             throw new InitialisationException(e, this);
199         }
200         // TODO DO: call registerSupportedProtocol if axisTransportProtocols are set from external?
201 
202         if (clientProvider == null)
203         {
204             clientProvider = createAxisProvider(clientConfig);
205         }
206         else
207         {
208             if (!DEFAULT_MULE_AXIS_CLIENT_CONFIG.equals(clientConfig))
209             {
210                 logger.warn(AxisMessages.clientProviderAndClientConfigConfigured());
211             }
212         }
213 
214         if (axis == null)
215         {
216             if (serverProvider == null)
217             {
218                 serverProvider = this.createAxisProvider(serverConfig);
219             }
220             else
221             {
222                 if (!DEFAULT_MULE_AXIS_SERVER_CONFIG.equals(serverConfig))
223                 {
224                     logger.warn(AxisMessages.serverProviderAndServerConfigConfigured());
225                 }
226             }
227 
228             // Create the AxisServer
229             axis = new AxisServer(serverProvider);
230             // principle of least surprise: doAutoTypes only has effect on our self-configured AxisServer
231             axis.setOption("axis.doAutoTypes", Boolean.valueOf(doAutoTypes));
232         }
233 
234         // Register the Mule service serverProvider
235         WSDDProvider.registerProvider(QNAME_MULE_PROVIDER, new WSDDJavaMuleProvider(this));
236 
237         try
238         {
239             registerTransportTypes();
240         }
241         catch (ClassNotFoundException e)
242         {
243             throw new InitialisationException(
244                     CoreMessages.cannotLoadFromClasspath(e.getMessage()), e, this);
245         }
246 
247         // Register all our UrlStreamHandlers here so they can be resolved. This is necessary
248         // to make Mule work in situations where modification of system properties at runtime
249         // is not reliable, e.g. when running in maven's surefire test executor.
250         MuleUrlStreamHandlerFactory.registerHandler("jms", new org.mule.transport.soap.axis.transport.jms.Handler());
251         MuleUrlStreamHandlerFactory.registerHandler("pop3", new org.mule.transport.soap.axis.transport.pop3.Handler());
252         MuleUrlStreamHandlerFactory.registerHandler("smtp", new org.mule.transport.soap.axis.transport.smtp.Handler());
253         MuleUrlStreamHandlerFactory.registerHandler("vm", new org.mule.transport.soap.axis.transport.vm.Handler());
254 
255         try
256         {
257             registerTypes((TypeMappingRegistryImpl) axis.getTypeMappingRegistry(), beanTypes);
258         }
259         catch (ClassNotFoundException e)
260         {
261             throw new InitialisationException(e, this);
262         }
263     }
264 
265     protected void registerTransportTypes() throws ClassNotFoundException
266     {
267         // Register Transport handlers
268         // By default these will all be handled by Mule, however some companies may
269         // have their own they wish to use
270         for (Iterator iterator = getAxisTransportProtocols().keySet().iterator(); iterator.hasNext();)
271         {
272             String protocol = (String) iterator.next();
273             Object temp = getAxisTransportProtocols().get(protocol);
274             Class clazz;
275             if (temp instanceof String)
276             {
277                 clazz = ClassUtils.loadClass(temp.toString(), getClass());
278             }
279             else
280             {
281                 clazz = (Class) temp;
282             }
283             Call.setTransportForProtocol(protocol, clazz);
284         }
285     }
286 
287     protected SimpleProvider createAxisProvider(String config) throws InitialisationException
288     {
289         // Use our custom file provider that does not require services to be declared
290         // in the WSDD. This only affects the
291         // client side as the client will fallback to the FileProvider when invoking
292         // a service.
293         WSDDFileProvider fileProvider = new WSDDFileProvider(config);
294         fileProvider.setSearchClasspath(true);
295         /*
296          * Wrap the FileProvider with a SimpleProvider so we can programmatically
297          * configure the Axis server (you can only use wsdd descriptors with the
298          * FileProvider)
299          */
300         return new MuleConfigProvider(fileProvider);
301     }
302 
303     public String getProtocol()
304     {
305         return AXIS;
306     }
307 
308     /**
309      * The method determines the key used to store the receiver against.
310      *
311      * @param flowConstruct the component for which the endpoint is being registered
312      * @param endpoint  the endpoint being registered for the component
313      * @return the key to store the newly created receiver against. In this case it
314      *         is the component name, which is equivalent to the Axis service name.
315      */
316     @Override
317     protected Object getReceiverKey(FlowConstruct flowConstruct, InboundEndpoint endpoint)
318     {
319         if (endpoint.getEndpointURI().getPort() == -1)
320         {
321             return flowConstruct.getName();
322         }
323         else
324         {
325             return endpoint.getEndpointURI().getAddress() + "/" + flowConstruct.getName();
326         }
327     }
328 
329     protected void unregisterReceiverWithMuleService(MessageReceiver receiver, EndpointURI ep)
330             throws MuleException
331     {
332         String endpointKey = getCounterEndpointKey(receiver.getEndpointURI());
333 
334         for (Iterator iterator = ((ServiceCompositeMessageSource) axisComponent.getMessageSource()).getEndpoints().iterator(); iterator.hasNext();)
335         {
336             ImmutableEndpoint endpoint = (ImmutableEndpoint) iterator.next();
337             if (endpointKey.startsWith(endpoint.getEndpointURI().getAddress()))
338             {
339                 logger.info("Unregistering Axis endpoint: " + endpointKey + " for service: "
340                         + ((AxisMessageReceiver) receiver).getSoapService().getName());
341             }
342             try
343             {
344                 endpoint.getConnector()
345                         .unregisterListener(receiver.getEndpoint(), axisComponent);
346             }
347             catch (Exception e)
348             {
349                 logger.error("Failed to unregister Axis endpoint: " + endpointKey + " for service: "
350                         + receiver.getFlowConstruct().getName() + ". Error is: "
351                         + e.getMessage(), e);
352             }
353         }
354     }
355 
356     protected void registerReceiverWithMuleService(MessageReceiver receiver, EndpointURI ep)
357             throws MuleException
358     {
359         // If this is the first receiver we need to create the Axis service
360         // component this will be registered with Mule when the Connector starts
361         // See if the axis descriptor has already been added. This allows
362         // developers to override the default configuration, say to increase
363         // the threadpool
364         if (axisComponent == null)
365         {
366             axisComponent = getOrCreateAxisComponent();
367         }
368         else
369         {
370             // Lets unregister the 'template' instance, configure it and
371             // then register again later
372             muleContext.getRegistry().unregisterService(AXIS_SERVICE_PROPERTY + getName());
373         }
374 
375         String serviceName = ((AxisMessageReceiver) receiver).getSoapService().getName();
376         // No determine if the endpointUri requires a new connector to be
377         // registed in the case of http we only need to register the new endpointUri
378         // if the port is different If we're using VM or Jms we just use the resource
379         // info directly without appending a service name
380         String endpoint;
381         String scheme = ep.getScheme().toLowerCase();
382         if (scheme.equals("jms") || scheme.equals("vm") || scheme.equals("servlet"))
383         {
384             endpoint = ep.toString();
385         }
386         else
387         {
388             endpoint = receiver.getEndpointURI().getAddress() + "/" + serviceName;
389         }
390         if (logger.isDebugEnabled())
391         {
392             logger.debug("Modified endpoint with " + scheme + " scheme to " + endpoint);
393         }
394 
395         EndpointBuilder serviceEndpointbuilder = new EndpointURIEndpointBuilder(endpoint, muleContext);
396         serviceEndpointbuilder.setExchangePattern(receiver.getEndpoint().getExchangePattern());
397         serviceEndpointbuilder.setName(ep.getScheme() + ":" + serviceName);
398         // Set the transformers on the endpoint too
399         serviceEndpointbuilder.setTransformers(receiver.getEndpoint().getTransformers().isEmpty() ? null
400                                                                                                   : receiver.getEndpoint().getTransformers());
401         serviceEndpointbuilder.setResponseTransformers(receiver.getEndpoint().getResponseTransformers().isEmpty() ? null
402                                                                                                                  : receiver.getEndpoint().getResponseTransformers());
403         // set the filter on the axis endpoint on the real receiver endpoint
404         serviceEndpointbuilder.addMessageProcessor(new MessageFilter(receiver.getEndpoint().getFilter()));
405         // set the Security filter on the axis endpoint on the real receiver
406         // endpoint
407         SecurityFilter securityFilter = receiver.getEndpoint().getSecurityFilter();
408         if (securityFilter != null)
409         {
410             serviceEndpointbuilder.addMessageProcessor(new SecurityFilterMessageProcessor(securityFilter));
411         }
412 
413         // TODO Do we really need to modify the existing receiver endpoint? What happens if we don't security,
414         // filters and transformers will get invoked twice?
415         AbstractEndpointBuilder receiverEndpointBuilder = new EndpointURIEndpointBuilder(receiver.getEndpoint());
416         // Remove the Axis filter now
417 
418         List<MessageProcessor> procs = new ArrayList(receiverEndpointBuilder.getMessageProcessors());
419         CollectionUtils.removeType(procs, MessageFilter.class);
420         CollectionUtils.removeType(procs, SecurityFilterMessageProcessor.class);
421         receiverEndpointBuilder.setMessageProcessors(procs);
422 
423         InboundEndpoint serviceEndpoint = muleContext.getEndpointFactory()
424             .getInboundEndpoint(serviceEndpointbuilder);
425 
426         InboundEndpoint receiverEndpoint = muleContext.getEndpointFactory()
427             .getInboundEndpoint(receiverEndpointBuilder);
428 
429         receiver.setEndpoint(receiverEndpoint);
430 
431         ((CompositeMessageSource) axisComponent.getMessageSource()).addSource(serviceEndpoint);
432     }
433 
434     private String getCounterEndpointKey(EndpointURI endpointURI)
435     {
436         StringBuffer endpointKey = new StringBuffer(64);
437 
438         endpointKey.append(endpointURI.getScheme());
439         endpointKey.append("://");
440         endpointKey.append(endpointURI.getHost());
441         if (endpointURI.getPort() > -1)
442         {
443             endpointKey.append(":");
444             endpointKey.append(endpointURI.getPort());
445         }
446         return endpointKey.toString();
447     }
448 
449     // This initialization could be performed in the initialize() method.  Putting it here essentially makes
450     // it a lazy-create/lazy-init
451     // Another option would be to put it in the default-axis-config.xml (MULE-2102) with lazy-init="true"
452     // but that makes us depend on Spring.
453     // Another consideration is how/when this implicit component gets disposed.
454     protected Service getOrCreateAxisComponent() throws MuleException
455     {
456         Service service = muleContext.getRegistry().lookupService(AXIS_SERVICE_PROPERTY + getName());
457 
458         if (service == null)
459         {
460             // TODO MULE-2228 Simplify this API
461             service = new SedaService(muleContext);
462             service.setName(AXIS_SERVICE_PROPERTY + getName());
463             service.setModel(muleContext.getRegistry().lookupSystemModel());
464 
465             Map props = new HashMap();
466             props.put(AXIS, axis);
467             SingletonObjectFactory of = new SingletonObjectFactory(AxisServiceComponent.class, props);
468             final DefaultJavaComponent component = new DefaultJavaComponent(of);
469             component.setMuleContext(muleContext);
470             service.setComponent(component);
471         }
472         return service;
473     }
474 
475     /**
476      * Template method to perform any work when starting the connectoe
477      *
478      * @throws org.mule.api.MuleException if the method fails
479      */
480     @Override
481     protected void doStart() throws MuleException
482     {
483         axis.start();
484     }
485 
486     /**
487      * Template method to perform any work when stopping the connectoe
488      *
489      * @throws org.mule.api.MuleException if the method fails
490      */
491     @Override
492     protected void doStop() throws MuleException
493     {
494         axis.stop();
495         // Model model = muleContext.getRegistry().lookupModel();
496         // model.unregisterComponent(model.getDescriptor(AXIS_SERVICE_COMPONENT_NAME));
497     }
498 
499     @Override
500     protected void doConnect() throws Exception
501     {
502         // template method
503     }
504 
505     @Override
506     protected void doDisconnect() throws Exception
507     {
508         // template method
509     }
510 
511     @Override
512     protected void doDispose()
513     {
514         // clear static references to classloaders to prevent loading classes from
515         // closed jars and avoid memory leaks on application redeploy.
516         try
517         {
518             Field field = AxisProperties.class.getDeclaredField("loaders");
519             field.setAccessible(true);
520             field.set(null, null);
521 
522             field = AxisProperties.class.getDeclaredField("nameDiscoverer");
523             field.setAccessible(true);
524             field.set(null, null);
525         }
526         catch (Exception e)
527         {
528             logger.error(
529                 "Error disposing AxisConnector, this may cause a memory leak. Error is: " + e.getMessage(), e);
530         }
531 
532     }
533 
534     public String getServerConfig()
535     {
536         return serverConfig;
537     }
538 
539     public void setServerConfig(String serverConfig)
540     {
541         this.serverConfig = serverConfig;
542     }
543 
544     public List getBeanTypes()
545     {
546         return beanTypes;
547     }
548 
549     public void setBeanTypes(List beanTypes)
550     {
551         this.beanTypes = beanTypes;
552     }
553 
554     public String getClientConfig()
555     {
556         return clientConfig;
557     }
558 
559     public void setClientConfig(String clientConfig)
560     {
561         this.clientConfig = clientConfig;
562     }
563 
564     public AxisServer getAxis()
565     {
566         return axis;
567     }
568 
569     public void setAxis(AxisServer axisServer)
570     {
571         this.axis = axisServer;
572     }
573 
574     public SimpleProvider getServerProvider()
575     {
576         return serverProvider;
577     }
578 
579     public void setServerProvider(SimpleProvider serverProvider)
580     {
581         this.serverProvider = serverProvider;
582     }
583 
584     public SimpleProvider getClientProvider()
585     {
586         return clientProvider;
587     }
588 
589     public void setClientProvider(SimpleProvider clientProvider)
590     {
591         this.clientProvider = clientProvider;
592     }
593 
594     public Map getAxisTransportProtocols()
595     {
596         return axisTransportProtocols;
597     }
598 
599     public void setAxisTransportProtocols(Map axisTransportProtocols)
600     {
601         this.axisTransportProtocols.putAll(axisTransportProtocols);
602     }
603 
604     void addServletService(SOAPService service)
605     {
606         servletServices.add(service);
607     }
608 
609     public List getSupportedSchemes()
610     {
611         return supportedSchemes;
612     }
613 
614     public void setSupportedSchemes(List supportedSchemes)
615     {
616         this.supportedSchemes = supportedSchemes;
617     }
618 
619     public boolean isDoAutoTypes()
620     {
621         return doAutoTypes;
622     }
623 
624     public void setDoAutoTypes(boolean doAutoTypes)
625     {
626         this.doAutoTypes = doAutoTypes;
627     }
628 
629     void registerTypes(TypeMappingRegistryImpl registry, List types) throws ClassNotFoundException
630     {
631         if (types != null)
632         {
633             Class clazz;
634             for (Iterator iterator = types.iterator(); iterator.hasNext();)
635             {
636                 clazz = ClassUtils.loadClass(iterator.next().toString(), getClass());
637                 String localName = Types.getLocalNameFromFullName(clazz.getName());
638                 QName xmlType = new QName(Namespaces.makeNamespace(clazz.getName()), localName);
639 
640                 registry.getDefaultTypeMapping().register(clazz, xmlType,
641                         new BeanSerializerFactory(clazz, xmlType), new BeanDeserializerFactory(clazz, xmlType));
642             }
643         }
644     }
645 
646     public boolean isTreatMapAsNamedParams()
647     {
648         return treatMapAsNamedParams;
649     }
650 
651     public void setTreatMapAsNamedParams(boolean treatMapAsNamedParams)
652     {
653         this.treatMapAsNamedParams = treatMapAsNamedParams;
654     }
655 
656     public void onNotification(MuleContextNotification notification)
657     {
658         try
659         {
660             if (notification.getAction() == MuleContextNotification.CONTEXT_STARTED)
661             {
662                 // We need to register the Axis service component once the muleContext
663                 // starts because when the model starts listeners on components are started, thus
664                 // all listener need to be registered for this connector before the Axis service
665                 // component is registered.
666                 // The implication of this is that to add a new service and a
667                 // different http port the model needs to be restarted before the listener is available
668                 if (muleContext.getRegistry().lookupService(AXIS_SERVICE_PROPERTY + getName()) == null)
669                 {
670                     // Descriptor might be null if no inbound endpoints have been
671                     // register for the Axis connector
672                     if (axisComponent == null)
673                     {
674                         axisComponent = getOrCreateAxisComponent();
675                     }
676                     muleContext.getRegistry().registerService(axisComponent);
677 
678                     // We have to perform a small hack here to rewrite servlet://
679                     // endpoints with the
680                     // real http:// address
681                     for (Iterator iterator = servletServices.iterator(); iterator.hasNext();)
682                     {
683                         SOAPService service = (SOAPService) iterator.next();
684                         ServletConnector servletConnector = (ServletConnector) new TransportFactory(muleContext).getConnectorByProtocol("servlet");
685                         String url = servletConnector.getServletUrl();
686                         if (url != null)
687                         {
688                             service.getServiceDescription().setEndpointURL(url + "/" + service.getName());
689                         }
690                         else
691                         {
692                             logger.error("The servletUrl property on the ServletConntector has not been set this means that wsdl generation for service '"
693                                     + service.getName() + "' may be incorrect");
694                         }
695                     }
696                     servletServices.clear();
697                 }
698             }
699         }
700         catch (MuleException e)
701         {
702             throw new MuleRuntimeException(e);
703         }
704     }
705 }