/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.jbi.serviceengine.comm;
import com.sun.enterprise.jbi.serviceengine.core.JavaEEServiceEngineContext;
import com.sun.enterprise.jbi.serviceengine.util.DOMUtil;
import com.sun.enterprise.jbi.serviceengine.util.JBIConstants;
import com.sun.enterprise.jbi.serviceengine.util.DOMStreamReader;
import com.sun.enterprise.jbi.serviceengine.util.soap.SOAPConstants;
import com.sun.enterprise.jbi.serviceengine.util.soap.StringTranslator;
import com.sun.logging.LogDomains;
import com.sun.xml.bind.api.Bridge;
import com.sun.xml.ws.api.message.HeaderList;
import com.sun.xml.ws.api.message.Message;
import com.sun.enterprise.jbi.serviceengine.util.StAXSource;
import com.sun.xml.ws.message.DOMHeader;
import com.sun.xml.ws.message.DataHandlerAttachment;
import com.sun.xml.ws.message.stream.StreamHeader11;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jbi.messaging.NormalizedMessage;
import javax.wsdl.Part;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
/**
*
* This class is used to unwrap the incoming JBI request message when the
* Java EE Service Engine is the Provider.
*
* This class unwraps and extracts the 'payload' from the incomoming
* request message which is in normalized form.
*
* The current implentation supports the following WSDL1.1 SOAP binding styles :
*
* 1. Wrapped Document/literal
* 2. RPC/Literal
*
* The characterstics of the Wrapped Document/literal style are
*
* 1. The input message has a single part.
* 2. The part is an element.
* 3. The element has the same name as the operation.
* 4. The element's complex type has no attributes.
*
* For wrapped document/literal, the incoming request message looks like :
*
* <?xml version="1.0" encoding="UTF-8"?>
* <jbi:message
* xmlns:msgns="http://example.web.service/Calculator"
* name="add"
* type="msgns:add"
* version="1.0"
* xmlns:jbi="http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper">
* <jbi:part>
* <ns2:add xmlns:ns2="http://example.web.service/Calculator">
* <arg0>1.0</arg0>
* <arg1>2.0</arg1>
* </ns2:add>
* </jbi:part>
* </jbi:message>
*
* and the payLoad node for this is :
*
* <ns2:add xmlns:ns2="http://example.web.service/Calculator">
* <arg0>1.0</arg0>
* <arg1>2.0</arg1>
* </ns2:add>
*
* For RPC/literal, the incoming request message looks like this :
*
* <?xml version="1.0" encoding="UTF-8"?>
* <jbi:message
* xmlns:msgns="http://example.web.service/Calculator"
* name="add"
* type="msgns:add"
* version="1.0"
* xmlns:jbi="http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper">
* <jbi:part><int_1>1</int_1></jbi:part>
* <jbi:part><int_2>2</int_2></jbi:part>
* </jbi:message>
*
* and the payLoad node for this is:
*
* <ns2:add xmlns:ns2="http://example.web.service/Calculator">
* <int_1>1</int_1>
* <int_2>2</int_2>
* </ns2:add>
*
* The styles which are not supported by JAX-WS 2.0 are:
* RPC/encoded
* Document/encoded
*
* The style(s) which are treated/converted as wrapped document/literal by JAX-WS tools are
* document/literal
*
* @author bhavanishankar@dev.java.net
*/
public final class UnWrappedMessage extends Message
implements JBIConstants, SOAPConstants {
private static Logger logger =
LogDomains.getLogger(UnWrappedMessage.class, LogDomains.SERVER_LOGGER);
private String payloadLocalName;
private String payloadNamespaceURI;
private Source payLoadAsSource;
private XMLStreamReader payLoadAsStreamReader;
private ByteArrayOutputStream payLoadAsBaos;
private HeaderList headers = new HeaderList();
private boolean isFault;
private boolean log = false;
private void setLog() {
if(logger.isLoggable(Level.FINE)) {
log = true;
}
}
public UnWrappedMessage() {
setLog();
}
/**
* Variables used for unwrapping the message.
*/
Source nmContent;
NormalizedMessage normalizedMessage;
QName wsdlMessageType;
String wsdlBindingStyle;
List<Part> wsdlOrderedParts;
int[] wsdlPartBindings; // represents whether the part is bound to 'header', 'body', or 'attachment'.
public void setNormalizedMessage(NormalizedMessage normalizedMessage) {
this.normalizedMessage = normalizedMessage;
this.nmContent = normalizedMessage.getContent();
}
public void setWSDLMessageType(QName wsdlMessageType) {
this.wsdlMessageType = wsdlMessageType;
}
public void setWSDLBindingStyle(String wsdlBindingStyle) {
this.wsdlBindingStyle = wsdlBindingStyle;
}
public void setWSDLOrderedParts(List<Part> wsdlOrderedParts) {
this.wsdlOrderedParts = wsdlOrderedParts;
}
public void setWSDLPartBindings(int[] wsdlPartBindings) {
this.wsdlPartBindings = wsdlPartBindings;
}
public void unwrap() throws Exception {
if(log) {
String s = (nmContent instanceof DOMSource) ? toString(nmContent) : "StreamSource";
logger.log(Level.FINE, "bindingStyle = " + wsdlBindingStyle + ", received message = " + s);
}
if(JavaEEServiceEngineContext.getInstance().isServiceMix()) {
if(log) {
logger.log(Level.FINE, "Skipping the unwrapping...");
}
setPayLoad(nmContent);
} else {
if(RPC_STYLE.equalsIgnoreCase(wsdlBindingStyle)) {
new RPCStyleUnWrapper().unwrap();
} else {
new DocumentStyleUnWrapper().unwrap();
}
}
processAttachments();
if(payLoadAsStreamReader == null) {
throw new Exception(StringTranslator.getDefaultInstance().getString(
"serviceengine.unwrapping_failed"));
}
}
public void unwrapFault() throws Exception {
if(log) {
String s = (nmContent instanceof DOMSource) ? toString(nmContent) : "StreamSource";
logger.log(Level.FINE, "bindingStyle = " + wsdlBindingStyle + ", received fault = " + s);
}
isFault = true;
if(JavaEEServiceEngineContext.getInstance().isServiceMix()) {
if(log) {
logger.log(Level.FINE, "Skipping the unwrapping...");
}
setPayLoad(nmContent);
} else {
unWrapFault();
}
if(payLoadAsStreamReader == null) {
throw new Exception(StringTranslator.getDefaultInstance().getString(
"serviceengine.unwrapping_failed"));
}
}
public boolean isFault() {
return isFault;
}
public String getPayloadLocalPart() {
return payloadLocalName;
}
public String getPayloadNamespaceURI() {
return payloadNamespaceURI;
}
public boolean hasPayload() {
return payLoadAsStreamReader == null;
}
public boolean hasHeaders() {
return (headers.size() != 0);
}
public HeaderList getHeaders() {
if(log) {
logger.log(Level.FINE, "Headers = " + headers);
}
return headers;
}
public Message copy() {
return null;
}
public Source readEnvelopeAsSource() {
return null;
}
public XMLStreamReader readPayload() throws XMLStreamException {
if(log) {
logger.log(Level.FINE, "UnWrappedMessage :: readPayLoad()");
}
return payLoadAsStreamReader;
}
public Source readPayloadAsSource() {
if(log) {
logger.log(Level.FINE, "UnWrappedMessage :: readPayLoadAsSource()");
}
return payLoadAsSource;
}
public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
if(System.getSecurityManager() == null) {
return (T)unmarshaller.unmarshal(payLoadAsSource);
} else {
try {
final Unmarshaller funmarshaller = unmarshaller;
final Source fpayLoad = payLoadAsSource;
return (T) java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction() {
public java.lang.Object run() throws JAXBException{
return funmarshaller.unmarshal(fpayLoad);
}});
} catch (java.security.PrivilegedActionException e) {
throw (JAXBException) e.getException();
}
}
}
public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException {
if(System.getSecurityManager() == null) {
return bridge.unmarshal(payLoadAsSource);
} else {
try {
final Bridge<T> fbridge = bridge;
final Source fpayLoad = payLoadAsSource;
return (T) java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction() {
public java.lang.Object run() throws JAXBException{
return fbridge.unmarshal(fpayLoad);
}});
} catch (java.security.PrivilegedActionException e) {
throw (JAXBException) e.getException();
}
}
}
public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException {
throw new XMLStreamException("Operaion is not supported.");
}
public void writeTo(XMLStreamWriter sw) throws XMLStreamException {
throw new XMLStreamException("Operaion is not supported.");
}
public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException {
throw new SAXException("Operaion is not supported.");
}
public SOAPMessage readAsSOAPMessage() throws SOAPException {
String methodSig =
"\ncom.sun.enterprise.jbi.serviceengine.comm.UnWrappedMessage" +
"::readAsSOAPMessage()";
String usedWith = System.getProperty(USED_WITH);
if(usedWith == null || usedWith.indexOf(USED_WITH_JMAC_PROVIDER) == -1) {
throw new SOAPException(
methodSig + " operation is not supported." +
"\nSet this system property to workaround this issue : " +
"com.sun.enterprise.jbi.se.usedwith=jmacprovider");
}
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLStreamWriter writer = XOF.createXMLStreamWriter(baos, "UTF-8");
writer.writeStartDocument();
writer.writeStartElement(SOAP_ENVELOPE);
writer.writeAttribute("xmlns:" + SOAP_PREFIX, SOAP_NAMESPACE);
writer.writeEmptyElement(SOAP_HEADER);
writer.writeStartElement(SOAP_BODY);
if(payLoadAsBaos == null) {
if(payLoadAsSource instanceof DOMSource) {
Node payLoadNode = ((DOMSource)payLoadAsSource).getNode();
DOMUtil.UTIL.writeNode(payLoadNode, writer);
} else {
DOMUtil.UTIL.writeNode(payLoadAsStreamReader, writer);
}
} else {
baos.write(">".getBytes());
baos.write(payLoadAsBaos.toByteArray());
}
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SOAPMessage message = MessageFactory.newInstance().createMessage(null, bais);
if(log) {
logger.log(Level.FINE, methodSig + " :: SOAPMessage = " + toString(message));
}
return message;
} catch(Exception ex) {
throw new SOAPException(methodSig + ex.getMessage());
}
}
public void setPayLoad(Source s) throws Exception {
if(s instanceof DOMSource) {
setPayLoad(((DOMSource)s).getNode());
} else if(s instanceof StreamSource) {
XMLStreamReader reader = XIF.
createXMLStreamReader(((StreamSource)s).getInputStream());
setPayLoad(reader);
} else if(s instanceof SAXSource) {
InputSource source = ((SAXSource) s).getInputSource();
XMLStreamReader reader = (source.getCharacterStream() != null)?
XIF.createXMLStreamReader(source.getCharacterStream()):
XIF.createXMLStreamReader(source.getByteStream());
setPayLoad(reader);
} else {
logger.log(Level.WARNING, "UnWrappedMessage :: Transforming the input message to DOM");
Transformer t = TF.newTransformer();
DOMResult result = new DOMResult();
t.transform(s, result);
setPayLoad(result.getNode());
}
}
public void setPayLoad(Node n) {
if(n.getNodeType() == Node.DOCUMENT_NODE) {
n = n.getFirstChild();
}
payloadLocalName = n.getLocalName();
payloadNamespaceURI = n.getNamespaceURI();
payLoadAsSource = new DOMSource(n);
payLoadAsStreamReader = new DOMStreamReader(n);
printPayLoad("");
}
public void setPayLoad(XMLStreamReader reader) throws Exception {
if(reader.getEventType() == XMLStreamReader.START_DOCUMENT) {
reader.next();
}
payloadLocalName = reader.getLocalName();
payloadNamespaceURI = reader.getNamespaceURI();
payLoadAsSource = new StAXSource(reader, true); // StAXSource will be available in JDK6.
payLoadAsStreamReader = reader;
XMLStreamReader r = reader;
printPayLoad("");
}
public void copyPayLoad(XMLStreamReader r) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLStreamWriter writer = XOF.createXMLStreamWriter(baos, "UTF-8");
DOMUtil.UTIL.writeNode(r, writer);
writer.flush();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
XMLStreamReader reader = XIF.createXMLStreamReader(bais);
if(log) {
logger.log(Level.FINE, "Payload = " + baos.toString());
}
setPayLoad(reader);
}
// Methods for debugging purposes.
public static String toString(SOAPMessage soapMessage) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
soapMessage.writeTo(baos);
return baos.toString();
} catch(Exception e) {
return e.getMessage();
}
}
public static String toString(Node n) {
return toString(new DOMSource(n));
}
public static String toString(XMLStreamReader reader) {
return toString(new StAXSource(reader, true));
}
public static String toString(Source s) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamResult sr = new StreamResult(baos);
TF.newTransformer().transform(s, sr);
return baos.toString();
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
public StreamSource getStreamSource(Source src) {
try {
if(src instanceof StreamSource) {
return (StreamSource)src;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamResult result = new StreamResult(baos);
TF.newTransformer().transform(src, result);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
StreamSource ss = new StreamSource(bais);
return ss;
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
public void printPayLoad(String message) {
if(!log) {
return;
}
StringBuffer msg = new StringBuffer("\n\n");
if(payLoadAsSource instanceof DOMSource) {
Node n = ((DOMSource)payLoadAsSource).getNode();
msg.append("Unwrapped message " + UnWrappedMessage.toString(n));
}
msg
.append(message)
.append("\n\npayLoadLocalName = ")
.append(payloadLocalName)
.append("\npayLoadNamespaceURI = ")
.append(payloadNamespaceURI)
.append("\n\n");
logger.log(Level.FINE, msg.toString());
}
/**
* Adds the header node to the header list.
*/
private void addHeader(Node n) {
if(log) {
logger.log(Level.FINE, "Header = " + toString(n));
}
DOMHeader header = new DOMHeader((Element)n);
headers.add(header);
}
/**
* Adds the header node pointed by XMLStreamReader to the header list.
*/
private void addHeader(XMLStreamReader r) {
try {
if(log) {
logger.log(Level.FINE, "Header = " + r.getName());
}
StreamHeader11 header = new StreamHeader11(r);
headers.add(header);
} catch(Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
private void processAttachments() {
for(String aName : (Set<String>)normalizedMessage.getAttachmentNames()) {
logger.log(Level.FINE, "Adding attachment with ID = " + aName);
getAttachments().add(new DataHandlerAttachment(
aName, normalizedMessage.getAttachment(aName)));
}
}
// END :: Methods for debugging purposes.
class DocumentStyleUnWrapper {
void unwrap() throws Exception {
if(nmContent instanceof DOMSource) { // most cases it will be DOMSource
Node n = ((DOMSource)nmContent).getNode();
unwrap(getOwnerDocument(n));
} else if(nmContent instanceof StreamSource) {
XMLStreamReader reader = XIF.
createXMLStreamReader(((StreamSource)nmContent).getInputStream());
unwrap(reader);
} else if(nmContent instanceof SAXSource) {
InputSource source = ((SAXSource) nmContent).getInputSource();
XMLStreamReader reader = (source.getCharacterStream() != null)?
XIF.createXMLStreamReader(source.getCharacterStream()):
XIF.createXMLStreamReader(source.getByteStream());
unwrap(reader);
} else {
logger.log(Level.WARNING, "UnWrappedMessage :: Transforming the input message to DOM");
Transformer t = TF.newTransformer();
DOMResult result = new DOMResult();
t.transform(nmContent, result);
unwrap(getOwnerDocument(result.getNode()));
}
}
/**
* Searches for the payLoad node in the given node and makes
* payLoadAsSource and payLoadAsStreamReader point to the 'payload' node.
*
* If the payLode node is not found in the given node, then payLoadAsSource
* and payLoadAsStreamReader will remain null.
*
* @param n node representing a JBI inbound request message
* @param operation operation to be invoked on the endpoint
*/
private void unwrap(Node n) {
try {
if(n.getNodeType() == Node.DOCUMENT_NODE) {
n = n.getFirstChild();
}
if(isJBINode(n, WRAPPER_MESSAGE_LOCALNAME)) {
NodeList nl = n.getChildNodes();
for(int i=0, partIndex=0; i<wsdlPartBindings.length; i++, partIndex++) {
Node partValue = nl.item(partIndex).getFirstChild();
switch (wsdlPartBindings[i]) {
case SOAP_BODY_BINDING :
if(log) {
logger.log(Level.FINE, "Setting part number " + i + " as payload");
}
setPayLoad(partValue);
break;
case SOAP_HEADER_BINDING :
if(log) {
logger.log(Level.FINE, "Adding part number " + i + " to header");
}
addHeader(partValue);
break;
case SOAP_ATTACHMENT_BINDING :
if(log) {
logger.log(Level.FINE, "Part number " + i + " is an attachment");
}
--partIndex; // Stay on the same node.
break;
}
}
} else {
logger.log(Level.SEVERE, "Received message is not <jbi:message>");
}
} catch(Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
/**
* Searches for the payLoad in the given reader and makes
* payLoadAsSource and payLoadAsStreamReader point to the 'payload' node.
*
* If the payLode is not found in the given reader, then payLoadAsSource
* and payLoadAsStreamReader will remain null.
*
* @param reader reader pointing to a JBI inbound request message
* @param operation operation to be invoked on the endpoint
*/
private void unwrap(XMLStreamReader reader) {
String methodSig = "UnWrappedMessage$DocumentStyleUnwrapper :: " +
"unwrap(XMLStreamReader, QName) : ";
try {
if(!findJBINode(reader,WRAPPER_MESSAGE_LOCALNAME)) {
logger.log(Level.SEVERE, "Received message is not <jbi:message>");
return;
}
for(int i=0; i<wsdlPartBindings.length; i++) {
switch (wsdlPartBindings[i]) {
case SOAP_BODY_BINDING :
if(!findJBINode(reader, WRAPPER_PART_LOCALNAME)) {
logger.log(Level.SEVERE, "Required <jbi:part> is not found in the received message");
continue;
}
reader.next(); // point reader to <jbi:part>'s value
if(wsdlPartBindings.length == 1) {
if(log) {
logger.log(Level.FINE, "Setting part number " + i + " as payload");
}
setPayLoad(reader);
} else {
if(log) {
logger.log(Level.FINE, "Copying part number " + i + " to payload");
}
copyPayLoad(reader);
}
break;
case SOAP_HEADER_BINDING :
if(!findJBINode(reader, WRAPPER_PART_LOCALNAME)) {
logger.log(Level.SEVERE, "Required <jbi:part> is not found in the received message");
continue;
}
reader.next(); // point reader to <jbi:part>'s value
if(log) {
logger.log(Level.FINE, "Adding part number " + i + " to header");
}
addHeader(reader);
break;
case SOAP_ATTACHMENT_BINDING :
if(log) {
logger.log(Level.FINE, "Part number " + i + " is an attachment");
}
break;
}
}
} catch(Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
class RPCStyleUnWrapper {
void unwrap() throws Exception {
if(nmContent instanceof DOMSource) { // most cases it will be DOMSource
Node n = ((DOMSource)nmContent).getNode();
unwrap(getOwnerDocument(n));
} else if(nmContent instanceof StreamSource) {
XMLStreamReader reader = XIF.
createXMLStreamReader(((StreamSource)nmContent).getInputStream());
unwrap(reader);
} else if(nmContent instanceof SAXSource) {
InputSource source = ((SAXSource) nmContent).getInputSource();
XMLStreamReader reader = (source.getCharacterStream() != null)?
XIF.createXMLStreamReader(source.getCharacterStream()):
XIF.createXMLStreamReader(source.getByteStream());
unwrap(reader);
} else {
logger.log(Level.WARNING, "UnWrappedMessage :: Transforming the input message to DOM");
Transformer t = TF.newTransformer();
DOMResult result = new DOMResult();
t.transform(nmContent, result);
unwrap(getOwnerDocument(result.getNode()));
}
}
/**
*
* Unwraps the incoming JBI request message and sets
* payLoadAsSource and payLoadAsStreamReader to hold the 'payload'.
*
* @param wrappedDocument XMLStreamReader or Node representing the JBI
* request message which is in the following form:
*
* <jbi:message
* xmlns:msgns="http://example.web.service/Calculator"
* name="add"
* type="msgns:add"
* version="1.0"
* xmlns:jbi="http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper">
* <jbi:part><int_1>1</int_1></jbi:part>
* <jbi:part><int_2>2</int_2></jbi:part>
* </jbi:message>
* @param payLoadName Name of the operation to be invoked on the endpoint
* @param payLoadNsUri Target name space URI which is unique for a webservice.
* @return Sets payLoadAsSource and payLoadAsStreamReader to the payload which is
*
* <ns2:add xmlns:ns2="http://example.web.service/Calculator">
* <int_1>1</int_1>
* <int_2>2</int_2>
* </ns2:add>
*/
private void unwrap(Object wrappedDocument) {
String methodSig = "UnWrappedMessage$RPCStyleUnwrapper :: " +
"unwrap(Object, String, String, ServiceEngineEndpoint) : ";
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLStreamWriter writer = XOF.createXMLStreamWriter(baos, "UTF-8");
/**
* Extract the payLoad content from wrappedDocument and write it
* to writer. This does not involve creating or importing a DOM node.
*/
writer.writeStartElement(DEFAULT_OPERATION_PREFIX + ":" + wsdlMessageType.getLocalPart());
writer.writeAttribute(DEFAULT_XML_NS_SCHEME + ":" + DEFAULT_OPERATION_PREFIX,
wsdlMessageType.getNamespaceURI());
if(wrappedDocument instanceof Node) {
writeJBIParts((Node)wrappedDocument, writer);
} else if(wrappedDocument instanceof XMLStreamReader) {
writeJBIParts((XMLStreamReader)wrappedDocument, writer);
}
writer.writeEndElement();
writer.flush();
/**
* Create payLoadAsStreamReader and payLoadAsSource from the
* content available in ByteArrayOutputStream.
*/
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
payLoadAsBaos = baos;
payloadLocalName = wsdlMessageType.getLocalPart();
payloadNamespaceURI = wsdlMessageType.getNamespaceURI();
payLoadAsStreamReader = XIF.createXMLStreamReader(bais);
payLoadAsStreamReader.next(); // skip the <?xml ...?> node.
payLoadAsSource = new StAXSource(payLoadAsStreamReader, true);
printPayLoad("Unwrapped message = " + baos.toString());
} catch(Exception ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
private boolean isSimpleType(Part part) {
QName parttype = part.getTypeName();
if (parttype != null) {
String s = parttype.getNamespaceURI();
if ( s != null && s.trim().equals("http://www.w3.org/2001/XMLSchema")) {
return true;
}
}
return false;
}
private void writeJBIParts(XMLStreamReader reader,
XMLStreamWriter writer) throws Exception {
long startTime = System.currentTimeMillis();
/**
* The following loop is expected to iterate only once always,
* because there could be only one <jbi:message> in the request.
*/
if(!findJBINode(reader, WRAPPER_MESSAGE_LOCALNAME)) {
logger.log(Level.SEVERE, "Received message is not <jbi:message>");
return;
}
for(int k=0; k<wsdlPartBindings.length; k++) {
switch(wsdlPartBindings[k]) {
case SOAP_HEADER_BINDING :
if(!findJBINode(reader, WRAPPER_PART_LOCALNAME)) {
logger.log(Level.SEVERE, "Required <jbi:part> is not found in the received message");
continue;
}
/**
* <jbi:part>'s value will always be an element, so
* point reader to <jbi:part>'s value.
*/
reader.next();
if(log) {
logger.log(Level.FINE, "Adding part number " + k + " to header");
}
addHeader(reader);
break;
case SOAP_BODY_BINDING :
if(!findJBINode(reader, WRAPPER_PART_LOCALNAME)) {
logger.log(Level.SEVERE, "Required <jbi:part> is not found in the received message");
continue;
}
if(log) {
logger.log(Level.FINE, "Adding part number " + k + " to payload");
}
Part part = wsdlOrderedParts.get(k);
writer.writeStartElement(part.getName());
DOMUtil.UTIL.writeChildren(reader, writer);
writer.writeEndElement();
break;
case SOAP_ATTACHMENT_BINDING :
if(log) {
logger.log(Level.FINE, "Part number " + k + " is an attachment");
}
break;
}
}
long timeTaken = System.currentTimeMillis() - startTime;
if(log) {
logger.log(Level.FINE, "TimeTaken to write JBI parts to payload = " + timeTaken);
}
}
private void writeJBIParts(Node wrappedDocument,
XMLStreamWriter writer) throws Exception {
NodeList jbiMessages = wrappedDocument.getChildNodes();
/**
* The following loop is expected to iterate only once always,
* because there could be only one <jbi:message> in the request.
*/
long startTime = System.currentTimeMillis();
for(int i=0; i<jbiMessages.getLength(); i++) {
Node jbiMessage = jbiMessages.item(i);
if(!isJBINode(jbiMessage, WRAPPER_MESSAGE_LOCALNAME)) continue;
NodeList jbiParts = jbiMessage.getChildNodes();
/**
* The following loop is expected to iterate as much as
* there are <jbi:part> elements.
*/
for(int j = 0, k = 0; j< jbiParts.getLength(); j++) {
Node jbiPart = jbiParts.item(j);
if(!isJBINode(jbiPart, WRAPPER_PART_LOCALNAME)) continue;
switch(wsdlPartBindings[k]) {
case SOAP_HEADER_BINDING :
/**
* <jbi:part>'s value will always be an element, so
* add <jbi:part>'s value as header.
*/
if(log) {
logger.log(Level.FINE, "Adding part number " + k + " as header");
}
addHeader(jbiPart.getFirstChild());
break;
case SOAP_BODY_BINDING :
if(log) {
logger.log(Level.FINE, "Adding part number " + k + " to payload");
}
Part part = wsdlOrderedParts.get(k);
writer.writeStartElement(part.getName());
DOMUtil.UTIL.writeChildren(writer, jbiPart);
writer.writeEndElement();
break;
case SOAP_ATTACHMENT_BINDING :
if(log) {
logger.log(Level.FINE, "Part number " + k + " is an attachment");
}
--j; // stay on the same node.
break;
}
++k;
}
}
long timeTaken = System.currentTimeMillis() - startTime;
if(log) {
logger.log(Level.FINE, "TimeTaken to write JBI parts to payload = " + timeTaken);
}
}
}
private boolean findJBINode(XMLStreamReader reader, String localName) throws Exception {
while(reader.hasNext()) {
if(isJBINode(reader,localName)) {
return true;
}
reader.next();
}
return false;
}
private boolean isJBINode(Node node, String localName) {
if(WRAPPER_DEFAULT_NAMESPACE.equalsIgnoreCase(node.getNamespaceURI()) &&
localName.equalsIgnoreCase(node.getLocalName())) {
return true;
}
return false;
}
private boolean isJBINode(XMLStreamReader reader, String localName) {
if(reader.getEventType() != XMLStreamReader.START_ELEMENT) {
return false;
}
if(WRAPPER_DEFAULT_NAMESPACE.equalsIgnoreCase(reader.getNamespaceURI()) &&
localName.equalsIgnoreCase(reader.getLocalName())) {
return true;
}
return false;
}
public Node getOwnerDocument(Node n) {
Node ownerDocument = n.getOwnerDocument();
return ownerDocument != null
? ownerDocument
: n;
}
private void unWrapFault() throws Exception {
Source s = this.nmContent;
Node n;
if(s instanceof DOMSource) {
n = ((DOMSource)s).getNode();
} else {
Transformer t = TF.newTransformer();
DOMResult result = new DOMResult();
t.transform(s, result);
n = result.getNode();
}
Document d = (n instanceof Document) ? (Document) n : n.getOwnerDocument();
NodeList nl = d.getElementsByTagNameNS(WRAPPER_DEFAULT_NAMESPACE, WRAPPER_PART_LOCALNAME);
Node jbiPart = (nl != null && nl.getLength() > 0)
? nl.item(0).getFirstChild()
: d.getFirstChild();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLStreamWriter writer = XOF.createXMLStreamWriter(baos);
writer.writeStartDocument();
writer.writeStartElement(SOAP_FAULT);
writer.writeAttribute("xmlns:" + SOAP_PREFIX, SOAP_NAMESPACE);
String faultCode = jbiPart == null ? SERVER_FAULT_CODE : CLIENT_FAULT_CODE;
String faultString = FAULT_STRING;
writer.writeStartElement(FAULT_CODE_ELEMENT);
writer.writeCharacters(SOAP_PREFIX + ":" + faultCode);
writer.writeEndElement();
writer.writeStartElement(FAULT_STRING_ELEMENT);
writer.writeCharacters(faultString);
writer.writeEndElement();
writer.writeStartElement(FAULT_DETAIL_ELEMENT);
if(jbiPart != null)
DOMUtil.UTIL.writeNode(jbiPart, writer);
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
writer.flush();
setPayLoad(baos.toByteArray());
printPayLoad("\n\nUnwrapped fault = " + baos.toString());
}
public void setPayLoad(byte[] data) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
payLoadAsStreamReader = XIF.createXMLStreamReader(bais);
payLoadAsStreamReader.next(); // skip the <?xml ...?> node.
payLoadAsSource = new StAXSource(payLoadAsStreamReader, true);
payloadLocalName = payLoadAsStreamReader.getLocalName();
payloadNamespaceURI = payLoadAsStreamReader.getNamespaceURI();
}
}