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.STAXUtils;
26  import org.codehaus.xfire.util.stax.DepthXMLStreamReader;
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 element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
190 
191         element.addAttribute(new Attribute("name", opName));
192 
193         Element complex = new Element(AbstractWSDL.complexQ, SoapConstants.XSD);
194         element.appendChild(complex);
195 
196         if (message.getMessageParts().size() > 0)
197         {
198             Element sequence = createSequence(complex);
199 
200             writeParametersSchema(builder, message.getMessageParts(), sequence);
201         }
202 
203         Element schemaEl = builder.createSchemaType(builder.getInfo().getTargetNamespace());
204         schemaEl.appendChild(element);
205         
206         return new QName(builder.getInfo().getTargetNamespace(), opName);
207     }
208 
209     /***
210      * @param op
211      * @param sequence
212      */
213     private void writeParametersSchema(WSDLBuilder builder,
214                                        Collection params, 
215                                        Element sequence)
216     {
217         for (Iterator itr = params.iterator(); itr.hasNext();)
218         {
219             MessagePartInfo param = (MessagePartInfo) itr.next();
220 
221             QName pName = param.getName();
222             SchemaType type = param.getSchemaType();
223 
224             builder.addDependency(type);
225             QName schemaType = type.getSchemaType();
226 
227             builder.addNamespaceImport(builder.getService().getServiceInfo().getName().getNamespaceURI(), 
228                                        schemaType.getNamespaceURI());
229             
230             String uri = type.getSchemaType().getNamespaceURI();
231             String prefix = builder.getNamespacePrefix(uri);
232             builder.addNamespace(prefix, uri);
233 
234             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
235             sequence.appendChild(element);
236 
237             if (type.isAbstract())
238             {
239                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
240                 
241                 element.addAttribute(new Attribute("type", 
242                                                    prefix + ":" + schemaType.getLocalPart()));
243             }
244             else
245             {
246                 element.addAttribute(new Attribute("ref",  prefix + ":" + schemaType.getLocalPart()));
247             }
248 
249             element.addAttribute(new Attribute("minOccurs", "1"));
250             element.addAttribute(new Attribute("maxOccurs", "1"));
251         }
252     }
253 
254     private Element createSequence(Element complex)
255     {
256         Element sequence = new Element(AbstractWSDL.sequenceQ, SoapConstants.XSD);
257         complex.appendChild(sequence);
258         return sequence;
259     }
260 
261     public Object clone()
262     {
263         WrappedBinding binding = new WrappedBinding();
264         binding.setBindingProvider(getBindingProvider());
265         
266         return binding;
267     }    
268 }