| /* |
| * 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<OMElement> 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; |
| } |
| |
| } |