package org.jboss.net.axis.server;
import org.jboss.axis.MessageContext;
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.Target;
import org.jboss.axis.encoding.TypeMapping;
import org.jboss.axis.encoding.ser.SimpleDeserializer;
import org.jboss.axis.message.SOAPHandler;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.net.axis.ParameterizableDeserializer;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
public class EntityBeanDeserializer
extends DeserializerImpl
implements ParameterizableDeserializer
{
protected Map options;
protected Object home;
protected Method findMethod;
protected List findElements = new java.util.ArrayList(1);
protected Object[] findObjects;
protected TypeDesc typeDesc;
protected QName xmlType;
protected Class javaType;
protected Map propertyMap = new java.util.HashMap(4);
protected int collectionIndex = -1;
protected Collection fieldSetters = new java.util.ArrayList(4);
protected boolean initialized = false;
public EntityBeanDeserializer(Class remoteType, QName xmlType)
throws Exception
{
this.xmlType = xmlType;
this.javaType = remoteType;
}
protected String getStringOption(String key, String def)
{
String value = (String)options.get(key);
if (value == null)
{
value = def;
}
return value;
}
protected void initialize(MessageContext ctx) throws SAXException
{
if (!initialized)
{
initialized = true;
try
{
this.home =
new InitialContext().lookup(getStringOption("JndiName", javaType.getName() + "Home"));
String findMethodName = getStringOption("FindMethodName", "findByPrimaryKey");
String findMethodSignatureString =
getStringOption("FindMethodSignature", "java.lang.String");
List findMethodSignatureClasses = new java.util.ArrayList(1);
StringTokenizer tokenizer = new StringTokenizer(findMethodSignatureString, ";");
while (tokenizer.hasMoreTokens())
{
findMethodSignatureClasses.add(ctx.getClassLoader().loadClass(tokenizer.nextToken()));
}
this.findMethod =
home.getClass().getMethod(findMethodName,
(Class[])findMethodSignatureClasses.toArray(new Class[findMethodSignatureClasses.size()]));
BeanPropertyDescriptor[] pd = getPd(javaType);
for (int i = 0; i < pd.length; i++)
{
BeanPropertyDescriptor descriptor = pd[i];
propertyMap.put(descriptor.getName(), descriptor);
propertyMap.put(JavaUtils.xmlNameToJava(descriptor.getName()), descriptor);
}
typeDesc = TypeDesc.getTypeDescForClass(javaType);
String findMethodElements = getStringOption("FindMethodElements", "name");
tokenizer = new StringTokenizer(findMethodElements, ";");
while (tokenizer.hasMoreElements())
{
if (typeDesc != null)
{
this.findElements.add(typeDesc.getAttributeNameForField(tokenizer.nextToken()));
}
else
{
this.findElements.add(new QName("", tokenizer.nextToken()));
}
}
this.findObjects = new Object[findElements.size()];
}
catch (NamingException e)
{
throw new SAXException("Could not lookup home.", e);
}
catch (ClassNotFoundException e)
{
throw new SAXException("Could not find signature class.", e);
}
catch (NoSuchMethodException e)
{
throw new SAXException("Could not find finder method.", e);
}
}
}
public void setOptions(Map options)
{
this.options = options;
}
public Map getOptions()
{
return options;
}
public SOAPHandler onStartChild(String namespace,
String localName,
String prefix,
Attributes attributes,
DeserializationContext context)
throws SAXException
{
BeanPropertyDescriptor propDesc = null;
if (typeDesc != null)
{
QName elemQName = new QName(namespace, localName);
String fieldName = typeDesc.getFieldNameForElement(elemQName);
propDesc = (BeanPropertyDescriptor)propertyMap.get(fieldName);
}
if (propDesc == null)
{
propDesc = (BeanPropertyDescriptor)propertyMap.get(localName);
}
if (propDesc == null)
{
propDesc =
(BeanPropertyDescriptor)propertyMap.get(JavaUtils.xmlNameToJava(localName));
}
if (propDesc == null)
{
throw new SAXException(Messages.getMessage("badElem00", javaType.getName(), localName));
}
QName qn = context.getTypeFromAttributes(namespace, localName, attributes);
Deserializer dSer = context.getDeserializerForType(qn);
if (dSer == null)
{
dSer = new DeserializerImpl();
TypeMapping tm = context.getTypeMapping();
Class type = propDesc.getType();
dSer.setDefaultType(tm.getTypeQName(type));
}
QName elementQName = new QName(namespace, localName);
if (findElements.contains(elementQName))
{
dSer.registerValueTarget(new FindPropertyTarget(findElements.indexOf(elementQName)));
}
else if (propDesc.getWriteMethod().getParameterTypes().length == 1)
{
collectionIndex = -1;
dSer.registerValueTarget(new BeanPropertyTarget(propDesc));
}
else
{
collectionIndex++;
dSer.registerValueTarget(new BeanPropertyTarget(propDesc, collectionIndex));
}
return (SOAPHandler)dSer;
}
public void onStartElement(String namespace,
String localName,
String qName,
Attributes attributes,
DeserializationContext context)
throws SAXException
{
initialize(context.getMessageContext());
if (typeDesc == null)
return;
for (int i = 0; i < attributes.getLength(); i++)
{
QName 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.getWriteMethod() == null)
continue;
TypeMapping tm = context.getTypeMapping();
Class type = bpd.getType();
QName qn = tm.getTypeQName(type);
if (qn == null)
throw new SAXException(Messages.getMessage("unregistered00", type.toString()));
Deserializer dSer = context.getDeserializerForType(qn);
if (dSer == null)
throw new SAXException(Messages.getMessage("noDeser00", type.toString()));
if (!(dSer instanceof SimpleDeserializer))
throw new SAXException(Messages.getMessage("AttrNotSimpleType00", bpd.getName(), type.toString()));
if (findElements.contains(attrQName))
{
dSer.registerValueTarget(new FindPropertyTarget(findElements.indexOf(attrQName)));
}
else if (bpd.getWriteMethod().getParameterTypes().length == 1)
{
try
{
Object val = ((SimpleDeserializer)dSer).makeValue(attributes.getValue(i));
bpd.getWriteMethod().invoke(value, new Object[]{val});
}
catch (Exception e)
{
throw new SAXException(e);
}
}
} } }
public void onEndElement(String namespace,
String localName,
DeserializationContext context)
throws SAXException
{
try
{
value = findMethod.invoke(home, findObjects);
Iterator allSetters = fieldSetters.iterator();
while (allSetters.hasNext())
{
((BeanPropertyTarget)allSetters.next()).setReal(value);
}
fieldSetters = null;
}
catch (InvocationTargetException e)
{
throw new SAXException("Encountered exception " + e.getTargetException());
}
catch (IllegalAccessException e)
{
throw new SAXException("Encountered exception " + e);
}
super.onEndElement(namespace, localName, context);
}
public class FindPropertyTarget implements Target
{
int position;
public FindPropertyTarget(int index)
{
this.position = index;
}
public void set(Object value) throws SAXException
{
findObjects[position] = value;
}
}
public class BeanPropertyTarget implements Target
{
private BeanPropertyDescriptor pd;
private int index = -1;
Object value;
public BeanPropertyTarget(BeanPropertyDescriptor pd)
{
this.pd = pd;
this.index = -1; }
public BeanPropertyTarget(BeanPropertyDescriptor pd, int i)
{
this.pd = pd;
this.index = i;
}
public void set(Object value) throws SAXException
{
this.value = value;
if (fieldSetters != null)
{
fieldSetters.add(this);
}
else
{
setReal(EntityBeanDeserializer.this.value);
}
}
public void setReal(Object target) throws SAXException
{
try
{
if (index < 0)
pd.getWriteMethod().invoke(target, new Object[]{value});
else
pd.getWriteMethod().invoke(target, new Object[]{new Integer(index), value});
}
catch (Exception e)
{
Class type = pd.getReadMethod().getReturnType();
value = JavaUtils.convert(value, type);
try
{
if (index < 0)
pd.getWriteMethod().invoke(target, new Object[]{value});
else
pd.getWriteMethod().invoke(target, new Object[]{new Integer(index), value});
}
catch (Exception ex)
{
throw new SAXException(ex);
}
}
}
}
static class BeanPropertyDescriptor
{
private String name;
private Method getter;
private Method setter;
public BeanPropertyDescriptor(String _name, Method _getter, Method _setter)
{
name = _name;
getter = _getter;
setter = _setter;
}
public Method getReadMethod()
{
return getter;
}
public Method getWriteMethod()
{
return setter;
}
public String getName()
{
return name;
}
public Class getType()
{
return getter.getReturnType();
}
static BeanPropertyDescriptor[] processPropertyDescriptors(PropertyDescriptor[] rawPd,
Class cls)
{
BeanPropertyDescriptor[] myPd = new BeanPropertyDescriptor[rawPd.length];
for (int i = 0; i < rawPd.length; i++)
{
myPd[i] =
new BeanPropertyDescriptor(rawPd[i].getName(),
rawPd[i].getReadMethod(),
rawPd[i].getWriteMethod());
}
try
{
int index = 0;
BeanPropertyDescriptor[] newPd = new BeanPropertyDescriptor[rawPd.length];
Method[] methods = cls.getMethods();
for (int i = 0; i < methods.length; i++)
{
Method method = methods[i];
if (method.getName().startsWith("set"))
{
boolean found = false;
for (int j = 0; j < myPd.length && !found; j++)
{
if (myPd[j].getWriteMethod() != null
&& myPd[j].getWriteMethod().equals(method))
{
found = true;
newPd[index] = myPd[j];
index++;
}
}
}
}
if (index < myPd.length)
{
for (int m = 0; m < myPd.length && index < myPd.length; m++)
{
boolean found = false;
for (int n = 0; n < index && !found; n++)
{
found = (myPd[m] == newPd[n]);
}
if (!found)
{
newPd[index] = myPd[m];
index++;
}
}
}
if (index == myPd.length)
{
myPd = newPd;
}
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().startsWith("set")
&& methods[i].getParameterTypes().length == 2)
{
for (int j = 0; j < methods.length; j++)
{
if ((methods[j].getName().startsWith("get")
|| methods[j].getName().startsWith("is"))
&& methods[j].getParameterTypes().length == 1
&& methods[j].getReturnType() == methods[i].getParameterTypes()[1]
&& methods[j].getParameterTypes()[0] == int.class
&& methods[i].getParameterTypes()[0] == int.class)
{
for (int k = 0; k < myPd.length; k++)
{
if (myPd[k].getReadMethod() != null
&& myPd[k].getWriteMethod() != null
&& myPd[k].getReadMethod().getName().equals(methods[j].getName())
&& myPd[k].getWriteMethod().getName().equals(methods[i].getName()))
{
myPd[k] = new BeanPropertyDescriptor(myPd[k].getName(), methods[j], methods[i]);
}
}
}
}
}
}
}
catch (Exception e)
{
return myPd;
}
return myPd;
}
}
public static BeanPropertyDescriptor[] getPd(Class javaType)
{
BeanPropertyDescriptor[] pd;
try
{
PropertyDescriptor[] rawPd =
Introspector.getBeanInfo(javaType).getPropertyDescriptors();
pd = BeanPropertyDescriptor.processPropertyDescriptors(rawPd, javaType);
}
catch (Exception e)
{
throw new RuntimeException(e.getMessage());
}
return pd;
}
}