001: /*
002: * Copyright (c) 1998-2007 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Emil Ong
028: */
029:
030: package com.caucho.soap.skeleton;
031:
032: import com.caucho.jaxb.JAXBContextImpl;
033: import com.caucho.jaxb.JAXBUtil;
034: import static com.caucho.soap.wsdl.WSDLConstants.*;
035: import com.caucho.soap.wsdl.WSDLDefinitions;
036:
037: import com.caucho.util.L10N;
038:
039: import com.caucho.xml.stream.StaxUtil;
040:
041: import static javax.xml.XMLConstants.*;
042: import javax.xml.bind.JAXBException;
043: import javax.xml.bind.Marshaller;
044: import javax.xml.bind.Unmarshaller;
045: import javax.xml.namespace.QName;
046: import javax.xml.stream.XMLStreamException;
047: import javax.xml.stream.XMLStreamReader;
048: import javax.xml.stream.XMLStreamWriter;
049: import javax.xml.ws.Holder;
050: import javax.xml.ws.WebServiceException;
051: import java.io.IOException;
052: import java.lang.annotation.Annotation;
053: import java.lang.reflect.Method;
054: import java.lang.reflect.Type;
055: import java.util.ArrayList;
056: import java.util.HashMap;
057: import java.util.Map;
058: import java.util.logging.Logger;
059:
060: /**
061: * Document wrapped action
062: */
063: public class DocumentWrappedAction extends AbstractAction {
064: private final static Logger log = Logger
065: .getLogger(DocumentWrappedAction.class.getName());
066: public static final L10N L = new L10N(DocumentWrappedAction.class);
067:
068: /*
069: * Document wrapped arguments are in an xsd:sequence -- in other words,
070: * there is a prescribed order in which the arguments are expected to be
071: * given. (Any arguments from the header are excepted; headers are
072: * key/value pairs.)
073: *
074: */
075:
076: public DocumentWrappedAction(Method method, Method eiMethod,
077: JAXBContextImpl jaxbContext, String targetNamespace,
078: WSDLDefinitions wsdl, Marshaller marshaller,
079: Unmarshaller unmarshaller) throws JAXBException,
080: WebServiceException {
081: super (method, eiMethod, jaxbContext, targetNamespace, wsdl,
082: marshaller, unmarshaller);
083: }
084:
085: protected void writeMethodInvocation(XMLStreamWriter out,
086: Object[] args) throws IOException, XMLStreamException,
087: JAXBException {
088: out.writeStartElement(TARGET_NAMESPACE_PREFIX, _operationName,
089: _targetNamespace);
090: out.writeNamespace(TARGET_NAMESPACE_PREFIX, _targetNamespace);
091:
092: for (int i = 0; i < _bodyArgs.length; i++)
093: _bodyArgs[i].serializeCall(out, args);
094:
095: out.writeEndElement(); // name
096: }
097:
098: protected Object[] readMethodInvocation(XMLStreamReader header,
099: XMLStreamReader in) throws IOException, XMLStreamException,
100: JAXBException {
101: Object[] args = new Object[_arity];
102:
103: readHeaders(header, args);
104:
105: // skip the method name
106: in.nextTag();
107:
108: // document wrapped => everything must be in order
109: for (int i = 0; i < _bodyArgs.length; i++) {
110: _bodyArgs[i].prepareArgument(args);
111:
112: // services/1234:
113: // don't loop when an OutParameter is incorrectly specified
114: if (!(_bodyArgs[i] instanceof OutParameterMarshal)) {
115: // while loop for arrays/lists
116: while (in.getEventType() == in.START_ELEMENT
117: && _bodyArgs[i].getName().equals(in.getName()))
118: _bodyArgs[i].deserializeCall(in, args);
119: }
120: }
121:
122: // skip the method name close tag
123: in.nextTag();
124:
125: return args;
126: }
127:
128: protected void writeResponse(XMLStreamWriter out, Object value,
129: Object[] args) throws IOException, XMLStreamException,
130: JAXBException {
131: out.writeStartElement(TARGET_NAMESPACE_PREFIX, _responseName,
132: _targetNamespace);
133: out.writeNamespace(TARGET_NAMESPACE_PREFIX, _targetNamespace);
134:
135: if (_returnMarshal != null && !_headerReturn)
136: _returnMarshal.serializeReply(out, value);
137:
138: for (int i = 0; i < _bodyArgs.length; i++)
139: _bodyArgs[i].serializeReply(out, args);
140:
141: out.writeEndElement(); // response name
142: }
143:
144: protected Object readResponse(XMLStreamReader in, Object[] args)
145: throws IOException, XMLStreamException, JAXBException,
146: Throwable {
147: Object ret = null;
148:
149: in.nextTag();
150: in.require(XMLStreamReader.START_ELEMENT, null, "Envelope");
151:
152: in.nextTag();
153: in.require(XMLStreamReader.START_ELEMENT, null, null);
154:
155: if ("Header".equals(in.getLocalName())) {
156: in.nextTag();
157:
158: while (in.getEventType() == XMLStreamReader.START_ELEMENT) {
159: String tagName = in.getLocalName();
160:
161: ParameterMarshal marshal = _headerArguments
162: .get(tagName);
163:
164: if (marshal != null)
165: marshal.deserializeReply(in, args);
166: else {
167: int depth = 1;
168:
169: while (depth > 0) {
170: switch (in.nextTag()) {
171: case XMLStreamReader.START_ELEMENT:
172: depth++;
173: break;
174: case XMLStreamReader.END_ELEMENT:
175: depth--;
176: break;
177: default:
178: throw new IOException("expected </Header>");
179: }
180: }
181: }
182: }
183:
184: in.require(XMLStreamReader.END_ELEMENT, null, "Header");
185:
186: in.nextTag();
187: }
188:
189: in.require(XMLStreamReader.START_ELEMENT, null, "Body");
190:
191: in.nextTag();
192:
193: if (in.getEventType() == XMLStreamReader.START_ELEMENT
194: && "Fault".equals(in.getLocalName())) {
195: Throwable fault = readFault(in);
196:
197: if (fault == null)
198: throw new WebServiceException(); // XXX
199:
200: throw fault;
201: }
202:
203: in.require(XMLStreamReader.START_ELEMENT, null, _responseName);
204:
205: in.nextTag();
206:
207: if (_returnMarshal != null) {
208: // while loop for arrays/lists
209: while (in.getEventType() == in.START_ELEMENT
210: && _returnMarshal.getName().equals(in.getName())) {
211: ret = _returnMarshal.deserializeReply(in, ret);
212: }
213: }
214:
215: // document wrapped => everything must be in order
216: for (int i = 0; i < _bodyArgs.length; i++) {
217: // while loop for arrays/lists
218: while (in.getEventType() == in.START_ELEMENT
219: && _bodyArgs[i].getName().equals(in.getName()))
220: _bodyArgs[i].deserializeReply(in, args);
221: }
222:
223: in.require(XMLStreamReader.END_ELEMENT, null, _responseName);
224:
225: in.nextTag();
226: in.require(XMLStreamReader.END_ELEMENT, null, "Body");
227:
228: in.nextTag();
229: in.require(XMLStreamReader.END_ELEMENT, null, "Envelope");
230:
231: return ret;
232: }
233:
234: public void writeWSDLMessages(XMLStreamWriter out,
235: String soapNamespaceURI) throws XMLStreamException {
236: out.writeStartElement(WSDL_NAMESPACE, "message");
237: out.writeAttribute("name", _operationName);
238:
239: out.writeEmptyElement(WSDL_NAMESPACE, "part");
240: out.writeAttribute("name", "parameters"); // XXX partName?
241: out.writeAttribute("element", TARGET_NAMESPACE_PREFIX + ':'
242: + _operationName);
243:
244: out.writeEndElement(); // message
245:
246: if (!_isOneway) {
247: out.writeStartElement(WSDL_NAMESPACE, "message");
248: out.writeAttribute("name", _responseName);
249:
250: out.writeEmptyElement(WSDL_NAMESPACE, "part");
251: out.writeAttribute("name", "parameters"); // XXX partName?
252: out.writeAttribute("element", TARGET_NAMESPACE_PREFIX + ':'
253: + _responseName);
254:
255: out.writeEndElement(); // message
256: }
257: }
258:
259: public void writeWSDLBindingOperation(XMLStreamWriter out,
260: String soapNamespaceURI) throws XMLStreamException {
261: out.writeStartElement(WSDL_NAMESPACE, "operation");
262: out.writeAttribute("name", _operationName);
263: // XXX out.writeAttribute("parameterOrder", "");
264:
265: out.writeEmptyElement(soapNamespaceURI, "operation");
266: out.writeAttribute("soapAction", _soapAction);
267:
268: out.writeStartElement(WSDL_NAMESPACE, "input");
269: // XXX
270: out.writeEmptyElement(soapNamespaceURI, "body");
271: out.writeAttribute("use", "literal");
272:
273: out.writeEndElement(); // input
274:
275: if (!_isOneway) {
276: out.writeStartElement(WSDL_NAMESPACE, "output");
277: // XXX
278: out.writeEmptyElement(soapNamespaceURI, "body");
279: out.writeAttribute("use", "literal");
280:
281: out.writeEndElement(); // output
282: }
283:
284: out.writeEndElement(); // operation
285: }
286:
287: public void writeSchema(XMLStreamWriter out, String namespace,
288: JAXBContextImpl context) throws XMLStreamException,
289: WebServiceException {
290: QName qname = new QName(namespace, _operationName);
291:
292: if (context.hasRootElement(qname))
293: throw new WebServiceException(
294: L
295: .l(
296: "Duplicate element {0} (This method's name conflicts with an XML root element name)",
297: qname));
298:
299: if (context.hasXmlType(qname))
300: throw new WebServiceException(
301: L
302: .l(
303: "Duplicate type {0} (This method's name conflicts with the XML type name of a class)",
304: qname));
305:
306: // XXX header arguments
307:
308: out.writeEmptyElement(XML_SCHEMA_PREFIX, "element",
309: W3C_XML_SCHEMA_NS_URI);
310: out.writeAttribute("name", _operationName);
311: out.writeAttribute("type", TARGET_NAMESPACE_PREFIX + ':'
312: + _operationName);
313:
314: if (_bodyInputs + _headerInputs == 0) {
315: out.writeEmptyElement(XML_SCHEMA_PREFIX, "complexType",
316: W3C_XML_SCHEMA_NS_URI);
317: out.writeAttribute("name", _operationName);
318: } else {
319: out.writeStartElement(XML_SCHEMA_PREFIX, "complexType",
320: W3C_XML_SCHEMA_NS_URI);
321: out.writeAttribute("name", _operationName);
322:
323: out.writeStartElement(XML_SCHEMA_PREFIX, "sequence",
324: W3C_XML_SCHEMA_NS_URI);
325:
326: for (ParameterMarshal param : _bodyArguments.values()) {
327: if (!(param instanceof OutParameterMarshal))
328: param.writeElement(out);
329: }
330:
331: out.writeEndElement(); // sequence
332:
333: out.writeEndElement(); // complexType
334: }
335:
336: if (!_isOneway) {
337: QName responseQName = new QName(namespace, _operationName);
338:
339: if (context.hasRootElement(responseQName))
340: throw new WebServiceException(
341: L
342: .l(
343: "Duplicate element {0} (This method's name conflicts with an XML root element name)",
344: responseQName));
345:
346: if (context.hasXmlType(responseQName))
347: throw new WebServiceException(
348: L
349: .l(
350: "Duplicate type {0} (This method's name conflicts with the XML type name of a class)",
351: responseQName));
352:
353: out.writeEmptyElement(XML_SCHEMA_PREFIX, "element",
354: W3C_XML_SCHEMA_NS_URI);
355: out.writeAttribute("name", _responseName);
356: out.writeAttribute("type", TARGET_NAMESPACE_PREFIX + ':'
357: + _responseName);
358:
359: if (_bodyOutputs + _headerOutputs == 0) {
360: out.writeEmptyElement(XML_SCHEMA_PREFIX, "complexType",
361: W3C_XML_SCHEMA_NS_URI);
362: out.writeAttribute("name", _responseName);
363: } else {
364: out.writeStartElement(XML_SCHEMA_PREFIX, "complexType",
365: W3C_XML_SCHEMA_NS_URI);
366: out.writeAttribute("name", _responseName);
367:
368: out.writeStartElement(XML_SCHEMA_PREFIX, "sequence",
369: W3C_XML_SCHEMA_NS_URI);
370:
371: if (_returnMarshal != null)
372: _returnMarshal.writeElement(out);
373:
374: for (ParameterMarshal param : _bodyArguments.values()) {
375: if (!(param instanceof InParameterMarshal))
376: param.writeElement(out);
377: }
378:
379: out.writeEndElement(); // sequence
380:
381: out.writeEndElement(); // complexType
382: }
383: }
384: }
385:
386: public void writeWSDLOperation(XMLStreamWriter out,
387: String soapNamespaceURI) throws XMLStreamException {
388: out.writeStartElement(WSDL_NAMESPACE, "operation");
389: out.writeAttribute("name", _operationName);
390: // XXX out.writeAttribute("parameterOrder", "");
391:
392: out.writeEmptyElement(WSDL_NAMESPACE, "input");
393: out.writeAttribute("message", TARGET_NAMESPACE_PREFIX + ':'
394: + _operationName);
395:
396: if (!_isOneway) {
397: out.writeEmptyElement(WSDL_NAMESPACE, "output");
398: out.writeAttribute("message", TARGET_NAMESPACE_PREFIX + ':'
399: + _responseName);
400: }
401:
402: out.writeEndElement(); // operation
403: }
404:
405: public String toString() {
406: return "DocumentWrappedAction[" + _method.getName() + "]";
407: }
408: }
|