/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.databinding.utils; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.Queue; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingQueue; import javax.activation.DataHandler; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamReader; import org.apache.axiom.om.*; import org.apache.axiom.util.base64.Base64Utils; import org.apache.axis2.AxisFault; import org.apache.axis2.classloader.BeanInfoCache; import org.apache.axis2.context.MessageContext; import org.apache.axis2.databinding.typemapping.SimpleTypeMapper; import org.apache.axis2.databinding.utils.reader.ADBXMLStreamReaderImpl; import org.apache.axis2.deployment.util.BeanExcludeInfo; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.java2wsdl.TypeTable; import org.apache.axis2.engine.ObjectSupplier; import org.apache.axis2.util.Loader; import org.apache.axis2.util.StreamWrapper; import org.w3c.dom.Document; public class BeanUtil { private static int nsCount = 1; /** * To Serilize Bean object this method is used, this will create an object array using given * bean object */ public static XMLStreamReader getPullParser(Object beanObject, QName beanName, TypeTable typeTable, boolean qualified, boolean processingDocLitBare) { Class beanClass = beanObject.getClass(); List<Object> propertyQnameValueList = getPropertyQnameList(beanObject, beanClass, beanName, typeTable, qualified, processingDocLitBare); ArrayList<QName> objectAttributes = new ArrayList<QName>(); if ((typeTable != null)) { QName qNamefortheType = typeTable.getQNamefortheType(getClassName(beanClass)); if (qNamefortheType != null) { objectAttributes.add(new QName(Constants.XSI_NAMESPACE, "type", "xsi")); objectAttributes.add(qNamefortheType); } } return new ADBXMLStreamReaderImpl(beanName, propertyQnameValueList.toArray(), objectAttributes.toArray(), typeTable, qualified); } private static String getClassName(Class type) { String name = type.getName(); if (name.indexOf("$") > 0) { name = name.replace('$', '_'); } return name; } private static BeanInfo getBeanInfo(Class beanClass, Class beanSuperclass) throws IntrospectionException { return BeanInfoCache.getCachedBeanInfo(beanClass, beanSuperclass); } private static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException { return getBeanInfo(beanClass, null); } private static List<Object> getPropertyQnameList(Object beanObject, Class<?> beanClass, QName beanName, TypeTable typeTable, boolean qualified, boolean processingDocLitBare) { List<Object> propertyQnameValueList; Class<?> supperClass = beanClass.getSuperclass(); if (!getQualifiedName(supperClass.getPackage()).startsWith("java.")) { propertyQnameValueList = getPropertyQnameList(beanObject, supperClass, beanName, typeTable, qualified, processingDocLitBare); } else { propertyQnameValueList = new ArrayList<Object>(); } try { QName elemntNameSpace = null; if (typeTable != null && qualified) { QName qNamefortheType = typeTable.getQNamefortheType(beanClass.getName()); if (qNamefortheType == null) { qNamefortheType = typeTable.getQNamefortheType(beanClass.getPackage().getName()); } if (qNamefortheType == null) { throw new AxisFault("Mapping qname not fond for the package: " + beanObject.getClass().getPackage().getName()); } elemntNameSpace = new QName(qNamefortheType.getNamespaceURI(), "elementName", qNamefortheType.getPrefix()); } AxisService axisService = null; if (MessageContext.getCurrentMessageContext() != null) { axisService = MessageContext.getCurrentMessageContext().getAxisService(); } BeanExcludeInfo beanExcludeInfo = null; if (axisService != null && axisService.getExcludeInfo() != null) { beanExcludeInfo = axisService.getExcludeInfo().getBeanExcludeInfoForClass(beanClass.getName()); } BeanInfo beanInfo = getBeanInfo(beanClass, beanClass.getSuperclass()); PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : properties) { String propertyName = property.getName(); Class<?> ptype = property.getPropertyType(); if (propertyName.equals("class") || beanExcludeInfo != null && beanExcludeInfo.isExcludedProperty(propertyName) || ptype == null) { continue; } Method readMethod = property.getReadMethod(); if (readMethod == null) { Class propertyType = property.getPropertyType(); if (propertyType == java.lang.Boolean.class) { Method writeMethod = property.getWriteMethod(); if (writeMethod != null) { String tmpWriteMethodName = writeMethod.getName(); PropertyDescriptor tmpPropDesc = new PropertyDescriptor(property.getName(), beanObject.getClass(), "is" + tmpWriteMethodName.substring(3), tmpWriteMethodName); readMethod = tmpPropDesc.getReadMethod(); } } } Object value; if (readMethod != null) { readMethod.setAccessible(true); value = readMethod.invoke(beanObject); } else { throw new AxisFault("Property '" + propertyName + "' in bean class '" + beanClass.getName() + "'is not readable."); } if (SimpleTypeMapper.isSimpleType(ptype)) { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add( value == null ? null : SimpleTypeMapper.getStringValue(value)); } else if(SimpleTypeMapper.isDomDocument(ptype)){ addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); OMFactory fac = OMAbstractFactory.getOMFactory(); propertyQnameValueList.add(convertDOMtoOM(fac, value)); } else if (ptype.isArray()) { if (SimpleTypeMapper.isSimpleType(ptype.getComponentType())) { if (value != null) { if (Byte.TYPE.equals(ptype.getComponentType())) { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(Base64Utils.encode((byte[]) value)); } else { int i1 = Array.getLength(value); for (int j = 0; j < i1; j++) { Object o = Array.get(value, j); addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(o == null ? null : SimpleTypeMapper.getStringValue(o)); } } } else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(value); } } else { if (value != null) { for (Object o : (Object[]) value) { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); QName propertyQName = null; if (elemntNameSpace != null) { propertyQName = new QName( elemntNameSpace.getNamespaceURI(), propertyName, elemntNameSpace.getPrefix()); } else { propertyQName = new QName(propertyName); } if (SimpleTypeMapper .isObjectArray(o.getClass()) || SimpleTypeMapper .isMultidimensionalObjectArray(o .getClass())) { /** * If it is a Object[] we need to add instance type * attributes to the response message. * Copied from ADBXMLStreamReaderImpl. * For inner Arrary Complex types we use the special local name array - "array" */ QName itemName; if (qualified) { itemName = new QName(elemntNameSpace.getNamespaceURI(), Constants.INNER_ARRAY_COMPLEX_TYPE_NAME, elemntNameSpace.getPrefix()); } else { itemName = new QName(Constants.INNER_ARRAY_COMPLEX_TYPE_NAME); } propertyQnameValueList.add(getOMElement(propertyQName , (Object[]) o, itemName, qualified, typeTable)); } else { if(SimpleTypeMapper.isObjectArray(value.getClass())){ OMFactory fac = OMAbstractFactory.getOMFactory(); OMElement element = fac.createOMElement(propertyQName); element.addChild(fac.createOMText(SimpleTypeMapper.getStringValue(o))); addInstanceTypeAttribute(fac, element, o, typeTable); propertyQnameValueList.add(element); } else { propertyQnameValueList.add(o); } } } } else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(value); } } } else if (SimpleTypeMapper.isCollection(ptype) && value != null) { if (typeTable != null) { OMFactory fac = OMAbstractFactory.getOMFactory(); QName qNamefortheType = null; qNamefortheType = (QName) typeTable .getComplexSchemaMap().get(getClassName(beanClass)); Type genericType = property.getReadMethod().getGenericReturnType(); OMElement collection = BeanUtil.getCollectionElement( fac, genericType, (Collection) value, propertyName,null, qNamefortheType,typeTable, qualified); // addTypeQname(elemntNameSpace, propertyQnameValueList, // property, beanName, processingDocLitBare); Iterator childItr = collection.getChildren(); while(childItr.hasNext()){ addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(childItr.next()); } } else { Collection<?> objList = (Collection<?>) value; if (objList != null && objList.size() > 0) { //this was given error , when the array.size = 0 // and if the array contain simple type , then the ADBPullParser asked // PullParser from That simpel type for (Object o : objList) { if (SimpleTypeMapper.isSimpleType(o)) { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(o); } else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(o); } } } else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(value); } } } else if (SimpleTypeMapper.isMap(ptype) && value != null) { OMFactory fac = OMAbstractFactory.getOMFactory(); QName qNamefortheType = (QName) typeTable .getComplexSchemaMap().get(getClassName(beanClass)); OMNamespace ns = fac.createOMNamespace( qNamefortheType.getNamespaceURI(), qNamefortheType.getPrefix()); List<OMElement> mapEntries = getMapElement(fac, ptype, (Map) value, typeTable, qualified); OMElement map = fac.createOMElement(propertyName, qNamefortheType.getNamespaceURI(), qNamefortheType.getPrefix()); for (OMElement ele : mapEntries) { map.addChild(ele); } addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add(map); } else if (SimpleTypeMapper.isEnum(ptype)){ addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); propertyQnameValueList.add( value == null ? null : SimpleTypeMapper.getStringValue(value.toString())); }else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); if (Object.class.equals(ptype) && value != null) { //this is required to match this element prefix as //root element's prefix. QName qNamefortheType = (QName) typeTable .getComplexSchemaMap().get( getClassName(beanClass)); OMFactory fac = OMAbstractFactory.getOMFactory(); QName elementName; OMElement element; if (elemntNameSpace != null) { elementName = new QName( elemntNameSpace.getNamespaceURI(), property.getName(), qNamefortheType.getPrefix()); } else { elementName = new QName(property.getName()); } if(SimpleTypeMapper.isSimpleType(value)){ element = fac.createOMElement(elementName); element.addChild(fac.createOMText(SimpleTypeMapper .getStringValue(value))); }else{ XMLStreamReader xr = BeanUtil.getPullParser(value, elementName, typeTable, qualified, false); OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory.createStAXOMBuilder( OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); element = stAXOMBuilder.getDocumentElement(); } addInstanceTypeAttribute(fac, element, value, typeTable); propertyQnameValueList.add(element); continue; } propertyQnameValueList.add(value); } } return propertyQnameValueList; } catch (java.io.IOException e) { throw new RuntimeException(e); } catch (java.beans.IntrospectionException e) { throw new RuntimeException(e); } catch (java.lang.reflect.InvocationTargetException e) { throw new RuntimeException(e); } catch (java.lang.IllegalAccessException e) { throw new RuntimeException(e); } } private static void addTypeQname(QName elemntNameSpace, List<Object> propertyQnameValueList, PropertyDescriptor propDesc, QName beanName, boolean processingDocLitBare) { if (elemntNameSpace != null) { propertyQnameValueList.add(new QName(elemntNameSpace.getNamespaceURI(), propDesc.getName(), elemntNameSpace.getPrefix())); } else { if (processingDocLitBare) { propertyQnameValueList.add(new QName(propDesc.getName())); } else { propertyQnameValueList.add(new QName(beanName.getNamespaceURI(), propDesc.getName(), beanName.getPrefix())); } } } /** * to get the pull parser for a given bean object , generate the wrpper element using class * name * * @param beanObject */ public static XMLStreamReader getPullParser(Object beanObject) { String className = beanObject.getClass().getName(); if (className.indexOf(".") > 0) { className = className.substring(className.lastIndexOf('.') + 1, className.length()); } return getPullParser(beanObject, new QName(className), null, false, false); } public static Object deserialize(Class beanClass, OMElement beanElement, ObjectSupplier objectSupplier, String arrayLocalName) throws AxisFault { Object beanObj; try { // Added this block as a fix for issues AXIS2-2055 and AXIS2-1899 // to support polymorphism in POJO approach. // Retrieve the type name of the instance from the 'type' attribute // and retrieve the class. String instanceTypeName = null; if (beanClass != null && !beanClass.isArray()) { instanceTypeName = beanElement.getAttributeValue(new QName( Constants.XSI_NAMESPACE, "type")); } boolean hexBin = false; if (instanceTypeName != null) { MessageContext messageContext = MessageContext.getCurrentMessageContext(); // we can have this support only at the server side. we need to find the axisservice // to get the type table. if (messageContext != null) { AxisService axisService = messageContext.getAxisService(); if (axisService != null) { QName typeQName = beanElement.resolveQName(instanceTypeName); //Need this flag to differentiate "xsd:hexBinary" and "xsd:base64Binary" data. if(org.apache.ws.commons.schema.constants.Constants.XSD_HEXBIN.equals(typeQName)){ hexBin = true; } TypeTable typeTable = axisService.getTypeTable(); String className = typeTable.getClassNameForQName(typeQName); if (className != null) { try { beanClass = Loader.loadClass(axisService.getClassLoader(), className); } catch (ClassNotFoundException ce) { throw AxisFault.makeFault(ce); } } else { throw new AxisFault("Unknow type " + typeQName); } } } } // check for nil attribute: QName nilAttName = new QName(Constants.XSI_NAMESPACE, Constants.NIL, "xsi"); if (beanElement.getAttribute(nilAttName) != null) { return null; } if(beanClass.getName().equals(DataHandler.class.getName())){ return SimpleTypeMapper.getDataHandler(beanElement,hexBin); } if (beanClass.isArray()) { ArrayList<Object> valueList = new ArrayList<Object>(); Class arrayClassType = beanClass.getComponentType(); if ("byte".equals(arrayClassType.getName())) { // find the part first and decode it OMElement partElement = null; for (Iterator iter = beanElement.getChildElements(); iter.hasNext();) { partElement = (OMElement) iter.next(); if (partElement.getLocalName().equals(arrayLocalName)) { break; } } return Base64Utils.decode(partElement.getText()); } else { Iterator parts = beanElement.getChildElements(); OMElement omElement; while (parts.hasNext()) { Object objValue = parts.next(); if (objValue instanceof OMElement) { omElement = (OMElement) objValue; if ((arrayLocalName != null) && !arrayLocalName.equals(omElement.getLocalName())) { continue; } // this is a multi dimentional array so always inner element is array Object obj = deserialize(arrayClassType, omElement, objectSupplier, "array"); valueList.add(obj); } } return ConverterUtil.convertToArray(arrayClassType, valueList); } }else if(SimpleTypeMapper.isDomDocument(beanClass)){ return convertOMtoDOM(beanElement); } else if (XMLGregorianCalendar.class.getName().equals( beanClass.getName())) { return getXMLGregorianCalendar(beanElement); } else { if (SimpleTypeMapper.isSimpleType(beanClass)) { return getSimpleTypeObjectChecked(beanClass, beanElement); } else if ("java.lang.Object".equals(beanClass.getName())) { return beanElement.getFirstOMChild(); } //use a comaprator to ignore the case of the bean element //names eg. if the property descriptor is getServiceName it //should accept child element with ServiceName as well. //but currently accepts only serviceName Comparator comparator = new Comparator() { public int compare(Object o1, Object o2) { String string1 = (String) o1; String string2 = (String) o2; return string1.compareToIgnoreCase(string2); } }; Map<String, PropertyDescriptor> properties = new TreeMap<String, PropertyDescriptor>(comparator); BeanInfo beanInfo = getBeanInfo(beanClass); PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor proprty : propDescs) { properties.put(proprty.getName(), proprty); } Iterator elements = beanElement.getChildren(); beanObj = objectSupplier.getObject(beanClass); while (elements.hasNext()) { // the beanClass could be an abstract one. // so create an instance only if there are elements, in // which case a concrete subclass is available to instantiate. OMElement parts; Object objValue = elements.next(); if (objValue instanceof OMElement) { parts = (OMElement) objValue; } else { continue; } OMAttribute attribute = parts.getAttribute( new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi")); // if parts/@href != null then need to find element with id and deserialize. // before that first check whether we already have it in the hashtable String partsLocalName = parts.getLocalName(); PropertyDescriptor prty = properties.remove(partsLocalName); if (prty != null) { Class parameters = prty.getPropertyType(); if (prty.getName().equals("class")) continue; Object partObj; boolean isNil = false; if (attribute != null) { String nilValue = attribute.getAttributeValue(); if ("true".equals(nilValue) || "1".equals(nilValue)) { isNil = true; } } if (isNil) { partObj = null; } else { if (SimpleTypeMapper.isSimpleType(parameters)) { partObj = SimpleTypeMapper.getSimpleTypeObject(parameters, parts); } else if (SimpleTypeMapper.isHashSet(parameters)) { partObj = SimpleTypeMapper.getHashSet((OMElement) parts.getParent(), prty.getName()); } else if (SimpleTypeMapper.isCollection(parameters)) { Type type = prty.getReadMethod().getGenericReturnType(); partObj = processGenericCollection(parts, type, null, objectSupplier); } else if (SimpleTypeMapper.isDataHandler(parameters)) { partObj = SimpleTypeMapper.getDataHandler(parts); } else if (parameters.isArray()) { partObj = deserialize(parameters, (OMElement) parts.getParent(), objectSupplier, prty.getName()); } else if (SimpleTypeMapper.isMap(parameters)){ partObj = null; final Type type = prty.getReadMethod().getGenericReturnType(); if (type instanceof ParameterizedType) { ParameterizedType aType = (ParameterizedType) type; Type[] parameterArgTypes = aType.getActualTypeArguments(); partObj = processGenericsMapElement(parameterArgTypes , (OMElement) parts.getParent(), null, parts.getChildren(), objectSupplier, beanClass); } else { Type[] parameterArgTypes = {Object.class,Object.class}; partObj = processGenericsMapElement(parameterArgTypes , (OMElement) parts.getParent(), null, parts.getChildren(), objectSupplier, beanClass); } }else if (SimpleTypeMapper.isEnum(parameters)) { partObj =processEnumObject(parameters , parts); } else { partObj = deserialize(parameters, parts, objectSupplier, null); } } Object[] parms = new Object[]{partObj}; Method writeMethod = prty.getWriteMethod(); if (writeMethod != null) { writeMethod.setAccessible(true); writeMethod.invoke(beanObj, parms); } } } return beanObj; } } catch (IllegalAccessException e) { throw new AxisFault("IllegalAccessException : " + e); } catch (InvocationTargetException e) { throw new AxisFault("InvocationTargetException : " + e); } catch (IntrospectionException e) { throw new AxisFault("IntrospectionException : " + e); } catch (DatatypeConfigurationException e) { throw new AxisFault("DatatypeConfigurationException : " + e); } } public static Object deserialize(Class beanClass, OMElement beanElement, MultirefHelper helper, ObjectSupplier objectSupplier) throws AxisFault { Object beanObj; try { HashMap<String, PropertyDescriptor> properties = new HashMap<String, PropertyDescriptor>(); BeanInfo beanInfo = getBeanInfo(beanClass); PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor proprty : propDescs) { properties.put(proprty.getName(), proprty); } beanObj = objectSupplier.getObject(beanClass); Iterator elements = beanElement.getChildren(); while (elements.hasNext()) { Object child = elements.next(); OMElement parts; if (child instanceof OMElement) { parts = (OMElement) child; } else { continue; } String partsLocalName = parts.getLocalName(); PropertyDescriptor prty = properties.get( partsLocalName.toLowerCase()); if (prty != null) { Class parameters = prty.getPropertyType(); if (prty.getName().equals("class")) continue; Object partObj; OMAttribute attr = MultirefHelper.processRefAtt(parts); if (attr != null) { String refId = MultirefHelper.getAttvalue(attr); partObj = helper.getObject(refId); if (partObj == null) { partObj = helper.processRef(parameters, refId, objectSupplier); } } else { partObj = SimpleTypeMapper.getSimpleTypeObject(parameters, parts); if (partObj == null) { partObj = deserialize(parameters, parts, objectSupplier, null); } } Object[] parms = new Object[]{partObj}; Method writeMethod = prty.getWriteMethod(); if (writeMethod != null) { writeMethod.setAccessible(true); writeMethod.invoke(beanObj, parms); } } } } catch (IllegalAccessException e) { throw new AxisFault("IllegalAccessException : " + e); } catch (InvocationTargetException e) { throw new AxisFault("InvocationTargetException : " + e); } catch (IntrospectionException e) { throw new AxisFault("IntrospectionException : " + e); } return beanObj; } /** * To get JavaObjects from XML element , the element most of the time contains only one element * in that case that element will be converted to the JavaType specified by the javaTypes array * The algo is as follows, get the childerns of the response element , and if it conatian more * than one element then check the retuen type of that element and conver that to corresponding * JavaType * * @param response OMElement * @param javaTypes Array of JavaTypes * @return Array of objects * @throws AxisFault */ public static Object[] deserialize(OMElement response, Object[] javaTypes, ObjectSupplier objectSupplier) throws AxisFault { return BeanUtil.deserialize(response, javaTypes, objectSupplier, null, null); } public static Object[] deserialize(OMElement response, Object[] javaTypes, ObjectSupplier objectSupplier, String[] parameterNames, Method method) throws AxisFault { /* * Take the number of parameters in the method and , only take that much of child elements * from the OMElement , other are ignore , as an example * if the method is , foo(String a , int b) * and if the OMElemet * <foo> * <arg0>Val1</arg0> * <arg1>Val2</arg1> * <arg2>Val3</arg2> * * only the val1 and Val2 take into account */ int length = javaTypes.length; int count = 0; Object[] retObjs = new Object[length]; /* * If the body first child contains , then there can not be any other element withot * refs , so I can assume if the first child of the body first element has ref then * the message has to handle as mutiref message. * as an exmple if the body is like below * <foo> * <arg0 href="#0"/> * </foo> * * then there can not be any element without refs , meaning following we are not handling * <foo> * <arg0 href="#0"/> * <arg1>absbsbs</arg1> * </foo> */ Iterator parts = response.getChildren(); //to handle multirefs //have to check the instanceof MultirefHelper helper = new MultirefHelper((OMElement) response.getParent()); //to support array . if the parameter type is array , then all the omelemnts with that paramtre name // has to get and add to the list Class classType; String currentLocalName; Type[] genericParameterTypes = null; if (method != null) { genericParameterTypes = method.getGenericParameterTypes(); } Type genericType = null; while (parts.hasNext() && count < length) { Object objValue = parts.next(); OMElement omElement; if (objValue instanceof OMElement) { omElement = (OMElement) objValue; } else { continue; } // if the local part is not match. this means element is not present // due to min occurs zero. // we need to hard code arg and item since that has been used in RPCService client // and some test cases while ((parameterNames != null) && (!omElement.getQName().getLocalPart().startsWith("arg")) && (!omElement.getQName().getLocalPart().startsWith("item")) && !omElement.getQName().getLocalPart().equals(parameterNames[count])) { // POJO handles OMElement in a differnt way so need this check for OMElement Class paramClassType = (Class) javaTypes[count]; if (!paramClassType.getName().equals(OMElement.class.getName())) { count++; } else { break; } } currentLocalName = omElement.getLocalName(); classType = (Class) javaTypes[count]; if (genericParameterTypes != null) { genericType = genericParameterTypes[count]; } /* * In bare invocation "parameterNames" comes as null value. */ boolean bare = false; if(parameterNames == null){ bare = true; } omElement = processElement(classType, omElement, helper, parts, currentLocalName, retObjs, count, objectSupplier, genericType, bare); while (omElement != null) { count++; // if the local part is not match. this means element is not present // due to min occurs zero. // we need to hard code arg and item since that has been used in RPCService client // and some test cases while ((parameterNames != null) && (!omElement.getQName().getLocalPart().startsWith("arg")) && (!omElement.getQName().getLocalPart().startsWith("item")) && !omElement.getQName().getLocalPart().equals(parameterNames[count])) { // POJO handles OMElement in a differnt way so need this check for OMElement Class paramClassType = (Class) javaTypes[count]; if (!paramClassType.getName().equals(OMElement.class.getName())) { count++; } else { break; } } currentLocalName = omElement.getLocalName(); classType = (Class) javaTypes[count]; if (genericParameterTypes != null) { genericType = genericParameterTypes[count]; } omElement = processElement((Class) javaTypes[count], omElement, helper, parts, omElement.getLocalName(), retObjs, count, objectSupplier, genericType); } count++; } // Ensure that we have at least a zero element array for (int i = 0; i < length; i++) { Class clazz = (Class) javaTypes[i]; if (retObjs[i] == null && clazz.isArray()) { retObjs[i] = Array.newInstance(clazz.getComponentType(), 0); } } helper.clean(); return retObjs; } private static OMElement processElement(Class classType, OMElement omElement, MultirefHelper helper, Iterator parts, String currentLocalName, Object[] retObjs, int count, ObjectSupplier objectSupplier, Type genericType) throws AxisFault { return processElement(classType, omElement, helper, parts, currentLocalName, retObjs, count, objectSupplier, genericType, false); } private static OMElement processElement(Class classType, OMElement omElement, MultirefHelper helper, Iterator parts, String currentLocalName, Object[] retObjs, int count, ObjectSupplier objectSupplier, Type genericType, boolean bare) throws AxisFault { Object objValue; boolean isRef = false; OMAttribute omatribute = MultirefHelper.processRefAtt(omElement); if (omatribute != null) { isRef = true; } if (classType.isArray()) { boolean done = true; ArrayList<Object> valueList = new ArrayList<Object>(); Class arrayClassType = classType.getComponentType(); if ("byte".equals(arrayClassType.getName())) { retObjs[count] = processObject(omElement, arrayClassType, helper, true, objectSupplier, genericType); return null; } else { valueList.add(processObject(omElement, arrayClassType, helper, true, objectSupplier, genericType)); } while (parts.hasNext()) { objValue = parts.next(); if (objValue instanceof OMElement) { omElement = (OMElement) objValue; } else { continue; } if (!currentLocalName.equals(omElement.getLocalName())) { done = false; break; } Object o = processObject(omElement, arrayClassType, helper, true, objectSupplier, genericType); valueList.add(o); } if (valueList.size() == 1 && valueList.get(0) == null) { retObjs[count] = null; } else { retObjs[count] = ConverterUtil.convertToArray(arrayClassType, valueList); } if (!done) { return omElement; } } else if(SimpleTypeMapper.isCollection(classType) && ! isRef){ if(bare){ OMElement[] toReturn = new OMElement[1]; parts = omElement.getChildren(); retObjs[count] = processGenericCollection(omElement.getFirstElement(), toReturn, genericType, helper, objectSupplier, parts,bare); OMNode node = omElement.getNextOMSibling(); while(node != null){ if(OMElement.class.isAssignableFrom(node.getClass())){ return (OMElement) node; } else { node = node.getNextOMSibling(); } } } else { OMElement[] toReturn = new OMElement[1]; retObjs[count] = processGenericCollection(omElement, toReturn, genericType, helper, objectSupplier, parts,bare); if (toReturn[0] != null) { return toReturn[0]; } } } else if (SimpleTypeMapper.isEnum(classType)) { /* handling enum types */ retObjs[count] = processEnumObject(classType, omElement); } else{ //handling refs retObjs[count] = processObject(omElement, classType, helper, false, objectSupplier, genericType); } return null; } private static Collection<Object> processGenericsElement(Type classType, OMElement omElement, MultirefHelper helper, Iterator parts, ObjectSupplier objectSupplier, Type genericType) throws AxisFault { Object objValue; Collection<Object> valueList = getCollectionInstance(genericType); while (parts.hasNext()) { objValue = parts.next(); Object o; if (objValue instanceof OMElement) { omElement = (OMElement) objValue; } else { continue; } if (classType instanceof ParameterizedType) { ParameterizedType parameterizedClassType = (ParameterizedType) classType; if (Collection.class .isAssignableFrom((Class<?>) parameterizedClassType .getRawType())) { o = processGenericCollection(omElement.getFirstElement(), classType, helper, objectSupplier); } else if (Map.class .isAssignableFrom((Class<?>) parameterizedClassType .getRawType())) { o = processGenericsMapElement( parameterizedClassType.getActualTypeArguments(), omElement, helper, omElement.getChildren(), objectSupplier, parameterizedClassType); } else { o = processObject(omElement, (Class) classType, helper, true, objectSupplier, genericType); } } else { o = processObject(omElement, (Class) classType, helper, true, objectSupplier, genericType); } valueList.add(o); } return valueList; } public static Object processObject(OMElement omElement, Class classType, MultirefHelper helper, boolean isArrayType, ObjectSupplier objectSupplier, Type generictype) throws AxisFault { boolean hasRef = false; OMAttribute omatribute = MultirefHelper.processRefAtt(omElement); String ref = null; if (omatribute != null) { hasRef = true; ref = MultirefHelper.getAttvalue(omatribute); } if (OMElement.class.isAssignableFrom(classType)) { if (hasRef) { OMElement elemnt = helper.getOMElement(ref); if (elemnt == null) { return helper.processOMElementRef(ref); } else { return elemnt; } } else return omElement; } else { if (hasRef) { if (helper.getObject(ref) != null) { return helper.getObject(ref); } else { return helper.processRef(classType, generictype, ref, objectSupplier); } } else { OMAttribute attribute = omElement.getAttribute( new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi")); if (attribute != null) { return null; } if (SimpleTypeMapper.isSimpleType(classType)) { if (isArrayType && "byte".equals(classType.getName())) { String value = omElement.getText(); return Base64Utils.decode(value); } else { return getSimpleTypeObjectChecked(classType, omElement); } } else if (SimpleTypeMapper.isCollection(classType)) { return processGenericCollection(omElement, generictype, null, objectSupplier); } else if (SimpleTypeMapper.isDataHandler(classType)) { return SimpleTypeMapper.getDataHandler(omElement); } else if(SimpleTypeMapper.isDomDocument(classType)){ return convertOMtoDOM(omElement); } else if(SimpleTypeMapper.isMap(classType)){ if (generictype != null && (generictype instanceof ParameterizedType)) { ParameterizedType aType = (ParameterizedType) generictype; Type[] parameterArgTypes = aType.getActualTypeArguments(); Iterator parts = omElement.getChildElements(); return processGenericsMapElement(parameterArgTypes , omElement, helper, parts, objectSupplier, generictype); } else { Type[] parameterArgTypes = {Object.class,Object.class}; Iterator parts = omElement.getChildElements(); return processGenericsMapElement(parameterArgTypes, omElement, helper, parts, objectSupplier, generictype); } }else if(SimpleTypeMapper.isEnum(classType)){ return processEnumObject(classType, omElement); }else { return BeanUtil.deserialize(classType, omElement, objectSupplier, null); } } } } /*This method check is service method required enum type instance as method parameter * if so return required enum object * * @param classType method required instance type * @param omElement OMElement * @return an Enum object * */ public static Object processEnumObject(Class classType , OMElement omElement)throws AxisFault{ /* *reason to add this block is check is soap sending a string but service require Enum * then this convert string to relevant enum object and add to retObjs[] as object * */ String paraArgString = omElement.getText(); Object enumIbj; if (paraArgString == null || paraArgString.length() == 0) { enumIbj = null; }else{ enumIbj = Enum.valueOf(classType , paraArgString); } return enumIbj; } public static OMElement getOMElement(QName opName, Object[] args, QName partName, boolean qualifed, TypeTable typeTable) { ArrayList<Object> objects; objects = new ArrayList<Object>(); int argCount = 0; for (Object arg : args) { if (arg == null) { if (partName == null) { objects.add("item" + argCount); } else { objects.add(partName); } objects.add(arg); continue; } if (arg instanceof Object[]) { // at the client side the partname is always null. At client side this means user try to // invoke a service with an array argument. if (partName == null) { Object array[] = (Object[]) arg; for (Object o : array) { if (o == null) { objects.add("item" + argCount); objects.add(o); } else { if (SimpleTypeMapper.isSimpleType(o)) { objects.add("item" + argCount); objects.add(SimpleTypeMapper.getStringValue(o)); } else { objects.add(new QName("item" + argCount)); if (o instanceof OMElement) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMElement wrappingElement; wrappingElement = fac.createOMElement("item" + argCount, null); wrappingElement.addChild((OMElement) o); objects.add(wrappingElement); } else { objects.add(o); } } } } } else { // this happens at the server side. this means it is an multidimentional array. objects.add(partName); if (SimpleTypeMapper.isObjectArray(arg.getClass()) || SimpleTypeMapper .isMultidimensionalObjectArray(arg .getClass())) { /** * If it is a Object[] we need to add instance type * attributes to the response message. * Copied from ADBXMLStreamReaderImpl. * For inner Arrary Complex types we use the special local name array - "array" */ QName itemName = new QName(partName.getNamespaceURI(), Constants.INNER_ARRAY_COMPLEX_TYPE_NAME, partName.getPrefix()); objects.add(getOMElement(partName, (Object[]) arg, itemName, qualifed, typeTable)); } else { objects.add(arg); } } } else { if (SimpleTypeMapper.isSimpleType(arg)) { OMElement element; OMFactory fac = OMAbstractFactory.getOMFactory(); if(partName != null){ element = fac.createOMElement(partName, null); }else{ String eleName = "arg" + argCount; element = fac.createOMElement(eleName, null); } element.addChild(fac.createOMText(SimpleTypeMapper .getStringValue(arg))); if (SimpleTypeMapper.isObjectArray(args.getClass())) { addInstanceTypeAttribute(fac, element, arg, typeTable); } objects.add(element.getQName()); objects.add(element); } else { if (partName == null) { objects.add(new QName("arg" + argCount)); } else { objects.add(partName); } if (arg instanceof OMElement) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMElement wrappingElement; if (partName == null) { wrappingElement = fac.createOMElement("arg" + argCount, null); wrappingElement.addChild((OMElement) arg); } else { wrappingElement = fac.createOMElement(partName, null); wrappingElement.addChild((OMElement) arg); } objects.add(wrappingElement); } else if (arg instanceof byte[]) { objects.add(Base64Utils.encode((byte[]) arg)); } else if (SimpleTypeMapper.isDataHandler(arg.getClass())) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMElement wrappingElement; if (partName == null) { wrappingElement = fac.createOMElement("arg" + argCount, null); } else { wrappingElement = fac.createOMElement(partName, null); } OMText text = fac.createOMText((DataHandler)arg, true); wrappingElement.addChild(text); objects.add(wrappingElement); }else if (SimpleTypeMapper.isEnum(arg.getClass())) { // in here i can return enum instances but for now i return it as a simple string objects.add(arg.toString()); } else { objects.add(arg); } } } argCount++; } XMLStreamReader xr = new ADBXMLStreamReaderImpl(opName, objects.toArray(), null, typeTable, qualifed); StreamWrapper parser = new StreamWrapper(xr); OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory.createStAXOMBuilder( OMAbstractFactory.getSOAP11Factory(), parser); return stAXOMBuilder.getDocumentElement(); } /** * @deprecated Please use getUniquePrefix */ public static synchronized String getUniquePrifix() { return getUniquePrefix(); } /** * increments the namespace counter and returns a new prefix * * @return unique prefix */ public static synchronized String getUniquePrefix() { if (nsCount > 1000) { nsCount = 1; } return "s" + nsCount++; } private static String getQualifiedName(Package packagez) { if (packagez != null) { return packagez.getName(); } else { return ""; } } private static Object getSimpleTypeObjectChecked(Class classType, OMElement omElement) throws AxisFault { try { return SimpleTypeMapper.getSimpleTypeObject(classType, omElement); } catch (NumberFormatException e) { MessageContext msgContext = MessageContext.getCurrentMessageContext(); QName faultCode = msgContext != null ? msgContext.getEnvelope().getVersion().getSenderFaultCode() : null; throw new AxisFault("Invalid value \"" + omElement.getText() + "\" for element " + omElement.getLocalName(), faultCode, e); } } /** * Adds the instance type attribute to the passed OMElement. * * e.g - <sam:obj xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" * xmlns:xsd="http://www.w3.org/2001/XMLSchema" * xsi:type="xsd:string"> * String Value * </sam:obj> * * * @param fac the SOAPFactory instance. * @param element the child OMElement to add attributes. * @param resObject the java reflection method * @param resObject the res object * @param typeTable the type table of particular Axis2 service */ public static void addInstanceTypeAttribute(OMFactory fac, OMElement element, Object resObject, TypeTable typeTable) { if(typeTable == null){ return; } OMNamespace xsiNS = fac.createOMNamespace(Constants.XSI_NAMESPACE, Constants.DEFAULT_XSI_NAMESPACE_PREFIX); OMNamespace xsdNS = fac.createOMNamespace(Constants.XSD_NAMESPACE, Constants.DEFAULT_XSD_NAMESPACE_PREFIX); element.declareNamespace(xsiNS); element.declareNamespace(xsdNS); QName xsdType = typeTable.getSchemaTypeName(resObject.getClass() .getName()); String attrValue = xsdType.getPrefix() + ":" + xsdType.getLocalPart(); element.addAttribute(Constants.XSI_TYPE_ATTRIBUTE, attrValue, xsiNS); } /** * Gets the DOOM implementation of org.w3c.dom.Document * * @param omElement the OMelement * @return the DOOM document */ public static OMDocument convertOMtoDOM(OMContainer omElement) { // use an Axiom meta factory with feature "dom" to get org.w3c.dom.Document OMFactory doomFactory = OMAbstractFactory.getMetaFactory( OMAbstractFactory.FEATURE_DOM).getOMFactory(); OMXMLParserWrapper doomBuilder = OMXMLBuilderFactory.createStAXOMBuilder(doomFactory, omElement.getXMLStreamReader()); OMDocument domElement = doomBuilder.getDocument(); return domElement; } /** * Convert DOM Document to a OMElement. * * @param fac the fac * @param document the document * @return the OMElement */ public static OMElement convertDOMtoOM(OMFactory fac, Object document) { if( document == null ) { return null; } if (document instanceof OMDocument) { return ((OMDocument)document).getOMDocumentElement(); } else { return OMXMLBuilderFactory.createOMBuilder((Document)document, false).getDocumentElement(true); } } /** * This method deserialize OM model in to a instance of java.util.Map * * @param parameterArgTypes the parameter argument types of Map <k,V> * @param omElement the OMElement * @param helper the helper * @param parts the parts * @param objectSupplier the object supplier * @param genericType the generic type * @return a instance of java.util.Map * @throws AxisFault the axis fault */ public static Map<Object,Object> processGenericsMapElement(Type[] parameterArgTypes, OMElement omElement, MultirefHelper helper, Iterator parts, ObjectSupplier objectSupplier, Type genericType) throws AxisFault { Object objValue; Map<Object,Object> valueMap = getMapInstance(genericType) ; while (parts.hasNext()) { objValue = parts.next(); if (objValue instanceof OMElement) { omElement = (OMElement) objValue; } else { continue; } if(omElement != null){ Iterator entryParts = omElement.getChildren(); Object entryKey = null; Object entryValue = null; while (entryParts.hasNext()) { objValue = entryParts.next(); if (objValue instanceof OMElement) { omElement = (OMElement) objValue; } else { continue; } if (omElement.getLocalName().equals( org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME)) { entryKey = processMapParameterObject( parameterArgTypes[0], omElement, helper, objectSupplier, genericType); continue; } if (omElement.getLocalName().equals( org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME)) { entryValue = processMapParameterObject( parameterArgTypes[1], omElement, helper, objectSupplier, genericType); continue; } } if(entryKey != null){ valueMap.put(entryKey, entryValue); } } } return valueMap; } /** * This method convert a instance of java.util.Map into * OM object model for serialization. * * @param fac the OMFactory * @param type of the java.util.Map * @param results the results values * @param typeTable the type table * @param elementFormDefault the element form default * @return list of OMElement */ public static List<OMElement> getMapElement(OMFactory fac, Type type, Map results, TypeTable typeTable, boolean elementFormDefault) { Iterator<Object> keyItr = results.keySet().iterator(); List<OMElement> list = new ArrayList<OMElement>(); OMNamespace ns = null; Type keyType = Object.class; Type valueType = Object.class; if (elementFormDefault) { ns = fac.createOMNamespace( org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_URI, org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_PREFIX); } if (type instanceof ParameterizedType) { ParameterizedType aType = (ParameterizedType) type; Type[] parameterArgTypes = aType.getActualTypeArguments(); keyType = parameterArgTypes[0]; valueType = parameterArgTypes[1]; } while (keyItr.hasNext()) { OMElement omEntry; Object key = keyItr.next(); Object value; if (key != null) { value = results.get(key); List<Object> properties = new ArrayList<Object>(); QName keyName; QName valueName; if (elementFormDefault) { keyName = new QName(ns.getNamespaceURI(), org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME, ns.getPrefix()); valueName = new QName(ns.getNamespaceURI(), org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME, ns.getPrefix()); } else { keyName = new QName( org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME); valueName = new QName( org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME); } Object kValue = getMapParameterElement(fac, org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME, key, keyType, typeTable, ns, elementFormDefault); Object vValue = getMapParameterElement(fac, org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME, value, valueType, typeTable, ns, elementFormDefault); if(Iterator.class.isAssignableFrom(kValue.getClass())){ Iterator valItr = (Iterator) kValue; while (valItr.hasNext()) { properties.add(keyName); properties.add(valItr.next()); } } else { properties.add(keyName); properties.add(kValue); } if(vValue != null && Iterator.class.isAssignableFrom(vValue.getClass())){ Iterator valItr = (Iterator) vValue; while (valItr.hasNext()) { properties.add(valueName); properties.add(valItr.next()); } } else { properties.add(valueName); properties.add(vValue); } QName entryQName; if (elementFormDefault) { entryQName = new QName(ns.getNamespaceURI(), org.apache.axis2.Constants.MAP_ENTRY_ELEMENT_NAME, ns.getPrefix()); } else { entryQName = new QName( org.apache.axis2.Constants.MAP_ENTRY_ELEMENT_NAME); } XMLStreamReader pullParser = new ADBXMLStreamReaderImpl( entryQName, properties.toArray(), null, typeTable, elementFormDefault); OMXMLParserWrapper builder = OMXMLBuilderFactory.createStAXOMBuilder( new StreamWrapper(pullParser)); omEntry = builder.getDocumentElement(); list.add(omEntry); } } return list; } /** * Helper method to deserialize each parameter of Map. * * @param paraType the parameter type * @param omElement the OMElement * @param helper the helper * @param objectSupplier the object supplier * @param genericType the generic type * @return the object * @throws AxisFault the axis fault */ private static Object processMapParameterObject(Type paraType, OMElement omElement, MultirefHelper helper, ObjectSupplier objectSupplier, Type genericType) throws AxisFault { if (paraType instanceof ParameterizedType) { if (Map.class.isAssignableFrom((Class) ((ParameterizedType) paraType).getRawType())) { return processGenericsMapElement( ((ParameterizedType) paraType).getActualTypeArguments(), omElement, helper, omElement.getChildren(), objectSupplier, paraType); } else if (Collection.class.isAssignableFrom((Class) ((ParameterizedType) paraType).getRawType())) { return processGenericCollection( omElement, (ParameterizedType) paraType, helper, objectSupplier); } else { throw new AxisFault("Map parameter does not support for " + ((ParameterizedType) paraType).getRawType()); } } else { return processObject(omElement, (Class) paraType, helper, true, objectSupplier, genericType); } } /** * This method instantiate a Map instance according to the expected * parameter type of the service method. a instance HashMap<Object, Object> * returns as the default value and in case of Exception. * * @param genericType the generic type * @return the map instance */ private static Map<Object, Object> getMapInstance(Type genericType) { Class rowType; if (genericType instanceof ParameterizedType) { rowType = (Class) ((ParameterizedType) genericType).getRawType(); } else { rowType = (Class) genericType; } if (Map.class.getName().equals(rowType.getName())) { return new HashMap<Object, Object>(); } else if (ConcurrentMap.class.getName().equals(rowType.getName())) { return new ConcurrentHashMap<Object, Object>(); } else if (SortedMap.class.getName().equals(rowType.getName())) { return new TreeMap<Object, Object>(); } // TODO - Enable this logic once the Axis2 move to Java 1.6. // else if (NavigableMap.class.getName().equals(rowType.getName())) { // return new TreeMap<Object, Object>(); // // } else if (ConcurrentNavigableMap.class.getName().equals(rowType.getName())) { // return new ConcurrentSkipListMap<Object, Object>(); // } // else { try { return (Map<Object, Object>) rowType.newInstance(); } catch (Exception e) { return new HashMap<Object, Object>(); } } } /** * Process the provided return value and constructs OMElement accordingly. * * @param fac the OMFactory instance * @param elementName the element name for return OMElement * @param value the actual return value * @param valueType the value type of return value * @param typeTable the type table * @param ns the OMNamespace * @param elementFormDefault the element form default * @return the map parameter object */ private static Object getMapParameterElement(OMFactory fac, String elementName, Object value, Type valueType, TypeTable typeTable, OMNamespace ns, boolean elementFormDefault) { //TODO - key/value can be a Collection, Array , Dom document ,OMElement etc if(value == null) { return null; } if (SimpleTypeMapper.isMap(value.getClass())) { List<OMElement> childList = getMapElement(fac, valueType, (Map) value, typeTable, elementFormDefault); OMElement omValue; if(elementFormDefault) { omValue = fac.createOMElement(elementName, ns.getNamespaceURI(), ns.getPrefix()); } else { omValue = fac.createOMElement(elementName, null); } for (OMElement child : childList) { omValue.addChild(child); } return omValue; } else if (SimpleTypeMapper.isCollection(value.getClass())) { QName elementQName; if(elementFormDefault) { elementQName = new QName(ns.getNamespaceURI(), elementName, ns.getPrefix()); } else { elementQName = new QName(elementName); } return getCollectionElement(fac, valueType, (Collection) value, elementName, null, elementQName, typeTable, elementFormDefault).getChildren(); } else if(SimpleTypeMapper.isDomDocument((Class)valueType)) { return convertDOMtoOM(fac, value); } else if (SimpleTypeMapper.isObjectType((Class) valueType)) { OMElement omValue; omValue = fac.createOMElement(elementName, ns); if (SimpleTypeMapper.isSimpleType(value)) { omValue.addChild(fac.createOMText(SimpleTypeMapper .getStringValue(value))); } else { QName name; if(elementFormDefault) { name = new QName(ns.getNamespaceURI(), elementName, ns.getPrefix()); } else { name = new QName(elementName); } XMLStreamReader xr = BeanUtil.getPullParser(value, name, typeTable, true, false); OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory .createStAXOMBuilder(OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); omValue = stAXOMBuilder.getDocumentElement(); } addInstanceTypeAttribute(fac, omValue, value, typeTable); return omValue; } else if (SimpleTypeMapper.isSimpleType(value)) { OMElement omValue; omValue = fac.createOMElement(elementName, ns); omValue.addChild(fac.createOMText(SimpleTypeMapper .getStringValue(value))); return omValue; } return value; } /** * Process generic collection. * * @param omElement the om element * @param generictype the generictype * @param helper the helper * @param objectSupplier the object supplier * @return the collection * @throws AxisFault the axis fault */ public static Collection<Object> processGenericCollection(OMElement omElement, Type generictype, MultirefHelper helper, ObjectSupplier objectSupplier) throws AxisFault { QName partName = omElement.getQName(); Type parameter = Object.class; if (generictype != null && (generictype instanceof ParameterizedType)) { ParameterizedType aType = (ParameterizedType) generictype; Type[] parameterArgTypes = aType.getActualTypeArguments(); parameter = parameterArgTypes[0]; } /* * Fix for AXIS2-5090. Use siblings with same QName instead of look for * children because list elements available on same level. */ Iterator parts = omElement.getParent().getChildrenWithName(partName); return processGenericsElement(parameter, omElement, helper, parts, objectSupplier, generictype); } /** * Process collection. * * @param omElement the om element * @param toReturn the to return * @param generictype the generictype * @param helper the helper * @param objectSupplier the object supplier * @param parts the parts * @param bare the bare * @return the collection * @throws AxisFault the axis fault */ public static Collection<Object> processGenericCollection(OMElement omElement, OMElement[] toReturn, Type generictype, MultirefHelper helper, ObjectSupplier objectSupplier, Iterator parts, boolean bare) throws AxisFault { String currentLocalName = omElement.getLocalName(); Type parameter = Object.class; List<OMElement> eleList = new ArrayList<OMElement>(); // in 'Bare' style no need to add first element to the list. if (!bare) { eleList.add(omElement); } if (generictype != null && (generictype instanceof ParameterizedType)) { ParameterizedType aType = (ParameterizedType) generictype; Type[] parameterArgTypes = aType.getActualTypeArguments(); parameter = parameterArgTypes[0]; } while (parts.hasNext()) { Object objValue = parts.next(); OMElement currElement; if (objValue instanceof OMElement) { currElement = (OMElement) objValue; } else { continue; } if (currentLocalName.equals(currElement.getLocalName())) { eleList.add(currElement); } else { // This just a container to bring back un-proceeded OMEleemnt. toReturn[0] = currElement; break; } } return processGenericsElement(parameter, omElement, helper, eleList.iterator(), objectSupplier, generictype); } /** * Gets the collection element. * * @param fac the fac * @param type the type * @param results the results * @param name the name * @param innerName the inner name * @param elementQName the element q name * @param typeTable the type table * @param elementFormDefault the element form default * @return the collection element */ public static OMElement getCollectionElement(OMFactory fac, Type type, Collection results, String name, String innerName, QName elementQName, TypeTable typeTable, boolean elementFormDefault) { String elementName = (innerName == null) ? name : innerName; Iterator<Object> itr = results.iterator(); List<Object> properties = new ArrayList<Object>(); OMNamespace ns = fac.createOMNamespace(elementQName.getNamespaceURI(), elementQName.getPrefix()); Type valueType = Object.class; if (type instanceof ParameterizedType) { ParameterizedType aType = (ParameterizedType) type; Type[] parameterArgTypes = aType.getActualTypeArguments(); valueType = parameterArgTypes[0]; } while (itr.hasNext()) { Object value = itr.next(); if (value != null) { value = getCollectionItemElement(fac, elementName, value, valueType, typeTable, ns, elementFormDefault); QName valueQName; if (elementFormDefault) { valueQName = new QName(ns.getNamespaceURI(), elementName, ns.getPrefix()); } else { valueQName = new QName(elementName); } properties.add(valueQName); properties.add(value); } } QName eleQName; if (elementFormDefault) { eleQName = new QName(ns.getNamespaceURI(), elementQName.getLocalPart(), ns.getPrefix()); } else { eleQName = new QName(elementQName.getLocalPart()); } XMLStreamReader pullParser = new ADBXMLStreamReaderImpl(eleQName, properties.toArray(), null, typeTable, elementFormDefault); OMXMLParserWrapper builder = OMXMLBuilderFactory.createStAXOMBuilder( new StreamWrapper(pullParser)); return builder.getDocumentElement(); } /** * Gets the collection item element. * * @param fac the fac * @param elementName the element name * @param value the value * @param valueType the value type * @param typeTable the type table * @param ns the ns * @param elementFormDefault the element form default * @return the collection item element */ private static Object getCollectionItemElement(OMFactory fac, String elementName, Object value, Type valueType, TypeTable typeTable, OMNamespace ns, boolean elementFormDefault) { if (SimpleTypeMapper.isMap(value.getClass())) { List<OMElement> childList = getMapElement(fac, valueType, (Map) value, typeTable, elementFormDefault); OMElement omValue = fac.createOMElement(elementName, ns.getNamespaceURI(), ns.getPrefix()); for (OMElement child : childList) { omValue.addChild(child); } return omValue; } else if (SimpleTypeMapper.isCollection(value.getClass())) { return getCollectionElement( fac, valueType, (Collection) value, elementName, Constants.INNER_ARRAY_COMPLEX_TYPE_NAME, new QName(ns.getNamespaceURI(), elementName, ns.getPrefix()), typeTable, elementFormDefault); } else if (SimpleTypeMapper.isObjectType((Class) valueType)) { OMElement omValue; omValue = fac.createOMElement(elementName, ns); if (SimpleTypeMapper.isSimpleType(value)) { omValue.addChild(fac.createOMText(SimpleTypeMapper .getStringValue(value))); } else { QName name; if (elementFormDefault) { name = new QName(ns.getNamespaceURI(), elementName, ns.getPrefix()); } else { name = new QName(elementName); } XMLStreamReader xr = BeanUtil.getPullParser(value, name, typeTable, true, false); OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory .createStAXOMBuilder(OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); omValue = stAXOMBuilder.getDocumentElement(); } addInstanceTypeAttribute(fac, omValue, value, typeTable); return omValue; } return value; } /** * Gets the collection instance object according to the genericType passed. * * @param genericType the generic type * @return the collection instance */ private static Collection<Object> getCollectionInstance(Type genericType) { Class rowType; if (genericType instanceof ParameterizedType) { rowType = (Class) ((ParameterizedType) genericType).getRawType(); } else { rowType = (Class) genericType; } if (Collection.class.getName().equals(rowType.getName()) || List.class.getName().equals(rowType.getName())) { return new ArrayList<Object>(); } else if (Set.class.getName().equals(rowType.getName())) { return new HashSet<Object>(); } else if (Queue.class.getName().equals(rowType.getName())) { return new LinkedList<Object>(); } else if (BlockingQueue.class.getName().equals(rowType.getName())) { return new LinkedBlockingQueue<Object>(); } // TODO - Enable this logic once the Axis2 move to Java 1.6. // else if (BlockingDeque.class.getName().equals(rowType.getName())) { // return new LinkedBlockingDeque<Object>(); // // }else if (NavigableSet.class.getName().equals(rowType.getName()) // || SortedSet.class.getName().equals(rowType.getName())) { // return new TreeSet<Object>(); // // } else { try { return (Collection<Object>) rowType.newInstance(); } catch (Exception e) { return new ArrayList<Object>(); } } } private static XMLGregorianCalendar getXMLGregorianCalendar( OMElement beanElement) throws DatatypeConfigurationException { String greCal = beanElement.getText(); XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance() .newXMLGregorianCalendar(greCal); return xmlCal; } }