1 package org.codehaus.xfire.java.type;
2
3 import java.beans.BeanInfo;
4 import java.beans.IntrospectionException;
5 import java.beans.Introspector;
6 import java.beans.PropertyDescriptor;
7 import java.lang.reflect.InvocationTargetException;
8
9 import org.codehaus.xfire.SOAPConstants;
10 import org.codehaus.xfire.XFireRuntimeException;
11 import org.codehaus.xfire.java.message.MessageReader;
12 import org.codehaus.xfire.java.message.MessageWriter;
13 import org.codehaus.xfire.util.NamespaceHelper;
14 import org.dom4j.Element;
15 import org.dom4j.Namespace;
16
17 /***
18 * Serializes JavaBeans.
19 *
20 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
21 */
22 public class BeanType
23 extends Type
24 {
25
26 /***
27 * @see org.codehaus.xfire.java.type.Type#readObject(org.dom4j.Element)
28 */
29 public Object readObject(MessageReader reader)
30 throws XFireRuntimeException
31 {
32 try
33 {
34 Class clazz = getTypeClass();
35 Object object = clazz.newInstance();
36
37 BeanInfo info = Introspector.getBeanInfo( clazz, Object.class );
38
39 PropertyDescriptor[] pd = info.getPropertyDescriptors();
40
41 for ( int i = 0; i < pd.length; i++ )
42 {
43
44 Class typeClass = pd[i].getPropertyType();
45 Type type = getTypeMapping().getType( typeClass );
46
47 if ( type == null )
48 throw new XFireRuntimeException( "Couldn't find type for " + typeClass + " for property " + pd[i].getName() );
49
50 Object writeObj = type.readObject( reader.getReader( pd[i].getName() ) );
51
52 pd[i].getWriteMethod().invoke( object , new Object[] { writeObj } );
53 }
54
55 return object;
56 }
57 catch (IntrospectionException e)
58 {
59 throw new XFireRuntimeException("Couldn't introspect.", e);
60 }
61 catch (IllegalArgumentException e)
62 {
63 throw new XFireRuntimeException("Illegal argument.", e);
64 }
65 catch (IllegalAccessException e)
66 {
67 throw new XFireRuntimeException("Illegal access.", e);
68 }
69 catch (InvocationTargetException e)
70 {
71
72 throw new XFireRuntimeException("Couldn't invoke.", e);
73 }
74 catch (InstantiationException e)
75 {
76 throw new XFireRuntimeException("Couldn't instantiate.", e);
77 }
78 }
79
80 /***
81 * @see org.codehaus.xfire.java.type.Type#writeObject(java.lang.Object)
82 */
83 public void writeObject(Object object, MessageWriter writer)
84 throws XFireRuntimeException
85 {
86 try
87 {
88
89 BeanInfo info = Introspector.getBeanInfo( getTypeClass(), Object.class );
90
91 PropertyDescriptor[] pd = info.getPropertyDescriptors();
92
93 for ( int i = 0; i < pd.length; i++ )
94 {
95 Class typeClass = pd[i].getPropertyType();
96 Type type = getTypeMapping().getType( typeClass );
97
98 if ( type == null )
99 throw new XFireRuntimeException( "Couldn't find type for " + typeClass + " for property " + pd[i].getName() );
100
101 type.writeObject( pd[i].getReadMethod().invoke( object , new Object[0] ),
102 writer.getWriter( pd[i].getName() ) );
103 }
104 }
105 catch (IntrospectionException e)
106 {
107 throw new XFireRuntimeException("Couldn't introspect.", e);
108 }
109 catch (IllegalArgumentException e)
110 {
111 throw new XFireRuntimeException("Illegal argument.", e);
112 }
113 catch (IllegalAccessException e)
114 {
115 throw new XFireRuntimeException("Illegal access.", e);
116 }
117 catch (InvocationTargetException e)
118 {
119
120 throw new XFireRuntimeException("Couldn't invoke.", e);
121 }
122 }
123
124 /***
125 * @see org.codehaus.xfire.java.type.Type#writeSchema()
126 */
127 public void writeSchema( Element root )
128 {
129 try
130 {
131
132 BeanInfo info = Introspector.getBeanInfo( getTypeClass(), Object.class );
133
134 Namespace xsdNs = root.getNamespaceForURI( SOAPConstants.XSD );
135 org.dom4j.QName complexQ = new org.dom4j.QName("complexType", xsdNs);
136
137 Element complex = root.addElement( complexQ );
138
139 complex.addAttribute( "name", this.getSchemaType().getName() );
140
141 org.dom4j.QName seqQ = new org.dom4j.QName("sequence", xsdNs);
142 Element seq = complex.addElement( seqQ );
143
144 PropertyDescriptor[] pd = info.getPropertyDescriptors();
145
146 org.dom4j.QName elementQ = new org.dom4j.QName("element", xsdNs);
147
148 for ( int i = 0; i < pd.length; i++ )
149 {
150 Class typeClass = pd[i].getPropertyType();
151
152 Element element = seq.addElement( elementQ );
153
154 Type type = getTypeMapping().getType( typeClass );
155
156 Namespace typeNS = NamespaceHelper.getNamespace( root, type.getSchemaType().getNamespaceURI() );
157
158 element.addAttribute( "name", pd[i].getDisplayName() );
159
160 element.addAttribute( "nillable", "true" );
161 element.addAttribute("type", typeNS.getPrefix() + ":" + type.getSchemaType().getName());
162 }
163 }
164 catch (IntrospectionException e)
165 {
166 throw new XFireRuntimeException("Couldn't introspect.", e);
167 }
168 catch (IllegalArgumentException e)
169 {
170 throw new XFireRuntimeException("Illegal argument.", e);
171 }
172 }
173
174 /***
175 * We need to write a complex type schema for Beans, so return true.
176 *
177 * @see org.codehaus.xfire.java.type.Type#isComplex()
178 */
179 public boolean isComplex()
180 {
181 return true;
182 }
183 }