View Javadoc

1   package org.codehaus.xfire.service.binding;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.List;
7   
8   import javax.wsdl.Message;
9   import javax.wsdl.Part;
10  import javax.xml.namespace.QName;
11  import javax.xml.stream.XMLStreamException;
12  import javax.xml.stream.XMLStreamWriter;
13  
14  import org.codehaus.xfire.MessageContext;
15  import org.codehaus.xfire.XFireRuntimeException;
16  import org.codehaus.xfire.exchange.InMessage;
17  import org.codehaus.xfire.exchange.MessageSerializer;
18  import org.codehaus.xfire.exchange.OutMessage;
19  import org.codehaus.xfire.fault.XFireFault;
20  import org.codehaus.xfire.service.MessageInfo;
21  import org.codehaus.xfire.service.MessagePartInfo;
22  import org.codehaus.xfire.service.OperationInfo;
23  import org.codehaus.xfire.service.Service;
24  import org.codehaus.xfire.soap.SoapConstants;
25  import org.codehaus.xfire.util.DepthXMLStreamReader;
26  import org.codehaus.xfire.util.STAXUtils;
27  import org.codehaus.xfire.wsdl.SchemaType;
28  import org.codehaus.xfire.wsdl11.WSDL11ParameterBinding;
29  import org.codehaus.xfire.wsdl11.builder.AbstractWSDL;
30  import org.codehaus.xfire.wsdl11.builder.WSDLBuilder;
31  import org.codehaus.yom.Attribute;
32  import org.codehaus.yom.Element;
33  
34  public class WrappedBinding
35      extends AbstractBinding
36      implements WSDL11ParameterBinding, MessageSerializer
37  {
38      public WrappedBinding()
39      {
40          setStyle(SoapConstants.STYLE_WRAPPED);
41          setUse(SoapConstants.USE_LITERAL);
42      }
43      
44      public void readMessage(InMessage inMessage, MessageContext context)
45          throws XFireFault
46      {
47          Service endpoint = context.getService();
48          
49          List parameters = new ArrayList();
50          DepthXMLStreamReader dr = new DepthXMLStreamReader(context.getInMessage().getXMLStreamReader());
51  
52          if ( !STAXUtils.toNextElement(dr) )
53              throw new XFireFault("There must be a method name element.", XFireFault.SENDER);
54          
55          MessageInfo msgInfo = null;
56          if (isClientModeOn())
57          {
58              OperationInfo op = context.getExchange().getOperation();
59              
60              msgInfo = op.getOutputMessage();
61          }
62          else
63          {
64              if (context.getExchange().getOperation() == null)
65              {
66                  OperationInfo op = endpoint.getServiceInfo().getOperation( dr.getLocalName() );
67                  
68                  if (op == null)
69                  {
70                      throw new XFireFault("Invalid operation: " + dr.getName(), XFireFault.SENDER);
71                  }
72          
73                  setOperation(op, context);
74              }
75              
76              msgInfo = context.getExchange().getOperation().getInputMessage();
77          }
78          
79          // Move from Operation element to whitespace or start element
80          nextEvent(dr);
81  
82          while(STAXUtils.toNextElement(dr))
83          {
84              MessagePartInfo p = msgInfo.getMessagePart(dr.getName());
85  
86              if (p == null)
87              {
88                  throw new XFireFault("Parameter " + dr.getName() + " does not exist!", 
89                                       XFireFault.SENDER);
90              }
91  
92              parameters.add( getBindingProvider().readParameter(p, inMessage.getXMLStreamReader(), context) );
93          }
94          
95          inMessage.setBody(parameters);
96      }
97      
98      public void writeMessage(OutMessage message, XMLStreamWriter writer, MessageContext context)
99          throws XFireFault
100     {
101         try
102         {
103             Service endpoint = context.getService();
104             Object[] values = (Object[]) message.getBody();
105             
106             OperationInfo op = context.getExchange().getOperation();
107             String name = null;
108             
109             MessageInfo msgInfo = null;
110             if (isClientModeOn())
111             {
112                 name = op.getName();
113                 msgInfo = op.getInputMessage();
114             }
115             else
116             {
117                 name = op.getName() + "Response";
118                 msgInfo = op.getOutputMessage();
119             }
120 
121             writeStartElement(writer, name, endpoint.getServiceInfo().getName().getNamespaceURI());
122             
123             int i = 0;
124             for(Iterator itr = msgInfo.getMessageParts().iterator(); itr.hasNext();)
125             {
126                 MessagePartInfo outParam = (MessagePartInfo) itr.next();
127     
128                 getBindingProvider().writeParameter(outParam, writer, context, values[i]);
129                 i++;
130             }
131     
132             writer.writeEndElement();
133         }
134         catch (XMLStreamException e)
135         {
136             throw new XFireRuntimeException("Couldn't write start element.", e);
137         }
138     }
139     
140     public void writeStartElement(XMLStreamWriter writer, String name, String namespace) 
141         throws XMLStreamException
142     {
143         String prefix = "";
144         
145         writer.setPrefix(prefix, namespace);
146         writer.writeStartElement(prefix, name, namespace);
147         writer.writeNamespace(prefix, namespace);
148     }
149 
150     public void createInputParts(WSDLBuilder builder,
151                                  Message req, 
152                                  OperationInfo op)
153     {
154         Part part = builder.getDefinition().createPart();
155 
156         QName typeQName = createDocumentType(builder, 
157                                              op.getInputMessage(), 
158                                              part,
159                                              op.getName());
160         part.setName("parameters");
161         part.setElementName(typeQName);
162 
163         req.addPart(part);
164     }
165 
166     public void createOutputParts(WSDLBuilder builder,
167                                   Message req, 
168                                   OperationInfo op)
169     {
170         // response message part
171         Part part = builder.getDefinition().createPart();
172 
173         // Document style service
174         QName typeQName = createDocumentType(builder, 
175                                              op.getOutputMessage(), 
176                                              part,
177                                              op.getName() + "Response");
178         part.setElementName(typeQName);
179         part.setName("parameters");
180 
181         req.addPart(part);
182     }
183     
184     private QName createDocumentType(WSDLBuilder builder,
185                                      MessageInfo message, 
186                                      Part part,
187                                      String opName)
188     {
189         Element schemaEl = builder.createSchemaType(builder.getInfo().getTargetNamespace());
190         Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
191         schemaEl.appendChild(element);
192 
193         element.addAttribute(new Attribute("name", opName));
194 
195         Element complex = new Element(AbstractWSDL.complexQ, SoapConstants.XSD);
196         element.appendChild(complex);
197 
198         if (message.getMessageParts().size() > 0)
199         {
200             Element sequence = createSequence(complex);
201 
202             writeParametersSchema(builder, message.getMessageParts(), sequence);
203         }
204 
205         return new QName(builder.getInfo().getTargetNamespace(), opName);
206     }
207 
208     /***
209      * @param op
210      * @param sequence
211      */
212     private void writeParametersSchema(WSDLBuilder builder,
213                                        Collection params, 
214                                        Element sequence)
215     {
216         for (Iterator itr = params.iterator(); itr.hasNext();)
217         {
218             MessagePartInfo param = (MessagePartInfo) itr.next();
219 
220             Class clazz = param.getTypeClass();
221             QName pName = param.getName();
222             SchemaType type = param.getSchemaType();
223 
224             builder.addDependency(type);
225             QName schemaType = type.getSchemaType();
226 
227             String uri = type.getSchemaType().getNamespaceURI();
228             String prefix = builder.getNamespacePrefix(uri);
229             builder.addNamespace(prefix, uri);
230 
231             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
232             sequence.appendChild(element);
233 
234             if (type.isAbstract())
235             {
236                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
237                 
238                 element.addAttribute(new Attribute("type", 
239                                                    prefix + ":" + schemaType.getLocalPart()));
240             }
241             else
242             {
243                 element.addAttribute(new Attribute("ref",  prefix + ":" + schemaType.getLocalPart()));
244             }
245 
246             element.addAttribute(new Attribute("minOccurs", "1"));
247             element.addAttribute(new Attribute("maxOccurs", "1"));
248         }
249     }
250 
251     private Element createSequence(Element complex)
252     {
253         Element sequence = new Element(AbstractWSDL.sequenceQ, SoapConstants.XSD);
254         complex.appendChild(sequence);
255         return sequence;
256     }
257 
258     public Object clone()
259     {
260         WrappedBinding binding = new WrappedBinding();
261         binding.setBindingProvider(getBindingProvider());
262         
263         return binding;
264     }    
265 }