View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.module.cxf.builder;
8   
9   import org.mule.api.DefaultMuleException;
10  import org.mule.api.MuleContext;
11  import org.mule.api.MuleException;
12  import org.mule.api.context.MuleContextAware;
13  import org.mule.api.lifecycle.Callable;
14  import org.mule.api.lifecycle.Disposable;
15  import org.mule.api.lifecycle.Initialisable;
16  import org.mule.api.processor.MessageProcessorBuilder;
17  import org.mule.api.service.ServiceAware;
18  import org.mule.module.cxf.CxfConfiguration;
19  import org.mule.module.cxf.CxfConstants;
20  import org.mule.module.cxf.CxfInboundMessageProcessor;
21  import org.mule.module.cxf.MuleInvoker;
22  import org.mule.module.cxf.support.CxfUtils;
23  import org.mule.module.cxf.support.MuleHeadersInInterceptor;
24  import org.mule.module.cxf.support.MuleHeadersOutInterceptor;
25  import org.mule.module.cxf.support.MuleServiceConfiguration;
26  import org.mule.util.ClassUtils;
27  
28  import java.util.Collection;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.concurrent.CopyOnWriteArrayList;
33  
34  import org.apache.cxf.Bus;
35  import org.apache.cxf.configuration.Configurer;
36  import org.apache.cxf.endpoint.Server;
37  import org.apache.cxf.feature.AbstractFeature;
38  import org.apache.cxf.frontend.ServerFactoryBean;
39  import org.apache.cxf.interceptor.AttachmentOutInterceptor;
40  import org.apache.cxf.interceptor.Interceptor;
41  import org.apache.cxf.interceptor.OneWayProcessorInterceptor;
42  import org.apache.cxf.message.Message;
43  import org.apache.cxf.service.factory.AbstractServiceConfiguration;
44  import org.apache.cxf.service.factory.ReflectionServiceFactoryBean;
45  import org.apache.cxf.service.invoker.Invoker;
46  
47  /**
48   * An abstract builder for CXF services. It handles all common operations such
49   * as interceptor configuration, mule header enabling, etc. Subclasses can extend
50   * this and control how the Server is created and how the {@link CxfInboundMessageProcessor}
51   * is configured.
52   */
53  public abstract class AbstractInboundMessageProcessorBuilder implements MuleContextAware, MessageProcessorBuilder
54  {
55      private CxfConfiguration configuration;
56      private Server server;
57      private boolean enableMuleSoapHeaders = true;
58      private String wsdlLocation;
59      private String bindingId;
60      private String mtomEnabled;
61      private String soapVersion;
62      private String service;
63      private String namespace;
64      private List<AbstractFeature> features;
65      private List<Interceptor<? extends Message>> inInterceptors = new CopyOnWriteArrayList<Interceptor<? extends Message>>();
66      private List<Interceptor<? extends Message>> inFaultInterceptors = new CopyOnWriteArrayList<Interceptor<? extends Message>>();
67      private List<Interceptor<? extends Message>> outInterceptors = new CopyOnWriteArrayList<Interceptor<? extends Message>>();
68      private List<Interceptor<? extends Message>> outFaultInterceptors = new CopyOnWriteArrayList<Interceptor<? extends Message>>();
69      protected MuleContext muleContext;
70      private String port;
71      private Map<String,Object> properties = new HashMap<String, Object>();
72      private boolean validationEnabled;
73      private List<String> schemaLocations;
74      private String onException = CxfConstants.CREATE_SOAP_FAULT;
75  
76      public CxfInboundMessageProcessor build() throws MuleException
77      {
78          if (muleContext == null)
79          {
80              throw new IllegalStateException("MuleContext must be supplied.");
81          }
82  
83          if (configuration == null)
84          {
85              configuration = CxfConfiguration.getConfiguration(muleContext);
86          }
87  
88          if (configuration == null)
89          {
90              throw new IllegalStateException("A CxfConfiguration object must be supplied.");
91          }
92  
93          ServerFactoryBean sfb;
94          try
95          {
96              sfb = createServerFactory();
97          }
98          catch (Exception e)
99          {
100             throw new DefaultMuleException(e);
101         }
102 
103         // The binding - i.e. SOAP, XML, HTTP Binding, etc
104         if (bindingId != null)
105         {
106             sfb.setBindingId(bindingId);
107         }
108 
109         if (features != null)
110         {
111             sfb.getFeatures().addAll(features);
112         }
113 
114         if (mtomEnabled != null)
115         {
116             properties.put("mtom-enabled", mtomEnabled);
117             properties.put(AttachmentOutInterceptor.WRITE_ATTACHMENTS, true);
118         }
119 
120         if (inInterceptors != null)
121         {
122             sfb.getInInterceptors().addAll((Collection<? extends Interceptor<? extends Message>>) inInterceptors);
123         }
124 
125 
126         if (inFaultInterceptors != null)
127         {
128             sfb.getInFaultInterceptors().addAll((Collection<? extends Interceptor<? extends Message>>) inFaultInterceptors);
129         }
130 
131         if (outInterceptors != null)
132         {
133             sfb.getOutInterceptors().addAll((Collection<? extends Interceptor<? extends Message>>) outInterceptors);
134         }
135 
136         if (outFaultInterceptors != null)
137         {
138             sfb.getOutFaultInterceptors().addAll((Collection<? extends Interceptor<? extends Message>>) outFaultInterceptors);
139         }
140 
141         if (enableMuleSoapHeaders && !configuration.isEnableMuleSoapHeaders())
142         {
143             sfb.getInInterceptors().add(new MuleHeadersInInterceptor());
144             sfb.getInFaultInterceptors().add(new MuleHeadersInInterceptor());
145             sfb.getOutInterceptors().add(new MuleHeadersOutInterceptor());
146             sfb.getOutFaultInterceptors().add(new MuleHeadersOutInterceptor());
147         }
148 
149         String address = getAddress();
150         address = CxfUtils.mapUnsupportedSchemas(address);
151         sfb.setAddress(address); // dummy URL for CXF
152 
153         if (wsdlLocation != null)
154         {
155             sfb.setWsdlURL(wsdlLocation);
156         }
157 
158         sfb.setSchemaLocations(schemaLocations);
159 
160         ReflectionServiceFactoryBean svcFac = sfb.getServiceFactory();
161         initServiceFactory(svcFac);
162 
163         CxfInboundMessageProcessor processor = new CxfInboundMessageProcessor();
164         processor.setMuleContext(muleContext);
165         processor.setOnFaultInvokeStrategy(CxfConstants.INVOKE_EXCEPTION_STRATEGY.equals(onException));
166         configureMessageProcessor(sfb, processor);
167         sfb.setStart(false);
168 
169         Bus bus = configuration.getCxfBus();
170         sfb.setBus(bus);
171         svcFac.setBus(bus);
172 
173         Configurer configurer = bus.getExtension(Configurer.class);
174         if (null != configurer)
175         {
176             configurer.configureBean(svcFac.getEndpointName().toString(), sfb);
177         }
178 
179         if (validationEnabled)
180         {
181             properties.put("schema-validation-enabled", "true");
182         }
183 
184         // If there's a soapVersion defined then the corresponding bindingId will be set
185         if(soapVersion != null)
186         {
187             sfb.setBindingId(CxfUtils.getBindingIdForSoapVersion(soapVersion));
188         }
189         
190         sfb.setProperties(properties);
191         sfb.setInvoker(createInvoker(processor));
192         
193         server = sfb.create();
194         
195         CxfUtils.removeInterceptor(server.getEndpoint().getService().getInInterceptors(), OneWayProcessorInterceptor.class.getName());
196         configureServer(server);
197 
198         processor.setBus(sfb.getBus());
199         processor.setServer(server);
200         processor.setProxy(isProxy());
201         return processor;
202     }
203     
204     protected Invoker createInvoker(CxfInboundMessageProcessor processor)
205     {
206         return new MuleInvoker(processor, getServiceClass());
207     }
208 
209     protected void configureServer(Server server2)
210     {
211     }
212 
213     protected abstract Class<?> getServiceClass();
214 
215     protected void configureMessageProcessor(ServerFactoryBean sfb, CxfInboundMessageProcessor processor)
216     {
217     }
218 
219     protected abstract ServerFactoryBean createServerFactory() throws Exception;
220 
221     protected String getAddress()
222     {
223         return "http://internalMuleCxfRegistry/" + hashCode();
224     }
225 
226     /**
227      * This method configures the {@link ReflectionServiceFactoryBean}.
228      */
229     private void initServiceFactory(ReflectionServiceFactoryBean svcFac)
230     {
231         addIgnoredMethods(svcFac, Callable.class.getName());
232         addIgnoredMethods(svcFac, Initialisable.class.getName());
233         addIgnoredMethods(svcFac, Disposable.class.getName());
234         addIgnoredMethods(svcFac, ServiceAware.class.getName());
235 
236         svcFac.getServiceConfigurations().add(0, new MuleServiceConfiguration(this));
237 
238         svcFac.setServiceClass(getServiceClass());
239         for (AbstractServiceConfiguration c : svcFac.getServiceConfigurations())
240         {
241             c.setServiceFactory(svcFac);
242         }
243     }
244 
245     public void addIgnoredMethods(ReflectionServiceFactoryBean svcFac, String className)
246     {
247         try
248         {
249             Class<?> c = ClassUtils.loadClass(className, getClass());
250             for (int i = 0; i < c.getMethods().length; i++)
251             {
252                 svcFac.getIgnoredMethods().add(c.getMethods()[i]);
253             }
254         }
255         catch (ClassNotFoundException e)
256         {
257             // can be ignored.
258         }
259     }
260 
261 
262     public Server getServer()
263     {
264         return server;
265     }
266 
267     public abstract boolean isProxy();
268 
269     public CxfConfiguration getConfiguration()
270     {
271         return configuration;
272     }
273 
274     public void setConfiguration(CxfConfiguration configuration)
275     {
276         this.configuration = configuration;
277     }
278 
279     public boolean isEnableMuleSoapHeaders()
280     {
281         return enableMuleSoapHeaders;
282     }
283 
284     public void setEnableMuleSoapHeaders(boolean enableMuleSoapHeaders)
285     {
286         this.enableMuleSoapHeaders = enableMuleSoapHeaders;
287     }
288 
289     public String getWsdlLocation()
290     {
291         return wsdlLocation;
292     }
293 
294     public void setWsdlLocation(String wsdlUrl)
295     {
296         this.wsdlLocation = wsdlUrl;
297     }
298 
299     public String getBindingId()
300     {
301         return bindingId;
302     }
303 
304     public void setBindingId(String bindingId)
305     {
306         this.bindingId = bindingId;
307     }
308 
309     public void setSoapVersion(String soapVersion)
310     {
311         this.soapVersion = soapVersion;
312     }
313 
314     public String getSoapVersion()
315     {
316         return soapVersion;
317     }
318 
319     public String getMtomEnabled()
320     {
321         return mtomEnabled;
322     }
323 
324     public void setMtomEnabled(String mtomEnabled)
325     {
326         this.mtomEnabled = mtomEnabled;
327     }
328 
329     public String getService()
330     {
331         return service;
332     }
333 
334     public void setService(String name)
335     {
336         this.service = name;
337     }
338 
339     public String getNamespace()
340     {
341         return namespace;
342     }
343 
344     public void setNamespace(String namespace)
345     {
346         this.namespace = namespace;
347     }
348 
349     public List<AbstractFeature> getFeatures()
350     {
351         return features;
352     }
353 
354     public void setFeatures(List<AbstractFeature> features)
355     {
356         this.features = features;
357     }
358 
359     public List<Interceptor<? extends Message>> getInInterceptors()
360     {
361         return inInterceptors;
362     }
363 
364     public void setInInterceptors(List<Interceptor<? extends Message>> inInterceptors)
365     {
366         this.inInterceptors = inInterceptors;
367     }
368 
369     public List<Interceptor<? extends Message>> getInFaultInterceptors()
370     {
371         return inFaultInterceptors;
372     }
373 
374     public void setInFaultInterceptors(List<Interceptor<? extends Message>> inFaultInterceptors)
375     {
376         this.inFaultInterceptors = inFaultInterceptors;
377     }
378 
379     public List<Interceptor<? extends Message>> getOutInterceptors()
380     {
381         return outInterceptors;
382     }
383 
384     public void setOutInterceptors(List<Interceptor<? extends Message>> outInterceptors)
385     {
386         this.outInterceptors = outInterceptors;
387     }
388 
389     public List<Interceptor<? extends Message>> getOutFaultInterceptors()
390     {
391         return outFaultInterceptors;
392     }
393 
394     public void setOutFaultInterceptors(List<Interceptor<? extends Message>> outFaultInterceptors)
395     {
396         this.outFaultInterceptors = outFaultInterceptors;
397     }
398     
399     public void setMuleContext(MuleContext muleContext)
400     {
401         this.muleContext = muleContext;
402     }
403 
404     public String getPort()
405     {
406         return port;
407     }
408 
409     public void setPort(String endpoint)
410     {
411         this.port = endpoint;
412     }
413 
414     public Map<String, Object> getProperties()
415     {
416         return properties;
417     }
418 
419     public void setProperties(Map<String, Object> properties)
420     {
421         this.properties = properties;
422     }
423 
424     public boolean isValidationEnabled()
425     {
426         return validationEnabled;
427     }
428 
429     public void setValidationEnabled(boolean validationEnabled)
430     {
431         this.validationEnabled = validationEnabled;
432     }
433 
434     public List<String> getSchemaLocations()
435     {
436         return schemaLocations;
437     }
438 
439     public void setSchemaLocations(List<String> schemaLocations)
440     {
441         this.schemaLocations = schemaLocations;
442     }
443 
444     public String getOnException()
445     {
446         return this.onException;
447     }
448 
449     public void setOnException(String onException)
450     {
451         this.onException = onException;
452     }
453     
454 }