1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
package org.mule.transport.cxf; |
12 | |
|
13 | |
import org.mule.api.MuleEvent; |
14 | |
import org.mule.api.config.MuleProperties; |
15 | |
import org.mule.api.endpoint.EndpointURI; |
16 | |
import org.mule.api.endpoint.ImmutableEndpoint; |
17 | |
import org.mule.api.lifecycle.CreateException; |
18 | |
import org.mule.api.transport.DispatchException; |
19 | |
import org.mule.transport.cxf.i18n.CxfMessages; |
20 | |
import org.mule.transport.cxf.support.MuleHeadersInInterceptor; |
21 | |
import org.mule.transport.cxf.support.MuleHeadersOutInterceptor; |
22 | |
import org.mule.transport.cxf.support.MuleProtocolHeadersOutInterceptor; |
23 | |
import org.mule.transport.cxf.support.OutputPayloadInterceptor; |
24 | |
import org.mule.transport.cxf.support.ProxyService; |
25 | |
import org.mule.transport.soap.i18n.SoapMessages; |
26 | |
|
27 | |
import java.lang.reflect.Constructor; |
28 | |
import java.lang.reflect.Method; |
29 | |
import java.net.URL; |
30 | |
import java.util.HashMap; |
31 | |
import java.util.List; |
32 | |
|
33 | |
import javax.xml.namespace.QName; |
34 | |
import javax.xml.ws.BindingProvider; |
35 | |
import javax.xml.ws.Service; |
36 | |
import javax.xml.ws.WebEndpoint; |
37 | |
import javax.xml.ws.WebServiceClient; |
38 | |
|
39 | |
import org.apache.commons.lang.BooleanUtils; |
40 | |
import org.apache.cxf.Bus; |
41 | |
import org.apache.cxf.binding.Binding; |
42 | |
import org.apache.cxf.common.classloader.ClassLoaderUtils; |
43 | |
import org.apache.cxf.databinding.stax.StaxDataBinding; |
44 | |
import org.apache.cxf.databinding.stax.StaxDataBindingFeature; |
45 | |
import org.apache.cxf.endpoint.Client; |
46 | |
import org.apache.cxf.endpoint.ClientImpl; |
47 | |
import org.apache.cxf.endpoint.Endpoint; |
48 | |
import org.apache.cxf.endpoint.EndpointImpl; |
49 | |
import org.apache.cxf.feature.AbstractFeature; |
50 | |
import org.apache.cxf.frontend.ClientProxy; |
51 | |
import org.apache.cxf.frontend.ClientProxyFactoryBean; |
52 | |
import org.apache.cxf.frontend.MethodDispatcher; |
53 | |
import org.apache.cxf.interceptor.Interceptor; |
54 | |
import org.apache.cxf.interceptor.WrappedOutInterceptor; |
55 | |
import org.apache.cxf.message.Message; |
56 | |
import org.apache.cxf.phase.PhaseInterceptor; |
57 | |
import org.apache.cxf.resource.ResourceManager; |
58 | |
import org.apache.cxf.resource.URIResolver; |
59 | |
import org.apache.cxf.service.model.BindingOperationInfo; |
60 | |
import org.apache.cxf.service.model.EndpointInfo; |
61 | |
import org.apache.cxf.transport.ChainInitiationObserver; |
62 | |
import org.apache.cxf.transport.Destination; |
63 | |
import org.apache.cxf.transport.DestinationFactory; |
64 | |
import org.apache.cxf.transport.DestinationFactoryManager; |
65 | |
import org.apache.cxf.transport.MessageObserver; |
66 | |
|
67 | 76 | public class ClientWrapper |
68 | |
{ |
69 | |
|
70 | |
protected ImmutableEndpoint endpoint; |
71 | |
protected Bus bus; |
72 | |
protected Client client; |
73 | |
protected String defaultMethodName; |
74 | |
|
75 | |
|
76 | |
|
77 | |
protected BindingProvider clientProxy; |
78 | |
protected Method defaultMethod; |
79 | |
|
80 | |
protected boolean proxy; |
81 | |
|
82 | |
public Client getClient() |
83 | |
{ |
84 | 154 | return client; |
85 | |
} |
86 | |
|
87 | |
public BindingProvider getClientProxy() |
88 | |
{ |
89 | 12 | return clientProxy; |
90 | |
} |
91 | |
|
92 | |
@SuppressWarnings("unchecked") |
93 | |
public void initialize() throws Exception |
94 | |
{ |
95 | 76 | String clientClass = (String) endpoint.getProperty(CxfConstants.CLIENT_CLASS); |
96 | 76 | proxy = BooleanUtils.toBoolean((String) endpoint.getProperty(CxfConstants.PROXY)); |
97 | |
|
98 | 76 | if (clientClass != null) |
99 | |
{ |
100 | 6 | createClientFromClass(bus, clientClass); |
101 | |
} |
102 | 70 | else if (proxy) |
103 | |
{ |
104 | 6 | createClientProxy(bus); |
105 | |
} |
106 | |
else |
107 | |
{ |
108 | 64 | createClientFromLocalServer(bus); |
109 | |
} |
110 | |
|
111 | 76 | addInterceptors(client.getInInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.IN_INTERCEPTORS)); |
112 | 76 | addInterceptors(client.getInFaultInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.IN_FAULT_INTERCEPTORS)); |
113 | 76 | addInterceptors(client.getOutInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.OUT_INTERCEPTORS)); |
114 | 76 | addInterceptors(client.getOutFaultInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS)); |
115 | |
|
116 | 76 | if (proxy) |
117 | |
{ |
118 | 6 | client.getOutInterceptors().add(new OutputPayloadInterceptor()); |
119 | |
} |
120 | |
|
121 | 76 | List<AbstractFeature> features = (List<AbstractFeature>) endpoint.getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS); |
122 | |
|
123 | 76 | if (features != null) |
124 | |
{ |
125 | 0 | for (AbstractFeature f : features) |
126 | |
{ |
127 | 0 | f.initialize(client, bus); |
128 | |
} |
129 | |
} |
130 | |
|
131 | 76 | EndpointImpl ep = (EndpointImpl) client.getEndpoint(); |
132 | |
|
133 | 76 | Object mtomEnabled = endpoint.getProperty(CxfConstants.MTOM_ENABLED); |
134 | 76 | if (mtomEnabled != null) |
135 | |
{ |
136 | 2 | HashMap<String, Object> props = new HashMap<String, Object>(); |
137 | 2 | props.put(Message.MTOM_ENABLED, mtomEnabled); |
138 | 2 | ep.setProperties(props); |
139 | |
} |
140 | |
|
141 | 76 | addMuleInterceptors(); |
142 | 76 | } |
143 | |
|
144 | |
@SuppressWarnings("unchecked") |
145 | |
private void addInterceptors(List<Interceptor> col, List<Interceptor> supplied) |
146 | |
{ |
147 | 304 | if (supplied != null) |
148 | |
{ |
149 | 4 | col.addAll(supplied); |
150 | |
} |
151 | 304 | } |
152 | |
|
153 | |
protected Method findMethod(Class<?> clientCls) throws Exception |
154 | |
{ |
155 | 6 | if (defaultMethod == null) |
156 | |
{ |
157 | 6 | String op = (String) endpoint.getProperties().get(CxfConstants.OPERATION); |
158 | 6 | if (op == null) |
159 | |
{ |
160 | 0 | op = (String) endpoint.getProperties().get(CxfConstants.OPERATION); |
161 | |
} |
162 | |
|
163 | 6 | if (op != null) |
164 | |
{ |
165 | 6 | return getMethodFromOperation(op); |
166 | |
} |
167 | |
} |
168 | |
|
169 | 0 | return null; |
170 | |
} |
171 | |
|
172 | |
protected BindingOperationInfo getOperation(String opName) throws Exception |
173 | |
{ |
174 | |
|
175 | |
|
176 | |
|
177 | 58 | Endpoint ep = client.getEndpoint(); |
178 | 58 | QName q = new QName(ep.getService().getName().getNamespaceURI(), opName); |
179 | 58 | BindingOperationInfo bop = ep.getBinding().getBindingInfo().getOperation(q); |
180 | 58 | if (bop == null) |
181 | |
{ |
182 | 0 | throw new Exception("No such operation: " + defaultMethod); |
183 | |
} |
184 | |
|
185 | 58 | if (bop.isUnwrappedCapable()) |
186 | |
{ |
187 | 58 | bop = bop.getUnwrappedOperation(); |
188 | |
} |
189 | 58 | return bop; |
190 | |
} |
191 | |
|
192 | |
private Method getMethodFromOperation(String op) throws Exception |
193 | |
{ |
194 | 6 | BindingOperationInfo bop = getOperation(op); |
195 | 6 | MethodDispatcher md = (MethodDispatcher) client.getEndpoint().getService().get( |
196 | |
MethodDispatcher.class.getName()); |
197 | 6 | return md.getMethod(bop); |
198 | |
} |
199 | |
|
200 | |
protected void createClientProxy(Bus bus) throws Exception |
201 | |
{ |
202 | |
|
203 | 6 | String wsdlLocation = (String) endpoint.getProperty(CxfConstants.WSDL_LOCATION); |
204 | |
|
205 | 6 | ClientProxyFactoryBean cpf = new ClientProxyFactoryBean(); |
206 | 6 | cpf.setServiceClass(ProxyService.class); |
207 | 6 | cpf.setDataBinding(new StaxDataBinding()); |
208 | 6 | cpf.getFeatures().add(new StaxDataBindingFeature()); |
209 | 6 | cpf.setAddress(endpoint.getEndpointURI().getAddress()); |
210 | |
|
211 | 6 | if (wsdlLocation != null) |
212 | |
{ |
213 | 0 | cpf.setWsdlLocation(wsdlLocation); |
214 | |
} |
215 | |
|
216 | 6 | this.client = ClientProxy.getClient(cpf.create()); |
217 | |
|
218 | 6 | Binding binding = this.client.getEndpoint().getBinding(); |
219 | |
|
220 | 6 | removeInterceptor(binding.getOutInterceptors(), WrappedOutInterceptor.class.getName()); |
221 | |
|
222 | 6 | proxy = true; |
223 | 6 | } |
224 | |
|
225 | |
@SuppressWarnings("unchecked") |
226 | |
private void removeInterceptor(List<Interceptor> inInterceptors, String name) { |
227 | |
|
228 | 6 | for (Interceptor<?> i : inInterceptors) { |
229 | 30 | if (i instanceof PhaseInterceptor) { |
230 | 30 | PhaseInterceptor<Message> p = (PhaseInterceptor<Message>)i; |
231 | |
|
232 | 30 | if (p.getId().equals(name)) { |
233 | 6 | inInterceptors.remove(p); |
234 | 6 | return; |
235 | |
} |
236 | 24 | } |
237 | |
} |
238 | 0 | } |
239 | |
|
240 | |
protected void createClientFromClass(Bus bus, String clientClassName) throws Exception |
241 | |
{ |
242 | |
|
243 | 6 | String wsdlLocation = (String) endpoint.getProperty(CxfConstants.WSDL_LOCATION); |
244 | 6 | Class<?> clientCls = ClassLoaderUtils.loadClass(clientClassName, getClass()); |
245 | |
|
246 | 6 | Service s = null; |
247 | 6 | if (wsdlLocation != null) |
248 | |
{ |
249 | 6 | Constructor<?> cons = clientCls.getConstructor(URL.class, QName.class); |
250 | 6 | ResourceManager rr = bus.getExtension(ResourceManager.class); |
251 | 6 | URL url = rr.resolveResource(wsdlLocation, URL.class); |
252 | |
|
253 | 6 | if (url == null) |
254 | |
{ |
255 | 0 | URIResolver res = new URIResolver(wsdlLocation); |
256 | |
|
257 | 0 | if (!res.isResolved()) |
258 | |
{ |
259 | 0 | throw new CreateException(CxfMessages.wsdlNotFound(wsdlLocation), this); |
260 | |
} |
261 | 0 | url = res.getURL(); |
262 | |
} |
263 | |
|
264 | 6 | WebServiceClient clientAnn = clientCls.getAnnotation(WebServiceClient.class); |
265 | 6 | QName svcName = new QName(clientAnn.targetNamespace(), clientAnn.name()); |
266 | |
|
267 | 6 | s = (Service) cons.newInstance(url, svcName); |
268 | 6 | } |
269 | |
else |
270 | |
{ |
271 | 0 | s = (Service) clientCls.newInstance(); |
272 | |
} |
273 | 6 | String port = (String) endpoint.getProperty(CxfConstants.CLIENT_PORT); |
274 | |
|
275 | 6 | if (port == null) |
276 | |
{ |
277 | 0 | throw new CreateException(CxfMessages.mustSpecifyPort(), this); |
278 | |
} |
279 | |
|
280 | 6 | clientProxy = null; |
281 | 6 | if (port != null) |
282 | |
{ |
283 | 6 | for (Method m : clientCls.getMethods()) |
284 | |
{ |
285 | 6 | WebEndpoint we = m.getAnnotation(WebEndpoint.class); |
286 | |
|
287 | 6 | if (we != null && we.name().equals(port)) |
288 | |
{ |
289 | 6 | clientProxy = (BindingProvider) m.invoke(s, new Object[0]); |
290 | 6 | break; |
291 | |
} |
292 | |
} |
293 | |
} |
294 | |
|
295 | 6 | if (clientProxy == null) |
296 | |
{ |
297 | 0 | throw new CreateException(CxfMessages.portNotFound(port), this); |
298 | |
} |
299 | |
|
300 | 6 | EndpointURI uri = endpoint.getEndpointURI(); |
301 | 6 | if (uri.getUser() != null) |
302 | |
{ |
303 | 0 | clientProxy.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, uri.getUser()); |
304 | |
} |
305 | |
|
306 | 6 | if (uri.getPassword() != null) |
307 | |
{ |
308 | 0 | clientProxy.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, uri.getPassword()); |
309 | |
} |
310 | |
|
311 | 6 | clientProxy.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, uri.getAddress()); |
312 | |
|
313 | 6 | client = ClientProxy.getClient(clientProxy); |
314 | |
|
315 | 6 | defaultMethod = findMethod(clientCls); |
316 | 6 | defaultMethodName = getDefaultMethodName(); |
317 | 6 | } |
318 | |
|
319 | |
private String getDefaultMethodName() |
320 | |
{ |
321 | 6 | EndpointURI endpointUri = endpoint.getEndpointURI(); |
322 | 6 | String m = (String) endpointUri.getParams().get(MuleProperties.MULE_METHOD_PROPERTY); |
323 | |
|
324 | 6 | if (m == null) |
325 | |
{ |
326 | 6 | m = (String) endpoint.getProperties().get(MuleProperties.MULE_METHOD_PROPERTY); |
327 | |
} |
328 | |
|
329 | 6 | return m; |
330 | |
} |
331 | |
|
332 | |
protected void createClientFromLocalServer(final Bus bus) throws Exception |
333 | |
{ |
334 | 64 | String uri = endpoint.getEndpointURI().toString(); |
335 | 64 | int idx = uri.indexOf('?'); |
336 | 64 | if (idx != -1) |
337 | |
{ |
338 | 64 | uri = uri.substring(0, idx); |
339 | |
} |
340 | |
|
341 | 64 | EndpointInfo ei = new EndpointInfo(); |
342 | 64 | ei.setAddress(uri); |
343 | |
|
344 | 64 | DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); |
345 | 64 | DestinationFactory df = dfm.getDestinationFactoryForUri(uri); |
346 | 64 | if (df == null) |
347 | |
{ |
348 | 0 | throw new Exception("Could not find a destination factory for uri " + uri); |
349 | |
} |
350 | |
|
351 | 64 | Destination dest = df.getDestination(ei); |
352 | 64 | MessageObserver mo = dest.getMessageObserver(); |
353 | 64 | if (mo instanceof ChainInitiationObserver) |
354 | |
{ |
355 | 64 | ChainInitiationObserver cMo = (ChainInitiationObserver) mo; |
356 | 64 | Endpoint cxfEP = cMo.getEndpoint(); |
357 | |
|
358 | 64 | client = new ClientImpl(bus, cxfEP); |
359 | 64 | } |
360 | |
else |
361 | |
{ |
362 | 0 | throw new Exception("Could not create client! No Server was found directly on the endpoint: " |
363 | |
+ uri); |
364 | |
} |
365 | 64 | } |
366 | |
|
367 | |
protected void addMuleInterceptors() |
368 | |
{ |
369 | 76 | client.getInInterceptors().add(new MuleHeadersInInterceptor()); |
370 | 76 | client.getInFaultInterceptors().add(new MuleHeadersInInterceptor()); |
371 | 76 | client.getOutInterceptors().add(new MuleHeadersOutInterceptor()); |
372 | 76 | client.getOutFaultInterceptors().add(new MuleHeadersOutInterceptor()); |
373 | 76 | client.getOutInterceptors().add(new MuleProtocolHeadersOutInterceptor()); |
374 | 76 | client.getOutFaultInterceptors().add(new MuleProtocolHeadersOutInterceptor()); |
375 | 76 | } |
376 | |
|
377 | |
protected String getMethodOrOperationName(MuleEvent event) throws DispatchException |
378 | |
{ |
379 | |
|
380 | 52 | String method = (String) event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY); |
381 | |
|
382 | 52 | if (method == null) |
383 | |
{ |
384 | 6 | method = (String) event.getMessage().getProperty(CxfConstants.OPERATION); |
385 | |
} |
386 | |
|
387 | 52 | if (method == null) |
388 | |
{ |
389 | 6 | method = defaultMethodName; |
390 | |
} |
391 | |
|
392 | 52 | if (method == null && proxy) |
393 | |
{ |
394 | 6 | return "invoke"; |
395 | |
} |
396 | |
|
397 | 46 | if (method == null) |
398 | |
{ |
399 | 0 | throw new DispatchException(SoapMessages.cannotInvokeCallWithoutOperation(), event.getMessage(), |
400 | |
event.getEndpoint()); |
401 | |
} |
402 | |
|
403 | 46 | return method; |
404 | |
} |
405 | |
|
406 | |
public void setEndpoint(ImmutableEndpoint endpoint) |
407 | |
{ |
408 | 76 | this.endpoint = endpoint; |
409 | 76 | } |
410 | |
|
411 | |
public void setBus(Bus bus) |
412 | |
{ |
413 | 76 | this.bus = bus; |
414 | 76 | } |
415 | |
|
416 | |
public boolean isClientProxyAvailable() |
417 | |
{ |
418 | 58 | return clientProxy != null; |
419 | |
} |
420 | |
|
421 | |
public BindingOperationInfo getOperation(MuleEvent event) throws Exception |
422 | |
{ |
423 | 52 | String opName = getMethodOrOperationName(event); |
424 | |
|
425 | 52 | if (opName == null) |
426 | |
{ |
427 | 0 | opName = defaultMethodName; |
428 | |
} |
429 | |
|
430 | 52 | return getOperation(opName); |
431 | |
} |
432 | |
|
433 | |
public Method getMethod(MuleEvent event) throws Exception |
434 | |
{ |
435 | 6 | Method method = defaultMethod; |
436 | 6 | if (method == null) |
437 | |
{ |
438 | 0 | String opName = (String) event.getMessage().getProperty(CxfConstants.OPERATION); |
439 | 0 | if (opName != null) |
440 | |
{ |
441 | 0 | method = getMethodFromOperation(opName); |
442 | |
} |
443 | |
|
444 | 0 | if (method == null) |
445 | |
{ |
446 | 0 | opName = (String) endpoint.getProperty(CxfConstants.OPERATION); |
447 | 0 | if (opName != null) |
448 | |
{ |
449 | 0 | method = getMethodFromOperation(opName); |
450 | |
} |
451 | |
} |
452 | |
|
453 | 0 | if (method == null) |
454 | |
{ |
455 | 0 | opName = defaultMethodName; |
456 | 0 | if (opName != null) |
457 | |
{ |
458 | 0 | method = getMethodFromOperation(opName); |
459 | |
} |
460 | |
} |
461 | |
} |
462 | |
|
463 | 6 | if (method == null) |
464 | |
{ |
465 | 0 | throw new DispatchException(CxfMessages.noOperationWasFoundOrSpecified(), event.getMessage(), |
466 | |
endpoint); |
467 | |
} |
468 | 6 | return method; |
469 | |
} |
470 | |
} |