View Javadoc

1   package org.codehaus.xfire.xmlbeans;
2   
3   import java.util.HashSet;
4   import java.util.Iterator;
5   import java.util.Map;
6   import java.util.Set;
7   
8   import javax.xml.namespace.QName;
9   import javax.xml.stream.XMLStreamException;
10  import javax.xml.stream.XMLStreamReader;
11  
12  import org.apache.commons.logging.Log;
13  import org.apache.commons.logging.LogFactory;
14  import org.apache.xmlbeans.SchemaProperty;
15  import org.apache.xmlbeans.SchemaType;
16  import org.apache.xmlbeans.XmlBeans;
17  import org.apache.xmlbeans.XmlCursor;
18  import org.apache.xmlbeans.XmlException;
19  import org.apache.xmlbeans.XmlObject;
20  import org.codehaus.xfire.MessageContext;
21  import org.codehaus.xfire.XFireRuntimeException;
22  import org.codehaus.xfire.aegis.MessageReader;
23  import org.codehaus.xfire.aegis.MessageWriter;
24  import org.codehaus.xfire.aegis.stax.ElementReader;
25  import org.codehaus.xfire.aegis.stax.ElementWriter;
26  import org.codehaus.xfire.aegis.type.Type;
27  import org.codehaus.xfire.fault.XFireFault;
28  import org.codehaus.xfire.soap.handler.ReadHeadersHandler;
29  import org.codehaus.xfire.util.STAXUtils;
30  import org.codehaus.yom.Element;
31  
32  /***
33   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
34   * @since Nov 13, 2004
35   */
36  public class XmlBeansType 
37      extends Type
38  {
39      private SchemaType schemaType;
40  
41      private final static Log logger = LogFactory.getLog(XmlBeansType.class); 
42      
43      public XmlBeansType()
44      {
45      }
46      
47      public XmlBeansType(SchemaType schemaType)
48      {
49          this.schemaType = schemaType;
50          setTypeClass(schemaType.getJavaClass());
51      }
52  
53      public XmlBeansType(Class clazz)
54      {
55          this.schemaType = XmlBeans.typeForClass(clazz);
56          setTypeClass(clazz);
57      }
58  
59      public void writeSchema(Element root)
60      {
61      }
62      
63      public boolean isComplex()
64      {
65          return !schemaType.isPrimitiveType();
66      }
67  
68      public boolean isAbstract()
69      {
70          return schemaType.isAbstract();
71      }
72  
73      public Set getDependencies()
74      {
75          SchemaProperty[] properties = schemaType.getProperties();
76          HashSet deps = new HashSet();
77          for (int i = 0; i < properties.length; i++)
78          {
79              SchemaType etype = properties[i].getType();
80              SchemaProperty[] iprops = etype.getElementProperties();
81              for (int j = 0; j < iprops.length; j++)
82              {
83                  SchemaType itype = iprops[j].getType();
84                  
85                  if (!itype.isPrimitiveType() && itype.getSourceName() != null)
86                  {
87                      deps.add(new XmlBeansType(itype));
88                  }
89              }
90          }
91          return deps;
92      }
93  
94      public QName getSchemaType()
95      {
96          if (schemaType.isDocumentType())
97              return schemaType.getDocumentElementName();
98          else if (schemaType.getName() != null)
99              return schemaType.getName();
100         else
101         {
102             // No name for this type, use outer type (and recur up if same)
103             SchemaType outer = schemaType.getOuterType();
104             while (outer != null)
105             {
106                 if (outer.isDocumentType())
107                     return outer.getDocumentElementName();
108                 else if (outer.getName() != null)
109                     return outer.getName();
110                 else
111                     outer = outer.getOuterType();
112             }
113             
114             // No outer type, no type on this, should not be possible, so explode
115             throw new XFireRuntimeException("No type name is defined for <" + schemaType + "> " +
116                                             "and no outer type containing the inline type -- this " +
117                                             "should not be possible to be a legally defined schema");
118         }
119     }
120 
121     public Object readObject(MessageReader mreader, MessageContext context)
122         throws XFireFault
123     {
124         try
125         {
126             XMLStreamReader reader = ((ElementReader) mreader).getXMLStreamReader();
127             XmlObject parsed = XmlObject.Factory.parse(reader);
128             
129             /* Add namespace declarations from the XMLStreamReader NamespaceContext.
130              * This is important when values reference QNames. For instance, 
131              * xsi:type="xsd:string". If the xsd namespace is declared on the SOAP
132              * envelope then XMLBeans won't pick up. 
133              */
134             XmlCursor cursor = parsed.newCursor();
135             try
136             {
137                 cursor.toFirstContentToken();
138                 Map namespaces = (Map) context.getProperty(ReadHeadersHandler.DECLARED_NAMESPACES);
139                 for (Iterator itr = namespaces.entrySet().iterator(); itr.hasNext();)
140                 {
141                     Map.Entry entry = (Map.Entry) itr.next();
142                     cursor.insertNamespace((String) entry.getKey(), (String) entry.getValue());
143                 }
144             }
145             finally
146             {
147                 cursor.dispose();
148             }
149 
150             return parsed;
151         }
152         catch( XmlException e )
153         {
154             throw new XFireFault("Could not read request.", e, XFireFault.SENDER);
155         }
156     }
157 
158     public void writeObject(Object value, MessageWriter writer, MessageContext context)
159         throws XFireFault
160     {
161         try
162         {
163             XmlObject obj = (XmlObject) value; 
164        
165             XmlCursor cursor = obj.newCursor();
166             if (cursor.toFirstChild() && cursor.toFirstChild())
167             {
168                 do
169                 {
170                     STAXUtils.copy(cursor.newXMLStreamReader(), 
171                                    ((ElementWriter) writer).getXMLStreamWriter());
172                 }
173                 while(cursor.toNextSibling());
174             }
175         } 
176         catch (XMLStreamException e)
177         {
178             throw new XFireFault("Could not write response.", e, XFireFault.SENDER);
179         }
180     }
181 }