aboutsummaryrefslogtreecommitdiff
path: root/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java')
-rw-r--r--src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java662
1 files changed, 0 insertions, 662 deletions
diff --git a/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java b/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java
deleted file mode 100644
index 0db9233e..00000000
--- a/src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MtomCodec.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.xml.internal.ws.encoding;
-
-import com.sun.istack.internal.NotNull;
-import com.sun.xml.internal.bind.DatatypeConverterImpl;
-import com.sun.xml.internal.ws.api.SOAPVersion;
-import com.sun.xml.internal.ws.api.WSFeatureList;
-import com.sun.xml.internal.ws.api.message.Attachment;
-import com.sun.xml.internal.ws.api.message.AttachmentSet;
-import com.sun.xml.internal.ws.api.message.Packet;
-import com.sun.xml.internal.ws.api.pipe.ContentType;
-import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
-import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
-import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
-import com.sun.xml.internal.ws.developer.SerializationFeature;
-import com.sun.xml.internal.ws.developer.StreamingDataHandler;
-import com.sun.xml.internal.ws.message.MimeAttachmentSet;
-import com.sun.xml.internal.ws.streaming.XMLStreamWriterUtil;
-import com.sun.xml.internal.ws.util.ByteArrayDataSource;
-import com.sun.xml.internal.ws.util.xml.NamespaceContextExAdaper;
-import com.sun.xml.internal.ws.util.xml.XMLStreamReaderFilter;
-import com.sun.xml.internal.ws.util.xml.XMLStreamWriterFilter;
-import com.sun.xml.internal.ws.streaming.MtomStreamWriter;
-import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
-import com.sun.xml.internal.ws.server.UnsupportedMediaException;
-import com.sun.xml.internal.org.jvnet.staxex.Base64Data;
-import com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx;
-import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx;
-import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx;
-
-import javax.activation.DataHandler;
-import javax.xml.namespace.NamespaceContext;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-import javax.xml.ws.WebServiceException;
-import javax.xml.ws.soap.MTOMFeature;
-import javax.xml.bind.attachment.AttachmentMarshaller;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.nio.channels.WritableByteChannel;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * Mtom message Codec. It can be used even for non-soap message's mtom encoding.
- *
- * @author Vivek Pandey
- * @author Jitendra Kotamraju
- */
-public class MtomCodec extends MimeCodec {
-
- public static final String XOP_XML_MIME_TYPE = "application/xop+xml";
- public static final String XOP_LOCALNAME = "Include";
- public static final String XOP_NAMESPACEURI = "http://www.w3.org/2004/08/xop/include";
-
- private final StreamSOAPCodec codec;
- private final MTOMFeature mtomFeature;
- private final SerializationFeature sf;
- private final static String DECODED_MESSAGE_CHARSET = "decodedMessageCharset";
-
- MtomCodec(SOAPVersion version, StreamSOAPCodec codec, WSFeatureList features){
- super(version, features);
- this.codec = codec;
- sf = features.get(SerializationFeature.class);
- MTOMFeature mtom = features.get(MTOMFeature.class);
- if(mtom == null)
- this.mtomFeature = new MTOMFeature();
- else
- this.mtomFeature = mtom;
- }
-
- /**
- * Return the soap 1.1 and soap 1.2 specific XOP packaged ContentType
- *
- * @return A non-null content type for soap11 or soap 1.2 content type
- */
- @Override
- public ContentType getStaticContentType(Packet packet) {
- return getStaticContentTypeStatic(packet, version);
- }
-
- public static ContentType getStaticContentTypeStatic(Packet packet, SOAPVersion version) {
- ContentType ct = (ContentType) packet.getInternalContentType();
- if ( ct != null ) return ct;
-
- String uuid = UUID.randomUUID().toString();
- String boundary = "uuid:" + uuid;
- String rootId = "<rootpart*"+uuid+"@example.jaxws.sun.com>";
- String soapActionParameter = SOAPVersion.SOAP_11.equals(version) ? null : createActionParameter(packet);
-
- String boundaryParameter = "boundary=\"" + boundary +"\"";
- String messageContentType = MULTIPART_RELATED_MIME_TYPE +
- ";start=\""+rootId +"\"" +
- ";type=\"" + XOP_XML_MIME_TYPE + "\";" +
- boundaryParameter +
- ";start-info=\"" + version.contentType +
- (soapActionParameter == null? "" : soapActionParameter) +
- "\"";
-
- ContentTypeImpl ctImpl = SOAPVersion.SOAP_11.equals(version) ?
- new ContentTypeImpl(messageContentType, (packet.soapAction == null)?"":packet.soapAction, null) :
- new ContentTypeImpl(messageContentType, null, null);
- ctImpl.setBoundary(boundary);
- ctImpl.setRootId(rootId);
- packet.setContentType(ctImpl);
- return ctImpl;
- }
-
- private static String createActionParameter(Packet packet) {
- return packet.soapAction != null? ";action=\\\""+packet.soapAction+"\\\"" : "";
- }
-
- @Override
- public ContentType encode(Packet packet, OutputStream out) throws IOException {
- ContentTypeImpl ctImpl = (ContentTypeImpl) this.getStaticContentType(packet);
- String boundary = ctImpl.getBoundary();
- String rootId = ctImpl.getRootId();
-
- if(packet.getMessage() != null){
- try {
- String encoding = getPacketEncoding(packet);
- packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET);
-
- String actionParameter = getActionParameter(packet, version);
- String soapXopContentType = getSOAPXopContentType(encoding, version, actionParameter);
-
- writeln("--"+boundary, out);
- writeMimeHeaders(soapXopContentType, rootId, out);
-
- //mtom attachments that need to be written after the root part
- List<ByteArrayBuffer> mtomAttachments = new ArrayList<ByteArrayBuffer>();
- MtomStreamWriterImpl writer = new MtomStreamWriterImpl(
- XMLStreamWriterFactory.create(out, encoding), mtomAttachments, boundary, mtomFeature);
-
- packet.getMessage().writeTo(writer);
- XMLStreamWriterFactory.recycle(writer);
- writeln(out);
-
- for(ByteArrayBuffer bos : mtomAttachments){
- bos.write(out);
- }
-
- // now write out the attachments in the message that weren't
- // previously written
- writeNonMtomAttachments(packet.getMessage().getAttachments(),
- out, boundary);
-
- //write out the end boundary
- writeAsAscii("--"+boundary, out);
- writeAsAscii("--", out);
-
- } catch (XMLStreamException e) {
- throw new WebServiceException(e);
- }
- }
- //now create the boundary for next encode() call
-// createConteTypeHeader();
- return ctImpl;
- }
-
- public static String getSOAPXopContentType(String encoding, SOAPVersion version,
- String actionParameter) {
- return XOP_XML_MIME_TYPE +";charset="+encoding+";type=\""+version.contentType+ actionParameter + "\"";
- }
-
- public static String getActionParameter(Packet packet, SOAPVersion version) {
- return (version == SOAPVersion.SOAP_11) ? "" : createActionParameter(packet);
- }
-
- public static class ByteArrayBuffer{
- final String contentId;
-
- private final DataHandler dh;
- private final String boundary;
-
- ByteArrayBuffer(@NotNull DataHandler dh, String b) {
- this.dh = dh;
- String cid = null;
- if (dh instanceof StreamingDataHandler) {
- StreamingDataHandler sdh = (StreamingDataHandler) dh;
- if (sdh.getHrefCid() != null)
- cid = sdh.getHrefCid();
- }
- this.contentId = cid != null ? cid : encodeCid();
- boundary = b;
- }
-
- public void write(OutputStream os) throws IOException {
- //build attachment frame
- writeln("--"+boundary, os);
- writeMimeHeaders(dh.getContentType(), contentId, os);
- dh.writeTo(os);
- writeln(os);
- }
- }
-
- public static void writeMimeHeaders(String contentType, String contentId, OutputStream out) throws IOException {
- String cid = contentId;
- if(cid != null && cid.length() >0 && cid.charAt(0) != '<')
- cid = '<' + cid + '>';
- writeln("Content-Id: " + cid, out);
- writeln("Content-Type: " + contentType, out);
- writeln("Content-Transfer-Encoding: binary", out);
- writeln(out);
- }
-
- // Compiler warning for not calling close, but cannot call close,
- // will consume attachment bytes.
- @SuppressWarnings("resource")
- private void writeNonMtomAttachments(AttachmentSet attachments,
- OutputStream out, String boundary) throws IOException {
-
- for (Attachment att : attachments) {
-
- DataHandler dh = att.asDataHandler();
- if (dh instanceof StreamingDataHandler) {
- StreamingDataHandler sdh = (StreamingDataHandler) dh;
- // If DataHandler has href Content-ID, it is MTOM, so skip.
- if (sdh.getHrefCid() != null)
- continue;
- }
-
- // build attachment frame
- writeln("--" + boundary, out);
- writeMimeHeaders(att.getContentType(), att.getContentId(), out);
- att.writeTo(out);
- writeln(out); // write \r\n
- }
- }
-
- @Override
- public ContentType encode(Packet packet, WritableByteChannel buffer) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public MtomCodec copy() {
- return new MtomCodec(version, (StreamSOAPCodec)codec.copy(), features);
- }
-
- private static String encodeCid(){
- String cid="example.jaxws.sun.com";
- String name = UUID.randomUUID()+"@";
- return name + cid;
- }
-
- @Override
- protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException {
- //TODO shouldn't we check for SOAP1.1/SOAP1.2 and throw
- //TODO UnsupportedMediaException like StreamSOAPCodec
- String charset = null;
- String ct = mpp.getRootPart().getContentType();
- if (ct != null) {
- charset = new ContentTypeImpl(ct).getCharSet();
- }
- if (charset != null && !Charset.isSupported(charset)) {
- throw new UnsupportedMediaException(charset);
- }
-
- if (charset != null) {
- packet.invocationProperties.put(DECODED_MESSAGE_CHARSET, charset);
- } else {
- packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET);
- }
-
- // we'd like to reuse those reader objects but unfortunately decoder may be reused
- // before the decoded message is completely used.
- XMLStreamReader mtomReader = new MtomXMLStreamReaderEx( mpp,
- XMLStreamReaderFactory.create(null, mpp.getRootPart().asInputStream(), charset, true)
- );
-
- packet.setMessage(codec.decode(mtomReader, new MimeAttachmentSet(mpp)));
- packet.setMtomFeature(mtomFeature);
- packet.setContentType(mpp.getContentType());
- }
-
- private String getPacketEncoding(Packet packet) {
- // If SerializationFeature is set, just use that encoding
- if (sf != null && sf.getEncoding() != null) {
- return sf.getEncoding().equals("") ? SOAPBindingCodec.DEFAULT_ENCODING : sf.getEncoding();
- }
- return determinePacketEncoding(packet);
- }
-
- public static String determinePacketEncoding(Packet packet) {
- if (packet != null && packet.endpoint != null) {
- // Use request message's encoding for Server-side response messages
- String charset = (String)packet.invocationProperties.get(DECODED_MESSAGE_CHARSET);
- return charset == null
- ? SOAPBindingCodec.DEFAULT_ENCODING : charset;
- }
-
- // Use default encoding for client-side request messages
- return SOAPBindingCodec.DEFAULT_ENCODING;
- }
-
- public static class MtomStreamWriterImpl extends XMLStreamWriterFilter implements XMLStreamWriterEx,
- MtomStreamWriter, HasEncoding {
- private final List<ByteArrayBuffer> mtomAttachments;
- private final String boundary;
- private final MTOMFeature myMtomFeature;
- public MtomStreamWriterImpl(XMLStreamWriter w, List<ByteArrayBuffer> mtomAttachments, String b, MTOMFeature myMtomFeature) {
- super(w);
- this.mtomAttachments = mtomAttachments;
- this.boundary = b;
- this.myMtomFeature = myMtomFeature;
- }
-
- @Override
- public void writeBinary(byte[] data, int start, int len, String contentType) throws XMLStreamException {
- //check threshold and if less write as base64encoded value
- if(myMtomFeature.getThreshold() > len){
- writeCharacters(DatatypeConverterImpl._printBase64Binary(data, start, len));
- return;
- }
- ByteArrayBuffer bab = new ByteArrayBuffer(new DataHandler(new ByteArrayDataSource(data, start, len, contentType)), boundary);
- writeBinary(bab);
- }
-
- @Override
- public void writeBinary(DataHandler dataHandler) throws XMLStreamException {
- // TODO how do we check threshold and if less inline the data
- writeBinary(new ByteArrayBuffer(dataHandler, boundary));
- }
-
- @Override
- public OutputStream writeBinary(String contentType) throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void writePCDATA(CharSequence data) throws XMLStreamException {
- if(data == null)
- return;
- if(data instanceof Base64Data){
- Base64Data binaryData = (Base64Data)data;
- writeBinary(binaryData.getDataHandler());
- return;
- }
- writeCharacters(data.toString());
- }
-
- private void writeBinary(ByteArrayBuffer bab) {
- try {
- mtomAttachments.add(bab);
- String prefix = writer.getPrefix(XOP_NAMESPACEURI);
- if (prefix == null || !prefix.equals("xop")) {
- writer.setPrefix("xop", XOP_NAMESPACEURI);
- writer.writeNamespace("xop", XOP_NAMESPACEURI);
- }
- writer.writeStartElement(XOP_NAMESPACEURI, XOP_LOCALNAME);
- writer.writeAttribute("href", "cid:"+bab.contentId);
- writer.writeEndElement();
- writer.flush();
- } catch (XMLStreamException e) {
- throw new WebServiceException(e);
- }
- }
-
- @Override
- public Object getProperty(String name) throws IllegalArgumentException {
- // Hack for JDK6's SJSXP
- if (name.equals("sjsxp-outputstream") && writer instanceof Map) {
- Object obj = ((Map) writer).get("sjsxp-outputstream");
- if (obj != null) {
- return obj;
- }
- }
- return super.getProperty(name);
- }
-
- /**
- * JAXBMessage writes envelope directly to the OutputStream(for SJSXP, woodstox).
- * While writing, it calls the AttachmentMarshaller methods for adding attachments.
- * JAXB writes xop:Include in this case.
- */
- @Override
- public AttachmentMarshaller getAttachmentMarshaller() {
- return new AttachmentMarshaller() {
-
- @Override
- public String addMtomAttachment(DataHandler data, String elementNamespace, String elementLocalName) {
- // Should we do the threshold processing on DataHandler ? But that would be
- // expensive as DataHolder need to read the data again from its source
- ByteArrayBuffer bab = new ByteArrayBuffer(data, boundary);
- mtomAttachments.add(bab);
- return "cid:"+bab.contentId;
- }
-
- @Override
- public String addMtomAttachment(byte[] data, int offset, int length, String mimeType, String elementNamespace, String elementLocalName) {
- // inline the data based on the threshold
- if (myMtomFeature.getThreshold() > length) {
- return null; // JAXB inlines the attachment data
- }
- ByteArrayBuffer bab = new ByteArrayBuffer(new DataHandler(new ByteArrayDataSource(data, offset, length, mimeType)), boundary);
- mtomAttachments.add(bab);
- return "cid:"+bab.contentId;
- }
-
- @Override
- public String addSwaRefAttachment(DataHandler data) {
- ByteArrayBuffer bab = new ByteArrayBuffer(data, boundary);
- mtomAttachments.add(bab);
- return "cid:"+bab.contentId;
- }
-
- @Override
- public boolean isXOPPackage() {
- return true;
- }
- };
- }
-
- public List<ByteArrayBuffer> getMtomAttachments() {
- return this.mtomAttachments;
- }
-
- @Override
- public String getEncoding() {
- return XMLStreamWriterUtil.getEncoding(writer);
- }
-
- private static class MtomNamespaceContextEx implements NamespaceContextEx {
- private final NamespaceContext nsContext;
-
- public MtomNamespaceContextEx(NamespaceContext nsContext) {
- this.nsContext = nsContext;
- }
-
- @Override
- public Iterator<Binding> iterator() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getNamespaceURI(String prefix) {
- return nsContext.getNamespaceURI(prefix);
- }
-
- @Override
- public String getPrefix(String namespaceURI) {
- return nsContext.getPrefix(namespaceURI);
- }
-
- @Override
- public Iterator getPrefixes(String namespaceURI) {
- return nsContext.getPrefixes(namespaceURI);
- }
- }
-
- @Override
- public NamespaceContextEx getNamespaceContext() {
- NamespaceContext nsContext = writer.getNamespaceContext();
- return new MtomNamespaceContextEx(nsContext);
- }
- }
-
- public static class MtomXMLStreamReaderEx extends XMLStreamReaderFilter implements XMLStreamReaderEx {
- /**
- * The parser for the outer MIME 'shell'.
- */
- private final MimeMultipartParser mimeMP;
-
- private boolean xopReferencePresent = false;
- private Base64Data base64AttData;
-
- //To be used with #getTextCharacters
- private char[] base64EncodedText;
-
- private String xopHref;
-
- public MtomXMLStreamReaderEx(MimeMultipartParser mimeMP, XMLStreamReader reader) {
- super(reader);
- this.mimeMP = mimeMP;
- }
-
- @Override
- public CharSequence getPCDATA() throws XMLStreamException {
- if(xopReferencePresent){
- return base64AttData;
- }
- return reader.getText();
- }
-
- @Override
- public NamespaceContextEx getNamespaceContext() {
- return new NamespaceContextExAdaper(reader.getNamespaceContext());
- }
-
- @Override
- public String getElementTextTrim() throws XMLStreamException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getTextLength() {
- if (xopReferencePresent) {
- return base64AttData.length();
- }
- return reader.getTextLength();
- }
-
- @Override
- public int getTextStart() {
- if (xopReferencePresent) {
- return 0;
- }
- return reader.getTextStart();
- }
-
- @Override
- public int getEventType() {
- if(xopReferencePresent)
- return XMLStreamConstants.CHARACTERS;
- return super.getEventType();
- }
-
- @Override
- public int next() throws XMLStreamException {
- int event = reader.next();
- if (event == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals(XOP_LOCALNAME) && reader.getNamespaceURI().equals(XOP_NAMESPACEURI)) {
- //its xop reference, take the URI reference
- String href = reader.getAttributeValue(null, "href");
- try {
- xopHref = href;
- Attachment att = getAttachment(href);
- if(att != null){
- DataHandler dh = att.asDataHandler();
- if (dh instanceof StreamingDataHandler) {
- ((StreamingDataHandler)dh).setHrefCid(att.getContentId());
- }
- base64AttData = new Base64Data();
- base64AttData.set(dh);
- }
- xopReferencePresent = true;
- } catch (IOException e) {
- throw new WebServiceException(e);
- }
- //move to the </xop:Include>
- XMLStreamReaderUtil.nextElementContent(reader);
- return XMLStreamConstants.CHARACTERS;
- }
- if(xopReferencePresent){
- xopReferencePresent = false;
- base64EncodedText = null;
- xopHref = null;
- }
- return event;
- }
-
- private String decodeCid(String cid) {
- try {
- cid = URLDecoder.decode(cid, "utf-8");
- } catch (UnsupportedEncodingException e) {
- //on recceiving side lets not fail now, try to look for it
- }
- return cid;
- }
-
- private Attachment getAttachment(String cid) throws IOException {
- if (cid.startsWith("cid:"))
- cid = cid.substring(4, cid.length());
- if (cid.indexOf('%') != -1) {
- cid = decodeCid(cid);
- return mimeMP.getAttachmentPart(cid);
- }
- return mimeMP.getAttachmentPart(cid);
- }
-
- @Override
- public char[] getTextCharacters() {
- if (xopReferencePresent) {
- char[] chars = new char[base64AttData.length()];
- base64AttData.writeTo(chars, 0);
- return chars;
- }
- return reader.getTextCharacters();
- }
-
- @Override
- public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException {
- if(xopReferencePresent){
- if(target == null){
- throw new NullPointerException("target char array can't be null") ;
- }
-
- if(targetStart < 0 || length < 0 || sourceStart < 0 || targetStart >= target.length ||
- (targetStart + length ) > target.length) {
- throw new IndexOutOfBoundsException();
- }
-
- int textLength = base64AttData.length();
- if(sourceStart > textLength)
- throw new IndexOutOfBoundsException();
-
- if(base64EncodedText == null){
- base64EncodedText = new char[base64AttData.length()];
- base64AttData.writeTo(base64EncodedText, 0);
- }
-
- int copiedLength = Math.min(textLength - sourceStart, length);
- System.arraycopy(base64EncodedText, sourceStart , target, targetStart, copiedLength);
- return copiedLength;
- }
- return reader.getTextCharacters(sourceStart, target, targetStart, length);
- }
-
- @Override
- public String getText() {
- if (xopReferencePresent) {
- return base64AttData.toString();
- }
- return reader.getText();
- }
-
- protected boolean isXopReference() throws XMLStreamException {
- return xopReferencePresent;
- }
-
- protected String getXopHref() {
- return xopHref;
- }
-
- public MimeMultipartParser getMimeMultipartParser() {
- return mimeMP;
- }
- }
-
-}