public XmlDocument wrapBodyContent(XmlElement bodyContent) throws XsulException { if (bodyContent == null) { return null; } if (bodyContent.getParent() != null) { XmlContainer top = bodyContent.getRoot(); if (top instanceof XmlDocument) { return (XmlDocument) top; } } XmlDocument doc = builder.newDocument(); final XmlNamespace soapNs = builder.newNamespace("S", NS_URI_SOAP11); XmlElement envelope = doc.addDocumentElement(soapNs, ELEM_ENVELOPE); envelope.declareNamespace(soapNs); // declare prefixes for some common namespaces envelope.declareNamespace(XmlConstants.XS_NS); envelope.declareNamespace(XmlConstants.XSI_NS); XmlElement body = envelope.addElement(soapNs, "Body"); body.addElement(bodyContent); return doc; }
/** * Tests simple interaction with WS-MsgBox. * * @version $Revision: 1.6 $ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> */ public class AddOneService extends SoapHttpDynamicInfosetProcessor { private static final MLogger logger = MLogger.getLogger(); private static final XmlInfosetBuilder builder = XmlConstants.BUILDER; static final String MESSAGE_URI = "http://example.com/AddOne"; private static final XmlNamespace MESSAGE_URI_NS = builder.newNamespace(MESSAGE_URI); public static void main(String[] args) {} public AddOneService() {} public XmlDocument processSoapEnvelope(XmlElement envelope, final SoapUtil soapFragrance) { // concert envelope to String // System.err.println(getClass().getName()+" received envelope=" // +builder.serializeToString(envelope)); logger.finest("received envelope=" + builder.serializeToString(envelope)); // this XML string could be convertedto DOM ot whatever API one preferes (like JDOM, DOM4J, ...) // XmlElement soapHeader = envelope.element(null, XmlConstants.S_HEADER_EL); // if(soapHeader == null) { // throw new XsulException("SOAP message must have headers"); // } final WsaMessageInformationHeaders wsah = new WsaMessageInformationHeaders(envelope); // System.err.println(getClass().getName()+" message destinaiton="+wsah.getTo()); String location = getServer().getLocation(); // assertEquals(location, wsah.getTo().toString()); if (!location.equals(wsah.getTo().toString())) { throw new IllegalStateException(); } final XmlElement message = soapFragrance.requiredBodyContent(envelope); final XmlElement responseMessage = processMessage(message); // TODO: fire new thread to send response if replyTo is to not use current HTTP connection if (wsah.getReplyTo() != null) { // if(wsah.getReplyTo().getAddress().equals(WsAddressing.URI_ROLE_ANONYMOUS)) { if (false == WsaUtil.isAsyncReplyRequired(envelope)) { // to send back response wrapped in SOAP envelope return soapFragrance.wrapBodyContent(responseMessage); } else { Runnable r = new Runnable() { public void run() { try { XmlDocument responseEnvelope = soapFragrance.wrapBodyContent(responseMessage); // now we need to add all WSA headers etc ... WsaMessageInformationHeaders responseHeaders = new WsaMessageInformationHeaders(responseEnvelope); responseHeaders.explodeEndpointReference(wsah.getReplyTo()); URI messageId = wsah.getMessageId(); if (messageId != null) { responseHeaders.addRelatesTo(new WsaRelatesTo(wsah.getMessageId())); } WsaInvoker invoker = new WsaInvoker(); invoker.setDefaultAction(URI.create(MESSAGE_URI + "Response")); invoker.sendXml(responseEnvelope); } catch (Exception e) { logger.finest("could not send response to " + wsah.getReplyTo(), e); } } }; // LATER: use Executor new Thread(r).start(); // no response sent - actual response will be sent later over new connection return null; } } else { // no response needed return null; } } public XmlElement processMessage(XmlElement message) { // System.err.println(getClass().getName()+ logger.finest("received message " + builder.serializeToString(message)); final XmlElement response; // send no repsonse - one way try { response = (XmlElement) message.clone(); } catch (CloneNotSupportedException e) { throw new XsulException("internal error", e); } int value = Integer.parseInt(message.requiredTextContent()); response.setName(message.getName() + "Response"); response.replaceChildrenWithText(Integer.toString(value + 1)); return response; } }
/** * SOAP 1.1 envelope manipulations utility methods. * * @version $Revision: 1.14 $ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a> */ public class Soap11Util extends SoapUtil { private static final XmlInfosetBuilder builder = XmlConstants.BUILDER; public static final String SOAP11_ENC_PREFIX = "SOAP-ENC"; public static final String NS_URI_SOAP11 = XmlConstants.NS_URI_SOAP11; public static final String SOAP11_NEXT_ACTOR = "http://schemas.xmlsoap.org/soap/actor/next"; public static final XmlNamespace SOAP11_NS = XmlConstants.SOAP11_NS; public static final XmlNamespace SOAP11_ENC_NS = builder.newNamespace(SOAP11_ENC_PREFIX, "http://schemas.xmlsoap.org/soap/encoding/"); public static final String ELEM_ENVELOPE = XmlConstants.S_ENVELOPE; public static final String ELEM_HEADER = XmlConstants.S_HEADER; public static final String ELEM_BODY = XmlConstants.S_BODY; public static final String ATTR_MUST_UNDERSTAND = "mustUnderstand"; public static final String ATTR_ACTOR = "actor"; public static final String ATTR_ROLE = "role"; private static final Soap11Util instance = new Soap11Util(); Soap11Util() {} public static Soap11Util getInstance() { return instance; } public String getSoapVersion() { return "1.1"; } public boolean isSoapEnvelopeSupported(XmlElement root) { if (NS_URI_SOAP11.equals(root.getNamespace().getNamespaceName()) && ELEM_ENVELOPE.equals(root.getName())) { return true; } else { return false; } } public XmlDocument wrapBodyContent(XmlElement bodyContent) throws XsulException { if (bodyContent == null) { return null; } if (bodyContent.getParent() != null) { XmlContainer top = bodyContent.getRoot(); if (top instanceof XmlDocument) { return (XmlDocument) top; } } XmlDocument doc = builder.newDocument(); final XmlNamespace soapNs = builder.newNamespace("S", NS_URI_SOAP11); XmlElement envelope = doc.addDocumentElement(soapNs, ELEM_ENVELOPE); envelope.declareNamespace(soapNs); // declare prefixes for some common namespaces envelope.declareNamespace(XmlConstants.XS_NS); envelope.declareNamespace(XmlConstants.XSI_NS); XmlElement body = envelope.addElement(soapNs, "Body"); body.addElement(bodyContent); return doc; } public XmlElement generateSoapFault( XmlNamespace faultCodeValueNs, String faultCodeValueName, String reasonTextEnglish, Throwable ex) throws XsulException { XmlElement faultEl = builder.newFragment(SOAP11_NS, "Fault"); if (!NS_URI_SOAP11.equals(faultCodeValueNs.getNamespaceName())) { faultEl.declareNamespace("n", faultCodeValueNs.getNamespaceName()); } XmlElement faultCodeEl = faultEl.addElement("faultcode"); faultCodeEl.addChild( new QNameElText(faultCodeEl, faultCodeValueNs.getNamespaceName(), faultCodeValueName)); if (reasonTextEnglish == null) reasonTextEnglish = "{null}"; faultEl.addElement("faultstring").addChild(reasonTextEnglish); XmlElement detail = faultEl.addElement("detail"); if (ex != null) { final XmlNamespace axisNs = faultEl.newNamespace("n", "http://xml.apache.org/axis/"); String msg = ex.getMessage(); if (msg != null) { XmlElement exName = detail.addElement(axisNs, "exceptionName"); exName.declareNamespace(axisNs); exName.addChild(msg); } XmlElement stackTrace = detail.addElement(axisNs, "stackTrace"); stackTrace.declareNamespace(axisNs); StringWriter sw = new StringWriter(); ex.printStackTrace(new PrintWriter(sw)); stackTrace.addChild(sw.toString()); } return faultEl; // XmlDocument envelope = wrapBodyContent(faultEl); // // resolve prefix to use in fault code (it MUST be done after SOAP:Envelope is // constructed! // XmlNamespace ns = faultCodeEl.lookupNamespaceByName(faultCodeNs); // if(ns == null || ns.getPrefix() == null) { // // declare prefix if does nto exist // final XmlNamespace faultNs = builder.newNamespace("ns", faultCodeNs); // ns = faultCodeEl.declareNamespace(faultNs); // } // String faultcode = ns.getPrefix() + ':' + faultCodeName; // faultCodeEl.addChild(faultcode); // return envelope; } public XmlElement generateSoapClientFault(String reasonTextEnglish, Throwable ex) throws XsulException { return generateSoapFault(SOAP11_NS, "Client", reasonTextEnglish, ex); } public XmlElement generateSoapServerFault(String reasonTextEnglish, Throwable ex) throws XsulException { return generateSoapFault(SOAP11_NS, "Server", reasonTextEnglish, ex); } public XmlElement requiredBodyContent(XmlDocument respDoc) throws XsulException { // check if response has Envelope/Body XmlElement root = respDoc.getDocumentElement(); return requiredBodyContent(root); } public XmlElement requiredBodyContent(XmlElement root) throws XsulException { if (!NS_URI_SOAP11.equals(root.getNamespaceName())) { throw new XsulException("expected SOAP 1.1 Envelope not " + root); } if (!ELEM_ENVELOPE.equals(root.getName())) { throw new XsulException( "expected top level SOAP 1.1 element name to be Envelope not " + root); } XmlElement body = root.findElementByName(NS_URI_SOAP11, "Body"); if (body == null) { throw new XsulException("missing required Body element in SOAP 1.1 Envelope" + root); } // TODO get first non ignorable child element // add XPath to make it easier if (!body.hasChildren()) { throw new XsulException( "SOAP message must have body " // FIXME //TODO //ALEK throw new SoapClientFault + "- got " + XsulUtil.safeXmlToString(root)); } XmlElement content = (XmlElement) body.requiredElementContent().iterator().next(); return content; } // public XmlElement findBodyContent(XmlElement message, boolean rpc) { // Util.removeIgnorableSpace(message); // // if (NS_URI_SOAP11.equals(message.getNamespace().getNamespaceName())) { // if ("Envelope".equals(message.getName())) { // XmlElement envelope = message; // // XmlElement body = envelope.findElementByName(NS_URI_SOAP11, "Body"); // // if (body != null) { // XmlElement payload = (XmlElement) body.children().next(); // if (rpc) { // return (XmlElement) payload.children().next(); // } // return payload; // } else // //todo: process faults nicely // return envelope; // } // } // // return message; // } // /** // * Wrap XML message (this should be XmlElement correspondingto WSDL 1.1 message with parts) // * inside SOAP 1.1 Body and return whole SOAP 1.1 Envelope as XML document. // * If operation name is not null RPC style is assumend and message is element // * name is changed to operationName (and provided namespace if notn null). // * If operation name is null the first message child is extracted and put directly // * into SOAP Bpody elment. In this case if message must have exactly onechild // * or exception is thrown. // */ // public XmlDocument wrapMessageContent(XmlElement message, // String operationNamespace, // String operationName) // throws XsulException // { // try { // if (operationName != null) { // //logger.info("adding rpc style operation name and namespace"); // message.setName(operationName); //operation.getLocalPart()); // //String operationNamespace = operation.getNamespaceURI(); // //XmlNamespace ns = null; // //if (!("".equals(operationNamespace))) { // // ns = message.lookupNamespaceByName(operationNamespace); // // ns = message.declareNamespace("ns0", operationNamespace); // //} // // //deep-set of ns // //setNs(message, null); // if(operationNamespace != null) { // message.setNamespace(message.newNamespace(operationNamespace)); // } // //result = message; // } else { // // extract the ony one parameter as described in doc/lit binding // Iterator c = message.children(); // Object child = c.next(); // if(c.hasNext()) { // throw new IllegalArgumentException("expected only one part in message for // doc/lit"); // } // if(child instanceof XmlElement) { // message = (XmlElement) child; // message.setParent(null); // } else { // throw new IllegalArgumentException( // "illegal state: message part expected to be element not "+child); // } // } // // XmlDocument envelope = wrapBodyContent(message); // return envelope; // //return wrapBodyContent(message); // } catch(XmlBuilderException e) { // throw new XsulException("could not create SOAP 1.1 envelope", e); // } // } // }