View Javadoc

1   package org.codehaus.xfire.aegis;
2   
3   import java.util.Iterator;
4   
5   import javax.xml.namespace.QName;
6   import javax.xml.stream.XMLStreamReader;
7   import javax.xml.stream.XMLStreamWriter;
8   
9   import org.codehaus.xfire.MessageContext;
10  import org.codehaus.xfire.XFireRuntimeException;
11  import org.codehaus.xfire.aegis.stax.ElementReader;
12  import org.codehaus.xfire.aegis.stax.ElementWriter;
13  import org.codehaus.xfire.aegis.type.DefaultTypeMappingRegistry;
14  import org.codehaus.xfire.aegis.type.Type;
15  import org.codehaus.xfire.aegis.type.TypeMapping;
16  import org.codehaus.xfire.aegis.type.TypeMappingRegistry;
17  import org.codehaus.xfire.aegis.yom.YOMReader;
18  import org.codehaus.xfire.aegis.yom.YOMWriter;
19  import org.codehaus.xfire.fault.XFireFault;
20  import org.codehaus.xfire.service.MessageHeaderInfo;
21  import org.codehaus.xfire.service.MessagePartContainer;
22  import org.codehaus.xfire.service.MessagePartInfo;
23  import org.codehaus.xfire.service.OperationInfo;
24  import org.codehaus.xfire.service.Service;
25  import org.codehaus.xfire.service.binding.AbstractBinding;
26  import org.codehaus.xfire.service.binding.BindingProvider;
27  import org.codehaus.xfire.soap.SoapConstants;
28  import org.codehaus.yom.Element;
29  
30  /***
31   * A BindingProvider for the Aegis type system.
32   * 
33   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
34   */
35  public class AegisBindingProvider
36      implements BindingProvider
37  {
38      public static final String TYPE_MAPPING_KEY = "type.mapping";
39      public static final String ENCODING_URI_KEY = "type.encodingUri";
40      
41      private TypeMappingRegistry registry;
42      private boolean writeOuter = true;
43      
44      public AegisBindingProvider()
45      {
46          this(new DefaultTypeMappingRegistry(true));
47      }
48      
49      public AegisBindingProvider(TypeMappingRegistry registry)
50      {
51          this.registry = registry;
52      }
53      
54      public boolean isWriteOuter()
55      {
56          return writeOuter;
57      }
58  
59      public void setWriteOuter(boolean writeOuter)
60      {
61          this.writeOuter = writeOuter;
62      }
63  
64      /***
65       * Creates a type mapping for this class and registers it with the TypeMappingRegistry. This needs to be called
66       * before initializeOperations().
67       */
68      public void initialize(Service endpoint)
69      {
70          String encodingStyle = (String) endpoint.getProperty(ENCODING_URI_KEY);
71  
72          if (encodingStyle == null)
73          {
74              AbstractBinding binding = (AbstractBinding) endpoint.getBinding();
75              if (binding.getUse().equals(SoapConstants.USE_ENCODED))
76              {
77                  encodingStyle = endpoint.getSoapVersion().getSoapEncodingStyle();
78              }
79              else
80              {
81                  encodingStyle = SoapConstants.XSD;
82              }
83          }
84  
85          endpoint.setProperty(ENCODING_URI_KEY, encodingStyle);
86          final TypeMapping tm = registry.createTypeMapping(encodingStyle, true);
87  
88          endpoint.setProperty(TYPE_MAPPING_KEY, tm);
89          registry.register(endpoint.getServiceInfo().getName().getNamespaceURI(), tm);
90          
91          for (Iterator itr = endpoint.getServiceInfo().getOperations().iterator(); itr.hasNext();)
92          {
93              OperationInfo opInfo = (OperationInfo) itr.next();
94              try
95              {
96                  initializeMessage(endpoint, opInfo.getInputMessage());
97              }
98              catch(XFireRuntimeException e)
99              {
100                 e.prepend("Error initializing parameters for method " + opInfo.getMethod());
101                 throw e;
102             }
103             try
104             {
105                 initializeMessage(endpoint, opInfo.getOutputMessage());
106             }
107             catch(XFireRuntimeException e)
108             {
109                 e.prepend("Error initializing return value for method " + opInfo.getMethod());
110                 throw e;
111             }
112         }
113     }
114 
115     protected void initializeMessage(Service service, MessagePartContainer container)
116     {
117         for (Iterator itr = container.getMessageHeaders().iterator(); itr.hasNext();)
118         {
119             MessageHeaderInfo header = (MessageHeaderInfo) itr.next();
120             
121             header.setSchemaType(getParameterType(getTypeMapping(service), header));
122         }
123         
124         for (Iterator itr = container.getMessageParts().iterator(); itr.hasNext();)
125         {
126             MessagePartInfo part = (MessagePartInfo) itr.next();
127             
128             part.setSchemaType(getParameterType(getTypeMapping(service), part));
129         }
130     }
131 
132     public Object readParameter(MessagePartInfo p, XMLStreamReader xsr, MessageContext context) 
133         throws XFireFault
134     {
135         Type type = (Type) p.getSchemaType();
136 
137         MessageReader reader = new ElementReader(xsr);
138         
139         return type.readObject(reader, context);
140     }
141     
142     public void writeParameter(MessagePartInfo p,
143                                XMLStreamWriter writer,
144                                MessageContext context,
145                                Object value)
146         throws XFireFault
147     {
148         Type type = (Type) p.getSchemaType();
149 
150         MessageWriter mw;
151         if (writeOuter)
152             mw = new ElementWriter(writer, p.getName());
153         else
154             mw = new ElementWriter(writer);
155 
156         type.writeObject(value, mw, context);
157     
158         if (writeOuter)
159             mw.close();
160     }
161 
162     private Type getParameterType(TypeMapping tm, MessagePartInfo param)
163     {
164         Type type = tm.getType(param.getName());
165 
166         if (type == null && tm.isRegistered(param.getTypeClass()))
167         {
168             type = tm.getType(param.getTypeClass());
169         }
170         
171         if (type == null)
172         {
173             OperationInfo op = param.getContainer().getOperation();
174             
175             int index = -1;
176             
177             if (op.getInputMessage().getMessageParts().contains(param))
178                 index = param.getIndex();
179             
180             /* Note: we are not registering the type here, because it is an anonymous
181              * type. Potentially there could be many schema types with this name. For example,
182              * there could be many ns:in0 paramters.
183              */
184             type = tm.getTypeCreator().createType(op.getMethod(), index);
185             type.setTypeMapping(tm);
186         }
187 
188         return type;
189     }
190 
191     private Type getParameterType(TypeMapping tm, MessageHeaderInfo param)
192     {
193         Type type = tm.getType(param.getName());
194 
195         if (type == null && tm.isRegistered(param.getTypeClass()))
196         {
197             type = tm.getType(param.getTypeClass());
198         }
199         
200         if (type == null)
201         {
202             OperationInfo op = param.getContainer().getOperation();
203             
204             int index = -1;
205             
206             if (op.getInputMessage().getMessageHeaders().contains(param))
207                 index = param.getIndex();
208             
209             /* Note: we are not registering the type here, because it is an anonymous
210              * type. Potentially there could be many schema types with this name. For example,
211              * there could be many ns:in0 paramters.
212              */
213             type = tm.getTypeCreator().createType(op.getMethod(), index);
214             type.setTypeMapping(tm);
215         }
216 
217         return type;
218     }
219     
220     public static TypeMapping getTypeMapping(Service service)
221     {
222         return (TypeMapping) service.getProperty(TYPE_MAPPING_KEY);
223     }
224 
225     public Object readHeader(MessageHeaderInfo p, MessageContext context)
226         throws XFireFault
227     {
228         Type type = (Type) p.getSchemaType();
229 
230         QName name = p.getName();
231         Element headers = context.getExchange().getInMessage().getHeader();
232         Element header = headers.getFirstChildElement(name.getLocalPart(), name.getNamespaceURI());
233         
234         if (header == null) return null;
235         
236         return type.readObject(new YOMReader(header), context);
237     }
238 
239     public void writeHeader(MessagePartInfo p, MessageContext context, Object value)
240         throws XFireFault
241     {
242         Type type = (Type) p.getSchemaType();
243 
244         MessageWriter mw = new YOMWriter(context.getOutMessage().getHeader());
245 
246         type.writeObject(value, mw, context);
247     
248         mw.close();
249     }
250 
251 }