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 boolean isWriteOuter()
74      {
75          return false;
76      }
77  
78      public Set getDependencies()
79      {
80          SchemaProperty[] properties = schemaType.getProperties();
81          HashSet deps = new HashSet();
82          for (int i = 0; i < properties.length; i++)
83          {
84              SchemaType etype = properties[i].getType();
85              SchemaProperty[] iprops = etype.getElementProperties();
86              for (int j = 0; j < iprops.length; j++)
87              {
88                  SchemaType itype = iprops[j].getType();
89                  
90                  if (!itype.isPrimitiveType() && itype.getSourceName() != null)
91                  {
92                      deps.add(new XmlBeansType(itype));
93                  }
94              }
95          }
96          return deps;
97      }
98  
99      public QName getSchemaType()
100     {
101         if (schemaType.isDocumentType())
102             return schemaType.getDocumentElementName();
103         else if (schemaType.getName() != null)
104             return schemaType.getName();
105         else
106         {
107             // No name for this type, use outer type (and recur up if same)
108             SchemaType outer = schemaType.getOuterType();
109             while (outer != null)
110             {
111                 if (outer.isDocumentType())
112                     return outer.getDocumentElementName();
113                 else if (outer.getName() != null)
114                     return outer.getName();
115                 else
116                     outer = outer.getOuterType();
117             }
118             
119             // No outer type, no type on this, should not be possible, so explode
120             throw new XFireRuntimeException("No type name is defined for <" + schemaType + "> " +
121                                             "and no outer type containing the inline type -- this " +
122                                             "should not be possible to be a legally defined schema");
123         }
124     }
125 
126     public Object readObject(MessageReader mreader, MessageContext context)
127         throws XFireFault
128     {
129         try
130         {
131             XMLStreamReader reader = ((ElementReader) mreader).getXMLStreamReader();
132             XmlObject parsed = XmlObject.Factory.parse(reader);
133             
134             /* Add namespace declarations from the XMLStreamReader NamespaceContext.
135              * This is important when values reference QNames. For instance, 
136              * xsi:type="xsd:string". If the xsd namespace is declared on the SOAP
137              * envelope then XMLBeans won't pick up. 
138              */
139             XmlCursor cursor = parsed.newCursor();
140             try
141             {
142                 cursor.toFirstContentToken();
143                 Map namespaces = (Map) context.getProperty(ReadHeadersHandler.DECLARED_NAMESPACES);
144                 for (Iterator itr = namespaces.entrySet().iterator(); itr.hasNext();)
145                 {
146                     Map.Entry entry = (Map.Entry) itr.next();
147                     cursor.insertNamespace((String) entry.getKey(), (String) entry.getValue());
148                 }
149             }
150             finally
151             {
152                 cursor.dispose();
153             }
154 
155             return parsed;
156         }
157         catch( XmlException e )
158         {
159             throw new XFireFault("Could not read request.", e, XFireFault.SENDER);
160         }
161     }
162 
163     public void writeObject(Object value, MessageWriter writer, MessageContext context)
164         throws XFireFault
165     {
166         try
167         {
168             XmlObject obj = (XmlObject) value; 
169        
170             XmlCursor cursor = obj.newCursor();
171             
172             STAXUtils.copy(cursor.newXMLStreamReader(), 
173                             ((ElementWriter) writer).getXMLStreamWriter());
174         } 
175         catch (XMLStreamException e)
176         {
177             throw new XFireFault("Could not write response.", e, XFireFault.SENDER);
178         }
179     }
180 }