diff options
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.java | 662 |
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; - } - } - -} |