/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2014 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
* http://glassfish.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.xml.ws.message.saaj;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.UUID;
import javax.activation.DataHandler;
import javax.xml.bind.attachment.AttachmentMarshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.soap.MTOMFeature;
import com.sun.xml.ws.api.message.saaj.SaajStaxWriter;
import junit.framework.TestCase;
import org.jvnet.staxex.NamespaceContextEx;
import org.jvnet.staxex.XMLStreamWriterEx;
import com.oracle.webservices.api.message.ContentType;
import com.oracle.webservices.api.message.MessageContext;
import com.oracle.webservices.api.message.MessageContextFactory;
import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.addressing.AddressingVersion;
import com.sun.xml.ws.api.message.AddressingUtils;
import com.sun.xml.ws.api.message.Attachment;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.Message;
import com.sun.xml.ws.api.message.Packet;
import com.sun.xml.ws.api.streaming.XMLStreamWriterFactory;
import com.sun.xml.ws.developer.StreamingDataHandler;
import com.sun.xml.ws.encoding.MIMEPartStreamingDataHandler;
import com.sun.xml.ws.message.StringHeader;
/**
* @author Rama Pulavarthi
*/
public class SAAJMessageTest extends TestCase {
String MESSAGE = "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">"+
"<S:Header>" +
"<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">http://example.com/addNumbers</wsa:Action>" +
"</S:Header>" +
"<S:Body>" +
"<addNumbers xmlns=\"http://example.com/\">" +
"<number1>10</number1>" +
"<number2>10</number2>" +
"</addNumbers>" +
"</S:Body></S:Envelope>";
String FAULT_MESSAGE = "<S:Envelope xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'>"+
"<S:Header>" +
"<wsa:Action xmlns:wsa='http://www.w3.org/2005/08/addressing'>http://example.com/addNumbers</wsa:Action>" +
"</S:Header>" +
"<S:Body><S:Fault>" +
"<faultCode>S:Client</faultCode>" +
"<faultString>Fault Test</faultString>" +
"<detail xmlns:ns1='urn:fault'><ns1:entry></ns1:entry></detail>" +
"</S:Fault></S:Body></S:Envelope>";
public void test1() throws Exception {
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
Source src = new StreamSource(new ByteArrayInputStream(MESSAGE.getBytes()));
message.getSOAPPart().setContent(src);
SAAJMessage saajMsg = new SAAJMessage(message);
assertEquals("addNumbers",saajMsg.getPayloadLocalPart());
assertEquals("http://example.com/addNumbers",AddressingUtils.getAction(saajMsg.getHeaders(), AddressingVersion.W3C, SOAPVersion.SOAP_11));
Header header = new StringHeader(new QName("urn:foo","header1"),"test header ");
saajMsg.getHeaders().add(header);
SOAPMessage newMsg = saajMsg.readAsSOAPMessage();
newMsg.writeTo(System.out);
SAAJMessage saajMsg2 = new SAAJMessage(newMsg);
assertEquals(2,saajMsg2.getHeaders().asList().size());
Message saajMsg3 = saajMsg2.copy();
assertEquals("addNumbers",saajMsg3.getPayloadLocalPart());
assertEquals("http://example.com/addNumbers",AddressingUtils.getAction(saajMsg3.getHeaders(), AddressingVersion.W3C, SOAPVersion.SOAP_11));
assertEquals(2,saajMsg2.getHeaders().asList().size());
XMLStreamWriter writer = XMLStreamWriterFactory.create(System.out);
saajMsg3.writeTo(writer);
writer.close();
}
public void testFirstDetailEntryName() throws Exception {
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
Source src = new StreamSource(new ByteArrayInputStream(FAULT_MESSAGE.getBytes()));
message.getSOAPPart().setContent(src);
SAAJMessage saajMsg = new SAAJMessage(message);
QName exp = new QName("urn:fault", "entry");
assertEquals(exp, saajMsg.getFirstDetailEntryName());
}
// private MTOMFeature mtomf = new MTOMFeature(true);
private MessageContextFactory mcf = MessageContextFactory.createFactory(new MTOMFeature(true));
public void testMtomMessageReload() throws Exception {
String testMtomMessageReload_01 = "multipart/related;type=\"application/xop+xml\";boundary=\"----=_Part_0_1145105632.1353005695468\";start=\"<cbe648b3-2055-413e-b8ed-877cdf0f2477>\";start-info=\"text/xml\"";
String testMtomMessageReload_02 = "multipart/related;type=\"application/xop+xml\";boundary=\"----=_Part_0_1145105632.1353005695468\";start=\"<6e1e30fe-9874-43ff-a9d1-c02af3969f04>\";start-info=\"text/xml\"";
{
MessageContext m1 = mcf.createContext(getResource("testMtomMessageReload_01.msg"), testMtomMessageReload_01);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ContentType disiContentType = m1.writeTo(baos);
byte[] bytes = baos.toByteArray();
String strMsg = new String(bytes);
assertFalse(strMsg.startsWith("--null"));
}
{
MessageContext m2 = mcf.createContext(getResource("testMtomMessageReload_02.msg"), testMtomMessageReload_02);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ContentType disiContentType = m2.writeTo(baos);
byte[] bytes = baos.toByteArray();
String strMsg = new String(bytes);
assertFalse(strMsg.startsWith("--null"));
}
}
public void testMtomAttachment() throws Exception {
String testMtomMessageReload_01 = "multipart/related;type=\"application/xop+xml\";boundary=\"----=_Part_0_1145105632.1353005695468\";start=\"<cbe648b3-2055-413e-b8ed-877cdf0f2477>\";start-info=\"text/xml\"";
MessageContext m1 = mcf.createContext(getResource("testMtomMessageReload_01.msg"), testMtomMessageReload_01);
Packet packet = (Packet) m1;
Message message = packet.getInternalMessage();
Iterator<Attachment> as = packet.getInternalMessage().getAttachments().iterator();
Attachment att = null;
int counter = 0;
String cid1 = null;
while (as.hasNext()) {
att = as.next();
cid1 = att.getContentId();
counter++;
}
assertTrue(counter == 1);
//SAAJFactory:
SOAPVersion soapVersion = packet.getMessage().getSOAPVersion();
SOAPMessage msg = soapVersion.getMessageFactory().createMessage();
SaajStaxWriterEx writer = new SaajStaxWriterEx(msg, soapVersion.nsUri);
try {
message.writeTo(writer);
} catch (XMLStreamException e) {
throw (e.getCause() instanceof SOAPException) ? (SOAPException) e.getCause() : new SOAPException(e);
}
msg = writer.getSOAPMessage();
counter = 0;
String cid2 = null;
for(Attachment a : message.getAttachments()) {
counter++;
cid2 = a.getContentId();
}
assertTrue(writer.ma.size() == counter);
StreamingDataHandler sdh = (StreamingDataHandler)writer.ma.get(0);
assertEquals(cid1, sdh.getHrefCid());
assertEquals(cid2, sdh.getHrefCid());
}
public void testMtomAttachmentCid() throws Exception {
String testMtomMessageReload_01 = "multipart/related;type=\"application/xop+xml\";boundary=\"----=_Part_0_1145105632.1353005695468\";start=\"<cbe648b3-2055-413e-b8ed-877cdf0f2477>\";start-info=\"text/xml\"";
MessageContext m1 = mcf.createContext(getResource("testMtomMessageReload_01.msg"), testMtomMessageReload_01);
Packet packet = (Packet) m1;
Message riMsg = packet.getInternalMessage();
//This will cause all the attachments to be created ...
// Iterator<Attachment> as = packet.getInternalMessage().getAttachments().iterator();
//SAAJFactory:
SOAPVersion soapVersion = packet.getMessage().getSOAPVersion();
SOAPMessage saajMsg = soapVersion.getMessageFactory().createMessage();
SaajStaxWriterEx writer = new SaajStaxWriterEx(saajMsg, soapVersion.nsUri);
try {
riMsg.writeTo(writer);
} catch (XMLStreamException e) {
throw (e.getCause() instanceof SOAPException) ? (SOAPException) e.getCause() : new SOAPException(e);
}
saajMsg = writer.getSOAPMessage();
int counter = 0;
String hredCid = null;
for(Attachment a : riMsg.getAttachments()) {
hredCid = ((StreamingDataHandler)a.asDataHandler()).getHrefCid();
counter++;
}
assertTrue(writer.ma.size() == counter);
AttachmentPart ap = null;
// for (Iterator<AttachmentPart> itr = saajMsg.getAttachments(); itr.hasNext(); ) {
// System.out.println("\r\n itr.next().getContentId() " + itr.next().getContentId() );
// }
StreamingDataHandler sdh = (StreamingDataHandler)writer.ma.get(0);
assertEquals(hredCid, sdh.getHrefCid());
}
private InputStream getResource(String str) throws Exception {
// return new File("D:/oc4j/webservices/devtest/data/cts15/DLSwaTest/" + str).toURL();
return Thread.currentThread().getContextClassLoader().getResource("etc/"+str).openStream();
}
static class SaajStaxWriterEx extends SaajStaxWriter implements XMLStreamWriterEx, org.jvnet.staxex.util.MtomStreamWriter {
static final protected String xopNS = "http://www.w3.org/2004/08/xop/include";
static final protected String Include = "Include";
static final protected String href = "href";
private final int mtomThreshold = 0;
private enum State {xopInclude, others};
private State state = State.others;
ArrayList<Object> ma;
private Object binaryText;
public SaajStaxWriterEx(SOAPMessage msg, String ns) throws SOAPException {
super(msg, ns);
ma = new ArrayList<Object> ();
}
public void writeStartElement(String prefix, String ln, String ns) throws XMLStreamException {
if (xopNS.equals(ns) && Include.equals(ln)) {
state = State.xopInclude;
return;
} else {
super.writeStartElement(prefix, ln, ns);
}
}
@Override
public void writeEndElement() throws XMLStreamException {
if (state.equals(State.xopInclude)) {
state = State.others;
} else {
super.writeEndElement();
}
}
@Override
public void writeAttribute(String prefix, String ns, String ln, String value) throws XMLStreamException {
if (binaryText != null && href.equals(ln)) {
return;
} else {
super.writeAttribute(prefix, ns, ln, value);
}
}
@Override
public NamespaceContextEx getNamespaceContext() {
return new NamespaceContextEx() {
public String getNamespaceURI(String prefix) {
return currentElement.getNamespaceURI(prefix);
}
public String getPrefix(String namespaceURI) {
return currentElement.lookupPrefix(namespaceURI);
}
public Iterator getPrefixes(final String namespaceURI) {
return new Iterator() {
String prefix = getPrefix(namespaceURI);
public boolean hasNext() {
return (prefix != null);
}
public Object next() {
String next = prefix;
prefix = null;
return next;
}
public void remove() {}
};
}
public Iterator<Binding> iterator() {
return new Iterator<Binding>() {
public boolean hasNext() { return false; }
public Binding next() { return null; }
public void remove() {}
};
}
};
}
@Override
public void writeBinary(DataHandler data) throws XMLStreamException {
binaryText = data;
ma.add(data);
// binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl)soap, null, currentElement.getOwnerDocument(), data);
// currentElement.appendChild(binaryText);
}
@Override
public OutputStream writeBinary(String arg0) throws XMLStreamException {
return null;
}
@Override
public void writeBinary(byte[] data, int offset, int length, String contentType) throws XMLStreamException {
// if (mtomThreshold == -1 || mtomThreshold > length) return null;
byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length);
// binaryText = (BinaryTextImpl) ((ElementImpl) currentElement).addAsBase64TextNode(bytes);
binaryText = bytes;
ma.add(data);
}
@Override
public void writePCDATA(CharSequence arg0) throws XMLStreamException {
// binaryText = (BinaryTextImpl) ((ElementImpl) currentElement).addAsBase64TextNode(((Base64Data)arg0).getExact());
binaryText = arg0;
ma.add(arg0);
}
public AttachmentMarshaller getAttachmentMarshaller() {
return new AttachmentMarshaller() {
private String cid(){
String cid="example.jaxws.sun.com";
String name = UUID.randomUUID()+"@";
return name + cid;
}
@Override
public String addMtomAttachment(DataHandler data, String ns, String ln) {
if (mtomThreshold == -1) return null;
if (data instanceof MIMEPartStreamingDataHandler) {
StreamingDataHandler dh = (StreamingDataHandler)data;
}
// Should we do the threshold processing on DataHandler ? But that would be
// expensive as DataHolder need to read the data again from its source
// binaryText = BinaryTextImpl.createBinaryTextFromDataHandler((MessageImpl)soap, null, currentElement.getOwnerDocument(), data);
// currentElement.appendChild(binaryText);
binaryText = data;
ma.add(data);
// return binaryText.getHref();
return ((StreamingDataHandler)data).getHrefCid();
}
@Override
public String addMtomAttachment(byte[] data, int offset, int length, String mimeType, String ns, String ln) {
if (mtomThreshold == -1 || mtomThreshold > length) return null;
byte[] bytes = (offset == 0 && length == data.length) ? data : Arrays.copyOfRange(data, offset, offset + length);
// binaryText = (BinaryTextImpl) ((ElementImpl) currentElement).addAsBase64TextNode(bytes);
binaryText = data;
ma.add(data);
// return binaryText.getHref();
return cid();
}
@Override
public String addSwaRefAttachment(DataHandler data) {
return "cid:"+cid();
}
@Override
public boolean isXOPPackage() {
return true;
}
};
}
}
}