View Javadoc

1   /*
2    * $Id: CxfConnector.java 12289 2008-07-10 21:35:05Z dandiep $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.cxf;
12  
13  import org.mule.api.MuleException;
14  import org.mule.api.context.notification.MuleContextNotificationListener;
15  import org.mule.api.context.notification.ServerNotification;
16  import org.mule.api.endpoint.EndpointBuilder;
17  import org.mule.api.endpoint.EndpointURI;
18  import org.mule.api.endpoint.InboundEndpoint;
19  import org.mule.api.lifecycle.InitialisationException;
20  import org.mule.api.service.Service;
21  import org.mule.api.transport.MessageReceiver;
22  import org.mule.component.DefaultJavaComponent;
23  import org.mule.config.spring.SpringRegistry;
24  import org.mule.context.notification.MuleContextNotification;
25  import org.mule.endpoint.EndpointURIEndpointBuilder;
26  import org.mule.model.seda.SedaService;
27  import org.mule.object.SingletonObjectFactory;
28  import org.mule.routing.inbound.DefaultInboundRouterCollection;
29  import org.mule.transport.AbstractConnector;
30  import org.mule.transport.cxf.transport.MuleUniversalTransport;
31  import org.mule.transport.http.HttpConnector;
32  import org.mule.transport.http.HttpConstants;
33  
34  import java.util.ArrayList;
35  import java.util.HashMap;
36  import java.util.List;
37  import java.util.Map;
38  
39  import javax.xml.namespace.QName;
40  
41  import org.apache.cxf.Bus;
42  import org.apache.cxf.BusFactory;
43  import org.apache.cxf.bus.spring.SpringBusFactory;
44  import org.apache.cxf.endpoint.Server;
45  import org.apache.cxf.transport.ConduitInitiatorManager;
46  import org.apache.cxf.transport.DestinationFactoryManager;
47  import org.springframework.context.ApplicationContext;
48  
49  /**
50   * Connects Mule to a CXF bus instance.
51   */
52  public class CxfConnector extends AbstractConnector implements MuleContextNotificationListener
53  {
54  
55      public static final String CXF = "cxf";
56      public static final String CXF_SERVICE_COMPONENT_NAME = "_cxfServiceComponent";
57      public static final String CONFIGURATION_LOCATION = "configurationLocation";
58      public static final String DEFAULT_MULE_NAMESPACE_URI = "http://www.muleumo.org";
59      public static final String BUS_PROPERTY = CXF;
60  
61      // The CXF Bus object
62      private Bus bus;
63      private String configurationLocation;
64      private String defaultFrontend = CxfConstants.JAX_WS_FRONTEND;
65      private List<SedaService> services = new ArrayList<SedaService>();
66      private Map<String, Server> uriToServer = new HashMap<String, Server>();
67      private boolean initializeStaticBusInstance = false;
68      
69      public CxfConnector()
70      {
71          super();
72          registerProtocols();
73      }
74  
75      protected void registerProtocols()
76      {
77          registerSupportedProtocol("http");
78          registerSupportedProtocol("https");
79          registerSupportedProtocol("jms");
80          registerSupportedProtocol("vm");
81          registerSupportedProtocol("servlet");
82      }
83  
84      public String getProtocol()
85      {
86          return CXF;
87      }
88  
89      protected void doInitialise() throws InitialisationException
90      {
91          ApplicationContext context = (ApplicationContext) muleContext.getRegistry().lookupObject(SpringRegistry.SPRING_APPLICATION_CONTEXT);
92          
93          if (configurationLocation != null)
94          {
95              bus = new SpringBusFactory(context).createBus(configurationLocation, true);
96          }
97          else
98          {
99              bus = new SpringBusFactory(context).createBus((String)null, true);
100         }
101         
102         if (!initializeStaticBusInstance)
103         {
104             BusFactory.setDefaultBus(null);
105         }
106         
107         MuleUniversalTransport transport = new MuleUniversalTransport(this);
108         DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
109         dfm.registerDestinationFactory("http://schemas.xmlsoap.org/soap/http", transport);
110         dfm.registerDestinationFactory("http://schemas.xmlsoap.org/wsdl/soap/http", transport);
111         dfm.registerDestinationFactory(MuleUniversalTransport.TRANSPORT_ID, transport);
112 
113         ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
114         extension.registerConduitInitiator("http://schemas.xmlsoap.org/wsdl/soap/", transport);
115         extension.registerConduitInitiator("http://schemas.xmlsoap.org/soap/http", transport);
116         extension.registerConduitInitiator(MuleUniversalTransport.TRANSPORT_ID, transport);
117         
118         // Registers the listener
119         try
120         {
121         	muleContext.registerListener(this);
122         }
123         catch (Exception e)
124         {
125             throw new InitialisationException(e, this);
126         }
127     }
128 
129     protected void doDispose()
130     {
131         // template method
132     }
133 
134     protected void doConnect() throws Exception
135     {
136         // template method
137     }
138 
139     protected void doDisconnect() throws Exception
140     {
141         // template method
142     }
143 
144     protected void doStart() throws MuleException
145     {
146 
147     }
148 
149     protected void doStop() throws MuleException
150     {
151         bus.shutdown(true);
152     }
153 
154     public Bus getCxfBus()
155     {
156         return bus;
157     }
158 
159     public void setCxfBus(Bus bus)
160     {
161         this.bus = bus;
162     }
163 
164     public String getConfigurationLocation()
165     {
166         return configurationLocation;
167     }
168 
169     public void setConfigurationLocation(String configurationLocation)
170     {
171         this.configurationLocation = configurationLocation;
172     }
173 
174     public String getDefaultFrontend()
175     {
176         return defaultFrontend;
177     }
178 
179     public void setDefaultFrontend(String defaultFrontend)
180     {
181         this.defaultFrontend = defaultFrontend;
182     }
183 
184     @SuppressWarnings("unchecked")
185     protected void registerReceiverWithMuleService(MessageReceiver receiver, EndpointURI ep) throws MuleException
186     {
187         CxfMessageReceiver cxfReceiver = (CxfMessageReceiver) receiver;
188         Server server = cxfReceiver.getServer();
189 
190         uriToServer.put(server.getEndpoint().getEndpointInfo().getAddress(), server);
191         
192         // TODO MULE-2228 Simplify this API
193         SedaService c = new SedaService();
194         c.setName(CXF_SERVICE_COMPONENT_NAME + server.getEndpoint().getService().getName() + c.hashCode());
195         c.setModel(muleContext.getRegistry().lookupSystemModel());
196 
197         CxfServiceComponent svcComponent = new CxfServiceComponent(this, (CxfMessageReceiver) receiver);
198         svcComponent.setBus(bus);
199 
200         c.setComponent(new DefaultJavaComponent(new SingletonObjectFactory(svcComponent)));
201 
202         // No determine if the endpointUri requires a new connector to be
203         // registed in the case of http we only need to register the new
204         // endpointUri if the port is different
205         String endpoint = receiver.getEndpointURI().getAddress();
206         String scheme = ep.getScheme().toLowerCase();
207 
208         InboundEndpoint originalEndpoint = receiver.getEndpoint();
209         boolean sync = originalEndpoint.isSynchronous();
210 
211         // If we are using sockets then we need to set the endpoint name appropiately
212         // and if using http/https
213         // we need to default to POST and set the Content-Type
214         if (scheme.equals("http") || scheme.equals("https") || scheme.equals("ssl") || scheme.equals("tcp")
215             || scheme.equals("servlet"))
216         {
217             originalEndpoint.getProperties().put(HttpConnector.HTTP_METHOD_PROPERTY, "POST");
218             originalEndpoint.getProperties().put(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
219         }
220 
221         QName serviceName = server.getEndpoint().getEndpointInfo().getName();
222         
223         EndpointBuilder protocolEndpointBuilder = new EndpointURIEndpointBuilder(endpoint, muleContext);
224         protocolEndpointBuilder.setSynchronous(sync);
225         protocolEndpointBuilder.setName(ep.getScheme() + ":" + serviceName.getLocalPart());
226         
227         EndpointBuilder receiverEndpointBuilder = new EndpointURIEndpointBuilder(originalEndpoint,
228             muleContext);
229         
230         // Apply the transformers to the correct endpoint
231         EndpointBuilder transformerEndpoint;
232         if (cxfReceiver.isApplyTransformersToProtocol())
233         {
234             transformerEndpoint = protocolEndpointBuilder; 
235             receiverEndpointBuilder.setTransformers(null);
236             receiverEndpointBuilder.setResponseTransformers(null);
237         }
238         else
239         {  
240             transformerEndpoint = receiverEndpointBuilder;
241         }
242         transformerEndpoint.setTransformers(originalEndpoint.getTransformers());
243         transformerEndpoint.setResponseTransformers(originalEndpoint.getResponseTransformers());
244         
245         // apply the filters to the correct endpoint
246         EndpointBuilder filterEndpoint;
247         if (cxfReceiver.isApplyFiltersToProtocol())
248         {
249             filterEndpoint = protocolEndpointBuilder;   
250             receiverEndpointBuilder.setFilter(null);                                                                                                
251         }
252         else
253         {  
254             filterEndpoint = receiverEndpointBuilder;
255         }
256         filterEndpoint.setFilter(originalEndpoint.getFilter());
257         
258         // apply the security filter to the correct endpoint
259         EndpointBuilder secFilterEndpoint;
260         if (cxfReceiver.isApplySecurityToProtocol())
261         {
262             secFilterEndpoint = protocolEndpointBuilder;   
263             receiverEndpointBuilder.setSecurityFilter(null);                                                                                               
264         }
265         else
266         {  
267             secFilterEndpoint = receiverEndpointBuilder;
268         }             
269         secFilterEndpoint.setSecurityFilter(originalEndpoint.getSecurityFilter());
270 
271         InboundEndpoint protocolEndpoint = muleContext.getRegistry()
272             .lookupEndpointFactory()
273             .getInboundEndpoint(protocolEndpointBuilder);
274 
275         InboundEndpoint receiverEndpoint = muleContext.getRegistry()
276             .lookupEndpointFactory()
277             .getInboundEndpoint(receiverEndpointBuilder);
278 
279         receiver.setEndpoint(receiverEndpoint);
280         
281         c.setInboundRouter(new DefaultInboundRouterCollection());
282         c.getInboundRouter().addEndpoint(protocolEndpoint);
283         
284         services.add(c);
285     }
286 
287     /**
288      * The method determines the key used to store the receiver against.
289      * 
290      * @param service the service for which the endpoint is being registered
291      * @param endpoint the endpoint being registered for the service
292      * @return the key to store the newly created receiver against. In this case it
293      *         is the service name, which is equivilent to the Axis service name.
294      */
295     @Override
296     protected Object getReceiverKey(Service service, InboundEndpoint endpoint)
297     {
298         if (endpoint.getEndpointURI().getPort() == -1)
299         {
300             return service.getName();
301         }
302         else
303         {
304             return endpoint.getEndpointURI().getAddress();
305         }
306     }
307 
308     public void onNotification(ServerNotification event)
309     {
310         // We need to register the CXF service service once the model
311         // starts because
312         // when the model starts listeners on components are started, thus
313         // all listener
314         // need to be registered for this connector before the CXF service
315         // service is registered. The implication of this is that to add a
316         // new service and a
317         // different http port the model needs to be restarted before the
318         // listener is available
319         if (event.getAction() == MuleContextNotification.CONTEXT_STARTED)
320         {
321             for (Service c : services)
322             {
323                 try
324                 {
325                     muleContext.getRegistry().registerService(c);
326                 }
327                 catch (MuleException e)
328                 {
329                     handleException(e);
330                 }
331             }
332         }
333     }
334     
335     public boolean isSyncEnabled(String protocol)
336     {
337         protocol = protocol.toLowerCase();
338         if (protocol.equals("http") || protocol.equals("https") || protocol.equals("ssl") || protocol.equals("tcp")
339             || protocol.equals("servlet"))
340         {
341             return true;
342         }
343         else
344         {
345             return super.isSyncEnabled(protocol);
346         }
347     }
348 
349     public Server getServer(String uri)
350     {
351         return uriToServer.get(uri);
352     }
353 
354     public boolean isInitializeStaticBusInstance()
355     {
356         return initializeStaticBusInstance;
357     }
358 
359     public void setInitializeStaticBusInstance(boolean initializeStaticBusInstance)
360     {
361         this.initializeStaticBusInstance = initializeStaticBusInstance;
362     }
363     
364 }