View Javadoc

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