1 package org.andromda.cartridges.support.webservice.client;
2
3 import java.lang.reflect.Method;
4 import java.net.URL;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import javax.wsdl.Definition;
14 import javax.wsdl.Port;
15 import javax.wsdl.Service;
16 import javax.wsdl.extensions.soap.SOAPAddress;
17 import javax.wsdl.factory.WSDLFactory;
18 import javax.wsdl.xml.WSDLReader;
19 import javax.xml.namespace.QName;
20 import org.apache.axiom.om.OMElement;
21 import org.apache.axis2.AxisFault;
22 import org.apache.axis2.addressing.EndpointReference;
23 import org.apache.axis2.client.ServiceClient;
24 import org.apache.axis2.client.async.Callback;
25 import org.apache.axis2.transport.http.HTTPConstants;
26 import org.apache.axis2.transport.http.HttpTransportProperties.Authenticator;
27 import org.apache.commons.lang.StringUtils;
28 import org.xml.sax.InputSource;
29
30
31
32
33
34
35
36 public class WebServiceClient
37 {
38
39
40
41 private Class serviceClass;
42
43
44
45
46 private Definition definition;
47
48
49
50
51 private String wsdlUrl;
52
53
54
55
56 private final Object definitionMonitor = new Object();
57
58
59
60
61 private ServiceClient serviceClient;
62
63
64
65
66 private TypeMapper typeMapper = new DefaultTypeMapper();
67
68
69
70
71
72
73
74 public WebServiceClient(
75 final String wsdlUrl,
76 final Class serviceClass)
77 {
78 this(wsdlUrl, serviceClass, null, null);
79 }
80
81
82
83
84
85
86
87
88
89 public WebServiceClient(
90 final String wsdlUrl,
91 final Class serviceClass,
92 final String username,
93 final String password)
94 {
95 this(wsdlUrl, null, serviceClass, username, password);
96 }
97
98
99
100
101
102
103
104
105
106
107 public WebServiceClient(
108 final String wsdlUrl,
109 final String endpointAddress,
110 final Class serviceClass,
111 final String username,
112 final String password)
113 {
114 try
115 {
116 this.serviceClient = new ServiceClient();
117 this.serviceClass = serviceClass;
118 this.wsdlUrl = wsdlUrl;
119 final WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
120 if (StringUtils.isNotBlank(username))
121 {
122 final Authenticator authenticator = new Authenticator();
123 final List<String> authorizationSchemes = new ArrayList<String>();
124 authorizationSchemes.add(Authenticator.BASIC);
125 authenticator.setAuthSchemes(authorizationSchemes);
126 authenticator.setUsername(username);
127 authenticator.setPassword(password);
128 authenticator.setPreemptiveAuthentication(true);
129 this.serviceClient.getOptions().setProperty(
130 HTTPConstants.AUTHENTICATE,
131 authenticator);
132 synchronized (this.definitionMonitor)
133 {
134 this.definition =
135 this.readProtectedWsdl(
136 reader,
137 wsdlUrl,
138 username,
139 password);
140 }
141 }
142 else
143 {
144 synchronized (this.definitionMonitor)
145 {
146 this.definition = reader.readWSDL(wsdlUrl);
147 }
148 }
149 String portAddress;
150 if (StringUtils.isNotBlank(endpointAddress))
151 {
152 portAddress = endpointAddress;
153 }
154 else
155 {
156 portAddress = this.findEndPointAddress();
157 }
158 serviceClient.setTargetEPR(new EndpointReference(portAddress));
159 }
160 catch (Exception exception)
161 {
162 this.handleException(exception);
163 }
164 }
165
166
167
168
169
170
171 public void setTypeMapper(final TypeMapper typeMapper)
172 {
173 if (typeMapper == null)
174 {
175 throw new IllegalArgumentException("'typeMapper' can not be null");
176 }
177 this.typeMapper = typeMapper;
178 }
179
180
181
182
183
184
185 public void setTimeout(long seconds)
186 {
187 this.serviceClient.getOptions().setTimeOutInMilliSeconds(seconds * 1000);
188 }
189
190
191
192
193
194
195
196
197
198
199 private Definition readProtectedWsdl(
200 final WSDLReader reader,
201 String address,
202 String username,
203 String password)
204 {
205 Definition definition = null;
206 try
207 {
208 final org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
209 final org.apache.commons.httpclient.params.HttpClientParams params =
210 new org.apache.commons.httpclient.params.HttpClientParams();
211 params.setAuthenticationPreemptive(true);
212 client.setParams(params);
213
214 final org.apache.commons.httpclient.Credentials credentials =
215 new org.apache.commons.httpclient.UsernamePasswordCredentials(username, password);
216 final org.apache.commons.httpclient.auth.AuthScope scope =
217 new org.apache.commons.httpclient.auth.AuthScope(
218 new URL(address).getHost(),
219 org.apache.commons.httpclient.auth.AuthScope.ANY_PORT,
220 org.apache.commons.httpclient.auth.AuthScope.ANY_REALM);
221 client.getState().setCredentials(
222 scope,
223 credentials);
224
225 final org.apache.commons.httpclient.methods.GetMethod get =
226 new org.apache.commons.httpclient.methods.GetMethod(address);
227 get.setDoAuthentication(true);
228
229 int status = client.executeMethod(get);
230 if (status == 404)
231 {
232 throw new WebServiceClientException("WSDL could not be found at: '" + address + '\'');
233 }
234 InputSource inputSource = null;
235 boolean authenticated = status > 0 && status < 400;
236 if (authenticated)
237 {
238 inputSource = new InputSource(get.getResponseBodyAsStream());
239 }
240 else
241 {
242 throw new WebServiceClientException("Could not authenticate user: '" + username + "' to WSDL: '" +
243 address + '\'');
244 }
245 definition =
246 reader.readWSDL(
247 address,
248 inputSource);
249 get.releaseConnection();
250 }
251 catch (Exception exception)
252 {
253 this.handleException(exception);
254 }
255 return definition;
256 }
257
258
259
260
261
262
263 private String findEndPointAddress()
264 {
265 String address = null;
266 Map services;
267 synchronized (this.definitionMonitor)
268 {
269 services = this.definition.getServices();
270 }
271 if (services != null)
272 {
273 for (final Iterator iterator = services.keySet().iterator(); iterator.hasNext();)
274 {
275 final QName name = (QName)iterator.next();
276 if (this.serviceClass.getSimpleName().equals(name.getLocalPart()))
277 {
278 final Service service = (Service)services.get(name);
279 final Map ports = service.getPorts();
280 for (final Iterator portIterator = ports.keySet().iterator(); portIterator.hasNext();)
281 {
282 final String portName = (String)portIterator.next();
283 final Port port = (Port)ports.get(portName);
284 for (final Iterator addressIterator = port.getExtensibilityElements().iterator();
285 addressIterator.hasNext();)
286 {
287 final Object element = addressIterator.next();
288 if (element instanceof SOAPAddress)
289 {
290 address = ((SOAPAddress)element).getLocationURI();
291 }
292 }
293 }
294 }
295 }
296 }
297 return address;
298 }
299
300
301
302
303
304
305
306
307
308
309 public Object invokeBlocking(
310 String operationName,
311 Object[] arguments)
312 {
313 final Method method = this.getMethod(
314 operationName,
315 arguments);
316 OMElement omElement = this.getOperationElement(method, arguments);
317 Object result = null;
318 try
319 {
320 OMElement response = this.serviceClient.sendReceive(omElement);
321 if (method.getReturnType() != void.class)
322 {
323 result =
324 Axis2ClientUtils.deserialize(
325 response.getFirstElement(),
326 method.getReturnType(),
327 this.typeMapper);
328 }
329 omElement = null;
330 response = null;
331 }
332 catch (Exception exception)
333 {
334 this.handleException(exception);
335 }
336 return result;
337 }
338
339
340
341
342
343
344
345
346
347 private OMElement getOperationElement(final Method method, Object[] arguments)
348 {
349 OMElement element = null;
350 synchronized (this.definitionMonitor)
351 {
352 element =
353 Axis2ClientUtils.getOperationOMElement(
354 this.definition,
355 method,
356 arguments,
357 this.typeMapper);
358 }
359 if (element == null)
360 {
361 throw new WebServiceClientException("No operation named '" + method.getName()
362 + "' was found in WSDL: " + this.wsdlUrl);
363 }
364 return element;
365 }
366
367
368
369
370
371
372
373
374 public void invokeNonBlocking(
375 String operationName,
376 Object[] arguments,
377 Callback callback)
378 {
379 final Method method = this.getMethod(
380 operationName,
381 arguments);
382 OMElement omElement = this.getOperationElement(method, arguments);
383 try
384 {
385 this.serviceClient.sendReceiveNonBlocking(
386 omElement,
387 callback);
388 }
389 catch (AxisFault exception)
390 {
391 this.handleException(exception);
392 }
393 omElement = null;
394 }
395
396
397
398
399
400 public void invokeRobust(
401 String operationName,
402 Object[] arguments)
403 {
404 final Method method = this.getMethod(
405 operationName,
406 arguments);
407 OMElement omElement = this.getOperationElement(method, arguments);
408 try
409 {
410 this.serviceClient.sendRobust(omElement);
411 }
412 catch (AxisFault exception)
413 {
414 this.handleException(exception);
415 }
416 omElement = null;
417 }
418
419
420
421
422 public void cleanup()
423 {
424 try
425 {
426 this.serviceClient.cleanup();
427 }
428 catch (AxisFault exception)
429 {
430 this.handleException(exception);
431 }
432 }
433
434
435
436
437 private Map<String, Method> methods = new HashMap<String, Method>();
438
439 private Method getMethod(
440 final String name,
441 final Object[] arguments)
442 {
443 Method found = methods.get(name);
444 if (found == null)
445 {
446 for (final Iterator iterator = this.getAllMethods().iterator(); iterator.hasNext();)
447 {
448 final Method method = (Method)iterator.next();
449 if (method.getName().equals(name) && arguments.length == method.getParameterTypes().length)
450 {
451 found = method;
452 this.methods.put(
453 name,
454 found);
455 break;
456 }
457 }
458 }
459 return found;
460 }
461
462
463
464
465
466
467
468
469 private List getAllMethods()
470 {
471 final Set<Method> methods = new LinkedHashSet<Method>();
472 loadMethods(
473 this.serviceClass,
474 methods);
475 return new ArrayList<Method>(methods);
476 }
477
478
479
480
481
482
483
484
485 private void loadMethods(
486 final Class clazz,
487 final Set<Method> methods)
488 {
489 methods.addAll(Arrays.asList(clazz.getDeclaredMethods()));
490 if (clazz.getSuperclass() != null)
491 {
492 loadMethods(
493 clazz.getSuperclass(),
494 methods);
495 }
496 }
497
498
499
500
501
502
503
504 private void handleException(Exception exception)
505 {
506 if (!(exception instanceof WebServiceClientException))
507 {
508 exception = new WebServiceClientException(exception);
509 }
510 throw (WebServiceClientException)exception;
511 }
512 }