1 package org.andromda.cartridges.support.webservice.client;
2
3 import java.lang.reflect.Array;
4 import java.lang.reflect.Method;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11 import javax.wsdl.Definition;
12 import javax.wsdl.Types;
13 import javax.wsdl.extensions.schema.Schema;
14 import javax.xml.namespace.QName;
15 import org.apache.axiom.om.OMAbstractFactory;
16 import org.apache.axiom.om.OMElement;
17 import org.apache.axiom.om.OMFactory;
18 import org.apache.axiom.om.OMNamespace;
19 import org.apache.axiom.util.base64.Base64Utils;
20 import org.apache.commons.beanutils.PropertyUtils;
21 import org.apache.commons.lang.StringUtils;
22 import org.w3c.dom.Element;
23 import org.w3c.dom.Node;
24 import org.w3c.dom.NodeList;
25
26
27
28
29
30
31 public class Axis2ClientUtils
32 {
33
34
35
36
37
38
39
40
41 public static OMElement getOperationOMElement(
42 final Definition definition,
43 final Method method,
44 final Object[] arguments,
45 final TypeMapper typeMapper)
46 {
47 final Class serviceClass = method.getDeclaringClass();
48 OMElement operationOMElement = null;
49 try
50 {
51 final String operationName = method.getName();
52 final String serviceName = serviceClass.getSimpleName();
53 final Element operationElement = getElementByAttribute(
54 definition,
55 NAME,
56 operationName);
57 final Schema operationSchema = Axis2ClientUtils.getElementSchemaByAttribute(
58 definition,
59 NAME,
60 operationName);
61 if (operationSchema != null)
62 {
63 final OMFactory factory = OMAbstractFactory.getOMFactory();
64
65
66 final Map<String, OMNamespace> namespaces = new HashMap<String, OMNamespace>();
67 final OMNamespace xsiNamespace = factory.createOMNamespace(XSI_NS, XSI_PREFIX);
68 namespaces.put(XSI_PREFIX, xsiNamespace);
69
70 final Collection<Schema> schemas = getSchemas(definition);
71 for (final Schema schema : schemas)
72 {
73 final String namespace = Axis2ClientUtils.getTargetNamespace(schema);
74 final String prefix = getNamespacePrefix(
75 definition,
76 namespace);
77 namespaces.put(prefix, factory.createOMNamespace(namespace, prefix));
78 }
79
80 operationOMElement =
81 getOMElement(
82 definition,
83 operationSchema,
84 null,
85 null,
86 operationName,
87 factory,
88 namespaces,
89 typeMapper);
90 if (operationElement == null)
91 {
92 throw new RuntimeException("No operation with name '" + operationName + "' can be found on service: " +
93 serviceName);
94 }
95 final List argumentElements = Axis2ClientUtils.getElementsWithAttribute(
96 operationElement,
97 TYPE);
98 final Class[] parameterTypes = method.getParameterTypes();
99 if (argumentElements.size() != arguments.length)
100 {
101 throw new RuntimeException("Operation: " + operationName + " takes " + parameterTypes.length +
102 " argument(s), and 'arguments' only contains: " + arguments.length);
103 }
104
105
106 operationOMElement.declareNamespace(xsiNamespace);
107 for (final OMNamespace namespace : namespaces.values())
108 {
109 operationOMElement.declareNamespace(namespace);
110 }
111
112
113 for (int ctr = 0; ctr < argumentElements.size(); ctr++)
114 {
115 final Element argument = (Element)argumentElements.get(ctr);
116 final String argumentName = getAttributeValue(
117 argument,
118 NAME);
119 final OMElement element = getOMElement(
120 definition,
121 operationSchema,
122 argument,
123 arguments[ctr],
124 argumentName,
125 factory,
126 namespaces,
127 typeMapper);
128 operationOMElement.addChild(element);
129 }
130 }
131 }
132 catch (Exception exception)
133 {
134 throw new RuntimeException(exception);
135 }
136 return operationOMElement;
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 public static OMElement getOMElement(
153 final Definition definition,
154 final Schema schema,
155 final Element componentElement,
156 final Object bean,
157 final String elementName,
158 final OMFactory factory,
159 final Map<String, OMNamespace> namespaces,
160 final TypeMapper typeMapper)
161 {
162 return getOMElement(
163 definition,
164 schema,
165 componentElement,
166 bean,
167 elementName,
168 factory,
169 namespaces,
170 typeMapper,
171 new ArrayList<Object>());
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 private static OMElement getOMElement(
189 final Definition definition,
190 Schema schema,
191 final Element componentElement,
192 final Object bean,
193 final String elementName,
194 final OMFactory factory,
195 final Map<String, OMNamespace> namespaces,
196 final TypeMapper typeMapper,
197 final Collection<Object> evaluatingBeans)
198 {
199 final String componentElementName = componentElement != null ? componentElement.getAttribute(NAME) : null;
200 if (StringUtils.isNotBlank(componentElementName))
201 {
202 final Schema currentSchema = Axis2ClientUtils.getElementSchemaByAttribute(
203 definition,
204 NAME,
205 componentElementName);
206 if (currentSchema != null)
207 {
208 schema = currentSchema;
209 }
210 }
211
212 OMNamespace omNamespace = null;
213 if (isQualified(schema))
214 {
215 final String namespace = Axis2ClientUtils.getTargetNamespace(schema);
216 final String namespacePrefix = getNamespacePrefix(
217 definition,
218 namespace);
219 omNamespace = namespaces.get(namespacePrefix);
220 }
221
222 final OMElement omElement =
223 factory.createOMElement(
224 elementName,
225 omNamespace);
226 if (bean != null && evaluatingBeans != null && !evaluatingBeans.contains(bean))
227 {
228 evaluatingBeans.add(bean);
229 if (isSimpleType(bean, typeMapper))
230 {
231 omElement.addChild(factory.createOMText(typeMapper.getStringValue(bean)));
232 }
233 else if (bean instanceof byte[])
234 {
235 omElement.addChild(factory.createOMText(Base64Utils.encode((byte[])bean)));
236 }
237 else
238 {
239 final Element currentComponentElement =
240 Axis2ClientUtils.getElementByAttribute(
241 definition,
242 NAME,
243 bean.getClass().getSimpleName());
244 final Class beanType = bean.getClass();
245 if (beanType.isArray())
246 {
247 final Element arrayElement = Axis2ClientUtils.getRequiredElementByAttribute(
248 definition,
249 componentElement,
250 NAME,
251 elementName);
252 final Element arrayTypeElement =
253 Axis2ClientUtils.getElementByAttribute(
254 definition,
255 NAME,
256 stripPrefix(arrayElement.getAttribute(TYPE)));
257 final String arrayComponentName = Axis2ClientUtils.getAttributeValueFromChildElement(
258 arrayTypeElement,
259 NAME,
260 0);
261 for (int ctr = 0; ctr < Array.getLength(bean); ctr++)
262 {
263 omElement.addChild(
264 getOMElement(
265 definition,
266 schema,
267 currentComponentElement,
268 Array.get(
269 bean,
270 ctr),
271 arrayComponentName,
272 factory,
273 namespaces,
274 typeMapper,
275 evaluatingBeans));
276 }
277 }
278 else
279 {
280 final String attributeValue = omNamespace != null ?
281 omNamespace.getPrefix() + NS_SEPARATOR + beanType.getSimpleName() : beanType.getSimpleName();
282
283 omElement.addAttribute(TYPE, attributeValue, namespaces.get(XSI_PREFIX));
284 }
285 try
286 {
287 final java.util.Map<String, Object> properties = PropertyUtils.describe(bean);
288 for (final String name : properties.keySet())
289 {
290 if (!CLASS.equals(name))
291 {
292 final Object value = properties.get(name);
293 if (value != null)
294 {
295 omElement.addChild(
296 getOMElement(
297 definition,
298 schema,
299 currentComponentElement,
300 value,
301 name,
302 factory,
303 namespaces,
304 typeMapper,
305 evaluatingBeans));
306 }
307 }
308 }
309 }
310 catch (final Throwable throwable)
311 {
312 throw new RuntimeException(throwable);
313 }
314 }
315 evaluatingBeans.remove(bean);
316 }
317 return omElement;
318 }
319
320 private static final String ELEMENT_FORM_DEFAULT = "elementFormDefault";
321
322
323
324
325 private static final String QUALIFIED = "qualified";
326
327
328
329
330 private static final String TARGET_NAMESPACE = "targetNamespace";
331
332
333
334
335 private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
336
337
338
339
340 private static final String XSI_PREFIX = "xsi";
341
342
343
344
345 private static final String NS_SEPARATOR = ":";
346
347
348
349
350
351
352
353 private static boolean isQualified(Schema schema)
354 {
355 boolean isQualified = false;
356 if (schema != null)
357 {
358 final String qualified = Axis2ClientUtils.getAttributeValue(
359 schema.getElement(),
360 ELEMENT_FORM_DEFAULT);
361 isQualified = QUALIFIED.equalsIgnoreCase(qualified);
362 }
363 return isQualified;
364 }
365
366 private static String getTargetNamespace(Schema schema)
367 {
368 return Axis2ClientUtils.getAttributeValue(
369 schema.getElement(),
370 TARGET_NAMESPACE);
371 }
372
373 private static String stripPrefix(String name)
374 {
375 return name.replaceAll(
376 ".*:",
377 "");
378 }
379
380 private static String getNamespacePrefix(
381 final Definition definition,
382 final String namespace)
383 {
384 String prefix = null;
385 final Map<String, String> namespaces = definition.getNamespaces();
386 for (Map.Entry<String, String> entry : namespaces.entrySet())
387 {
388 if (entry.getValue().equals(namespace))
389 {
390 prefix = entry.getKey();
391 }
392 }
393 return prefix;
394 }
395
396 private static final String NAME = "name";
397 private static final String TYPE = "type";
398 private static final String BASE = "base";
399
400 private static Element getRequiredElementByAttribute(
401 final Definition definition,
402 final Element container,
403 final String attribute,
404 final String value)
405 {
406 Element element = null;
407 if (container != null)
408 {
409 element = Axis2ClientUtils.getElementByAttribute(
410 container,
411 attribute,
412 value);
413 }
414
415 if (element == null)
416 {
417 final String xsiTypeName = Axis2ClientUtils.getAttributeValueFromChildElement(container, BASE, 0);
418 final String typeName = getLocalName(xsiTypeName);
419 element = Axis2ClientUtils.getElementByAttribute(
420 Axis2ClientUtils.getElementByAttribute(definition, NAME, typeName),
421 attribute,
422 value);
423 }
424 if (element == null)
425 {
426 String attr = container==null ? "" : container.getAttribute(NAME);
427 throw new RuntimeException('\'' + value + "' was not found on element '" + attr + '\'');
428 }
429 return element;
430 }
431
432 private static Element getElementByAttribute(
433 final Definition definition,
434 final String attribute,
435 final String value)
436 {
437 Element element = null;
438 if (value != null)
439 {
440 final Types types = definition.getTypes();
441 final Collection elements = types.getExtensibilityElements();
442 for (final Iterator iterator = elements.iterator(); iterator.hasNext();)
443 {
444 final Object object = iterator.next();
445 if (object instanceof Schema)
446 {
447 final Schema schema = (Schema)object;
448 element =
449 getElementByAttribute(
450 schema.getElement(),
451 attribute,
452 value);
453 if (element != null)
454 {
455 break;
456 }
457 }
458 }
459 }
460 return element;
461 }
462
463 private static Collection<Schema> getSchemas(final Definition definition)
464 {
465 final Collection<Schema> schemas = new ArrayList<Schema>();
466 final Types types = definition.getTypes();
467 final Collection elements = types.getExtensibilityElements();
468 for (final Iterator iterator = elements.iterator(); iterator.hasNext();)
469 {
470 final Object object = iterator.next();
471 if (object instanceof Schema)
472 {
473 schemas.add((Schema)object);
474 }
475 }
476 return schemas;
477 }
478
479 private static Element getElementByAttribute(
480 final Schema schema,
481 final String attribute,
482 final String value)
483 {
484 return getElementByAttribute(
485 schema.getElement(),
486 attribute,
487 value);
488 }
489
490
491
492
493
494
495
496
497
498 private static Schema getElementSchemaByAttribute(
499 final Definition definition,
500 final String attribute,
501 final String value)
502 {
503 final Types types = definition.getTypes();
504 final Collection elements = types.getExtensibilityElements();
505 Schema schema = null;
506 for (final Iterator iterator = elements.iterator(); iterator.hasNext();)
507 {
508 final Object object = iterator.next();
509 if (object instanceof Schema)
510 {
511 final Element element = getElementByAttribute(
512 (Schema)object,
513 attribute,
514 value);
515 if (element != null)
516 {
517 schema = (Schema)object;
518 break;
519 }
520 }
521 }
522 return schema;
523 }
524
525 private static Element getElementByAttribute(
526 final Element element,
527 final String attribute,
528 final String value)
529 {
530 Element found = null;
531 if (element != null && value != null)
532 {
533 final String foundAttribute = element.getAttribute(attribute);
534 if (StringUtils.isNotBlank(value) && value.equals(foundAttribute))
535 {
536 found = element;
537 }
538 else
539 {
540 final NodeList nodes = element.getChildNodes();
541 for (int ctr = 0; ctr < nodes.getLength(); ctr++)
542 {
543 final Node node = nodes.item(ctr);
544 if (node instanceof Element)
545 {
546 found =
547 getElementByAttribute(
548 (Element)node,
549 attribute,
550 value);
551 if (found != null)
552 {
553 break;
554 }
555 }
556 }
557 }
558 }
559 return found;
560 }
561
562 private static List<Element> getElementsWithAttribute(
563 final Element element,
564 final String attribute)
565 {
566 final List<Element> found = new ArrayList<Element>();
567 if (element != null)
568 {
569 final String foundAttribute = element.getAttribute(attribute);
570 if (StringUtils.isNotBlank(foundAttribute))
571 {
572 found.add(element);
573 }
574 final NodeList nodes = element.getChildNodes();
575 for (int ctr = 0; ctr < nodes.getLength(); ctr++)
576 {
577 final Node node = nodes.item(ctr);
578 if (node instanceof Element)
579 {
580 found.addAll(getElementsWithAttribute(
581 (Element)node,
582 attribute));
583 }
584 }
585 }
586 return found;
587 }
588
589 private static String getAttributeValue(
590 final Element element,
591 final String attribute)
592 {
593 String value = null;
594 Element found = getElementWithAttribute(
595 element,
596 attribute);
597 if (found != null)
598 {
599 value = found.getAttribute(attribute);
600 }
601 return value;
602 }
603
604 private static String getAttributeValueFromChildElement(
605 final Element element,
606 final String attribute,
607 int childIndex)
608 {
609 String value = null;
610 if (element != null)
611 {
612 int elementIndex = 0;
613 for (int ctr = 0; ctr < element.getChildNodes().getLength(); ctr++)
614 {
615 final Node node = element.getChildNodes().item(ctr);
616 if (node instanceof Element)
617 {
618 if (elementIndex == childIndex)
619 {
620 value =
621 getAttributeValue(
622 (Element)node,
623 attribute);
624 }
625 elementIndex++;
626 }
627 }
628 }
629 return value;
630 }
631
632
633
634
635
636
637
638
639
640 private static Element getElementWithAttribute(
641 final Element element,
642 final String attribute)
643 {
644 Element found = null;
645 if (element != null)
646 {
647 final NodeList nodes = element.getChildNodes();
648 final String foundAttribute = element.getAttribute(attribute);
649 if (StringUtils.isNotBlank(foundAttribute))
650 {
651 found = element;
652 }
653 if (found == null)
654 {
655 for (int ctr = 0; ctr < nodes.getLength(); ctr++)
656 {
657 final Node node = nodes.item(ctr);
658 if (node instanceof Element)
659 {
660 found =
661 getElementWithAttribute(
662 (Element)node,
663 attribute);
664 }
665 }
666 }
667 }
668 return found;
669 }
670
671 private static final String CLASS = "class";
672
673
674
675
676
677
678
679
680
681
682 public static Object deserialize(
683 OMElement element,
684 Class type,
685 final TypeMapper typeMapper) throws Exception
686 {
687 Object bean = null;
688 if (typeMapper.isSimpleType(type))
689 {
690 bean = getSimpleTypeObject(type, element, typeMapper);
691 }
692 else if (type == byte[].class)
693 {
694 bean = Base64Utils.decode(element.getText());
695 }
696 else
697 {
698 if (type.isArray())
699 {
700 final Collection<Object> elements = new ArrayList<Object>();
701 for (final Iterator iterator = element.getChildElements(); iterator.hasNext();)
702 {
703 OMElement omElement = (OMElement)iterator.next();
704 elements.add(deserialize(
705 omElement,
706 type.getComponentType(),
707 typeMapper));
708 }
709 bean =
710 elements.toArray((Object[])Array.newInstance(
711 type.getComponentType(),
712 0));
713 }
714 else
715 {
716 try
717 {
718 type = getAppropriateType(element, type);
719 bean = typeMapper.getObject(type);
720 final java.beans.PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(type);
721 for (int ctr = 0; ctr < descriptors.length; ctr++)
722 {
723 final java.beans.PropertyDescriptor descriptor = descriptors[ctr];
724 final String name = descriptor.getName();
725 if (!CLASS.equals(name))
726 {
727 final OMElement propertyElement = findElementByName(
728 element,
729 name);
730
731 if (propertyElement != null)
732 {
733 PropertyUtils.setProperty(
734 bean,
735 name,
736 deserialize(
737 propertyElement,
738 descriptor.getPropertyType(),
739 typeMapper));
740 }
741 }
742 }
743 }
744 catch (final Throwable throwable)
745 {
746 throw new RuntimeException(throwable);
747 }
748 }
749 }
750 return bean;
751 }
752
753
754
755
756
757
758
759
760
761 private static Object getSimpleTypeObject(Class type,
762 OMElement element, TypeMapper typeMapper)
763 {
764 Object object = org.apache.axis2.databinding.typemapping.SimpleTypeMapper.getSimpleTypeObject(
765 type,
766 element);
767 if (object == null && element != null)
768 {
769 object = typeMapper.getObject(type, element.getText());
770 }
771 return object;
772 }
773
774
775
776
777 private static final String PACKAGE_SEPARATOR = ".";
778
779
780
781
782 private static final QName XSI_TYPE_QNAME = new QName(XSI_NS, TYPE);
783
784
785
786
787
788
789
790
791
792
793 private static Class getAppropriateType(final OMElement element, Class type) throws ClassNotFoundException
794 {
795 final String xsiTypeName = element.getAttributeValue(XSI_TYPE_QNAME);
796 if (xsiTypeName != null)
797 {
798 final String typeName = getLocalName(xsiTypeName);
799 if (!typeName.equals(type.getSimpleName()))
800 {
801
802
803 type = Thread.currentThread().getContextClassLoader().loadClass(
804 type.getPackage().getName() + PACKAGE_SEPARATOR + typeName);
805 }
806 }
807 return type;
808 }
809
810
811
812
813
814
815
816
817 private static String getLocalName(final String typeName)
818 {
819 String localName;
820 String[] names = typeName.split(NS_SEPARATOR);
821 if (names.length > 1)
822 {
823 localName = names[1];
824 }
825 else
826 {
827 localName = names[0];
828 }
829 return localName;
830 }
831
832
833
834
835
836
837
838
839
840 private static OMElement findElementByName(
841 final OMElement element,
842 final String name)
843 {
844 OMElement found = null;
845 for (final Iterator iterator = element.getChildElements(); iterator.hasNext();)
846 {
847 final OMElement child = (OMElement)iterator.next();
848 if (child.getLocalName().equals(name))
849 {
850 found = child;
851 break;
852 }
853 }
854 return found;
855 }
856
857
858
859
860
861
862
863
864
865 private static boolean isSimpleType(final Object bean, final TypeMapper typeMapper)
866 {
867 return typeMapper.isSimpleType(bean != null ? bean.getClass() : null);
868 }
869 }