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 public Object readObject(MessageReader reader)
26 throws XFireRuntimeException
27 {
28 try
29 {
30 Class clazz = getTypeClass();
31 Object object = clazz.newInstance();
32
33 BeanInfo info = Introspector.getBeanInfo( clazz, Object.class );
34
35 PropertyDescriptor[] pds = info.getPropertyDescriptors();
36
37 while( reader.hasMoreChildReaders() )
38 {
39 MessageReader childReader = reader.getNextChildReader();
40 String name = childReader.getLocalName();
41
42 PropertyDescriptor pd = findPropertyDescriptor( name, pds );
43
44 if ( pd == null )
45 throw new XFireRuntimeException( "Couldn't find property for " + name );
46
47 Type type = getTypeMapping().getType( pd.getPropertyType() );
48
49 if ( type == null )
50 throw new XFireRuntimeException( "Couldn't find type for "
51 + pd.getPropertyType() + " for property " + name );
52
53 Object writeObj = type.readObject( childReader );
54
55 pd.getWriteMethod().invoke( object , new Object[] { writeObj } );
56 }
57
58 return object;
59 }
60 catch (IntrospectionException e)
61 {
62 throw new XFireRuntimeException("Couldn't introspect.", e);
63 }
64 catch (IllegalArgumentException e)
65 {
66 throw new XFireRuntimeException("Illegal argument.", e);
67 }
68 catch (IllegalAccessException e)
69 {
70 throw new XFireRuntimeException("Illegal access.", e);
71 }
72 catch (InvocationTargetException e)
73 {
74 throw new XFireRuntimeException("Couldn't invoke.", e);
75 }
76 catch (InstantiationException e)
77 {
78 throw new XFireRuntimeException("Couldn't instantiate.", e);
79 }
80 }
81
82 protected PropertyDescriptor findPropertyDescriptor(String name, PropertyDescriptor[] pd)
83 {
84 for ( int i = 0; i < pd.length; i++ )
85 {
86 if ( pd[i].getName().equals(name) )
87 return pd[i];
88 }
89 return null;
90 }
91
92 /***
93 * @see org.codehaus.xfire.java.type.Type#writeObject(java.lang.Object)
94 */
95 public void writeObject(Object object, MessageWriter writer)
96 throws XFireRuntimeException
97 {
98 try
99 {
100
101 BeanInfo info = Introspector.getBeanInfo( getTypeClass(), Object.class );
102
103 PropertyDescriptor[] pd = info.getPropertyDescriptors();
104
105 for ( int i = 0; i < pd.length; i++ )
106 {
107 Class typeClass = pd[i].getPropertyType();
108 Type type = getTypeMapping().getType( typeClass );
109
110 if ( type == null )
111 throw new XFireRuntimeException( "Couldn't find type for " + typeClass + " for property " + pd[i].getName() );
112
113 MessageWriter cwriter = writer.getChildWriter( pd[i].getName() );
114 type.writeObject( pd[i].getReadMethod().invoke( object , new Object[0] ),
115 cwriter );
116 cwriter.close();
117 }
118 }
119 catch (IntrospectionException e)
120 {
121 throw new XFireRuntimeException("Couldn't introspect.", e);
122 }
123 catch (IllegalArgumentException e)
124 {
125 throw new XFireRuntimeException("Illegal argument.", e);
126 }
127 catch (IllegalAccessException e)
128 {
129 throw new XFireRuntimeException("Illegal access.", e);
130 }
131 catch (InvocationTargetException e)
132 {
133
134 throw new XFireRuntimeException("Couldn't invoke.", e);
135 }
136 }
137
138 /***
139 * @see org.codehaus.xfire.java.type.Type#writeSchema()
140 */
141 public void writeSchema( Element root )
142 {
143 try
144 {
145
146 BeanInfo info = Introspector.getBeanInfo( getTypeClass(), Object.class );
147
148 Namespace xsdNs = root.getNamespaceForURI( SOAPConstants.XSD );
149 org.dom4j.QName complexQ = new org.dom4j.QName("complexType", xsdNs);
150
151 Element complex = root.addElement( complexQ );
152
153 complex.addAttribute( "name", this.getSchemaType().getName() );
154
155 org.dom4j.QName seqQ = new org.dom4j.QName("sequence", xsdNs);
156 Element seq = complex.addElement( seqQ );
157
158 PropertyDescriptor[] pd = info.getPropertyDescriptors();
159
160 org.dom4j.QName elementQ = new org.dom4j.QName("element", xsdNs);
161
162 for ( int i = 0; i < pd.length; i++ )
163 {
164 Class typeClass = pd[i].getPropertyType();
165
166 Element element = seq.addElement( elementQ );
167
168 Type type = getTypeMapping().getType( typeClass );
169
170 Namespace typeNS = NamespaceHelper.getNamespace( root, type.getSchemaType().getNamespaceURI() );
171
172 element.addAttribute( "name", pd[i].getDisplayName() );
173
174 element.addAttribute( "nillable", "true" );
175 element.addAttribute("type", typeNS.getPrefix() + ":" + type.getSchemaType().getName());
176 }
177 }
178 catch (IntrospectionException e)
179 {
180 throw new XFireRuntimeException("Couldn't introspect.", e);
181 }
182 catch (IllegalArgumentException e)
183 {
184 throw new XFireRuntimeException("Illegal argument.", e);
185 }
186 }
187
188 /***
189 * We need to write a complex type schema for Beans, so return true.
190 *
191 * @see org.codehaus.xfire.java.type.Type#isComplex()
192 */
193 public boolean isComplex()
194 {
195 return true;
196 }
197 }