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
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
171 Part part = builder.getDefinition().createPart();
172
173
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 }