View Javadoc

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              // TODO: remember ITEs can go funny sometimes...
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          	// TODO: could be an exception as well.
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             // TODO: remember ITEs can go funny sometimes...
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             // TODO: this bean could be an exception as well.
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                 // TODO: Add config support for nillable
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 }