Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.codehaus.xfire.aegis.type.basic.BeanType Maven / Gradle / Ivy
package org.codehaus.xfire.aegis.type.basic;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.XFireRuntimeException;
import org.codehaus.xfire.aegis.AegisBindingProvider;
import org.codehaus.xfire.aegis.MessageReader;
import org.codehaus.xfire.aegis.MessageWriter;
import org.codehaus.xfire.aegis.type.Type;
import org.codehaus.xfire.aegis.type.TypeMapping;
import org.codehaus.xfire.fault.XFireFault;
import org.codehaus.xfire.soap.SoapConstants;
import org.codehaus.xfire.util.ClassLoaderUtils;
import org.codehaus.xfire.util.NamespaceHelper;
import org.jdom.Attribute;
import org.jdom.Element;
/**
* Serializes JavaBeans.
*
* @author Dan Diephouse
* @author Jack Hong
*/
public class BeanType
extends Type
{
private BeanTypeInfo _info;
private boolean isInterface = false;
private boolean isException = false;
public BeanType()
{
}
public BeanType(BeanTypeInfo info)
{
this._info = info;
this.setTypeClass(info.getTypeClass());
}
/*
* (non-Javadoc)
*
* @see org.codehaus.xfire.aegis.type.Type#readObject(org.codehaus.xfire.aegis.MessageReader,
* org.codehaus.xfire.MessageContext)
*/
public Object readObject(MessageReader reader, MessageContext context)
throws XFireFault
{
BeanTypeInfo info = getTypeInfo();
try
{
Class clazz = getTypeClass();
Object object = null;
InterfaceInvocationHandler delegate = null;
boolean isProxy = false;
if (isInterface)
{
String impl = null;
if (context.getService() != null)
{
impl = (String) context.getService().getProperty(clazz.getName()
+ ".implementation");
}
if (impl == null)
{
delegate = new InterfaceInvocationHandler();
object = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[] { clazz },
delegate);
isProxy = true;
}
else
{
try
{
clazz = ClassLoaderUtils.loadClass(impl, getClass());
object = clazz.newInstance();
}
catch (ClassNotFoundException e)
{
throw new XFireRuntimeException("Could not find implementation class "
+ impl + " for class " + clazz.getName());
}
}
}
else if (isException)
{
object = createFromFault(context);
}
else
{
object = clazz.newInstance();
}
// Read attributes
while (reader.hasMoreAttributeReaders())
{
MessageReader childReader = reader.getNextAttributeReader();
QName name = childReader.getName();
Type type = info.getType(name);
if (type != null)
{
Object writeObj = type.readObject(childReader, context);
if (isProxy)
{
delegate.writeProperty(name.getLocalPart(), writeObj);
}
else
{
writeProperty(name, object, writeObj, clazz, info);
}
}
}
// Read child elements
while (reader.hasMoreElementReaders())
{
MessageReader childReader = reader.getNextElementReader();
QName name = childReader.getName();
BeanType parent = getBeanTypeWithProperty(name);
Type defaultType = null;
if (parent != null)
{
info = parent.getTypeInfo();
defaultType = info.getType(name);
}
else
{
defaultType = null;
}
Type type = AegisBindingProvider.getReadType(childReader.getXMLStreamReader(),
context, defaultType, getTypeMapping());
if (type != null)
{
if (!childReader.isXsiNil())
{
Object writeObj = type.readObject(childReader, context);
if (isProxy)
{
delegate.writeProperty(name.getLocalPart(), writeObj);
}
else
{
writeProperty(name, object, writeObj, clazz, info);
}
}
else
{
if (!info.isNillable(name))
{
throw new XFireFault(
name.getLocalPart() + " is nil, but not nillable.",
XFireFault.SENDER);
}
childReader.readToEnd();
}
}
else
{
childReader.readToEnd();
}
}
return object;
}
catch (IllegalAccessException e)
{
throw new XFireFault("Illegal access. " + e.getMessage(), e, XFireFault.RECEIVER);
}
catch (InstantiationException e)
{
throw new XFireFault("Couldn't instantiate class. " + e.getMessage(), e,
XFireFault.SENDER);
}
catch (SecurityException e)
{
throw new XFireFault("Illegal access. " + e.getMessage(), e, XFireFault.RECEIVER);
}
catch (IllegalArgumentException e)
{
throw new XFireFault("Illegal argument. " + e.getMessage(), e, XFireFault.RECEIVER);
}
catch (InvocationTargetException e)
{
throw new XFireFault("Couldn't create class: " + e.getMessage(), e, XFireFault.RECEIVER);
}
}
/**
* If the class is an exception, this will try and instantiate it with
* information from the XFireFault (if it exists).
*/
protected Object createFromFault(MessageContext context)
throws SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
Class clazz = getTypeClass();
Constructor ctr;
Object o;
Object body = context.getExchange().getFaultMessage().getBody();
if (!(body instanceof XFireFault))
return clazz.newInstance();
XFireFault fault = (XFireFault) body;
try
{
ctr = clazz.getConstructor(new Class[] { String.class, Throwable.class });
o = ctr.newInstance(new Object[] { fault.getMessage(), fault });
}
catch (NoSuchMethodException e)
{
try
{
ctr = clazz.getConstructor(new Class[] { String.class, Exception.class });
o = ctr.newInstance(new Object[] { fault.getMessage(), fault });
}
catch (NoSuchMethodException e1)
{
try
{
ctr = clazz.getConstructor(new Class[] { String.class });
o = ctr.newInstance(new Object[] { fault.getMessage() });
}
catch (NoSuchMethodException e2)
{
return clazz.newInstance();
}
}
}
return o;
}
/**
* Write the specified property to a field.
*/
protected void writeProperty(QName name,
Object object,
Object property,
Class impl,
BeanTypeInfo info)
throws XFireFault
{
try
{
PropertyDescriptor desc = info.getPropertyDescriptorFromMappedName(name);
Method m = desc.getWriteMethod();
if (m == null)
{
if (getTypeClass().isInterface())
m = getWriteMethodFromImplClass(impl, desc);
if (m == null)
throw new XFireFault("No write method for property " + name + " in "
+ object.getClass(), XFireFault.SENDER);
}
Class propertyType = desc.getPropertyType();
if ((property == null && !propertyType.isPrimitive()) || (property != null))
{
m.invoke(object, new Object[] { property });
}
}
catch (Exception e)
{
if (e instanceof XFireFault)
throw (XFireFault) e;
throw new XFireFault("Couldn't set property " + name + " on " + object + ". "
+ e.getMessage(), e, XFireFault.SENDER);
}
}
/**
* This is a hack to get the write method from the implementation class for
* an interface.
*/
private Method getWriteMethodFromImplClass(Class impl, PropertyDescriptor pd)
throws Exception
{
String name = pd.getName();
name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
return impl.getMethod(name, new Class[] { pd.getPropertyType() });
}
/**
* @see org.codehaus.xfire.aegis.type.Type#writeObject(Object,
* org.codehaus.xfire.aegis.MessageWriter,
* org.codehaus.xfire.MessageContext)
*/
public void writeObject(Object object, MessageWriter writer, MessageContext context)
throws XFireFault
{
if (object == null)
return;
BeanTypeInfo info = getTypeInfo();
if (context.getService() != null)
{
Object writeXsiType = context.getService()
.getProperty(AegisBindingProvider.WRITE_XSI_TYPE_KEY);
if ((Boolean.TRUE.equals(writeXsiType) || "true".equals(writeXsiType))
&& object.getClass() == getTypeClass())
{
writer.writeXsiType(getSchemaType());
}
}
/*
* TODO: Replace this method with one split into two pieces so that we
* can front-load the attributes and traverse down the list of super
* classes.
*/
for (Iterator itr = info.getAttributes(); itr.hasNext();)
{
QName name = (QName) itr.next();
Object value = readProperty(object, name);
if (value != null)
{
Type type = getType(info, name);
if (type == null)
throw new XFireRuntimeException("Couldn't find type for " + value.getClass()
+ " for property " + name);
MessageWriter cwriter = writer.getAttributeWriter(name);
type.writeObject(value, cwriter, context);
cwriter.close();
}
}
for (Iterator itr = info.getElements(); itr.hasNext();)
{
QName name = (QName) itr.next();
if (info.isExtension()
&& info.getPropertyDescriptorFromMappedName(name).getReadMethod()
.getDeclaringClass() != info.getTypeClass())
{
continue;
}
Object value = readProperty(object, name);
Type type = getType(info, name);
type = AegisBindingProvider.getWriteType(context, value, type);
MessageWriter cwriter;
// Write the value if it is not null.
if (value != null)
{
cwriter = getWriter(writer, name, type);
if (type == null)
throw new XFireRuntimeException("Couldn't find type for " + value.getClass()
+ " for property " + name);
type.writeObject(value, cwriter, context);
cwriter.close();
}
else if (info.isNillable(name))
{
cwriter = getWriter(writer, name, type);
// Write the xsi:nil if it is null.
cwriter.writeXsiNil();
cwriter.close();
}
}
if (info.isExtension())
{
Type t = getSuperType();
if (t != null)
{
t.writeObject(object, writer, context);
}
}
}
private MessageWriter getWriter(MessageWriter writer, QName name, Type type)
{
MessageWriter cwriter;
if (type.isAbstract())
{
cwriter = writer.getElementWriter(name);
}
else
{
cwriter = writer.getElementWriter(name);
}
return cwriter;
}
protected Object readProperty(Object object, QName name)
{
try
{
PropertyDescriptor desc = getTypeInfo().getPropertyDescriptorFromMappedName(name);
Method m = desc.getReadMethod();
if (m == null)
throw new XFireFault("No read method for property " + name + " in class "
+ object.getClass().getName(), XFireFault.SENDER);
return m.invoke(object, new Object[0]);
}
catch (Exception e)
{
throw new XFireRuntimeException("Couldn't get property " + name + " from bean "
+ object, e);
}
}
/**
* @see org.codehaus.xfire.aegis.type.Type#writeSchema(org.jdom.Element)
*/
public void writeSchema(Element root)
{
BeanTypeInfo info = getTypeInfo();
Element complex = new Element("complexType", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
complex.setAttribute(new Attribute("name", getSchemaType().getLocalPart()));
root.addContent(complex);
Type sooperType = getSuperType();
/*
* See Java Virtual Machine specification:
* http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#75734
*/
if (((info.getTypeClass().getModifiers() & Modifier.ABSTRACT) != 0) &&
!info.getTypeClass().isInterface())
{
complex.setAttribute(new Attribute("abstract", "true"));
}
if (info.isExtension() && sooperType != null)
{
Element complexContent = new Element("complexContent", SoapConstants.XSD_PREFIX,
SoapConstants.XSD);
complex.addContent(complexContent);
complex = complexContent;
}
/*
* Decide if we're going to extend another type. If we are going to
* defer, then make sure that we extend the type for our superclass.
*/
boolean isExtension = info.isExtension();
Element dummy = complex;
if (isExtension && sooperType != null)
{
Element extension = new Element("extension", SoapConstants.XSD_PREFIX,
SoapConstants.XSD);
complex.addContent(extension);
QName baseType = sooperType.getSchemaType();
extension.setAttribute(new Attribute("base", getNameWithPrefix2(root, baseType
.getNamespaceURI(), baseType.getLocalPart())));
dummy = extension;
}
Element seq = null;
// Write out schema for elements
for (Iterator itr = info.getElements(); itr.hasNext();)
{
QName name = (QName) itr.next();
if (isExtension)
{
PropertyDescriptor pd = info.getPropertyDescriptorFromMappedName(name);
assert pd.getReadMethod() != null && pd.getWriteMethod() != null;
if (pd.getReadMethod().getDeclaringClass() != info.getTypeClass())
{
continue;
}
}
if (seq == null)
{
seq = new Element("sequence", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
dummy.addContent(seq);
}
Element element = new Element("element", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
seq.addContent(element);
Type type = getType(info, name);
String nameNS = name.getNamespaceURI();
String nameWithPrefix = getNameWithPrefix(root, nameNS, name.getLocalPart());
String prefix = NamespaceHelper.getUniquePrefix((Element) root.getParent(), type
.getSchemaType().getNamespaceURI());
writeTypeReference(name, nameWithPrefix, element, type, prefix);
}
/**
* if future proof then add element
*/
if (info.isExtensibleElements())
{
if (seq == null)
{
seq = new Element("sequence", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
dummy.addContent(seq);
}
seq.addContent(createAnyElement());
}
// Write out schema for attributes
for (Iterator itr = info.getAttributes(); itr.hasNext();)
{
QName name = (QName) itr.next();
Element element = new Element("attribute", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
dummy.addContent(element);
Type type = getType(info, name);
String nameNS = name.getNamespaceURI();
String nameWithPrefix = getNameWithPrefix(root, nameNS, name.getLocalPart());
String prefix = NamespaceHelper.getUniquePrefix((Element) root.getParent(), type
.getSchemaType().getNamespaceURI());
element.setAttribute(new Attribute("name", nameWithPrefix));
element.setAttribute(new Attribute("type", prefix + ':'
+ type.getSchemaType().getLocalPart()));
}
/**
* If extensible attributes then add
*/
if (info.isExtensibleAttributes())
{
dummy.addContent(createAnyAttribute());
}
}
private String getNameWithPrefix(Element root, String nameNS, String localName)
{
if (!nameNS.equals(getSchemaType().getNamespaceURI()))
{
String prefix = NamespaceHelper.getUniquePrefix((Element) root.getParent(), nameNS);
if (prefix == null || prefix.length() == 0)
prefix = NamespaceHelper.getUniquePrefix(root, nameNS);
return prefix + ":" + localName;
}
return localName;
}
private String getNameWithPrefix2(Element root, String nameNS, String localName)
{
String prefix = NamespaceHelper.getUniquePrefix((Element) root.getParent(), nameNS);
if (prefix == null || prefix.length() == 0)
prefix = NamespaceHelper.getUniquePrefix(root, nameNS);
return prefix + ":" + localName;
}
private Type getType(BeanTypeInfo info, QName name)
{
Type type = info.getType(name);
if (type == null)
{
throw new NullPointerException("Couldn't find type for" + name + " in class "
+ getTypeClass().getName());
}
return type;
}
private void writeTypeReference(QName name,
String nameWithPrefix,
Element element,
Type type,
String prefix)
{
if (type.isAbstract())
{
element.setAttribute(new Attribute("name", nameWithPrefix));
element.setAttribute(new Attribute("type", prefix + ':'
+ type.getSchemaType().getLocalPart()));
int minOccurs = getTypeInfo().getMinOccurs(name);
if (minOccurs != 1)
{
element.setAttribute(new Attribute("minOccurs", new Integer(minOccurs).toString()));
}
if (getTypeInfo().isNillable(name))
{
element.setAttribute(new Attribute("nillable", "true"));
}
}
else
{
element.setAttribute(new Attribute("ref", prefix + ':'
+ type.getSchemaType().getLocalPart()));
}
}
public void setTypeClass(Class typeClass)
{
super.setTypeClass(typeClass);
isInterface = typeClass.isInterface();
isException = Exception.class.isAssignableFrom(typeClass);
}
/**
* We need to write a complex type schema for Beans, so return true.
*
* @see org.codehaus.xfire.aegis.type.Type#isComplex()
*/
public boolean isComplex()
{
return true;
}
public Set getDependencies()
{
Set deps = new HashSet();
BeanTypeInfo info = getTypeInfo();
for (Iterator itr = info.getAttributes(); itr.hasNext();)
{
QName name = (QName) itr.next();
deps.add(info.getType(name));
}
for (Iterator itr = info.getElements(); itr.hasNext();)
{
QName name = (QName) itr.next();
if (info.isExtension()
&& info.getPropertyDescriptorFromMappedName(name).getReadMethod()
.getDeclaringClass() != info.getTypeClass())
continue;
deps.add(info.getType(name));
}
/*
* Automagically add chain of superclasses *if* this is an an extension.
*/
if (info.isExtension())
{
Type sooperType = getSuperType();
if (sooperType != null)
{
deps.add(sooperType);
}
}
return deps;
}
private BeanType getBeanTypeWithProperty(QName name)
{
BeanType sooper = this;
Type type = null;
while (type == null && sooper != null)
{
type = sooper.getTypeInfo().getType(name);
if (type == null)
sooper = sooper.getSuperType();
}
return (BeanType) sooper;
}
private BeanType getSuperType()
{
BeanTypeInfo info = getTypeInfo();
Class c = info.getTypeClass().getSuperclass();
/*
* Don't dig any deeper than Object or Exception
*/
if (c != null && c != Object.class && c != Exception.class && c != RuntimeException.class)
{
TypeMapping tm = info.getTypeMapping();
BeanType superType = (BeanType) tm.getType(c);
if (superType == null)
{
superType = (BeanType) getTypeMapping().getTypeCreator().createType(c);
Class cParent = c.getSuperclass();
if (cParent != null && cParent != Object.class)
{
superType.getTypeInfo().setExtension(true);
}
tm.register(superType);
}
return superType;
}
else
{
return null;
}
}
public BeanTypeInfo getTypeInfo()
{
if (_info == null)
{
_info = createTypeInfo();
}
// Delay initialization so things work in recursive scenarios
_info.initialize();
return _info;
}
public BeanTypeInfo createTypeInfo()
{
BeanTypeInfo info = new BeanTypeInfo(getTypeClass(), getSchemaType().getNamespaceURI());
info.setTypeMapping(getTypeMapping());
info.initialize();
return info;
}
/**
* Create an element to represent any future elements that might get added
* to the schema
*
* @return
*/
private Element createAnyElement()
{
Element result = new Element("any", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
result.setAttribute(new Attribute("minOccurs", "0"));
result.setAttribute(new Attribute("maxOccurs", "unbounded"));
return result;
}
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append(": [class=");
Class c = getTypeClass();
sb.append((c == null) ? ("") : (c.getName()));
sb.append(",\nQName=");
QName q = getSchemaType();
sb.append((q == null) ? ("") : (q.toString()));
sb.append(",\ninfo=");
sb.append(getTypeInfo().toString());
sb.append("]");
return sb.toString();
}
/**
* Create an element to represent any future attributes that might get added
* to the schema
*
* @return
*/
private Element createAnyAttribute()
{
Element result = new Element("anyAttribute", SoapConstants.XSD_PREFIX, SoapConstants.XSD);
return result;
}
}