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