package org.jboss.axis.encoding.ser;
import org.jboss.axis.Constants;
import org.jboss.axis.description.ElementDesc;
import org.jboss.axis.description.FieldDesc;
import org.jboss.axis.description.TypeDesc;
import org.jboss.axis.encoding.DeserializationContext;
import org.jboss.axis.encoding.Deserializer;
import org.jboss.axis.encoding.DeserializerImpl;
import org.jboss.axis.encoding.TypeMapping;
import org.jboss.axis.message.SOAPElementAxisImpl;
import org.jboss.axis.message.SOAPHandler;
import org.jboss.axis.soap.SOAPConstants;
import org.jboss.axis.utils.BeanPropertyDescriptor;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.logging.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
public class BeanDeserializer extends DeserializerImpl
{
private static Logger log = Logger.getLogger(BeanDeserializer.class.getName());
QName xmlType;
Class javaType;
protected Map propertyMap;
protected QName prevQName;
protected TypeDesc typeDesc = null;
protected int collectionIndex = -1;
protected SimpleDeserializer cacheStringDSer = null;
protected QName cacheXMLType = null;
protected String lastFieldName = null;
protected DeferedBeanConstruction deferedConstruction;
public BeanDeserializer(Class javaType, QName xmlType)
{
this(javaType, xmlType, TypeDesc.getTypeDescForClass(javaType));
}
public BeanDeserializer(Class javaType, QName xmlType, TypeDesc typeDesc)
{
this(javaType, xmlType, typeDesc, BeanDeserializerFactory.getProperties(javaType, typeDesc));
}
public BeanDeserializer(Class javaType, QName xmlType, TypeDesc typeDesc, Map propertyMap)
{
this.xmlType = xmlType;
this.javaType = javaType;
this.typeDesc = typeDesc;
this.propertyMap = propertyMap;
try
{
value = javaType.newInstance();
}
catch (Exception e)
{
}
}
public void onStartElement(String namespace, String localName,
String prefix, Attributes attributes,
DeserializationContext context)
throws SAXException
{
lastFieldName = null;
if (value == null)
{
try
{
value = javaType.newInstance();
}
catch (Exception e)
{
ArrayList propTypes = new ArrayList();
Iterator it = propertyMap.values().iterator();
while (it.hasNext())
{
BeanPropertyDescriptor bpd = (BeanPropertyDescriptor)it.next();
propTypes.add(bpd.getType());
}
Constructor[] ctors = javaType.getConstructors();
deferedConstruction = null;
for (int i = 0; deferedConstruction == null && i < ctors.length; i++)
{
Constructor ctor = ctors[i];
Class[] ctorArgs = ctor.getParameterTypes();
if (ctorArgs.length > 0)
{
boolean allFound = true;
for (int j = 0; j < ctorArgs.length; j++)
{
allFound &= propTypes.contains(ctorArgs[j]);
}
if (allFound)
{
deferedConstruction = new DeferedBeanConstruction(ctor);
}
}
}
if (value == null && deferedConstruction == null)
{
throw new SAXException(Messages.getMessage("cantCreateBean00",
javaType.getName(),
e.toString()));
}
}
}
if (typeDesc == null)
return;
SOAPConstants soapConstants = context.getMessageContext().getSOAPConstants();
String soapenvURI = soapConstants.getEnvelopeURI();
for (int i = 0; i < attributes.getLength(); i++)
{
QName attrQName = null;
if (soapenvURI.equals(attributes.getURI(i)))
attrQName = new QName(attributes.getLocalName(i));
else
attrQName = new QName(attributes.getURI(i), attributes.getLocalName(i));
String fieldName = typeDesc.getFieldNameForAttribute(attrQName);
if (fieldName == null)
continue;
BeanPropertyDescriptor bpd = (BeanPropertyDescriptor)propertyMap.get(fieldName);
if (bpd != null)
{
if (!bpd.isIndexed())
{
Deserializer dSer = getDeserializer(null, bpd.getType(), null, context);
if (dSer == null)
throw new SAXException(Messages.getMessage("unregistered00", bpd.getType().toString()));
if (!(dSer instanceof SimpleDeserializer))
throw new SAXException(Messages.getMessage("AttrNotSimpleType00", bpd.getName(), bpd.getType().toString()));
try
{
dSer.onStartElement(namespace, localName, prefix, attributes, context);
Object val = ((SimpleDeserializer)dSer).makeValue(attributes.getValue(i));
if (value != null)
{
bpd.set(value, val);
}
else if (deferedConstruction != null)
{
value = deferedConstruction.newBeanInstance(val);
}
}
catch (Exception e)
{
throw new SAXException(e);
}
}
} } }
public SOAPHandler onStartChild(String namespace,
String localName,
String prefix,
Attributes attributes,
DeserializationContext context)
throws SAXException
{
log.debug("onStartChild: " + new QName(namespace, localName));
BeanPropertyDescriptor propDesc = null;
FieldDesc fieldDesc = null;
SOAPConstants soapConstants = context.getMessageContext().getSOAPConstants();
String encodingStyle = context.getMessageContext().getEncodingStyle();
boolean isEncoded = Constants.isSOAP_ENC(encodingStyle);
QName elemQName = new QName(namespace, localName);
if ((prevQName == null) || (!prevQName.equals(elemQName)))
{
collectionIndex = -1;
}
prevQName = elemQName;
if (typeDesc != null)
{
String fieldName = typeDesc.getFieldNameForElement(elemQName);
propDesc = (BeanPropertyDescriptor)propertyMap.get(fieldName);
fieldDesc = typeDesc.getFieldByName(fieldName);
lastFieldName = fieldName;
}
else
{
lastFieldName = null;
}
if (propDesc == null)
{
propDesc = (BeanPropertyDescriptor)propertyMap.get(localName);
}
if (propDesc == null)
{
propDesc = getAnyPropertyDesc();
if (propDesc != null)
{
try
{
SOAPElementAxisImpl[] curElements = (SOAPElementAxisImpl[])propDesc.get(value);
int length = 0;
if (curElements != null)
{
length = curElements.length;
}
SOAPElementAxisImpl[] newElements = new SOAPElementAxisImpl[length + 1];
if (curElements != null)
{
System.arraycopy(curElements, 0,
newElements, 0, length);
}
SOAPElementAxisImpl thisEl = context.getCurElement();
newElements[length] = thisEl;
propDesc.set(value, newElements);
if (!localName.equals(thisEl.getName()))
{
return new SOAPHandler(newElements, length);
}
return new SOAPHandler();
}
catch (Exception e)
{
throw new SAXException(e);
}
}
}
if (propDesc == null)
{
throw new SAXException(Messages.getMessage("badElem00", javaType.getName(),
localName));
}
QName childXMLType = context.getTypeFromXSITypeAttr(namespace, localName, attributes);
String href = attributes.getValue(soapConstants.getAttrHref());
if (childXMLType == null && fieldDesc != null && href == null)
{
childXMLType = fieldDesc.getXmlType();
}
Class propType = propDesc.getType();
TypeMapping tm = context.getTypeMapping();
Class childType = tm.getClassForQName(childXMLType);
if (childType != null && propType.isAssignableFrom(childType))
propType = childType;
Deserializer dSer = getDeserializer(childXMLType, propType, href, context);
if (dSer == null)
{
dSer = new DeserializerImpl();
return (SOAPHandler)dSer;
}
if (propDesc.isWriteable() || deferedConstruction != null)
{
if (propDesc.isIndexed() && !(dSer instanceof ArrayDeserializer))
{
collectionIndex++;
dSer.registerValueTarget(getBeanPropertyTarget(propDesc));
}
else if (!isEncoded && JavaUtils.isArrayClass(propDesc.getType()) &&
!(dSer instanceof Base64Deserializer) && !(dSer instanceof HexDeserializer))
{
collectionIndex++;
dSer.registerValueTarget(getBeanPropertyTarget(propDesc));
}
else
{
collectionIndex = -1;
dSer.registerValueTarget(getBeanPropertyTarget(propDesc));
}
}
addChildDeserializer(dSer);
return (SOAPHandler)dSer;
}
public void onEndElement(String namespace, String localName, DeserializationContext context) throws SAXException
{
super.onEndElement(namespace, localName, context);
if (value == null && deferedConstruction != null)
throw new SAXException("Could not construct bean using: " + deferedConstruction);
}
private BeanPropertyTarget getBeanPropertyTarget(BeanPropertyDescriptor propDesc)
{
BeanPropertyTarget target = null;
if (value != null)
target = new BeanPropertyTarget(value, propDesc, collectionIndex);
else if (deferedConstruction != null)
target = new BeanPropertyTarget(this, deferedConstruction, propDesc);
else
throw new IllegalStateException("Cannot get a valid property target");
return target;
}
public BeanPropertyDescriptor getAnyPropertyDesc()
{
if (typeDesc == null)
return null;
return typeDesc.getAnyDesc();
}
protected Deserializer getDeserializer(QName xmlType, Class javaType, String href, DeserializationContext context)
{
String encodingStyle = context.getMessageContext().getEncodingStyle();
boolean isEncoded = Constants.isSOAP_ENC(encodingStyle);
if (cacheStringDSer != null)
{
if (String.class.equals(javaType) &&
href == null &&
(cacheXMLType == null && xmlType == null ||
cacheXMLType != null && cacheXMLType.equals(xmlType)))
{
cacheStringDSer.reset();
return cacheStringDSer;
}
}
Deserializer dSer = null;
TypeMapping tm = context.getTypeMapping();
if (xmlType != null && href == null)
{
dSer = context.getDeserializerForType(xmlType);
}
if (dSer == null)
{
QName defaultXMLType = tm.getTypeQName(javaType);
if (href == null)
{
dSer = context.getDeserializer(javaType, defaultXMLType);
}
else
{
dSer = new DeserializerImpl();
dSer.setDefaultType(defaultXMLType);
}
}
if (javaType.equals(String.class) &&
dSer instanceof SimpleDeserializer)
{
cacheStringDSer = (SimpleDeserializer)dSer;
cacheXMLType = xmlType;
}
if (dSer == null && !isEncoded && JavaUtils.isArrayClass(javaType) && javaType != Byte[].class && javaType != byte[].class)
{
FieldDesc fieldDesc = (lastFieldName != null) ? typeDesc.getFieldByName(lastFieldName) : null;
Class compType = javaType.getComponentType();
QName itemXmlType = null;
if (fieldDesc != null && fieldDesc instanceof ElementDesc)
{
itemXmlType = ((ElementDesc)fieldDesc).getItemXmlType();
}
if (itemXmlType == null)
{
itemXmlType = tm.getTypeQName(compType);
}
log.debug("Using itemXmlType = " + itemXmlType);
dSer = context.getDeserializer(compType, itemXmlType);
}
return dSer;
}
public void characters(char[] p1, int p2, int p3) throws SAXException
{
super.characters(p1, p2, p3);
if (typeDesc != null)
{
Iterator it = propertyMap.values().iterator();
while (it.hasNext())
{
BeanPropertyDescriptor bpDesc = (BeanPropertyDescriptor)it.next();
if (bpDesc.isWriteable())
{
String name = bpDesc.getName();
FieldDesc fieldDesc = typeDesc.getFieldByName(name);
if (fieldDesc instanceof ElementDesc && ((ElementDesc)fieldDesc).isAsContent())
{
String strContent = new String(p1, p2, p3);
try
{
log.debug("Setting content property: " + name + "=" + strContent);
bpDesc.set(value, strContent);
}
catch (Exception e)
{
log.warn("Cannot set content property", e);
}
}
}
}
}
}
}