View Javadoc

1   /*
2    * $Id: WebServiceMessageProcessorBuilder.java 19998 2010-10-24 14:39:16Z 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.module.cxf.builder;
12  
13  import org.mule.api.DefaultMuleException;
14  import org.mule.api.MuleException;
15  import org.mule.api.component.Component;
16  import org.mule.api.component.JavaComponent;
17  import org.mule.api.construct.FlowConstruct;
18  import org.mule.api.construct.FlowConstructAware;
19  import org.mule.api.endpoint.InboundEndpoint;
20  import org.mule.api.lifecycle.CreateException;
21  import org.mule.api.service.Service;
22  import org.mule.api.source.MessageSource;
23  import org.mule.construct.AbstractFlowConstruct;
24  import org.mule.module.cxf.CxfConstants;
25  import org.mule.module.cxf.CxfInboundMessageProcessor;
26  import org.mule.module.cxf.MuleJAXWSInvoker;
27  import org.mule.module.cxf.i18n.CxfMessages;
28  import org.mule.service.ServiceCompositeMessageSource;
29  
30  import java.util.List;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.cxf.aegis.databinding.AegisDatabinding;
35  import org.apache.cxf.databinding.DataBinding;
36  import org.apache.cxf.frontend.ServerFactoryBean;
37  import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
38  import org.apache.cxf.service.invoker.Invoker;
39  
40  /**
41   * Builds a CXF web service MessageProcessor using either the JAX-WS or
42   * simple frontends.  It must be configured in the following way:
43   * <ul>
44   * <li>If the builder is part of a {@link Service}, then it will try to
45   * detect the serviceClass from the component.</li>
46   * <li>If it is not part of a {@link Service}, then the serviceClass
47   * attribute must be supplied.</li>
48   * <li>The builder will use the JAX-WS frontend by default.</li>
49   */
50  public class WebServiceMessageProcessorBuilder
51      extends AbstractInboundMessageProcessorBuilder implements FlowConstructAware
52  {
53      protected transient Log logger = LogFactory.getLog(getClass());
54      
55      private List<DataBinding> databinding;
56      private String frontend = CxfConstants.JAX_WS_FRONTEND;
57      private FlowConstruct flowConstruct;
58      private Service muleService;
59      private Class<?> serviceClass;
60  
61      @Override
62      protected ServerFactoryBean createServerFactory() throws Exception
63      {
64          ServerFactoryBean sfb;
65          if (CxfConstants.SIMPLE_FRONTEND.equals(frontend))
66          {
67              sfb = new ServerFactoryBean();
68              sfb.setDataBinding(new AegisDatabinding());
69          }
70          else if (CxfConstants.JAX_WS_FRONTEND.equals(frontend))
71          {
72              sfb = new JaxWsServerFactoryBean();
73          }
74          else
75          {
76              throw new CreateException(CxfMessages.invalidFrontend(frontend), this);
77          }
78          
79          if (serviceClass == null)
80          {
81              serviceClass = getTargetClass(muleService);
82          }
83          sfb.setServiceClass(serviceClass);
84          
85          logger.info("Built CXF Inbound MessageProcessor for service class " + serviceClass.getName());
86          
87          // Configure Databinding
88          if (databinding != null && databinding.size() > 0)
89          {
90              // TODO: find a way to make this not a list
91              sfb.setDataBinding(databinding.get(0));
92          }
93          
94          if (muleService != null && muleService.getComponent() instanceof JavaComponent)
95          {
96              sfb.setServiceBean(((JavaComponent) muleService.getComponent()).getObjectFactory().getInstance(muleContext));
97          }
98          return sfb;
99      }
100     
101     @Override
102     protected Invoker createInvoker(CxfInboundMessageProcessor processor)
103     {
104         Invoker invoker = super.createInvoker(processor);
105         if (CxfConstants.JAX_WS_FRONTEND.equals(frontend))
106         {
107             invoker = new MuleJAXWSInvoker(invoker);
108         }
109         return invoker;
110     }
111 
112     /**
113      * Try to determine the target class from the Service.
114      * @param svcCls
115      * @param service
116      * @return
117      * @throws MuleException
118      * @throws ClassNotFoundException
119      */
120     protected Class<?> getTargetClass(Service service) throws MuleException, ClassNotFoundException
121     {
122         if (service == null)
123         {
124             throw new DefaultMuleException(CxfMessages.serviceClassRequiredWithPassThrough());
125         }
126         
127         Component component = service.getComponent();
128         if (!(component instanceof JavaComponent))
129         {
130             throw new DefaultMuleException(CxfMessages.serviceClassRequiredWithPassThrough());
131         }
132         
133         try
134         {
135             return ((JavaComponent) component).getObjectType();
136         }
137         catch (Exception e)
138         {
139             throw new CreateException(e, this);
140         }
141     }
142     
143     @Override
144     protected String getAddress()
145     {
146         if (flowConstruct != null)
147         {
148             if (flowConstruct instanceof Service)
149             {
150                 MessageSource source = ((Service) flowConstruct).getMessageSource();
151 
152                 if (source instanceof InboundEndpoint)
153                 {
154                     return ((InboundEndpoint) source).getEndpointURI().toString();
155                 }
156                 else if (source instanceof ServiceCompositeMessageSource)
157                 {
158                     List<InboundEndpoint> endpoints = ((ServiceCompositeMessageSource) muleService.getMessageSource()).getEndpoints();
159 
160                     if (endpoints.size() > 0)
161                     {
162                         return endpoints.get(0).getEndpointURI().toString();
163                     }
164                 }
165             }
166             else if (flowConstruct instanceof AbstractFlowConstruct)
167             {
168                 MessageSource source = ((AbstractFlowConstruct) flowConstruct).getMessageSource();
169 
170                 if (source instanceof InboundEndpoint)
171                 {
172                     return ((InboundEndpoint) source).getEndpointURI().toString();
173                 }
174             }
175         }
176         return "http://internalMuleCxfRegistry/" + hashCode();
177     }
178 
179     @Override
180     public boolean isProxy()
181     {
182         return false;
183     }
184 
185     @Override
186     public Class<?> getServiceClass()
187     {
188         return serviceClass;
189     }
190 
191     public void setServiceClass(Class<?> serviceClass)
192     {
193         this.serviceClass = serviceClass;
194     }
195 
196     public void setFlowConstruct(FlowConstruct flowConstruct)
197     {
198         this.flowConstruct = flowConstruct;
199         
200         if (flowConstruct instanceof Service)
201         {
202             this.muleService = (Service) flowConstruct;
203         }
204     }
205     public String getFrontend()
206     {
207         return frontend;
208     }
209 
210     /**
211      * Whether to use the simple frontend or JAX-WS frontend. Valid values
212      * are "simple" or "jaxws".
213      * @param frontend
214      */
215     public void setFrontend(String frontend)
216     {
217         this.frontend = frontend;
218     }
219 
220     public List<DataBinding> getDatabinding()
221     {
222         return databinding;
223     }
224 
225     public void setDatabinding(List<DataBinding> databinding)
226     {
227         this.databinding = databinding;
228     }
229 
230 }