View Javadoc

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