blob: e9c5e5325284ae75cefcb261b94e018e7f598c02 [file] [log] [blame]
/*
* 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;
}
}