/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Emil Ong */ package com.caucho.soap.skeleton; import com.caucho.jaxb.JAXBContextImpl; import com.caucho.jaxb.JAXBUtil; import static com.caucho.soap.wsdl.WSDLConstants.*; import com.caucho.soap.wsdl.WSDLDefinitions; import com.caucho.util.L10N; import com.caucho.xml.stream.StaxUtil; import static javax.xml.XMLConstants.*; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.ws.Holder; import javax.xml.ws.WebServiceException; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; /** * Document wrapped action */ public class DocumentWrappedAction extends AbstractAction { private final static Logger log = Logger.getLogger(DocumentWrappedAction.class.getName()); public static final L10N L = new L10N(DocumentWrappedAction.class); /* * Document wrapped arguments are in an xsd:sequence -- in other words, * there is a prescribed order in which the arguments are expected to be * given. (Any arguments from the header are excepted; headers are * key/value pairs.) * */ public DocumentWrappedAction(Method method, Method eiMethod, JAXBContextImpl jaxbContext, String targetNamespace, WSDLDefinitions wsdl, Marshaller marshaller, Unmarshaller unmarshaller) throws JAXBException, WebServiceException { super(method, eiMethod, jaxbContext, targetNamespace, wsdl, marshaller, unmarshaller); } protected void writeMethodInvocation(XMLStreamWriter out, Object []args) throws IOException, XMLStreamException, JAXBException { out.writeStartElement(TARGET_NAMESPACE_PREFIX, _operationName, _targetNamespace); out.writeNamespace(TARGET_NAMESPACE_PREFIX, _targetNamespace); for (int i = 0; i < _bodyArgs.length; i++) _bodyArgs[i].serializeCall(out, args); out.writeEndElement(); // name } protected Object[] readMethodInvocation(XMLStreamReader header, XMLStreamReader in) throws IOException, XMLStreamException, JAXBException { Object[] args = new Object[_arity]; readHeaders(header, args); // skip the method name in.nextTag(); // document wrapped => everything must be in order for (int i = 0; i < _bodyArgs.length; i++) { _bodyArgs[i].prepareArgument(args); // services/1234: // don't loop when an OutParameter is incorrectly specified if (! (_bodyArgs[i] instanceof OutParameterMarshal)) { // while loop for arrays/lists while (in.getEventType() == in.START_ELEMENT && _bodyArgs[i].getName().equals(in.getName())) _bodyArgs[i].deserializeCall(in, args); } } // skip the method name close tag in.nextTag(); return args; } protected void writeResponse(XMLStreamWriter out, Object value, Object[] args) throws IOException, XMLStreamException, JAXBException { out.writeStartElement(TARGET_NAMESPACE_PREFIX, _responseName, _targetNamespace); out.writeNamespace(TARGET_NAMESPACE_PREFIX, _targetNamespace); if (_returnMarshal != null && ! _headerReturn) _returnMarshal.serializeReply(out, value); for (int i = 0; i < _bodyArgs.length; i++) _bodyArgs[i].serializeReply(out, args); out.writeEndElement(); // response name } protected Object readResponse(XMLStreamReader in, Object []args) throws IOException, XMLStreamException, JAXBException, Throwable { Object ret = null; in.nextTag(); in.require(XMLStreamReader.START_ELEMENT, null, "Envelope"); in.nextTag(); in.require(XMLStreamReader.START_ELEMENT, null, null); if ("Header".equals(in.getLocalName())) { in.nextTag(); while (in.getEventType() == XMLStreamReader.START_ELEMENT) { String tagName = in.getLocalName(); ParameterMarshal marshal = _headerArguments.get(tagName); if (marshal != null) marshal.deserializeReply(in, args); else { int depth = 1; while (depth > 0) { switch (in.nextTag()) { case XMLStreamReader.START_ELEMENT: depth++; break; case XMLStreamReader.END_ELEMENT: depth--; break; default: throw new IOException("expected </Header>"); } } } } in.require(XMLStreamReader.END_ELEMENT, null, "Header"); in.nextTag(); } in.require(XMLStreamReader.START_ELEMENT, null, "Body"); in.nextTag(); if (in.getEventType() == XMLStreamReader.START_ELEMENT && "Fault".equals(in.getLocalName())) { Throwable fault = readFault(in); if (fault == null) throw new WebServiceException(); // XXX throw fault; } in.require(XMLStreamReader.START_ELEMENT, null, _responseName); in.nextTag(); if (_returnMarshal != null) { // while loop for arrays/lists while (in.getEventType() == in.START_ELEMENT && _returnMarshal.getName().equals(in.getName())) { ret = _returnMarshal.deserializeReply(in, ret); } } // document wrapped => everything must be in order for (int i = 0; i < _bodyArgs.length; i++) { // while loop for arrays/lists while (in.getEventType() == in.START_ELEMENT && _bodyArgs[i].getName().equals(in.getName())) _bodyArgs[i].deserializeReply(in, args); } in.require(XMLStreamReader.END_ELEMENT, null, _responseName); in.nextTag(); in.require(XMLStreamReader.END_ELEMENT, null, "Body"); in.nextTag(); in.require(XMLStreamReader.END_ELEMENT, null, "Envelope"); return ret; } public void writeWSDLMessages(XMLStreamWriter out, String soapNamespaceURI) throws XMLStreamException { out.writeStartElement(WSDL_NAMESPACE, "message"); out.writeAttribute("name", _operationName); out.writeEmptyElement(WSDL_NAMESPACE, "part"); out.writeAttribute("name", "parameters"); // XXX partName? out.writeAttribute("element", TARGET_NAMESPACE_PREFIX + ':' + _operationName); out.writeEndElement(); // message if (! _isOneway) { out.writeStartElement(WSDL_NAMESPACE, "message"); out.writeAttribute("name", _responseName); out.writeEmptyElement(WSDL_NAMESPACE, "part"); out.writeAttribute("name", "parameters"); // XXX partName? out.writeAttribute("element", TARGET_NAMESPACE_PREFIX + ':' + _responseName); out.writeEndElement(); // message } } public void writeWSDLBindingOperation(XMLStreamWriter out, String soapNamespaceURI) throws XMLStreamException { out.writeStartElement(WSDL_NAMESPACE, "operation"); out.writeAttribute("name", _operationName); // XXX out.writeAttribute("parameterOrder", ""); out.writeEmptyElement(soapNamespaceURI, "operation"); out.writeAttribute("soapAction", _soapAction); out.writeStartElement(WSDL_NAMESPACE, "input"); // XXX out.writeEmptyElement(soapNamespaceURI, "body"); out.writeAttribute("use", "literal"); out.writeEndElement(); // input if (! _isOneway) { out.writeStartElement(WSDL_NAMESPACE, "output"); // XXX out.writeEmptyElement(soapNamespaceURI, "body"); out.writeAttribute("use", "literal"); out.writeEndElement(); // output } out.writeEndElement(); // operation } public void writeSchema(XMLStreamWriter out, String namespace, JAXBContextImpl context) throws XMLStreamException, WebServiceException { QName qname = new QName(namespace, _operationName); if (context.hasRootElement(qname)) throw new WebServiceException(L.l("Duplicate element {0} (This method's name conflicts with an XML root element name)", qname)); if (context.hasXmlType(qname)) throw new WebServiceException(L.l("Duplicate type {0} (This method's name conflicts with the XML type name of a class)", qname)); // XXX header arguments out.writeEmptyElement(XML_SCHEMA_PREFIX, "element", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _operationName); out.writeAttribute("type", TARGET_NAMESPACE_PREFIX + ':' + _operationName); if (_bodyInputs + _headerInputs == 0) { out.writeEmptyElement(XML_SCHEMA_PREFIX, "complexType", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _operationName); } else { out.writeStartElement(XML_SCHEMA_PREFIX, "complexType", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _operationName); out.writeStartElement(XML_SCHEMA_PREFIX, "sequence", W3C_XML_SCHEMA_NS_URI); for (ParameterMarshal param : _bodyArguments.values()) { if (! (param instanceof OutParameterMarshal)) param.writeElement(out); } out.writeEndElement(); // sequence out.writeEndElement(); // complexType } if (! _isOneway) { QName responseQName = new QName(namespace, _operationName); if (context.hasRootElement(responseQName)) throw new WebServiceException(L.l("Duplicate element {0} (This method's name conflicts with an XML root element name)", responseQName)); if (context.hasXmlType(responseQName)) throw new WebServiceException(L.l("Duplicate type {0} (This method's name conflicts with the XML type name of a class)", responseQName)); out.writeEmptyElement(XML_SCHEMA_PREFIX, "element", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _responseName); out.writeAttribute("type", TARGET_NAMESPACE_PREFIX + ':' + _responseName); if (_bodyOutputs + _headerOutputs == 0) { out.writeEmptyElement(XML_SCHEMA_PREFIX, "complexType", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _responseName); } else { out.writeStartElement(XML_SCHEMA_PREFIX, "complexType", W3C_XML_SCHEMA_NS_URI); out.writeAttribute("name", _responseName); out.writeStartElement(XML_SCHEMA_PREFIX, "sequence", W3C_XML_SCHEMA_NS_URI); if (_returnMarshal != null) _returnMarshal.writeElement(out); for (ParameterMarshal param : _bodyArguments.values()) { if (! (param instanceof InParameterMarshal)) param.writeElement(out); } out.writeEndElement(); // sequence out.writeEndElement(); // complexType } } } public void writeWSDLOperation(XMLStreamWriter out, String soapNamespaceURI) throws XMLStreamException { out.writeStartElement(WSDL_NAMESPACE, "operation"); out.writeAttribute("name", _operationName); // XXX out.writeAttribute("parameterOrder", ""); out.writeEmptyElement(WSDL_NAMESPACE, "input"); out.writeAttribute("message", TARGET_NAMESPACE_PREFIX + ':' + _operationName); if (! _isOneway) { out.writeEmptyElement(WSDL_NAMESPACE, "output"); out.writeAttribute("message", TARGET_NAMESPACE_PREFIX + ':' + _responseName); } out.writeEndElement(); // operation } public String toString() { return "DocumentWrappedAction[" + _method.getName() + "]"; } }