feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1997, 2012, 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.
*/
/*
* @(#)ContentType.java 1.7 02/03/27
*/
package com.sun.xml.internal.ws.encoding;
import javax.xml.ws.WebServiceException;
/**
* This class represents a MIME ContentType value. It provides
* methods to parse a ContentType string into individual components
* and to generate a MIME style ContentType string.
*
* @version 1.7, 02/03/27
* @author John Mani
*/
public final class ContentType {
private String primaryType; // primary type
private String subType; // subtype
private ParameterList list; // parameter list
/**
* Constructor that takes a Content-Type string. The String
* is parsed into its constituents: primaryType, subType
* and parameters. A ParseException is thrown if the parse fails.
*
* @param s the Content-Type string.
* @exception WebServiceException if the parse fails.
*/
public ContentType(String s) throws WebServiceException {
HeaderTokenizer h = new HeaderTokenizer(s, HeaderTokenizer.MIME);
HeaderTokenizer.Token tk;
// First "type" ..
tk = h.next();
if (tk.getType() != HeaderTokenizer.Token.ATOM)
throw new WebServiceException();
primaryType = tk.getValue();
// The '/' separator ..
tk = h.next();
if ((char)tk.getType() != '/')
throw new WebServiceException();
// Then "subType" ..
tk = h.next();
if (tk.getType() != HeaderTokenizer.Token.ATOM)
throw new WebServiceException();
subType = tk.getValue();
// Finally parameters ..
String rem = h.getRemainder();
if (rem != null)
list = new ParameterList(rem);
}
/**
* Return the primary type.
* @return the primary type
*/
public String getPrimaryType() {
return primaryType;
}
/**
* Return the subType.
* @return the subType
*/
public String getSubType() {
return subType;
}
/**
* Return the MIME type string, without the parameters.
* The returned value is basically the concatenation of
* the primaryType, the '/' character and the secondaryType.
*
* @return the type
*/
public String getBaseType() {
return primaryType + '/' + subType;
}
/**
* Return the specified parameter value. Returns <code>null</code>
* if this parameter is absent.
*
* @param name parameter name
* @return parameter value
*/
public String getParameter(String name) {
if (list == null)
return null;
return list.get(name);
}
/**
* Return a ParameterList object that holds all the available
* parameters. Returns null if no parameters are available.
*
* @return ParameterList
*/
public ParameterList getParameterList() {
return list;
}
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 1997, 2012, 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.Nullable;
import com.sun.istack.internal.NotNull;
/**
* @author Vivek Pandey
*/
public final class ContentTypeImpl implements com.sun.xml.internal.ws.api.pipe.ContentType {
private final @NotNull String contentType;
private final @NotNull String soapAction;
private String accept;
private final @Nullable String charset;
private String boundary;
private String boundaryParameter;
private String rootId;
private ContentType internalContentType;
public ContentTypeImpl(String contentType) {
this(contentType, null, null);
}
public ContentTypeImpl(String contentType, @Nullable String soapAction) {
this(contentType, soapAction, null);
}
public ContentTypeImpl(String contentType, @Nullable String soapAction, @Nullable String accept) {
this(contentType, soapAction, accept, null);
}
public ContentTypeImpl(String contentType, @Nullable String soapAction, @Nullable String accept, String charsetParam) {
this.contentType = contentType;
this.accept = accept;
this.soapAction = getQuotedSOAPAction(soapAction);
if (charsetParam == null) {
String tmpCharset = null;
try {
internalContentType = new ContentType(contentType);
tmpCharset = internalContentType.getParameter("charset");
} catch(Exception e) {
//Ignore the parsing exception.
}
charset = tmpCharset;
} else {
charset = charsetParam;
}
}
/**
* Returns the character set encoding.
*
* @return returns the character set encoding.
*/
public @Nullable String getCharSet() {
return charset;
}
/** BP 1.1 R1109 requires SOAPAction too be a quoted value **/
private String getQuotedSOAPAction(String soapAction){
if(soapAction == null || soapAction.length() == 0){
return "\"\"";
}else if(soapAction.charAt(0) != '"' && soapAction.charAt(soapAction.length() -1) != '"'){
//surround soapAction by double quotes for BP R1109
return "\"" + soapAction + "\"";
}else{
return soapAction;
}
}
@Override
public String getContentType() {
return contentType;
}
@Override
public String getSOAPActionHeader() {
return soapAction;
}
@Override
public String getAcceptHeader() {
return accept;
}
public void setAcceptHeader(String accept) {
this.accept = accept;
}
public String getBoundary() {
if (boundary == null) {
if (internalContentType == null) internalContentType = new ContentType(contentType);
boundary = internalContentType.getParameter("boundary");
}
return boundary;
}
public void setBoundary(String boundary) {
this.boundary = boundary;
}
public String getBoundaryParameter() {
return boundaryParameter;
}
public void setBoundaryParameter(String boundaryParameter) {
this.boundaryParameter = boundaryParameter;
}
public String getRootId() {
if (rootId == null) {
if (internalContentType == null) internalContentType = new ContentType(contentType);
rootId = internalContentType.getParameter("start");
}
return rootId;
}
public void setRootId(String rootId) {
this.rootId = rootId;
}
public static class Builder {
public String contentType;
public String soapAction;
public String accept;
public String charset;
public ContentTypeImpl build() {
return new ContentTypeImpl(contentType, soapAction, accept, charset);
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 1997, 2012, 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 javax.activation.DataSource;
import javax.activation.DataHandler;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* {@link DataSource} impl using a DataHandler
*
* @author Jitendra Kotamraju
*/
public class DataHandlerDataSource implements DataSource {
private final DataHandler dataHandler;
public DataHandlerDataSource(DataHandler dh) {
this.dataHandler = dh;
}
/**
* Returns an <code>InputStream</code> representing this object.
*
* @return the <code>InputStream</code>
*/
public InputStream getInputStream() throws IOException {
return dataHandler.getInputStream();
}
/**
* Returns the <code>OutputStream</code> for this object.
*
* @return the <code>OutputStream</code>
*/
public OutputStream getOutputStream() throws IOException {
return dataHandler.getOutputStream();
}
/**
* Returns the MIME type of the data represented by this object.
*
* @return the MIME type
*/
public String getContentType() {
return dataHandler.getContentType();
}
/**
* Returns the name of this object.
*
* @return the name of this object
*/
public String getName() {
return dataHandler.getName();
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1997, 2012, 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 javax.activation.DataSource;
import java.io.*;
import com.sun.xml.internal.ws.developer.StreamingDataHandler;
/**
* @author Jitendra Kotamraju
*/
public class DataSourceStreamingDataHandler extends StreamingDataHandler {
public DataSourceStreamingDataHandler(DataSource ds) {
super(ds);
}
@Override
public InputStream readOnce() throws IOException {
return getInputStream();
}
@Override
public void moveTo(File file) throws IOException {
InputStream in = getInputStream();
OutputStream os = new FileOutputStream(file);
try {
byte[] temp = new byte[8192];
int len;
while((len=in.read(temp)) != -1) {
os.write(temp, 0, len);
}
in.close();
} finally {
if (os != null) {
os.close();
}
}
}
@Override
public void close() throws IOException {
// nothing to do here
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1997, 2012, 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;
/**
* A {@link javax.xml.stream.XMLStreamWriter} doesn't expose any method to
* give encoding. An implementation of writer may implement
* this interface to give the encoding with which the writer is created.
*
* @author Jitendra Kotamraju
* @since JAX-WS RI 2.2.6
*/
public interface HasEncoding {
public String getEncoding();
}

View File

@@ -0,0 +1,377 @@
/*
* Copyright (c) 1997, 2012, 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 javax.xml.ws.WebServiceException;
/**
* This class tokenizes RFC822 and MIME headers into the basic
* symbols specified by RFC822 and MIME. <p>
*
* This class handles folded headers (ie headers with embedded
* CRLF SPACE sequences). The folds are removed in the returned
* tokens.
*
* @version 1.9, 02/03/27
* @author John Mani
*/
class HeaderTokenizer {
/**
* The Token class represents tokens returned by the
* HeaderTokenizer.
*/
static class Token {
private int type;
private String value;
/**
* Token type indicating an ATOM.
*/
public static final int ATOM = -1;
/**
* Token type indicating a quoted string. The value
* field contains the string without the quotes.
*/
public static final int QUOTEDSTRING = -2;
/**
* Token type indicating a comment. The value field
* contains the comment string without the comment
* start and end symbols.
*/
public static final int COMMENT = -3;
/**
* Token type indicating end of input.
*/
public static final int EOF = -4;
/**
* Constructor.
* @param type Token type
* @param value Token value
*/
public Token(int type, String value) {
this.type = type;
this.value = value;
}
/**
* Return the type of the token. If the token represents a
* delimiter or a control character, the type is that character
* itself, converted to an integer. Otherwise, it's value is
* one of the following:
* <ul>
* <li><code>ATOM</code> A sequence of ASCII characters
* delimited by either SPACE, CTL, "(", <"> or the
* specified SPECIALS
* <li><code>QUOTEDSTRING</code> A sequence of ASCII characters
* within quotes
* <li><code>COMMENT</code> A sequence of ASCII characters
* within "(" and ")".
* <li><code>EOF</code> End of header
* </ul>
*/
public int getType() {
return type;
}
/**
* Returns the value of the token just read. When the current
* token is a quoted string, this field contains the body of the
* string, without the quotes. When the current token is a comment,
* this field contains the body of the comment.
*
* @return token value
*/
public String getValue() {
return value;
}
}
private String string; // the string to be tokenized
private boolean skipComments; // should comments be skipped ?
private String delimiters; // delimiter string
private int currentPos; // current parse position
private int maxPos; // string length
private int nextPos; // track start of next Token for next()
private int peekPos; // track start of next Token for peek()
/**
* RFC822 specials
*/
private final static String RFC822 = "()<>@,;:\\\"\t .[]";
/**
* MIME specials
*/
final static String MIME = "()<>@,;:\\\"\t []/?=";
// The EOF Token
private final static Token EOFToken = new Token(Token.EOF, null);
/**
* Constructor that takes a rfc822 style header.
*
* @param header The rfc822 header to be tokenized
* @param delimiters Set of delimiter characters
* to be used to delimit ATOMS. These
* are usually <code>RFC822</code> or
* <code>MIME</code>
* @param skipComments If true, comments are skipped and
* not returned as tokens
*/
HeaderTokenizer(String header, String delimiters,
boolean skipComments) {
string = (header == null) ? "" : header; // paranoia ?!
this.skipComments = skipComments;
this.delimiters = delimiters;
currentPos = nextPos = peekPos = 0;
maxPos = string.length();
}
/**
* Constructor. Comments are ignored and not returned as tokens
*
* @param header The header that is tokenized
* @param delimiters The delimiters to be used
*/
HeaderTokenizer(String header, String delimiters) {
this(header, delimiters, true);
}
/**
* Constructor. The RFC822 defined delimiters - RFC822 - are
* used to delimit ATOMS. Also comments are skipped and not
* returned as tokens
*/
HeaderTokenizer(String header) {
this(header, RFC822);
}
/**
* Parses the next token from this String. <p>
*
* Clients sit in a loop calling next() to parse successive
* tokens until an EOF Token is returned.
*
* @return the next Token
* @exception WebServiceException if the parse fails
*/
Token next() throws WebServiceException {
Token tk;
currentPos = nextPos; // setup currentPos
tk = getNext();
nextPos = peekPos = currentPos; // update currentPos and peekPos
return tk;
}
/**
* Peek at the next token, without actually removing the token
* from the parse stream. Invoking this method multiple times
* will return successive tokens, until <code>next()</code> is
* called. <p>
*
* @return the next Token
* @exception WebServiceException if the parse fails
*/
Token peek() throws WebServiceException {
Token tk;
currentPos = peekPos; // setup currentPos
tk = getNext();
peekPos = currentPos; // update peekPos
return tk;
}
/**
* Return the rest of the Header.
*
* @return String rest of header. null is returned if we are
* already at end of header
*/
String getRemainder() {
return string.substring(nextPos);
}
/*
* Return the next token starting from 'currentPos'. After the
* parse, 'currentPos' is updated to point to the start of the
* next token.
*/
private Token getNext() throws WebServiceException {
// If we're already at end of string, return EOF
if (currentPos >= maxPos)
return EOFToken;
// Skip white-space, position currentPos beyond the space
if (skipWhiteSpace() == Token.EOF)
return EOFToken;
char c;
int start;
boolean filter = false;
c = string.charAt(currentPos);
// Check or Skip comments and position currentPos
// beyond the comment
while (c == '(') {
// Parsing comment ..
int nesting;
for (start = ++currentPos, nesting = 1;
nesting > 0 && currentPos < maxPos;
currentPos++) {
c = string.charAt(currentPos);
if (c == '\\') { // Escape sequence
currentPos++; // skip the escaped character
filter = true;
} else if (c == '\r')
filter = true;
else if (c == '(')
nesting++;
else if (c == ')')
nesting--;
}
if (nesting != 0)
throw new WebServiceException("Unbalanced comments");
if (!skipComments) {
// Return the comment, if we are asked to.
// Note that the comment start & end markers are ignored.
String s;
if (filter) // need to go thru the token again.
s = filterToken(string, start, currentPos-1);
else
s = string.substring(start,currentPos-1);
return new Token(Token.COMMENT, s);
}
// Skip any whitespace after the comment.
if (skipWhiteSpace() == Token.EOF)
return EOFToken;
c = string.charAt(currentPos);
}
// Check for quoted-string and position currentPos
// beyond the terminating quote
if (c == '"') {
for (start = ++currentPos; currentPos < maxPos; currentPos++) {
c = string.charAt(currentPos);
if (c == '\\') { // Escape sequence
currentPos++;
filter = true;
} else if (c == '\r')
filter = true;
else if (c == '"') {
currentPos++;
String s;
if (filter)
s = filterToken(string, start, currentPos-1);
else
s = string.substring(start,currentPos-1);
return new Token(Token.QUOTEDSTRING, s);
}
}
throw new WebServiceException("Unbalanced quoted string");
}
// Check for SPECIAL or CTL
if (c < 040 || c >= 0177 || delimiters.indexOf(c) >= 0) {
currentPos++; // re-position currentPos
char ch[] = new char[1];
ch[0] = c;
return new Token((int)c, new String(ch));
}
// Check for ATOM
for (start = currentPos; currentPos < maxPos; currentPos++) {
c = string.charAt(currentPos);
// ATOM is delimited by either SPACE, CTL, "(", <">
// or the specified SPECIALS
if (c < 040 || c >= 0177 || c == '(' || c == ' ' ||
c == '"' || delimiters.indexOf(c) >= 0)
break;
}
return new Token(Token.ATOM, string.substring(start, currentPos));
}
// Skip SPACE, HT, CR and NL
private int skipWhiteSpace() {
char c;
for (; currentPos < maxPos; currentPos++)
if (((c = string.charAt(currentPos)) != ' ') &&
(c != '\t') && (c != '\r') && (c != '\n'))
return currentPos;
return Token.EOF;
}
/* Process escape sequences and embedded LWSPs from a comment or
* quoted string.
*/
private static String filterToken(String s, int start, int end) {
StringBuffer sb = new StringBuffer();
char c;
boolean gotEscape = false;
boolean gotCR = false;
for (int i = start; i < end; i++) {
c = s.charAt(i);
if (c == '\n' && gotCR) {
// This LF is part of an unescaped
// CRLF sequence (i.e, LWSP). Skip it.
gotCR = false;
continue;
}
gotCR = false;
if (!gotEscape) {
// Previous character was NOT '\'
if (c == '\\') // skip this character
gotEscape = true;
else if (c == '\r') // skip this character
gotCR = true;
else // append this character
sb.append(c);
} else {
// Previous character was '\'. So no need to
// bother with any special processing, just
// append this character
sb.append(c);
gotEscape = false;
}
}
return sb.toString();
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 1997, 2012, 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 javax.activation.DataContentHandler;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataSource;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.datatransfer.DataFlavor;
import java.util.logging.Logger;
import java.util.Iterator;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.util.Arrays;
/**
* @author Jitendra Kotamraju
*/
public class ImageDataContentHandler extends Component
implements DataContentHandler {
private static final Logger log = Logger.getLogger(ImageDataContentHandler.class.getName());
private final DataFlavor[] flavor;
public ImageDataContentHandler() {
String[] mimeTypes = ImageIO.getReaderMIMETypes();
flavor = new DataFlavor[mimeTypes.length];
for(int i=0; i < mimeTypes.length; i++) {
flavor[i] = new ActivationDataFlavor(Image.class, mimeTypes[i], "Image");
}
}
/**
* Returns an array of DataFlavor objects indicating the flavors the
* data can be provided in. The array should be ordered according to
* preference for providing the data (from most richly descriptive to
* least descriptive).
*
* @return The DataFlavors.
*/
public DataFlavor[] getTransferDataFlavors() {
return Arrays.copyOf(flavor, flavor.length);
}
/**
* Returns an object which represents the data to be transferred.
* The class of the object returned is defined by the representation class
* of the flavor.
*
* @param df The DataFlavor representing the requested type.
* @param ds The DataSource representing the data to be converted.
* @return The constructed Object.
*/
public Object getTransferData(DataFlavor df, DataSource ds)
throws IOException {
for (DataFlavor aFlavor : flavor) {
if (aFlavor.equals(df)) {
return getContent(ds);
}
}
return null;
}
/**
* Return an object representing the data in its most preferred form.
* Generally this will be the form described by the first DataFlavor
* returned by the <code>getTransferDataFlavors</code> method.
*
* @param ds The DataSource representing the data to be converted.
* @return The constructed Object.
*/
public Object getContent(DataSource ds) throws IOException {
return ImageIO.read(new BufferedInputStream(ds.getInputStream()));
}
/**
* Convert the object to a byte stream of the specified MIME type
* and write it to the output stream.
*
* @param obj The object to be converted.
* @param type The requested MIME type of the resulting byte stream.
* @param os The output stream into which to write the converted
* byte stream.
*/
public void writeTo(Object obj, String type, OutputStream os)
throws IOException {
try {
BufferedImage bufImage;
if (obj instanceof BufferedImage) {
bufImage = (BufferedImage)obj;
} else if (obj instanceof Image) {
bufImage = render((Image)obj);
} else {
throw new IOException(
"ImageDataContentHandler requires Image object, "
+ "was given object of type "
+ obj.getClass().toString());
}
ImageWriter writer = null;
Iterator<ImageWriter> i = ImageIO.getImageWritersByMIMEType(type);
if (i.hasNext()) {
writer = i.next();
}
if (writer != null) {
ImageOutputStream stream = ImageIO.createImageOutputStream(os);
writer.setOutput(stream);
writer.write(bufImage);
writer.dispose();
stream.close();
} else {
throw new IOException("Unsupported mime type:"+ type);
}
} catch (Exception e) {
throw new IOException("Unable to encode the image to a stream "
+ e.getMessage());
}
}
private BufferedImage render(Image img) throws InterruptedException {
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(img, 0);
tracker.waitForAll();
BufferedImage bufImage = new BufferedImage(img.getWidth(null),
img.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics g = bufImage.createGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
return bufImage;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1997, 2012, 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.xml.internal.org.jvnet.mimepull.MIMEPart;
import javax.activation.DataSource;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.File;
import com.sun.xml.internal.ws.developer.StreamingDataHandler;
/**
* Implementation of {@link StreamingDataHandler} to access MIME
* attachments efficiently. Applications can use the additional methods and decide
* on how to access the attachment data in JAX-WS applications.
*
* <p>
* for e.g.:
*
* DataHandler dh = proxy.getData();
* StreamingDataHandler sdh = (StreamingDataHandler)dh;
* // readOnce() doesn't store attachment on the disk in some cases
* // for e.g when only one huge attachment after soap envelope part in MIME message
* InputStream in = sdh.readOnce();
* ...
* in.close();
* sdh.close();
*
* @author Jitendra Kotamraju
*/
public class MIMEPartStreamingDataHandler extends StreamingDataHandler {
private final StreamingDataSource ds;
public MIMEPartStreamingDataHandler(MIMEPart part) {
super(new StreamingDataSource(part));
ds = (StreamingDataSource)getDataSource();
}
@Override
public InputStream readOnce() throws IOException {
return ds.readOnce();
}
@Override
public void moveTo(File file) throws IOException {
ds.moveTo(file);
}
@Override
public void close() throws IOException {
ds.close();
}
private static final class StreamingDataSource implements DataSource {
private final MIMEPart part;
StreamingDataSource(MIMEPart part) {
this.part = part;
}
@Override
public InputStream getInputStream() throws IOException {
return part.read(); //readOnce() ??
}
InputStream readOnce() throws IOException {
try {
return part.readOnce();
} catch(Exception e) {
throw new MyIOException(e);
}
}
void moveTo(File file) throws IOException {
part.moveTo(file);
}
@Override
public OutputStream getOutputStream() throws IOException {
return null;
}
@Override
public String getContentType() {
return part.getContentType();
}
@Override
public String getName() {
return "";
}
public void close() throws IOException {
part.close();
}
}
private static final class MyIOException extends IOException {
private final Exception linkedException;
MyIOException(Exception linkedException) {
this.linkedException = linkedException;
}
@Override
public Throwable getCause() {
return linkedException;
}
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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.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.AttachmentEx;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ReadableByteChannel;
import java.util.Iterator;
import java.util.UUID;
/**
* {@link Codec}s that uses the MIME multipart as the underlying format.
*
* <p>
* When the runtime needs to dynamically choose a {@link Codec}, and
* when there are more than one {@link Codec}s that use MIME multipart,
* it is often impossible to determine the right {@link Codec} unless
* you parse the multipart message to some extent.
*
* <p>
* By having all such {@link Codec}s extending from this class,
* the "sniffer" can decode a multipart message partially, and then
* pass the partial parse result to the ultimately-responsible {@link Codec}.
* This improves the performance.
*
* @author Kohsuke Kawaguchi
*/
abstract class MimeCodec implements Codec {
public static final String MULTIPART_RELATED_MIME_TYPE = "multipart/related";
protected Codec mimeRootCodec;
protected final SOAPVersion version;
protected final WSFeatureList features;
protected MimeCodec(SOAPVersion version, WSFeatureList f) {
this.version = version;
this.features = f;
}
public String getMimeType() {
return MULTIPART_RELATED_MIME_TYPE;
}
protected Codec getMimeRootCodec(Packet packet) {
return mimeRootCodec;
}
// TODO: preencode String literals to byte[] so that they don't have to
// go through char[]->byte[] conversion at runtime.
public ContentType encode(Packet packet, OutputStream out) throws IOException {
Message msg = packet.getMessage();
if (msg == null) {
return null;
}
ContentTypeImpl ctImpl = (ContentTypeImpl)getStaticContentType(packet);
String boundary = ctImpl.getBoundary();
boolean hasAttachments = (boundary != null);
Codec rootCodec = getMimeRootCodec(packet);
if (hasAttachments) {
writeln("--"+boundary, out);
ContentType ct = rootCodec.getStaticContentType(packet);
String ctStr = (ct != null) ? ct.getContentType() : rootCodec.getMimeType();
writeln("Content-Type: " + ctStr, out);
writeln(out);
}
ContentType primaryCt = rootCodec.encode(packet, out);
if (hasAttachments) {
writeln(out);
// Encode all the attchments
for (Attachment att : msg.getAttachments()) {
writeln("--"+boundary, out);
//SAAJ's AttachmentPart.getContentId() returns content id already enclosed with
//angle brackets. For now put angle bracket only if its not there
String cid = att.getContentId();
if(cid != null && cid.length() >0 && cid.charAt(0) != '<')
cid = '<' + cid + '>';
writeln("Content-Id:" + cid, out);
writeln("Content-Type: " + att.getContentType(), out);
writeCustomMimeHeaders(att, out);
writeln("Content-Transfer-Encoding: binary", out);
writeln(out); // write \r\n
att.writeTo(out);
writeln(out); // write \r\n
}
writeAsAscii("--"+boundary, out);
writeAsAscii("--", out);
}
// TODO not returing correct multipart/related type(no boundary)
return hasAttachments ? ctImpl : primaryCt;
}
private void writeCustomMimeHeaders(Attachment att, OutputStream out) throws IOException {
if (att instanceof AttachmentEx) {
Iterator<AttachmentEx.MimeHeader> allMimeHeaders = ((AttachmentEx) att).getMimeHeaders();
while (allMimeHeaders.hasNext()) {
AttachmentEx.MimeHeader mh = allMimeHeaders.next();
String name = mh.getName();
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Id".equalsIgnoreCase(name)) {
writeln(name +": " + mh.getValue(), out);
}
}
}
}
public ContentType getStaticContentType(Packet packet) {
ContentType ct = (ContentType) packet.getInternalContentType();
if ( ct != null ) return ct;
Message msg = packet.getMessage();
boolean hasAttachments = !msg.getAttachments().isEmpty();
Codec rootCodec = getMimeRootCodec(packet);
if (hasAttachments) {
String boundary = "uuid:" + UUID.randomUUID().toString();
String boundaryParameter = "boundary=\"" + boundary + "\"";
// TODO use primaryEncoder to get type
String messageContentType = MULTIPART_RELATED_MIME_TYPE +
"; type=\"" + rootCodec.getMimeType() + "\"; " +
boundaryParameter;
ContentTypeImpl impl = new ContentTypeImpl(messageContentType, packet.soapAction, null);
impl.setBoundary(boundary);
impl.setBoundaryParameter(boundaryParameter);
packet.setContentType(impl);
return impl;
} else {
ct = rootCodec.getStaticContentType(packet);
packet.setContentType(ct);
return ct;
}
}
/**
* Copy constructor.
*/
protected MimeCodec(MimeCodec that) {
this.version = that.version;
this.features = that.features;
}
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
MimeMultipartParser parser = new MimeMultipartParser(in, contentType, features.get(StreamingAttachmentFeature.class));
decode(parser,packet);
}
public void decode(ReadableByteChannel in, String contentType, Packet packet) {
throw new UnsupportedOperationException();
}
/**
* Parses a {@link Packet} from a {@link MimeMultipartParser}.
*/
protected abstract void decode(MimeMultipartParser mpp, Packet packet) throws IOException;
public abstract MimeCodec copy();
public static void writeln(String s,OutputStream out) throws IOException {
writeAsAscii(s,out);
writeln(out);
}
/**
* Writes a string as ASCII string.
*/
public static void writeAsAscii(String s,OutputStream out) throws IOException {
int len = s.length();
for( int i=0; i<len; i++ )
out.write((byte)s.charAt(i));
}
public static void writeln(OutputStream out) throws IOException {
out.write('\r');
out.write('\n');
}
}

View File

@@ -0,0 +1,275 @@
/*
* 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.istack.internal.Nullable;
import com.sun.xml.internal.ws.api.message.Attachment;
import com.sun.xml.internal.ws.api.message.AttachmentEx;
import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
import com.sun.xml.internal.ws.developer.StreamingDataHandler;
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
import com.sun.xml.internal.ws.util.ByteArrayDataSource;
import com.sun.xml.internal.org.jvnet.mimepull.Header;
import com.sun.xml.internal.org.jvnet.mimepull.MIMEMessage;
import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart;
import javax.activation.DataHandler;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.WebServiceException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Parses Mime multipart message into primary part and attachment parts. It
* parses the stream lazily as and when required.
*
* @author Vivek Pandey
* @author Jitendra Kotamraju
*/
public final class MimeMultipartParser {
private final String start;
private final MIMEMessage message;
private Attachment root;
private ContentTypeImpl contentType;
// Attachments without root part
private final Map<String, Attachment> attachments = new HashMap<String, Attachment>();
private boolean gotAll;
public MimeMultipartParser(InputStream in, String cType, StreamingAttachmentFeature feature) {
this.contentType = new ContentTypeImpl(cType);
// ContentType ct = new ContentType(cType);
// String boundary = ct.getParameter("boundary");
String boundary = contentType.getBoundary();
if (boundary == null || boundary.equals("")) {
throw new WebServiceException("MIME boundary parameter not found" + contentType);
}
message = (feature != null)
? new MIMEMessage(in, boundary, feature.getConfig())
: new MIMEMessage(in, boundary);
// Strip <...> from root part's Content-ID
// String st = ct.getParameter("start");
String st = contentType.getRootId();
if (st != null && st.length() > 2 && st.charAt(0) == '<' && st.charAt(st.length()-1) == '>') {
st = st.substring(1, st.length()-1);
}
start = st;
}
/**
* Parses the stream and returns the root part. If start parameter is
* present in Content-Type, it is used to determine the root part, otherwise
* root part is the first part.
*
* @return StreamAttachment for root part
* null if root part cannot be found
*
*/
public @Nullable Attachment getRootPart() {
if (root == null) {
root = new PartAttachment((start != null) ? message.getPart(start) : message.getPart(0));
}
return root;
}
/**
* Parses the entire stream and returns all MIME parts except root MIME part.
*
* @return Map<String, StreamAttachment> for all attachment parts
*/
public @NotNull Map<String, Attachment> getAttachmentParts() {
if (!gotAll) {
MIMEPart rootPart = (start != null) ? message.getPart(start) : message.getPart(0);
List<MIMEPart> parts = message.getAttachments();
for(MIMEPart part : parts) {
if (part != rootPart) {
String cid = part.getContentId();
if (!attachments.containsKey(cid)) {
PartAttachment attach = new PartAttachment(part);
attachments.put(attach.getContentId(), attach);
}
}
}
gotAll = true;
}
return attachments;
}
/**
* This method can be called to get a matching MIME attachment part for the
* given contentId. It parses the stream until it finds a matching part.
*
* @return StreamAttachment attachment for contentId
* null if there is no attachment for contentId
*/
public @Nullable Attachment getAttachmentPart(String contentId) throws IOException {
//first see if this attachment is already parsed, if so return it
Attachment attach = attachments.get(contentId);
if (attach == null) {
MIMEPart part = message.getPart(contentId);
attach = new PartAttachment(part);
attachments.put(contentId, attach);
}
return attach;
}
static class PartAttachment implements AttachmentEx {
final MIMEPart part;
byte[] buf;
private StreamingDataHandler streamingDataHandler;
PartAttachment(MIMEPart part) {
this.part = part;
}
public @NotNull @Override String getContentId() {
return part.getContentId();
}
public @NotNull @Override String getContentType() {
return part.getContentType();
}
@Override
public byte[] asByteArray() {
if (buf == null) {
ByteArrayBuffer baf = new ByteArrayBuffer();
try {
baf.write(part.readOnce());
} catch(IOException ioe) {
throw new WebServiceException(ioe);
} finally {
if (baf != null) {
try {
baf.close();
} catch (IOException ex) {
Logger.getLogger(MimeMultipartParser.class.getName()).log(Level.FINE, null, ex);
}
}
}
buf = baf.toByteArray();
}
return buf;
}
@Override
public DataHandler asDataHandler() {
if (streamingDataHandler == null) {
streamingDataHandler = (buf != null)
? new DataSourceStreamingDataHandler(new ByteArrayDataSource(buf,getContentType()))
: new MIMEPartStreamingDataHandler(part);
}
return streamingDataHandler;
}
@Override
public Source asSource() {
return (buf != null)
? new StreamSource(new ByteArrayInputStream(buf))
: new StreamSource(part.read());
}
@Override
public InputStream asInputStream() {
return (buf != null)
? new ByteArrayInputStream(buf) : part.read();
}
@Override
public void writeTo(OutputStream os) throws IOException {
if (buf != null) {
os.write(buf);
} else {
InputStream in = part.read();
byte[] temp = new byte[8192];
int len;
while((len=in.read(temp)) != -1) {
os.write(temp, 0, len);
}
in.close();
}
}
@Override
public void writeTo(SOAPMessage saaj) throws SOAPException {
saaj.createAttachmentPart().setDataHandler(asDataHandler());
}
// AttachmentEx methods begin here
@Override
public Iterator<MimeHeader> getMimeHeaders() {
final Iterator<? extends Header> ih = part.getAllHeaders()
.iterator();
return new Iterator<MimeHeader>() {
@Override
public boolean hasNext() {
return ih.hasNext();
}
@Override
public MimeHeader next() {
final Header hdr = ih.next();
return new AttachmentEx.MimeHeader() {
@Override
public String getValue() {
return hdr.getValue();
}
@Override
public String getName() {
return hdr.getName();
}
};
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
public ContentTypeImpl getContentType() {
return contentType;
}
}

View File

@@ -0,0 +1,662 @@
/*
* 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;
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 1997, 2012, 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 javax.xml.ws.WebServiceException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* This class holds MIME parameters (attribute-value pairs).
*
* @version 1.10, 03/02/12
* @author John Mani
*/
final class ParameterList {
private final Map<String, String> list;
/**
* Constructor that takes a parameter-list string. The String
* is parsed and the parameters are collected and stored internally.
* A ParseException is thrown if the parse fails.
* Note that an empty parameter-list string is valid and will be
* parsed into an empty ParameterList.
*
* @param s the parameter-list string.
* @exception WebServiceException if the parse fails.
*/
ParameterList(String s) {
HeaderTokenizer h = new HeaderTokenizer(s, HeaderTokenizer.MIME);
HeaderTokenizer.Token tk;
int type;
String name;
list = new HashMap<String, String>();
while (true) {
tk = h.next();
type = tk.getType();
if (type == HeaderTokenizer.Token.EOF) // done
return;
if ((char)type == ';') {
// expect parameter name
tk = h.next();
// tolerate trailing semicolon, even though it violates the spec
if (tk.getType() == HeaderTokenizer.Token.EOF)
return;
// parameter name must be a MIME Atom
if (tk.getType() != HeaderTokenizer.Token.ATOM)
throw new WebServiceException();
name = tk.getValue().toLowerCase();
// expect '='
tk = h.next();
if ((char)tk.getType() != '=')
throw new WebServiceException();
// expect parameter value
tk = h.next();
type = tk.getType();
// parameter value must be a MIME Atom or Quoted String
if (type != HeaderTokenizer.Token.ATOM &&
type != HeaderTokenizer.Token.QUOTEDSTRING)
throw new WebServiceException();
list.put(name, tk.getValue());
} else
throw new WebServiceException();
}
}
/**
* Return the number of parameters in this list.
*
* @return number of parameters.
*/
int size() {
return list.size();
}
/**
* Returns the value of the specified parameter. Note that
* parameter names are case-insensitive.
*
* @param name parameter name.
* @return Value of the parameter. Returns
* <code>null</code> if the parameter is not
* present.
*/
String get(String name) {
return list.get(name.trim().toLowerCase());
}
/**
* Return an enumeration of the names of all parameters in this
* list.
*
* @return Enumeration of all parameter names in this list.
*/
Iterator<String> getNames() {
return list.keySet().iterator();
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 1997, 2012, 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.ws.api.message.AttachmentSet;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Codec;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.ReadableByteChannel;
/**
* {@link Codec} that works only on the root part of the MIME/multipart.
* It doesn't work on the attachment parts, so it takes {@link AttachmentSet}
* as an argument and creates a corresponding {@link Message}. This enables
* attachments to be parsed lazily by wrapping the mimepull parser into an
* {@link AttachmentSet}
*
* @author Jitendra Kotamraju
*/
public interface RootOnlyCodec extends Codec {
/**
* Reads root part bytes from {@link InputStream} and constructs a {@link Message}
* along with the given attachments.
*
* @param in root part's data
*
* @param contentType root part's MIME content type (like "application/xml")
*
* @param packet the new created {@link Message} is set in this packet
*
* @param att attachments
*
* @throws IOException
* if {@link InputStream} throws an exception.
*/
void decode(@NotNull InputStream in, @NotNull String contentType, @NotNull Packet packet, @NotNull AttachmentSet att)
throws IOException;
/**
*
* @see #decode(InputStream, String, Packet, AttachmentSet)
*/
void decode(@NotNull ReadableByteChannel in, @NotNull String contentType, @NotNull Packet packet, @NotNull AttachmentSet att);
}

View File

@@ -0,0 +1,484 @@
/*
* 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.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.client.SelectOptimalEncodingFeature;
import com.sun.xml.internal.ws.api.fastinfoset.FastInfosetFeature;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.message.ExceptionHasMessage;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.Codecs;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
import com.sun.xml.internal.ws.client.ContentNegotiation;
import com.sun.xml.internal.ws.protocol.soap.MessageCreationException;
import com.sun.xml.internal.ws.resources.StreamingMessages;
import com.sun.xml.internal.ws.server.UnsupportedMediaException;
import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.MTOMFeature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
//import java.util.StringTokenizer;
/**
* SOAP binding {@link Codec} that can handle MTOM, SwA, and SOAP messages
* encoded using XML or Fast Infoset.
*
* <p>
* This is used when we need to determine the encoding from what we received (for decoding)
* and from configuration and {@link Message} contents (for encoding)
*
* <p>
* TODO: Split this Codec into two, one that supports FI and one that does not.
* Then further split the FI Codec into two, one for client and one for
* server. This will simplify the logic and make it easier to understand/maintain.
*
* @author Vivek Pandey
* @author Kohsuke Kawaguchi
*/
public class SOAPBindingCodec extends MimeCodec implements com.sun.xml.internal.ws.api.pipe.SOAPBindingCodec {
public static final String UTF8_ENCODING = "utf-8";
public static final String DEFAULT_ENCODING = UTF8_ENCODING;
/**
* True if Fast Infoset functionality has been
* configured to be disabled, or the Fast Infoset
* runtime is not available.
*/
private boolean isFastInfosetDisabled;
/**
* True if the Fast Infoset codec should be used for encoding.
*/
private boolean useFastInfosetForEncoding;
/**
* True if the content negotiation property should
* be ignored by the client. This will be used in
* the case of Fast Infoset being configured to be
* disabled or automatically selected.
*/
private boolean ignoreContentNegotiationProperty;
// The XML SOAP codec
private final StreamSOAPCodec xmlSoapCodec;
// The Fast Infoset SOAP codec
private final Codec fiSoapCodec;
// The XML MTOM codec
private final MimeCodec xmlMtomCodec;
// The XML SWA codec
private final MimeCodec xmlSwaCodec;
// The Fast Infoset SWA codec
private final MimeCodec fiSwaCodec;
/**
* The XML SOAP MIME type
*/
private final String xmlMimeType;
/**
* The Fast Infoset SOAP MIME type
*/
private final String fiMimeType;
/**
* The Accept header for XML encodings
*/
private final String xmlAccept;
/**
* The Accept header for Fast Infoset and XML encodings
*/
private final String connegXmlAccept;
public StreamSOAPCodec getXMLCodec() {
return xmlSoapCodec;
}
private ContentTypeImpl setAcceptHeader(Packet p, ContentTypeImpl c) {
String _accept;
if (!ignoreContentNegotiationProperty && p.contentNegotiation != ContentNegotiation.none) {
_accept = connegXmlAccept;
} else {
_accept = xmlAccept;
}
c.setAcceptHeader(_accept);
return c;
}
public SOAPBindingCodec(WSFeatureList features) {
this(features, Codecs.createSOAPEnvelopeXmlCodec(features));
}
public SOAPBindingCodec(WSFeatureList features, StreamSOAPCodec xmlSoapCodec) {
super(getSoapVersion(features), features);
this.xmlSoapCodec = xmlSoapCodec;
xmlMimeType = xmlSoapCodec.getMimeType();
xmlMtomCodec = new MtomCodec(version, xmlSoapCodec, features);
xmlSwaCodec = new SwACodec(version, features, xmlSoapCodec);
String clientAcceptedContentTypes = xmlSoapCodec.getMimeType() + ", " +
xmlMtomCodec.getMimeType();
WebServiceFeature fi = features.get(FastInfosetFeature.class);
isFastInfosetDisabled = (fi != null && !fi.isEnabled());
if (!isFastInfosetDisabled) {
fiSoapCodec = getFICodec(xmlSoapCodec, version);
if (fiSoapCodec != null) {
fiMimeType = fiSoapCodec.getMimeType();
fiSwaCodec = new SwACodec(version, features, fiSoapCodec);
connegXmlAccept = fiMimeType + ", " + clientAcceptedContentTypes;
/**
* This feature will only be present on the client side.
*
* Fast Infoset is enabled on the client if the service
* explicitly supports Fast Infoset.
*/
WebServiceFeature select = features.get(SelectOptimalEncodingFeature.class);
if (select != null) { // if the client FI feature is set - ignore negotiation property
ignoreContentNegotiationProperty = true;
if (select.isEnabled()) {
// If the client's FI encoding feature is enabled, and server's is not disabled
if (fi != null) { // if server's FI feature also enabled
useFastInfosetForEncoding = true;
}
clientAcceptedContentTypes = connegXmlAccept;
} else { // If client FI feature is disabled
isFastInfosetDisabled = true;
}
}
} else {
// Fast Infoset could not be loaded by the runtime
isFastInfosetDisabled = true;
fiSwaCodec = null;
fiMimeType = "";
connegXmlAccept = clientAcceptedContentTypes;
ignoreContentNegotiationProperty = true;
}
} else {
// Fast Infoset is explicitly not supported by the service
fiSoapCodec = fiSwaCodec = null;
fiMimeType = "";
connegXmlAccept = clientAcceptedContentTypes;
ignoreContentNegotiationProperty = true;
}
xmlAccept = clientAcceptedContentTypes;
if(getSoapVersion(features) == null)
throw new WebServiceException("Expecting a SOAP binding but found ");
}
public String getMimeType() {
return null;
}
public ContentType getStaticContentType(Packet packet) {
ContentType toAdapt = getEncoder(packet).getStaticContentType(packet);
return setAcceptHeader(packet, (ContentTypeImpl)toAdapt);
}
public ContentType encode(Packet packet, OutputStream out) throws IOException {
preEncode(packet);
ContentType ct = getEncoder(packet).encode(packet, out);
ct = setAcceptHeader(packet, (ContentTypeImpl)ct);
postEncode();
return ct;
}
public ContentType encode(Packet packet, WritableByteChannel buffer) {
preEncode(packet);
ContentType ct = getEncoder(packet).encode(packet, buffer);
ct = setAcceptHeader(packet, (ContentTypeImpl)ct);
postEncode();
return ct;
}
/**
* Should be called before encode().
* Set the state so that such state is used by encode process.
*/
private void preEncode(Packet p) {
}
/**
* Should be called after encode()
* Reset the encoding state.
*/
private void postEncode() {
}
/**
* Should be called before decode().
* Set the state so that such state is used by decode().
*/
private void preDecode(Packet p) {
if (p.contentNegotiation == null)
useFastInfosetForEncoding = false;
}
/**
* Should be called after decode().
* Set the state so that such state is used by encode().
*/
private void postDecode(Packet p) {
p.setFastInfosetDisabled(isFastInfosetDisabled);
if(features.isEnabled(MTOMFeature.class)) p.checkMtomAcceptable();
// p.setMtomAcceptable( isMtomAcceptable(p.acceptableMimeTypes) );
MTOMFeature mtomFeature = features.get(MTOMFeature.class);
if (mtomFeature != null) {
p.setMtomFeature(mtomFeature);
}
if (!useFastInfosetForEncoding) {
useFastInfosetForEncoding = p.getFastInfosetAcceptable(fiMimeType);
// useFastInfosetForEncoding = isFastInfosetAcceptable(p.acceptableMimeTypes);
}
}
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
if (contentType == null) {
contentType = xmlMimeType;
}
packet.setContentType(new ContentTypeImpl(contentType));
preDecode(packet);
try {
if(isMultipartRelated(contentType))
// parse the multipart portion and then decide whether it's MTOM or SwA
super.decode(in, contentType, packet);
else if(isFastInfoset(contentType)) {
if (!ignoreContentNegotiationProperty && packet.contentNegotiation == ContentNegotiation.none)
throw noFastInfosetForDecoding();
useFastInfosetForEncoding = true;
fiSoapCodec.decode(in, contentType, packet);
} else
xmlSoapCodec.decode(in, contentType, packet);
} catch(RuntimeException we) {
if (we instanceof ExceptionHasMessage || we instanceof UnsupportedMediaException) {
throw we;
} else {
throw new MessageCreationException(version, we);
}
}
postDecode(packet);
}
public void decode(ReadableByteChannel in, String contentType, Packet packet) {
if (contentType == null) {
throw new UnsupportedMediaException();
}
preDecode(packet);
try {
if(isMultipartRelated(contentType))
super.decode(in, contentType, packet);
else if(isFastInfoset(contentType)) {
if (packet.contentNegotiation == ContentNegotiation.none)
throw noFastInfosetForDecoding();
useFastInfosetForEncoding = true;
fiSoapCodec.decode(in, contentType, packet);
} else
xmlSoapCodec.decode(in, contentType, packet);
} catch(RuntimeException we) {
if (we instanceof ExceptionHasMessage || we instanceof UnsupportedMediaException) {
throw we;
} else {
throw new MessageCreationException(version, we);
}
}
postDecode(packet);
}
public SOAPBindingCodec copy() {
return new SOAPBindingCodec(features, (StreamSOAPCodec)xmlSoapCodec.copy());
}
@Override
protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException {
// is this SwA or XOP?
final String rootContentType = mpp.getRootPart().getContentType();
boolean isMTOM = isApplicationXopXml(rootContentType);
packet.setMtomRequest(isMTOM);
if(isMTOM) {
xmlMtomCodec.decode(mpp,packet);
} else if (isFastInfoset(rootContentType)) {
if (packet.contentNegotiation == ContentNegotiation.none)
throw noFastInfosetForDecoding();
useFastInfosetForEncoding = true;
fiSwaCodec.decode(mpp,packet);
} else if (isXml(rootContentType))
xmlSwaCodec.decode(mpp,packet);
else {
// TODO localize exception
throw new IOException("");
}
// checkDuplicateKnownHeaders(packet);
}
private boolean isMultipartRelated(String contentType) {
return compareStrings(contentType, MimeCodec.MULTIPART_RELATED_MIME_TYPE);
}
private boolean isApplicationXopXml(String contentType) {
return compareStrings(contentType, MtomCodec.XOP_XML_MIME_TYPE);
}
private boolean isXml(String contentType) {
return compareStrings(contentType, xmlMimeType);
}
private boolean isFastInfoset(String contentType) {
if (isFastInfosetDisabled) return false;
return compareStrings(contentType, fiMimeType);
}
private boolean compareStrings(String a, String b) {
return a.length() >= b.length() &&
b.equalsIgnoreCase(
a.substring(0,
b.length()));
}
// private boolean isFastInfosetAcceptable(String accept) {
// if (accept == null || isFastInfosetDisabled) return false;
//
// StringTokenizer st = new StringTokenizer(accept, ",");
// while (st.hasMoreTokens()) {
// final String token = st.nextToken().trim();
// if (token.equalsIgnoreCase(fiMimeType)) {
// return true;
// }
// }
// return false;
// }
/*
* Just check if the Accept header contains application/xop+xml,
* no need to worry about q values.
*/
// private boolean isMtomAcceptable(String accept) {
// if (accept == null || isFastInfosetDisabled) return false;
// StringTokenizer st = new StringTokenizer(accept, ",");
// while (st.hasMoreTokens()) {
// final String token = st.nextToken().trim();
// if (token.toLowerCase().contains(MtomCodec.XOP_XML_MIME_TYPE)) {
// return true;
// }
// }
// return false;
// }
/**
* Determines the encoding codec.
*/
private Codec getEncoder(Packet p) {
/**
* The following logic is only for outbound packets
* to be encoded by a client.
* For a server the p.contentNegotiation == null.
*/
if (!ignoreContentNegotiationProperty) {
if (p.contentNegotiation == ContentNegotiation.none) {
// The client may have changed the negotiation property from
// pessismistic to none between invocations
useFastInfosetForEncoding = false;
} else if (p.contentNegotiation == ContentNegotiation.optimistic) {
// Always encode using Fast Infoset if in optimisitic mode
useFastInfosetForEncoding = true;
}
}
// Override the MTOM binding for now
// Note: Using FI with MTOM does not make sense
if (useFastInfosetForEncoding) {
final Message m = p.getMessage();
if(m==null || m.getAttachments().isEmpty() || features.isEnabled(MTOMFeature.class))
return fiSoapCodec;
else
return fiSwaCodec;
}
//If the packet does not have a binding, explicitly set the MTOMFeature
//on the packet so that it has a way to determine whether to use MTOM
if (p.getBinding() == null) {
if (features != null) {
p.setMtomFeature(features.get(MTOMFeature.class));
}
}
if (p.shouldUseMtom()) {
return xmlMtomCodec;
}
Message m = p.getMessage();
if(m==null || m.getAttachments().isEmpty())
return xmlSoapCodec;
else
return xmlSwaCodec;
}
private RuntimeException noFastInfosetForDecoding() {
return new RuntimeException(StreamingMessages.FASTINFOSET_DECODING_NOT_ACCEPTED());
}
/**
* Obtain an FI SOAP codec instance using reflection.
*/
private static Codec getFICodec(StreamSOAPCodec soapCodec, SOAPVersion version) {
try {
Class c = Class.forName("com.sun.xml.internal.ws.encoding.fastinfoset.FastInfosetStreamSOAPCodec");
Method m = c.getMethod("create", StreamSOAPCodec.class, SOAPVersion.class);
return (Codec)m.invoke(null, soapCodec, version);
} catch (Exception e) {
// TODO Log that FI cannot be loaded
return null;
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.xml.internal.stream.buffer.XMLStreamBuffer;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.Header;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.message.stream.StreamHeader11;
import javax.xml.stream.XMLStreamReader;
import java.util.Collections;
import java.util.List;
/**
* {@link StreamSOAPCodec} for SOAP 1.1.
*
* @author Paul.Sandoz@Sun.Com
*/
final class StreamSOAP11Codec extends StreamSOAPCodec {
public static final String SOAP11_MIME_TYPE = "text/xml";
public static final String DEFAULT_SOAP11_CONTENT_TYPE =
SOAP11_MIME_TYPE+"; charset="+SOAPBindingCodec.DEFAULT_ENCODING;
private static final List<String> EXPECTED_CONTENT_TYPES = Collections.singletonList(SOAP11_MIME_TYPE);
/*package*/ StreamSOAP11Codec() {
super(SOAPVersion.SOAP_11);
}
/*package*/ StreamSOAP11Codec(WSBinding binding) {
super(binding);
}
/*package*/ StreamSOAP11Codec(WSFeatureList features) {
super(features);
}
public String getMimeType() {
return SOAP11_MIME_TYPE;
}
@Override
protected ContentType getContentType(Packet packet) {
ContentTypeImpl.Builder b = getContenTypeBuilder(packet);
b.soapAction = packet.soapAction;
return b.build();
}
@Override
protected String getDefaultContentType() {
return DEFAULT_SOAP11_CONTENT_TYPE;
}
protected List<String> getExpectedContentTypes() {
return EXPECTED_CONTENT_TYPES;
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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.xml.internal.stream.buffer.XMLStreamBuffer;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.Header;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.message.AttachmentSet;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.message.stream.StreamHeader12;
import javax.xml.stream.XMLStreamReader;
import java.util.Collections;
import java.util.List;
import java.io.InputStream;
import java.io.IOException;
/**
* {@link StreamSOAPCodec} for SOAP 1.2.
*
* @author Paul.Sandoz@Sun.Com
*/
final class StreamSOAP12Codec extends StreamSOAPCodec {
public static final String SOAP12_MIME_TYPE = "application/soap+xml";
public static final String DEFAULT_SOAP12_CONTENT_TYPE =
SOAP12_MIME_TYPE+"; charset="+SOAPBindingCodec.DEFAULT_ENCODING;
private static final List<String> EXPECTED_CONTENT_TYPES = Collections.singletonList(SOAP12_MIME_TYPE);
/*package*/ StreamSOAP12Codec() {
super(SOAPVersion.SOAP_12);
}
/*package*/ StreamSOAP12Codec(WSBinding binding) {
super(binding);
}
/*package*/ StreamSOAP12Codec(WSFeatureList features) {
super(features);
}
public String getMimeType() {
return SOAP12_MIME_TYPE;
}
@Override
protected ContentType getContentType(Packet packet) {
ContentTypeImpl.Builder b = getContenTypeBuilder(packet);
// TODO: set accept header
if (packet.soapAction == null) {
return b.build();
} else {
b.contentType = b.contentType + ";action="+fixQuotesAroundSoapAction(packet.soapAction);
return b.build();
}
}
@Override
public void decode(InputStream in, String contentType, Packet packet, AttachmentSet att ) throws IOException {
com.sun.xml.internal.ws.encoding.ContentType ct = new com.sun.xml.internal.ws.encoding.ContentType(contentType);
packet.soapAction = fixQuotesAroundSoapAction(ct.getParameter("action"));
super.decode(in,contentType,packet,att);
}
private String fixQuotesAroundSoapAction(String soapAction) {
if(soapAction != null && (!soapAction.startsWith("\"") || !soapAction.endsWith("\"")) ) {
String fixedSoapAction = soapAction;
if(!soapAction.startsWith("\""))
fixedSoapAction = "\"" + fixedSoapAction;
if(!soapAction.endsWith("\""))
fixedSoapAction = fixedSoapAction + "\"";
return fixedSoapAction;
}
return soapAction;
}
protected List<String> getExpectedContentTypes() {
return EXPECTED_CONTENT_TYPES;
}
@Override
protected String getDefaultContentType() {
return DEFAULT_SOAP12_CONTENT_TYPE;
}
}

View File

@@ -0,0 +1,327 @@
/*
* 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 static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
import com.oracle.webservices.internal.impl.encoding.StreamDecoderImpl;
import com.oracle.webservices.internal.impl.internalspi.encoding.StreamDecoder;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
import com.sun.xml.internal.stream.buffer.XMLStreamBufferMark;
import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferCreator;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.AttachmentSet;
import com.sun.xml.internal.ws.api.message.Header;
import com.sun.xml.internal.ws.api.message.HeaderList;
import com.sun.xml.internal.ws.api.message.Message;
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.streaming.XMLStreamWriterFactory;
import com.sun.xml.internal.ws.developer.SerializationFeature;
import com.sun.xml.internal.ws.message.AttachmentSetImpl;
import com.sun.xml.internal.ws.message.stream.StreamMessage;
import com.sun.xml.internal.ws.protocol.soap.VersionMismatchException;
import com.sun.xml.internal.ws.server.UnsupportedMediaException;
import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
import com.sun.xml.internal.ws.util.ServiceFinder;
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 java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A stream SOAP codec.
*
* @author Paul Sandoz
*/
@SuppressWarnings({"StringEquality"})
public abstract class StreamSOAPCodec implements com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec, RootOnlyCodec {
private static final String SOAP_ENVELOPE = "Envelope";
private static final String SOAP_HEADER = "Header";
private static final String SOAP_BODY = "Body";
private final SOAPVersion soapVersion;
protected final SerializationFeature serializationFeature;
private final StreamDecoder streamDecoder;
// charset of last decoded message. Will be used for encoding server's
// response messages with the request message's encoding
// it will stored in the packet.invocationProperties
private final static String DECODED_MESSAGE_CHARSET = "decodedMessageCharset";
/*package*/ StreamSOAPCodec(SOAPVersion soapVersion) {
this(soapVersion, null);
}
/*package*/ StreamSOAPCodec(WSBinding binding) {
this(binding.getSOAPVersion(), binding.getFeature(SerializationFeature.class));
}
StreamSOAPCodec(WSFeatureList features) {
this(getSoapVersion(features), features.get(SerializationFeature.class));
}
private StreamSOAPCodec(SOAPVersion soapVersion, @Nullable SerializationFeature sf) {
this.soapVersion = soapVersion;
this.serializationFeature = sf;
this.streamDecoder = selectStreamDecoder();
}
private StreamDecoder selectStreamDecoder() {
for (StreamDecoder sd : ServiceFinder.find(StreamDecoder.class)) {
return sd;
}
return new StreamDecoderImpl();
}
public ContentType getStaticContentType(Packet packet) {
return getContentType(packet);
}
public ContentType encode(Packet packet, OutputStream out) {
if (packet.getMessage() != null) {
String encoding = getPacketEncoding(packet);
packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET);
XMLStreamWriter writer = XMLStreamWriterFactory.create(out, encoding);
try {
packet.getMessage().writeTo(writer);
writer.flush();
} catch (XMLStreamException e) {
throw new WebServiceException(e);
}
XMLStreamWriterFactory.recycle(writer);
}
return getContentType(packet);
}
protected abstract ContentType getContentType(Packet packet);
protected abstract String getDefaultContentType();
public ContentType encode(Packet packet, WritableByteChannel buffer) {
//TODO: not yet implemented
throw new UnsupportedOperationException();
}
protected abstract List<String> getExpectedContentTypes();
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
decode(in, contentType, packet, new AttachmentSetImpl());
}
/*
* Checks against expected Content-Type headers that is handled by a codec
*
* @param ct the Content-Type of the request
* @param expected expected Content-Types for a codec
* @return true if the codec supports this Content-Type
* false otherwise
*/
private static boolean isContentTypeSupported(String ct, List<String> expected) {
for(String contentType : expected) {
if (ct.contains(contentType)) {
return true;
}
}
return false;
}
/**
* Decodes a message from {@link XMLStreamReader} that points to
* the beginning of a SOAP infoset.
*
* @param reader
* can point to the start document or the start element.
*/
public final @NotNull Message decode(@NotNull XMLStreamReader reader) {
return decode(reader,new AttachmentSetImpl());
}
/**
* Decodes a message from {@link XMLStreamReader} that points to
* the beginning of a SOAP infoset.
*
* @param reader
* can point to the start document or the start element.
* @param attachmentSet
* {@link StreamSOAPCodec} can take attachments parsed outside,
* so that this codec can be used as a part of a biggre codec
* (like MIME multipart codec.)
*/
public final Message decode(XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) {
return decode(soapVersion, reader, attachmentSet);
}
public static final Message decode(SOAPVersion soapVersion, XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) {
// Move to soap:Envelope and verify
if(reader.getEventType()!=XMLStreamConstants.START_ELEMENT)
XMLStreamReaderUtil.nextElementContent(reader);
XMLStreamReaderUtil.verifyReaderState(reader,XMLStreamConstants.START_ELEMENT);
if (SOAP_ENVELOPE.equals(reader.getLocalName()) && !soapVersion.nsUri.equals(reader.getNamespaceURI())) {
throw new VersionMismatchException(soapVersion, soapVersion.nsUri, reader.getNamespaceURI());
}
XMLStreamReaderUtil.verifyTag(reader, soapVersion.nsUri, SOAP_ENVELOPE);
return new StreamMessage(soapVersion, reader, attachmentSet);
}
public void decode(ReadableByteChannel in, String contentType, Packet packet ) {
throw new UnsupportedOperationException();
}
public final StreamSOAPCodec copy() {
return this;
}
public void decode(InputStream in, String contentType, Packet packet, AttachmentSet att ) throws IOException {
List<String> expectedContentTypes = getExpectedContentTypes();
if (contentType != null && !isContentTypeSupported(contentType,expectedContentTypes)) {
throw new UnsupportedMediaException(contentType, expectedContentTypes);
}
com.oracle.webservices.internal.api.message.ContentType pct = packet.getInternalContentType();
ContentTypeImpl cti = (pct != null && pct instanceof ContentTypeImpl) ?
(ContentTypeImpl)pct : new ContentTypeImpl(contentType);
String charset = cti.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);
}
packet.setMessage(streamDecoder.decode(in, charset, att, soapVersion));
}
public void decode(ReadableByteChannel in, String contentType, Packet response, AttachmentSet att ) {
throw new UnsupportedOperationException();
}
/*
* Creates a new {@link StreamSOAPCodec} instance.
*/
public static StreamSOAPCodec create(SOAPVersion version) {
if(version==null)
// this decoder is for SOAP, not for XML/HTTP
throw new IllegalArgumentException();
switch(version) {
case SOAP_11:
return new StreamSOAP11Codec();
case SOAP_12:
return new StreamSOAP12Codec();
default:
throw new AssertionError();
}
}
/*
* Creates a new {@link StreamSOAPCodec} instance using binding
*/
public static StreamSOAPCodec create(WSFeatureList features) {
SOAPVersion version = getSoapVersion(features);
if(version==null)
// this decoder is for SOAP, not for XML/HTTP
throw new IllegalArgumentException();
switch(version) {
case SOAP_11:
return new StreamSOAP11Codec(features);
case SOAP_12:
return new StreamSOAP12Codec(features);
default:
throw new AssertionError();
}
}
/**
* Creates a new {@link StreamSOAPCodec} instance using binding
*
* @deprecated use {@link #create(WSFeatureList)}
*/
public static StreamSOAPCodec create(WSBinding binding) {
SOAPVersion version = binding.getSOAPVersion();
if(version==null)
// this decoder is for SOAP, not for XML/HTTP
throw new IllegalArgumentException();
switch(version) {
case SOAP_11:
return new StreamSOAP11Codec(binding);
case SOAP_12:
return new StreamSOAP12Codec(binding);
default:
throw new AssertionError();
}
}
private String getPacketEncoding(Packet packet) {
// If SerializationFeature is set, just use that encoding
if (serializationFeature != null && serializationFeature.getEncoding() != null) {
return serializationFeature.getEncoding().equals("")
? SOAPBindingCodec.DEFAULT_ENCODING : serializationFeature.getEncoding();
}
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;
}
protected ContentTypeImpl.Builder getContenTypeBuilder(Packet packet) {
ContentTypeImpl.Builder b = new ContentTypeImpl.Builder();
String encoding = getPacketEncoding(packet);
if (SOAPBindingCodec.DEFAULT_ENCODING.equalsIgnoreCase(encoding)) {
b.contentType = getDefaultContentType();
b.charset = SOAPBindingCodec.DEFAULT_ENCODING;
return b;
}
b.contentType = getMimeType()+" ;charset="+encoding;
b.charset = encoding;
return b;
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1997, 2012, 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 javax.activation.ActivationDataFlavor;
import javax.activation.DataSource;
import javax.activation.DataContentHandler;
import java.awt.datatransfer.DataFlavor;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* JavaMail's data content handler for text/plain -->String
*/
public class StringDataContentHandler implements DataContentHandler {
private static final ActivationDataFlavor myDF = new ActivationDataFlavor(
java.lang.String.class, "text/plain", "Text String");
protected ActivationDataFlavor getDF() {
return myDF;
}
/**
* Return the DataFlavors for this <code>DataContentHandler</code>.
*
* @return The DataFlavors
*/
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{getDF()};
}
/**
* Return the Transfer Data of type DataFlavor from InputStream.
*
* @param df The DataFlavor
* @param ds The DataSource corresponding to the data
* @return String object
*/
public Object getTransferData(DataFlavor df, DataSource ds)
throws IOException {
// use myDF.equals to be sure to get ActivationDataFlavor.equals,
// which properly ignores Content-Type parameters in comparison
if (getDF().equals(df))
return getContent(ds);
else
return null;
}
public Object getContent(DataSource ds) throws IOException {
String enc = null;
InputStreamReader is;
try {
enc = getCharset(ds.getContentType());
is = new InputStreamReader(ds.getInputStream(), enc);
} catch (IllegalArgumentException iex) {
/*
* An unknown charset of the form ISO-XXX-XXX will cause
* the JDK to throw an IllegalArgumentException. The
* JDK will attempt to create a classname using this string,
* but valid classnames must not contain the character '-',
* and this results in an IllegalArgumentException, rather than
* the expected UnsupportedEncodingException. Yikes.
*/
throw new UnsupportedEncodingException(enc);
}
try {
int pos = 0;
int count;
char buf[] = new char[1024];
while ((count = is.read(buf, pos, buf.length - pos)) != -1) {
pos += count;
if (pos >= buf.length) {
int size = buf.length;
if (size < 256 * 1024)
size += size;
else
size += 256 * 1024;
char tbuf[] = new char[size];
System.arraycopy(buf, 0, tbuf, 0, pos);
buf = tbuf;
}
}
return new String(buf, 0, pos);
} finally {
try {
is.close();
} catch (IOException ex) {
// not much can be done
}
}
}
/**
* Write the object to the output stream, using the specified MIME type.
*/
public void writeTo(Object obj, String type, OutputStream os)
throws IOException {
if (!(obj instanceof String))
throw new IOException("\"" + getDF().getMimeType() +
"\" DataContentHandler requires String object, " +
"was given object of type " + obj.getClass().toString());
String enc = null;
OutputStreamWriter osw;
try {
enc = getCharset(type);
osw = new OutputStreamWriter(os, enc);
} catch (IllegalArgumentException iex) {
/*
* An unknown charset of the form ISO-XXX-XXX will cause
* the JDK to throw an IllegalArgumentException. The
* JDK will attempt to create a classname using this string,
* but valid classnames must not contain the character '-',
* and this results in an IllegalArgumentException, rather than
* the expected UnsupportedEncodingException. Yikes.
*/
throw new UnsupportedEncodingException(enc);
}
String s = (String) obj;
osw.write(s, 0, s.length());
osw.flush();
}
private String getCharset(String type) {
try {
ContentType ct = new ContentType(type);
String charset = ct.getParameter("charset");
if (charset == null)
// If the charset parameter is absent, use US-ASCII.
charset = "us-ascii";
return Charset.forName(charset).name();
//return MimeUtility.javaCharset(charset);
} catch (Exception ex) {
return null;
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 1997, 2012, 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.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.message.Attachment;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.message.MimeAttachmentSet;
import java.io.IOException;
import java.nio.channels.WritableByteChannel;
import java.util.Map;
import javax.xml.ws.WebServiceFeature;
/**
* {@link Codec} that uses MIME/multipart as the base format.
*
* @author Jitendra Kotamraju
*/
public final class SwACodec extends MimeCodec {
public SwACodec(SOAPVersion version, WSFeatureList f, Codec rootCodec) {
super(version, f);
this.mimeRootCodec = rootCodec;
}
private SwACodec(SwACodec that) {
super(that);
this.mimeRootCodec = that.mimeRootCodec.copy();
}
@Override
protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException {
// TODO: handle attachments correctly
Attachment root = mpp.getRootPart();
Codec rootCodec = getMimeRootCodec(packet);
if (rootCodec instanceof RootOnlyCodec) {
((RootOnlyCodec)rootCodec).decode(root.asInputStream(),root.getContentType(),packet, new MimeAttachmentSet(mpp));
} else {
rootCodec.decode(root.asInputStream(),root.getContentType(),packet);
Map<String, Attachment> atts = mpp.getAttachmentParts();
for(Map.Entry<String, Attachment> att : atts.entrySet()) {
packet.getMessage().getAttachments().add(att.getValue());
}
}
}
public ContentType encode(Packet packet, WritableByteChannel buffer) {
//TODO: not yet implemented
throw new UnsupportedOperationException();
}
public SwACodec copy() {
return new SwACodec(this);
}
}

View File

@@ -0,0 +1,257 @@
/*
* 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 java.util.List;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.XMLStreamException;
import com.sun.xml.internal.ws.message.stream.StreamMessage;
import com.sun.xml.internal.ws.encoding.StreamSOAPCodec;
import com.sun.istack.internal.Nullable;
import com.sun.istack.internal.NotNull;
/**
* Complete infoset about a start tag.
*
* <p>
* This is used between {@link StreamMessage} and {@link StreamSOAPCodec}
* to capture the infoset of the s:Envelope, s:Header, and s:Body elements.
*
*
* <h3>Design Note</h3>
* <p>
* Since StAX and SAX uses different null vs empty string convention, one has
* to choose which format we store things. It can go either way, but I'm assuming
* that we'll be using StAX more in JAX-WS, so things are kept in the StAX style
* in this class.
*
* @author Kohsuke Kawaguchi
*/
public final class TagInfoset {
/**
* Namespace declarations on this tag. Read-only.
*
* This is an array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }.
*
* URIs/prefixes can be null (StAX-style)
*/
public final @NotNull String[] ns;
/**
* Attributes on this tag. Read-only.
*/
public final @NotNull AttributesImpl atts;
/**
* Prefix of the start tag in stax-style.
*/
public final @Nullable String prefix;
/**
* Namespace URI of the start tag in stax-style.
*/
public final @Nullable String nsUri;
/**
* Local name of the start tag.
*/
public final @NotNull String localName;
/**
* Lazily computed QName (i.e., "foo:bar")
*/
private @Nullable String qname;
public TagInfoset(String nsUri, String localName, String prefix, AttributesImpl atts, String... ns) {
this.nsUri = nsUri;
this.prefix = prefix;
this.localName = localName;
this.atts = atts;
this.ns = ns;
}
/**
* Fills a {@link TagInfoset} object by the current element
* that the reader points to.
*/
public TagInfoset(XMLStreamReader reader) {
prefix = reader.getPrefix();
nsUri = reader.getNamespaceURI();
localName = reader.getLocalName();
int nsc = reader.getNamespaceCount();
if(nsc>0) {
ns = new String[nsc*2];
for(int i=0; i<nsc; i++){
ns[i*2 ] = fixNull(reader.getNamespacePrefix(i));
ns[i*2+1] = fixNull(reader.getNamespaceURI(i));
}
} else {
ns = EMPTY_ARRAY;
}
int ac = reader.getAttributeCount();
if(ac>0) {
atts = new AttributesImpl();
StringBuilder sb = new StringBuilder();
for(int i=0; i< ac;i++){
sb.setLength(0);
String prefix = reader.getAttributePrefix(i);
String localName = reader.getAttributeLocalName(i);
String qname;
if(prefix != null && prefix.length()!=0){
sb.append(prefix);
sb.append(":");
sb.append(localName);
qname = sb.toString();
} else {
qname = localName;
}
atts.addAttribute(
fixNull(reader.getAttributeNamespace(i)),
localName,
qname,
reader.getAttributeType(i),
reader.getAttributeValue(i));
}
} else {
atts = EMPTY_ATTRIBUTES;
}
}
/**
* Writes the start element event.
*/
public void writeStart(ContentHandler contentHandler) throws SAXException {
for( int i=0; i<ns.length; i+=2 )
contentHandler.startPrefixMapping(fixNull(ns[i]),fixNull(ns[i+1]));
contentHandler.startElement(fixNull(nsUri), localName ,getQName(), atts);
}
/**
* Writes the end element event.
*/
public void writeEnd(ContentHandler contentHandler) throws SAXException{
contentHandler.endElement(fixNull(nsUri),localName,getQName());
for( int i=ns.length-2; i>=0; i-=2 ) {
contentHandler.endPrefixMapping(fixNull(ns[i]));
}
}
/**
* Writes the start element event.
*/
public void writeStart(XMLStreamWriter w) throws XMLStreamException {
// write start tag.
if(prefix==null) {
if(nsUri==null)
w.writeStartElement(localName);
else {
//fix Null prefix. otherwise throws XMLStreamException,
// if the namespace URI has not been bound to a prefix
w.writeStartElement("",localName,nsUri);
}
} else {
w.writeStartElement(prefix,localName,nsUri);
}
for( int i=0; i<ns.length; i+=2 ) {
w.writeNamespace(ns[i],ns[i+1]);
}
for( int i=0; i<atts.getLength(); i++ ) {
String nsUri = atts.getURI(i);
if(nsUri==null || nsUri.length() ==0) {
w.writeAttribute(atts.getLocalName(i),atts.getValue(i));
} else {
String rawName = atts.getQName(i);
String prefix = rawName.substring(0,rawName.indexOf(':'));
w.writeAttribute(prefix,nsUri,atts.getLocalName(i),atts.getValue(i));
}
}
}
private String getQName() {
if(qname!=null) return qname;
StringBuilder sb = new StringBuilder();
if(prefix!=null){
sb.append(prefix);
sb.append(':');
sb.append(localName);
qname = sb.toString();
} else {
qname = localName;
}
return qname;
}
private static String fixNull(String s) {
if(s==null) return "";
else return s;
}
private static final String[] EMPTY_ARRAY = new String[0];
private static final AttributesImpl EMPTY_ATTRIBUTES = new AttributesImpl();
public String getNamespaceURI(String prefix) {
int size = ns.length/2;
for(int i=0; i<size; i++){
String p = ns[i*2 ];
String n = ns[i*2+1];
if (prefix.equals(p)) return n;
}
return null;
}
public String getPrefix(String namespaceURI) {
int size = ns.length/2;
for(int i=0; i<size; i++){
String p = ns[i*2 ];
String n = ns[i*2+1];
if (namespaceURI.equals(n)) return p;
}
return null;
}
//Who wants this?
public List<String> allPrefixes(String namespaceURI) {
int size = ns.length/2;
List<String> l = new java.util.ArrayList<String>();
for(int i=0; i<size; i++){
String p = ns[i*2 ];
String n = ns[i*2+1];
if (namespaceURI.equals(n)) l.add(p);
}
return l;
}
}

View File

@@ -0,0 +1,336 @@
/*
* 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.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.client.ContentNegotiation;
import com.sun.xml.internal.ws.encoding.xml.XMLCodec;
import com.sun.xml.internal.ws.encoding.xml.XMLMessage;
import com.sun.xml.internal.ws.encoding.xml.XMLMessage.MessageDataSource;
import com.sun.xml.internal.ws.encoding.xml.XMLMessage.UnknownContent;
import com.sun.xml.internal.ws.encoding.xml.XMLMessage.XMLMultiPart;
import com.sun.xml.internal.ws.resources.StreamingMessages;
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
import javax.activation.DataSource;
import javax.xml.ws.WebServiceException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.channels.WritableByteChannel;
import java.util.StringTokenizer;
/**
* XML (infoset) over HTTP binding {@link Codec}.
* <p>
* TODO: Support FI for multipart/related
* Support FI for MessageDataSource
*
* @author Jitendra Kotamraju
*/
public final class XMLHTTPBindingCodec extends MimeCodec {
/**
* Base HTTP Accept request-header.
*/
private static final String BASE_ACCEPT_VALUE =
"*";
/**
* Fast Infoset MIME type.
*/
private static final String APPLICATION_FAST_INFOSET_MIME_TYPE =
"application/fastinfoset";
/**
* True if the Fast Infoset codec should be used
*/
private boolean useFastInfosetForEncoding;
/**
* The XML codec
*/
private final Codec xmlCodec;
/**
* The FI codec
*/
private final Codec fiCodec;
/**
* The Accept header for XML encodings
*/
private static final String xmlAccept = null;
/**
* The Accept header for Fast Infoset and XML encodings
*/
private static final String fiXmlAccept = APPLICATION_FAST_INFOSET_MIME_TYPE + ", " + BASE_ACCEPT_VALUE;
private ContentTypeImpl setAcceptHeader(Packet p, ContentType c) {
ContentTypeImpl ctImpl = (ContentTypeImpl)c;
if (p.contentNegotiation == ContentNegotiation.optimistic
|| p.contentNegotiation == ContentNegotiation.pessimistic) {
ctImpl.setAcceptHeader(fiXmlAccept);
} else {
ctImpl.setAcceptHeader(xmlAccept);
}
p.setContentType(ctImpl);
return ctImpl;
}
public XMLHTTPBindingCodec(WSFeatureList f) {
super(SOAPVersion.SOAP_11, f);
xmlCodec = new XMLCodec(f);
fiCodec = getFICodec();
}
@Override
public String getMimeType() {
return null;
}
@Override
public ContentType getStaticContentType(Packet packet) {
ContentType ct;
if (packet.getInternalMessage() instanceof MessageDataSource) {
final MessageDataSource mds = (MessageDataSource)packet.getInternalMessage();
if (mds.hasUnconsumedDataSource()) {
ct = getStaticContentType(mds);
return (ct != null)
? setAcceptHeader(packet, ct) //_adaptingContentType.set(packet, ct)
: null;
}
}
ct = super.getStaticContentType(packet);
return (ct != null)
? setAcceptHeader(packet, ct) //_adaptingContentType.set(packet, ct)
: null;
}
@Override
public ContentType encode(Packet packet, OutputStream out) throws IOException {
if (packet.getInternalMessage() instanceof MessageDataSource) {
final MessageDataSource mds = (MessageDataSource)packet.getInternalMessage();
if (mds.hasUnconsumedDataSource())
return setAcceptHeader(packet, encode(mds, out));
}
return setAcceptHeader(packet, super.encode(packet, out));
}
@Override
public ContentType encode(Packet packet, WritableByteChannel buffer) {
throw new UnsupportedOperationException();
}
@Override
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
/**
* Reset the encoding state when on the server side for each
* decode/encode step.
*/
if (packet.contentNegotiation == null)
useFastInfosetForEncoding = false;
if (contentType == null) {
xmlCodec.decode(in, contentType, packet);
} else if (isMultipartRelated(contentType)) {
packet.setMessage(new XMLMultiPart(contentType, in, features));
} else if(isFastInfoset(contentType)) {
if (fiCodec == null) {
throw new RuntimeException(StreamingMessages.FASTINFOSET_NO_IMPLEMENTATION());
}
useFastInfosetForEncoding = true;
fiCodec.decode(in, contentType, packet);
} else if (isXml(contentType)) {
xmlCodec.decode(in, contentType, packet);
} else {
packet.setMessage(new UnknownContent(contentType, in));
}
if (!useFastInfosetForEncoding) {
useFastInfosetForEncoding = isFastInfosetAcceptable(packet.acceptableMimeTypes);
}
}
@Override
protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException {
// This method will never be invoked
}
@Override
public MimeCodec copy() {
return new XMLHTTPBindingCodec(features);
}
private boolean isMultipartRelated(String contentType) {
return compareStrings(contentType, MimeCodec.MULTIPART_RELATED_MIME_TYPE);
}
private boolean isXml(String contentType) {
return compareStrings(contentType, XMLCodec.XML_APPLICATION_MIME_TYPE)
|| compareStrings(contentType, XMLCodec.XML_TEXT_MIME_TYPE)
|| (compareStrings(contentType, "application/")&&(contentType.toLowerCase().indexOf("+xml") != -1));
}
private boolean isFastInfoset(String contentType) {
return compareStrings(contentType, APPLICATION_FAST_INFOSET_MIME_TYPE);
}
private boolean compareStrings(String a, String b) {
return a.length() >= b.length() &&
b.equalsIgnoreCase(
a.substring(0,
b.length()));
}
private boolean isFastInfosetAcceptable(String accept) {
if (accept == null) return false;
StringTokenizer st = new StringTokenizer(accept, ",");
while (st.hasMoreTokens()) {
final String token = st.nextToken().trim();
if (token.equalsIgnoreCase(APPLICATION_FAST_INFOSET_MIME_TYPE)) {
return true;
}
}
return false;
}
private ContentType getStaticContentType(MessageDataSource mds) {
final String contentType = mds.getDataSource().getContentType();
final boolean isFastInfoset = XMLMessage.isFastInfoset(contentType);
if (!requiresTransformationOfDataSource(isFastInfoset,
useFastInfosetForEncoding)) {
return new ContentTypeImpl(contentType);
} else {
return null;
}
}
private ContentType encode(MessageDataSource mds, OutputStream out) {
try {
final boolean isFastInfoset = XMLMessage.isFastInfoset(
mds.getDataSource().getContentType());
DataSource ds = transformDataSource(mds.getDataSource(),
isFastInfoset, useFastInfosetForEncoding, features);
InputStream is = ds.getInputStream();
byte[] buf = new byte[1024];
int count;
while((count=is.read(buf)) != -1) {
out.write(buf, 0, count);
}
return new ContentTypeImpl(ds.getContentType());
} catch(IOException ioe) {
throw new WebServiceException(ioe);
}
}
@Override
protected Codec getMimeRootCodec(Packet p) {
/**
* The following logic is only for outbound packets
* to be encoded by client.
* On the server the p.contentNegotiation == null.
*/
if (p.contentNegotiation == ContentNegotiation.none) {
// The client may have changed the negotiation property from
// pessismistic to none between invocations
useFastInfosetForEncoding = false;
} else if (p.contentNegotiation == ContentNegotiation.optimistic) {
// Always encode using Fast Infoset if in optimisitic mode
useFastInfosetForEncoding = true;
}
return (useFastInfosetForEncoding && fiCodec != null)? fiCodec : xmlCodec;
}
public static boolean requiresTransformationOfDataSource(
boolean isFastInfoset, boolean useFastInfoset) {
return (isFastInfoset && !useFastInfoset) || (!isFastInfoset && useFastInfoset);
}
public static DataSource transformDataSource(DataSource in,
boolean isFastInfoset, boolean useFastInfoset, WSFeatureList f) {
try {
if (isFastInfoset && !useFastInfoset) {
// Convert from Fast Infoset to XML
Codec codec = new XMLHTTPBindingCodec(f);
Packet p = new Packet();
codec.decode(in.getInputStream(), in.getContentType(), p);
p.getMessage().getAttachments();
codec.getStaticContentType(p);
ByteArrayBuffer bos = new ByteArrayBuffer();
ContentType ct = codec.encode(p, bos);
return XMLMessage.createDataSource(ct.getContentType(), bos.newInputStream());
} else if (!isFastInfoset && useFastInfoset) {
// Convert from XML to Fast Infoset
Codec codec = new XMLHTTPBindingCodec(f);
Packet p = new Packet();
codec.decode(in.getInputStream(), in.getContentType(), p);
p.contentNegotiation = ContentNegotiation.optimistic;
p.getMessage().getAttachments();
codec.getStaticContentType(p);
ByteArrayBuffer bos = new ByteArrayBuffer();
com.sun.xml.internal.ws.api.pipe.ContentType ct = codec.encode(p, bos);
return XMLMessage.createDataSource(ct.getContentType(), bos.newInputStream());
}
} catch(Exception ex) {
throw new WebServiceException(ex);
}
return in;
}
/**
* Obtain an FI SOAP codec instance using reflection.
*/
private static Codec getFICodec() {
try {
Class c = Class.forName("com.sun.xml.internal.ws.encoding.fastinfoset.FastInfosetCodec");
Method m = c.getMethod("create");
return (Codec)m.invoke(null);
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1997, 2012, 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.xml.internal.ws.util.xml.XmlUtil;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataContentHandler;
import javax.activation.DataSource;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.awt.datatransfer.DataFlavor;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
/**
* JAF data handler for XML content
*
* @author Jitendra Kotamraju
*/
public class XmlDataContentHandler implements DataContentHandler {
private final DataFlavor[] flavors;
public XmlDataContentHandler() throws ClassNotFoundException {
flavors = new DataFlavor[3];
flavors[0] = new ActivationDataFlavor(StreamSource.class, "text/xml", "XML");
flavors[1] = new ActivationDataFlavor(StreamSource.class, "application/xml", "XML");
flavors[2] = new ActivationDataFlavor(String.class, "text/xml", "XML String");
}
public DataFlavor[] getTransferDataFlavors() {
return Arrays.copyOf(flavors, flavors.length);
}
public Object getTransferData(DataFlavor df, DataSource ds)
throws IOException {
for (DataFlavor aFlavor : flavors) {
if (aFlavor.equals(df)) {
return getContent(ds);
}
}
return null;
}
/**
* Create an object from the input stream
*/
public Object getContent(DataSource ds) throws IOException {
String ctStr = ds.getContentType();
String charset = null;
if (ctStr != null) {
ContentType ct = new ContentType(ctStr);
if (!isXml(ct)) {
throw new IOException(
"Cannot convert DataSource with content type \""
+ ctStr + "\" to object in XmlDataContentHandler");
}
charset = ct.getParameter("charset");
}
return (charset != null)
? new StreamSource(new InputStreamReader(ds.getInputStream()), charset)
: new StreamSource(ds.getInputStream());
}
/**
* Convert the object to a byte stream
*/
public void writeTo(Object obj, String mimeType, OutputStream os)
throws IOException {
if (!(obj instanceof DataSource || obj instanceof Source || obj instanceof String)) {
throw new IOException("Invalid Object type = "+obj.getClass()+
". XmlDataContentHandler can only convert DataSource|Source|String to XML.");
}
ContentType ct = new ContentType(mimeType);
if (!isXml(ct)) {
throw new IOException(
"Invalid content type \"" + mimeType + "\" for XmlDataContentHandler");
}
String charset = ct.getParameter("charset");
if (obj instanceof String) {
String s = (String) obj;
if (charset == null) {
charset = "utf-8";
}
OutputStreamWriter osw = new OutputStreamWriter(os, charset);
osw.write(s, 0, s.length());
osw.flush();
return;
}
Source source = (obj instanceof DataSource)
? (Source)getContent((DataSource)obj) : (Source)obj;
try {
Transformer transformer = XmlUtil.newTransformer();
if (charset != null) {
transformer.setOutputProperty(OutputKeys.ENCODING, charset);
}
StreamResult result = new StreamResult(os);
transformer.transform(source, result);
} catch (Exception ex) {
throw new IOException(
"Unable to run the JAXP transformer in XmlDataContentHandler "
+ ex.getMessage());
}
}
private boolean isXml(ContentType ct) {
return ct.getSubType().equals("xml") &&
(ct.getPrimaryType().equals("text") || ct.getPrimaryType().equals("application"));
}
}

View File

@@ -0,0 +1,273 @@
/*
* 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.fastinfoset;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary;
import com.sun.xml.internal.fastinfoset.vocab.SerializerVocabulary;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Messages;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
import java.io.BufferedInputStream;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.ws.WebServiceException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.ReadableByteChannel;
import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetSource;
/**
* A codec for encoding/decoding XML infosets to/from fast
* infoset documents.
*
* @author Paul Sandoz
*/
public class FastInfosetCodec implements Codec {
private static final int DEFAULT_INDEXED_STRING_SIZE_LIMIT = 32;
private static final int DEFAULT_INDEXED_STRING_MEMORY_LIMIT = 4 * 1024 * 1024; //4M limit
private StAXDocumentParser _parser;
private StAXDocumentSerializer _serializer;
private final boolean _retainState;
private final ContentType _contentType;
/* package */ FastInfosetCodec(boolean retainState) {
_retainState = retainState;
_contentType = (retainState) ? new ContentTypeImpl(FastInfosetMIMETypes.STATEFUL_INFOSET) :
new ContentTypeImpl(FastInfosetMIMETypes.INFOSET);
}
public String getMimeType() {
return _contentType.getContentType();
}
public Codec copy() {
return new FastInfosetCodec(_retainState);
}
public ContentType getStaticContentType(Packet packet) {
return _contentType;
}
public ContentType encode(Packet packet, OutputStream out) {
Message message = packet.getMessage();
if (message != null && message.hasPayload()) {
final XMLStreamWriter writer = getXMLStreamWriter(out);
try {
writer.writeStartDocument();
packet.getMessage().writePayloadTo(writer);
writer.writeEndDocument();
writer.flush();
} catch (XMLStreamException e) {
throw new WebServiceException(e);
}
}
return _contentType;
}
public ContentType encode(Packet packet, WritableByteChannel buffer) {
//TODO: not yet implemented
throw new UnsupportedOperationException();
}
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
/* Implements similar logic as the XMLMessage.create(String, InputStream).
* But it's faster, as we know the InputStream has FastInfoset content*/
Message message;
in = hasSomeData(in);
if (in != null) {
message = Messages.createUsingPayload(new FastInfosetSource(in),
SOAPVersion.SOAP_11);
} else {
message = Messages.createEmpty(SOAPVersion.SOAP_11);
}
packet.setMessage(message);
}
public void decode(ReadableByteChannel in, String contentType, Packet response) {
throw new UnsupportedOperationException();
}
private XMLStreamWriter getXMLStreamWriter(OutputStream out) {
if (_serializer != null) {
_serializer.setOutputStream(out);
return _serializer;
} else {
return _serializer = createNewStreamWriter(out, _retainState);
}
}
/**
* Creates a new {@link FastInfosetCodec} instance.
*
* @return a new {@link FastInfosetCodec} instance.
*/
public static FastInfosetCodec create() {
return create(false);
}
/**
* Creates a new {@link FastInfosetCodec} instance.
*
* @param retainState if true the Codec should retain the state of
* vocabulary tables for multiple encode/decode invocations.
* @return a new {@link FastInfosetCodec} instance.
*/
public static FastInfosetCodec create(boolean retainState) {
return new FastInfosetCodec(retainState);
}
/**
* Create a new (@link StAXDocumentSerializer} instance.
*
* @param in the OutputStream to serialize to.
* @param retainState if true the serializer should retain the state of
* vocabulary tables for multiple serializations.
* @return a new {@link StAXDocumentSerializer} instance.
*/
/* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out, boolean retainState) {
return createNewStreamWriter(out, retainState, DEFAULT_INDEXED_STRING_SIZE_LIMIT, DEFAULT_INDEXED_STRING_MEMORY_LIMIT);
}
/**
* Create a new (@link StAXDocumentSerializer} instance.
*
* @param in the OutputStream to serialize to.
* @param retainState if true the serializer should retain the state of
* vocabulary tables for multiple serializations.
* @return a new {@link StAXDocumentSerializer} instance.
*/
/* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out,
boolean retainState, int indexedStringSizeLimit, int stringsMemoryLimit) {
StAXDocumentSerializer serializer = new StAXDocumentSerializer(out);
if (retainState) {
/**
* Create a serializer vocabulary external to the serializer.
* This will ensure that the vocabulary will never be cleared
* for each serialization and will be retained (and will grow)
* for each serialization
*/
SerializerVocabulary vocabulary = new SerializerVocabulary();
serializer.setVocabulary(vocabulary);
serializer.setMinAttributeValueSize(0);
serializer.setMaxAttributeValueSize(indexedStringSizeLimit);
serializer.setMinCharacterContentChunkSize(0);
serializer.setMaxCharacterContentChunkSize(indexedStringSizeLimit);
serializer.setAttributeValueMapMemoryLimit(stringsMemoryLimit);
serializer.setCharacterContentChunkMapMemoryLimit(stringsMemoryLimit);
}
return serializer;
}
/**
* Create a new (@link StAXDocumentParser} instance.
*
* @param in the InputStream to parse from.
* @param retainState if true the parser should retain the state of
* vocabulary tables for multiple parses.
* @return a new {@link StAXDocumentParser} instance.
*/
/* package */ static StAXDocumentParser createNewStreamReader(InputStream in, boolean retainState) {
StAXDocumentParser parser = new StAXDocumentParser(in);
parser.setStringInterning(true);
if (retainState) {
/**
* Create a parser vocabulary external to the parser.
* This will ensure that the vocabulary will never be cleared
* for each parse and will be retained (and will grow)
* for each parse.
*/
ParserVocabulary vocabulary = new ParserVocabulary();
parser.setVocabulary(vocabulary);
}
return parser;
}
/**
* Create a new (@link StAXDocumentParser} recyclable instance.
*
* @param in the InputStream to parse from.
* @param retainState if true the parser should retain the state of
* vocabulary tables for multiple parses.
* @return a new recyclable {@link StAXDocumentParser} instance.
*/
/* package */ static StAXDocumentParser createNewStreamReaderRecyclable(InputStream in, boolean retainState) {
StAXDocumentParser parser = new FastInfosetStreamReaderRecyclable(in);
parser.setStringInterning(true);
parser.setForceStreamClose(true);
if (retainState) {
/**
* Create a parser vocabulary external to the parser.
* This will ensure that the vocabulary will never be cleared
* for each parse and will be retained (and will grow)
* for each parse.
*/
ParserVocabulary vocabulary = new ParserVocabulary();
parser.setVocabulary(vocabulary);
}
return parser;
}
/**
* Method is copied from com.sun.xml.internal.ws.encoding.xml.XMLMessage
* @TODO method should be public in some util package?
*
* Finds if the stream has some content or not
*
* @return null if there is no data
* else stream to be used
*/
private static InputStream hasSomeData(InputStream in) throws IOException {
if (in != null) {
if (in.available() < 1) {
if (!in.markSupported()) {
in = new BufferedInputStream(in);
}
in.mark(1);
if (in.read() != -1) {
in.reset();
} else {
in = null; // No data
}
}
}
return in;
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1997, 2012, 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.fastinfoset;
/**
* MIME types for Infosets encoded as fast infoset documents.
*
* @author Paul.Sandoz@Sun.Com
*/
public final class FastInfosetMIMETypes {
/**
* MIME type for a generic Infoset encoded as a fast infoset document.
*/
static public final String INFOSET = "application/fastinfoset";
/**
* MIME type for a SOAP 1.1 Infoset encoded as a fast infoset document.
*/
static public final String SOAP_11 = "application/fastinfoset";
/**
* MIME type for a SOAP 1.2 Infoset encoded as a fast infoset document.
*/
static public final String SOAP_12 = "application/soap+fastinfoset";
/**
* MIME type for a generic Infoset encoded as a stateful fast infoset document.
*/
static public final String STATEFUL_INFOSET = "application/vnd.sun.stateful.fastinfoset";
/**
* MIME type for a SOAP 1.1 Infoset encoded as a stateful fast infoset document.
*/
static public final String STATEFUL_SOAP_11 = "application/vnd.sun.stateful.fastinfoset";
/**
* MIME type for a SOAP 1.2 Infoset encoded as a stateful fast infoset document.
*/
static public final String STATEFUL_SOAP_12 = "application/vnd.sun.stateful.soap+fastinfoset";
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 1997, 2012, 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.fastinfoset;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
import java.io.InputStream;
import java.io.Reader;
import javax.xml.stream.XMLStreamReader;
/**
* @author Alexey Stashok
*/
public final class FastInfosetStreamReaderFactory extends XMLStreamReaderFactory {
private static final FastInfosetStreamReaderFactory factory = new FastInfosetStreamReaderFactory();
private ThreadLocal<StAXDocumentParser> pool = new ThreadLocal<StAXDocumentParser>();
public static FastInfosetStreamReaderFactory getInstance() {
return factory;
}
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
StAXDocumentParser parser = fetch();
if (parser == null) {
return FastInfosetCodec.createNewStreamReaderRecyclable(in, false);
}
parser.setInputStream(in);
return parser;
}
public XMLStreamReader doCreate(String systemId, Reader reader, boolean rejectDTDs) {
throw new UnsupportedOperationException();
}
private StAXDocumentParser fetch() {
StAXDocumentParser parser = pool.get();
pool.set(null);
return parser;
}
public void doRecycle(XMLStreamReader r) {
if (r instanceof StAXDocumentParser) {
pool.set((StAXDocumentParser) r);
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1997, 2012, 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.fastinfoset;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
import java.io.InputStream;
/**
* @author Alexey Stashok
*/
public final class FastInfosetStreamReaderRecyclable extends StAXDocumentParser implements XMLStreamReaderFactory.RecycleAware {
private static final FastInfosetStreamReaderFactory READER_FACTORY = FastInfosetStreamReaderFactory.getInstance();
public FastInfosetStreamReaderRecyclable() {
super();
}
public FastInfosetStreamReaderRecyclable(InputStream in) {
super(in);
}
public void onRecycled() {
READER_FACTORY.doRecycle(this);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1997, 2012, 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.fastinfoset;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
import com.sun.xml.internal.ws.message.stream.StreamHeader;
import com.sun.xml.internal.ws.message.stream.StreamHeader11;
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
import javax.xml.stream.XMLStreamReader;
/**
* A codec that converts SOAP 1.1 messages infosets to fast infoset
* documents.
*
* @author Paul.Sandoz@Sun.Com
*/
final class FastInfosetStreamSOAP11Codec extends FastInfosetStreamSOAPCodec {
/*package*/ FastInfosetStreamSOAP11Codec(StreamSOAPCodec soapCodec, boolean retainState) {
super(soapCodec, SOAPVersion.SOAP_11, retainState,
(retainState) ? FastInfosetMIMETypes.STATEFUL_SOAP_11 : FastInfosetMIMETypes.SOAP_11);
}
private FastInfosetStreamSOAP11Codec(FastInfosetStreamSOAP11Codec that) {
super(that);
}
public Codec copy() {
return new FastInfosetStreamSOAP11Codec(this);
}
protected final StreamHeader createHeader(XMLStreamReader reader, XMLStreamBuffer mark) {
return new StreamHeader11(reader, mark);
}
protected ContentType getContentType(String soapAction) {
if (soapAction == null || soapAction.length() == 0) {
return _defaultContentType;
} else {
return new ContentTypeImpl(_defaultContentType.getContentType(), soapAction);
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 1997, 2012, 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.fastinfoset;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
import com.sun.xml.internal.ws.message.stream.StreamHeader;
import com.sun.xml.internal.ws.message.stream.StreamHeader12;
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
import javax.xml.stream.XMLStreamReader;
/**
* A codec that converts SOAP 1.2 messages infosets to fast infoset
* documents.
*
* @author Paul.Sandoz@Sun.Com
*/
final class FastInfosetStreamSOAP12Codec extends FastInfosetStreamSOAPCodec {
/*package*/ FastInfosetStreamSOAP12Codec(StreamSOAPCodec soapCodec, boolean retainState) {
super(soapCodec, SOAPVersion.SOAP_12, retainState,
(retainState) ? FastInfosetMIMETypes.STATEFUL_SOAP_12 : FastInfosetMIMETypes.SOAP_12);
}
private FastInfosetStreamSOAP12Codec(FastInfosetStreamSOAPCodec that) {
super(that);
}
public Codec copy() {
return new FastInfosetStreamSOAP12Codec(this);
}
protected final StreamHeader createHeader(XMLStreamReader reader, XMLStreamBuffer mark) {
return new StreamHeader12(reader, mark);
}
protected ContentType getContentType(String soapAction) {
if (soapAction == null) {
return _defaultContentType;
} else {
return new ContentTypeImpl(
_defaultContentType.getContentType() + ";action=\""+soapAction+"\"");
}
}
}

View File

@@ -0,0 +1,179 @@
/*
* 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.fastinfoset;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
import com.sun.xml.internal.ws.message.stream.StreamHeader;
import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.XMLStreamReader;
import javax.xml.ws.WebServiceException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.ReadableByteChannel;
/**
* A stream SOAP codec for handling SOAP message infosets to fast
* infoset documents.
*
* <p>
* This implementation currently defers to {@link StreamSOAPCodec} for the decoding
* using {@link XMLStreamReader}.
*
* @author Paul Sandoz
*/
public abstract class FastInfosetStreamSOAPCodec implements Codec {
private static final FastInfosetStreamReaderFactory READER_FACTORY = FastInfosetStreamReaderFactory.getInstance();
private StAXDocumentParser _statefulParser;
private StAXDocumentSerializer _serializer;
private final StreamSOAPCodec _soapCodec;
private final boolean _retainState;
protected final ContentType _defaultContentType;
/* package */ FastInfosetStreamSOAPCodec(StreamSOAPCodec soapCodec, SOAPVersion soapVersion, boolean retainState, String mimeType) {
// _soapCodec = StreamSOAPCodec.create(soapVersion);
_soapCodec = soapCodec;
_retainState = retainState;
_defaultContentType = new ContentTypeImpl(mimeType);
}
/* package */ FastInfosetStreamSOAPCodec(FastInfosetStreamSOAPCodec that) {
this._soapCodec = (StreamSOAPCodec) that._soapCodec.copy();
this._retainState = that._retainState;
this._defaultContentType = that._defaultContentType;
}
public String getMimeType() {
return _defaultContentType.getContentType();
}
public ContentType getStaticContentType(Packet packet) {
return getContentType(packet.soapAction);
}
public ContentType encode(Packet packet, OutputStream out) {
if (packet.getMessage() != null) {
final XMLStreamWriter writer = getXMLStreamWriter(out);
try {
packet.getMessage().writeTo(writer);
writer.flush();
} catch (XMLStreamException e) {
throw new WebServiceException(e);
}
}
return getContentType(packet.soapAction);
}
public ContentType encode(Packet packet, WritableByteChannel buffer) {
//TODO: not yet implemented
throw new UnsupportedOperationException();
}
public void decode(InputStream in, String contentType, Packet response) throws IOException {
response.setMessage(
_soapCodec.decode(getXMLStreamReader(in)));
}
public void decode(ReadableByteChannel in, String contentType, Packet response) {
throw new UnsupportedOperationException();
}
protected abstract StreamHeader createHeader(XMLStreamReader reader, XMLStreamBuffer mark);
protected abstract ContentType getContentType(String soapAction);
private XMLStreamWriter getXMLStreamWriter(OutputStream out) {
if (_serializer != null) {
_serializer.setOutputStream(out);
return _serializer;
} else {
return _serializer = FastInfosetCodec.createNewStreamWriter(out, _retainState);
}
}
private XMLStreamReader getXMLStreamReader(InputStream in) {
// If the _retainState is true (FI stateful) then pick up Codec assiciated XMLStreamReader
if (_retainState) {
if (_statefulParser != null) {
_statefulParser.setInputStream(in);
return _statefulParser;
} else {
return _statefulParser = FastInfosetCodec.createNewStreamReader(in, _retainState);
}
}
// Otherwise thread assiciated XMLStreamReader
return READER_FACTORY.doCreate(null, in, false);
}
/**
* Creates a new {@link FastInfosetStreamSOAPCodec} instance.
*
* @param version the SOAP version of the codec.
* @return a new {@link FastInfosetStreamSOAPCodec} instance.
*/
public static FastInfosetStreamSOAPCodec create(StreamSOAPCodec soapCodec, SOAPVersion version) {
return create(soapCodec, version, false);
}
/**
* Creates a new {@link FastInfosetStreamSOAPCodec} instance.
*
* @param version the SOAP version of the codec.
* @param retainState if true the Codec should retain the state of
* vocabulary tables for multiple encode/decode invocations.
* @return a new {@link FastInfosetStreamSOAPCodec} instance.
*/
public static FastInfosetStreamSOAPCodec create(StreamSOAPCodec soapCodec,
SOAPVersion version, boolean retainState) {
if(version==null)
// this decoder is for SOAP, not for XML/HTTP
throw new IllegalArgumentException();
switch(version) {
case SOAP_11:
return new FastInfosetStreamSOAP11Codec(soapCodec, retainState);
case SOAP_12:
return new FastInfosetStreamSOAP12Codec(soapCodec, retainState);
default:
throw new AssertionError();
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import javax.xml.namespace.QName;
/**
* File holding all encoding constants
*
* @author Marek Potociar (marek.potociar at sun.com)
*/
public final class EncodingConstants {
/** Prevents creation of new EncodingConstants instance */
private EncodingConstants() {
}
public static final String SUN_FI_SERVICE_NS = "http://java.sun.com/xml/ns/wsit/2006/09/policy/fastinfoset/service";
public static final QName OPTIMIZED_FI_SERIALIZATION_ASSERTION = new QName(SUN_FI_SERVICE_NS, "OptimizedFastInfosetSerialization");
public static final String SUN_ENCODING_CLIENT_NS = "http://java.sun.com/xml/ns/wsit/2006/09/policy/encoding/client";
public static final QName SELECT_OPTIMAL_ENCODING_ASSERTION = new QName(SUN_ENCODING_CLIENT_NS, "AutomaticallySelectOptimalEncoding");
public static final String OPTIMIZED_MIME_NS = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
public static final QName OPTIMIZED_MIME_SERIALIZATION_ASSERTION = new QName(OPTIMIZED_MIME_NS, "OptimizedMimeSerialization");
public static final String ENCODING_NS = "http://schemas.xmlsoap.org/ws/2004/09/policy/encoding";
public static final QName UTF816FFFE_CHARACTER_ENCODING_ASSERTION = new QName(ENCODING_NS, "Utf816FFFECharacterEncoding");
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import com.sun.xml.internal.ws.policy. PolicyAssertion;
import com.sun.xml.internal.ws.policy.spi.PolicyAssertionValidator;
import com.sun.xml.internal.ws.policy.spi.PolicyAssertionValidator.Fitness;
import java.util.ArrayList;
import javax.xml.namespace.QName;
import static com.sun.xml.internal.ws.encoding.policy.EncodingConstants.*;
/**
*
* @author Jakub Podlesak (jakub.podlesak at sun.com)
*/
public class EncodingPolicyValidator implements PolicyAssertionValidator {
private static final ArrayList<QName> serverSideSupportedAssertions = new ArrayList<QName>(3);
private static final ArrayList<QName> clientSideSupportedAssertions = new ArrayList<QName>(4);
static {
serverSideSupportedAssertions.add(OPTIMIZED_MIME_SERIALIZATION_ASSERTION);
serverSideSupportedAssertions.add(UTF816FFFE_CHARACTER_ENCODING_ASSERTION);
serverSideSupportedAssertions.add(OPTIMIZED_FI_SERIALIZATION_ASSERTION);
clientSideSupportedAssertions.add(SELECT_OPTIMAL_ENCODING_ASSERTION);
clientSideSupportedAssertions.addAll(serverSideSupportedAssertions);
}
/**
* Creates a new instance of EncodingPolicyValidator
*/
public EncodingPolicyValidator() {
}
public Fitness validateClientSide(PolicyAssertion assertion) {
return clientSideSupportedAssertions.contains(assertion.getName()) ? Fitness.SUPPORTED : Fitness.UNKNOWN;
}
public Fitness validateServerSide(PolicyAssertion assertion) {
QName assertionName = assertion.getName();
if (serverSideSupportedAssertions.contains(assertionName)) {
return Fitness.SUPPORTED;
} else if (clientSideSupportedAssertions.contains(assertionName)) {
return Fitness.UNSUPPORTED;
} else {
return Fitness.UNKNOWN;
}
}
public String[] declareSupportedDomains() {
return new String[] {OPTIMIZED_MIME_NS, ENCODING_NS, SUN_ENCODING_CLIENT_NS, SUN_FI_SERVICE_NS};
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import com.sun.xml.internal.ws.policy.spi.PrefixMapper;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author Fabian Ritzmann
*/
public class EncodingPrefixMapper implements PrefixMapper {
private static final Map<String, String> prefixMap = new HashMap<String, String>();
static {
prefixMap.put(EncodingConstants.ENCODING_NS, "wspe");
prefixMap.put(EncodingConstants.OPTIMIZED_MIME_NS, "wsoma");
prefixMap.put(EncodingConstants.SUN_ENCODING_CLIENT_NS, "cenc");
prefixMap.put(EncodingConstants.SUN_FI_SERVICE_NS, "fi");
}
public Map<String, String> getPrefixMap() {
return prefixMap;
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import com.sun.xml.internal.ws.api.fastinfoset.FastInfosetFeature;
import com.sun.xml.internal.ws.policy.AssertionSet;
import com.sun.xml.internal.ws.policy.Policy;
import com.sun.xml.internal.ws.policy.PolicyAssertion;
import com.sun.xml.internal.ws.policy.PolicyException;
import com.sun.xml.internal.ws.policy.PolicyMap;
import com.sun.xml.internal.ws.policy.PolicyMapKey;
import com.sun.xml.internal.ws.policy.jaxws.spi.PolicyFeatureConfigurator;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import javax.xml.namespace.QName;
import static com.sun.xml.internal.ws.encoding.policy.EncodingConstants.OPTIMIZED_FI_SERIALIZATION_ASSERTION;
import javax.xml.ws.WebServiceFeature;
/**
* A configurator provider for FastInfoset policy assertions.
*
* @author Paul.Sandoz@Sun.Com
* @author Fabian Ritzmann
*/
public class FastInfosetFeatureConfigurator implements PolicyFeatureConfigurator {
public static final QName enabled = new QName("enabled");
/**
* Process FastInfoset policy assertions.
*
* @param key Key to identify the endpoint scope.
* @param policyMap the policy map.
* @throws PolicyException If retrieving the policy triggered an exception.
*/
public Collection<WebServiceFeature> getFeatures(final PolicyMapKey key, final PolicyMap policyMap) throws PolicyException {
final Collection<WebServiceFeature> features = new LinkedList<WebServiceFeature>();
if ((key != null) && (policyMap != null)) {
Policy policy = policyMap.getEndpointEffectivePolicy(key);
if (null!=policy && policy.contains(OPTIMIZED_FI_SERIALIZATION_ASSERTION)) {
Iterator <AssertionSet> assertions = policy.iterator();
while(assertions.hasNext()){
AssertionSet assertionSet = assertions.next();
Iterator<PolicyAssertion> policyAssertion = assertionSet.iterator();
while(policyAssertion.hasNext()){
PolicyAssertion assertion = policyAssertion.next();
if(OPTIMIZED_FI_SERIALIZATION_ASSERTION.equals(assertion.getName())){
String value = assertion.getAttributeValue(enabled);
boolean isFastInfosetEnabled = Boolean.valueOf(value.trim());
features.add(new FastInfosetFeature(isFastInfosetEnabled));
} // end-if non optional fast infoset assertion found
} // next assertion
} // next alternative
} // end-if policy contains fast infoset assertion
}
return features;
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundPortType;
import com.sun.xml.internal.ws.policy.AssertionSet;
import com.sun.xml.internal.ws.policy.Policy;
import com.sun.xml.internal.ws.policy.PolicyAssertion;
import com.sun.xml.internal.ws.policy.PolicyException;
import com.sun.xml.internal.ws.policy.PolicyMap;
import com.sun.xml.internal.ws.policy.PolicyMapKey;
import com.sun.xml.internal.ws.policy.jaxws.spi.PolicyFeatureConfigurator;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.MTOMFeature;
import static com.sun.xml.internal.ws.encoding.policy.EncodingConstants.OPTIMIZED_MIME_SERIALIZATION_ASSERTION;
/**
*
* @author japod
* @author Fabian Ritzmann
*/
public class MtomFeatureConfigurator implements PolicyFeatureConfigurator {
/**
* Creates a new instance of MtomFeatureConfigurator
*/
public MtomFeatureConfigurator() {
}
/**
* process Mtom policy assertions and if found and is not optional then mtom is enabled on the
* {@link WSDLBoundPortType}
*
* @param key Key that identifies the endpoint scope
* @param policyMap Must be non-null
* @throws PolicyException If retrieving the policy triggered an exception
*/
public Collection<WebServiceFeature> getFeatures(PolicyMapKey key, PolicyMap policyMap) throws PolicyException {
final Collection<WebServiceFeature> features = new LinkedList<WebServiceFeature>();
if ((key != null) && (policyMap != null)) {
Policy policy = policyMap.getEndpointEffectivePolicy(key);
if (null!=policy && policy.contains(OPTIMIZED_MIME_SERIALIZATION_ASSERTION)) {
Iterator <AssertionSet> assertions = policy.iterator();
while(assertions.hasNext()){
AssertionSet assertionSet = assertions.next();
Iterator<PolicyAssertion> policyAssertion = assertionSet.iterator();
while(policyAssertion.hasNext()){
PolicyAssertion assertion = policyAssertion.next();
if(OPTIMIZED_MIME_SERIALIZATION_ASSERTION.equals(assertion.getName())){
features.add(new MTOMFeature(true));
} // end-if non optional mtom assertion found
} // next assertion
} // next alternative
} // end-if policy contains mtom assertion
}
return features;
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import static com.sun.xml.internal.ws.encoding.policy.EncodingConstants.OPTIMIZED_MIME_SERIALIZATION_ASSERTION;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.model.SEIModel;
import com.sun.xml.internal.ws.policy.AssertionSet;
import com.sun.xml.internal.ws.policy.Policy;
import com.sun.xml.internal.ws.policy.PolicyAssertion;
import com.sun.xml.internal.ws.policy.PolicyException;
import com.sun.xml.internal.ws.policy.PolicyMap;
import com.sun.xml.internal.ws.policy.PolicySubject;
import com.sun.xml.internal.ws.policy.jaxws.spi.PolicyMapConfigurator;
import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
import com.sun.xml.internal.ws.policy.sourcemodel.AssertionData;
import com.sun.xml.internal.ws.policy.subject.WsdlBindingSubject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.MTOMFeature;
/**
* Generate an MTOM policy if MTOM was enabled.
*
* @author Jakub Podlesak (japod at sun.com)
* @author Fabian Ritzmann
*/
public class MtomPolicyMapConfigurator implements PolicyMapConfigurator {
private static final PolicyLogger LOGGER = PolicyLogger.getLogger(MtomPolicyMapConfigurator.class);
static class MtomAssertion extends PolicyAssertion {
private static final AssertionData mtomData;
static {
mtomData= AssertionData.createAssertionData(OPTIMIZED_MIME_SERIALIZATION_ASSERTION);
//JAX-WS MTOMFeature does n't currently capture if MTOM is required/optional.
//JAX-WS accepts both normal messages and XOP encoded messages. Using wsp:Optional=true represents that behavior.
//Moreover, this allows interoperability with non-MTOM aware clients.
//See https://wsit.dev.java.net/issues/show_bug.cgi?id=1062
mtomData.setOptionalAttribute(true);
}
MtomAssertion() {
super(mtomData, null, null);
}
}
/**
* Generates an MTOM policy if MTOM is enabled.
*
* <ol>
* <li>If MTOM is enabled
* <ol>
* <li>If MTOM policy does not already exist, generate
* <li>Otherwise do nothing
* </ol>
* <li>Otherwise, do nothing (that implies that we do not remove any MTOM policies if MTOM is disabled)
* </ol>
*
*/
public Collection<PolicySubject> update(PolicyMap policyMap, SEIModel model, WSBinding wsBinding) throws PolicyException {
LOGGER.entering(policyMap, model, wsBinding);
Collection<PolicySubject> subjects = new ArrayList<PolicySubject>();
if (policyMap != null) {
final MTOMFeature mtomFeature = wsBinding.getFeature(MTOMFeature.class);
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("mtomFeature = " + mtomFeature);
}
if ((mtomFeature != null) && mtomFeature.isEnabled()) {
final QName bindingName = model.getBoundPortTypeName();
final WsdlBindingSubject wsdlSubject = WsdlBindingSubject.createBindingSubject(bindingName);
final Policy mtomPolicy = createMtomPolicy(bindingName);
final PolicySubject mtomPolicySubject = new PolicySubject(wsdlSubject, mtomPolicy);
subjects.add(mtomPolicySubject);
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.fine("Added MTOM policy with ID \"" + mtomPolicy.getIdOrName() + "\" to binding element \"" + bindingName + "\"");
}
}
} // endif policy map not null
LOGGER.exiting(subjects);
return subjects;
}
/**
* Create a policy with an MTOM assertion.
*
* @param model The binding element name. Used to generate a (locally) unique ID for the policy.
* @return The policy.
*/
private Policy createMtomPolicy(final QName bindingName) {
ArrayList<AssertionSet> assertionSets = new ArrayList<AssertionSet>(1);
ArrayList<PolicyAssertion> assertions = new ArrayList<PolicyAssertion>(1);
assertions.add(new MtomAssertion());
assertionSets.add(AssertionSet.createAssertionSet(assertions));
return Policy.createPolicy(null, bindingName.getLocalPart() + "_MTOM_Policy", assertionSets);
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 1997, 2012, 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.policy;
import com.sun.xml.internal.ws.api.client.SelectOptimalEncodingFeature;
import com.sun.xml.internal.ws.policy.AssertionSet;
import com.sun.xml.internal.ws.policy.Policy;
import com.sun.xml.internal.ws.policy.PolicyAssertion;
import com.sun.xml.internal.ws.policy.PolicyException;
import com.sun.xml.internal.ws.policy.PolicyMap;
import com.sun.xml.internal.ws.policy.PolicyMapKey;
import com.sun.xml.internal.ws.policy.jaxws.spi.PolicyFeatureConfigurator;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import javax.xml.namespace.QName;
import static com.sun.xml.internal.ws.encoding.policy.EncodingConstants.SELECT_OPTIMAL_ENCODING_ASSERTION;
import javax.xml.ws.WebServiceFeature;
/**
* A configurator provider for FastInfoset policy assertions.
*
* @author Paul.Sandoz@Sun.Com
* @author Fabian Ritzmann
*/
public class SelectOptimalEncodingFeatureConfigurator implements PolicyFeatureConfigurator {
public static final QName enabled = new QName("enabled");
/**
* Process SelectOptimalEncoding policy assertions.
*
* @param key Key that identifies the endpoint scope.
* @param policyMap The policy map.
* @throws PolicyException If retrieving the policy triggered an exception.
*/
public Collection<WebServiceFeature> getFeatures(PolicyMapKey key, PolicyMap policyMap) throws PolicyException {
final Collection<WebServiceFeature> features = new LinkedList<WebServiceFeature>();
if ((key != null) && (policyMap != null)) {
Policy policy = policyMap.getEndpointEffectivePolicy(key);
if (null!=policy && policy.contains(SELECT_OPTIMAL_ENCODING_ASSERTION)) {
Iterator <AssertionSet> assertions = policy.iterator();
while(assertions.hasNext()){
AssertionSet assertionSet = assertions.next();
Iterator<PolicyAssertion> policyAssertion = assertionSet.iterator();
while(policyAssertion.hasNext()){
PolicyAssertion assertion = policyAssertion.next();
if(SELECT_OPTIMAL_ENCODING_ASSERTION.equals(assertion.getName())){
String value = assertion.getAttributeValue(enabled);
boolean isSelectOptimalEncodingEnabled = value == null || Boolean.valueOf(value.trim());
features.add(new SelectOptimalEncodingFeature(isSelectOptimalEncodingEnabled));
}
}
}
}
}
return features;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 1997, 2012, 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.soap;
import com.sun.istack.internal.localization.Localizable;
import com.sun.xml.internal.ws.util.exception.JAXWSExceptionBase;
/**
* DeserializationException represents an exception that occurred while
* deserializing a Java value from XML.
*
* @see JAXWSExceptionBase
*
* @author WS Development Team
*/
public class DeserializationException extends JAXWSExceptionBase {
public DeserializationException(String key, Object... args) {
super(key, args);
}
public DeserializationException(Throwable throwable) {
super(throwable);
}
public DeserializationException(Localizable arg) {
super("nestedDeserializationError", arg);
}
public String getDefaultResourceBundleName() {
return "com.sun.xml.internal.ws.resources.encoding";
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 1997, 2012, 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.soap;
import com.sun.xml.internal.ws.encoding.soap.streaming.SOAP12NamespaceConstants;
import javax.xml.namespace.QName;
/**
*
* @author WS Development Team
*/
public class SOAP12Constants {
public static final String URI_ENVELOPE = SOAP12NamespaceConstants.ENVELOPE;
public static final String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
public static final String URI_HTTP = SOAP12NamespaceConstants.TRANSPORT_HTTP;
public static final String URI_SOAP_RPC = SOAP12NamespaceConstants.SOAP_RPC;
public static final QName QNAME_SOAP_RPC = new QName(URI_SOAP_RPC, "rpc");
public static final QName QNAME_SOAP_RESULT = new QName(URI_SOAP_RPC, "result");
public static final QName QNAME_SOAP_ENVELOPE = new QName(URI_ENVELOPE, "Envelope");
public static final QName QNAME_SOAP_BODY = new QName(URI_ENVELOPE, "Body");
public static final QName QNAME_SOAP_HEADER = new QName(URI_ENVELOPE, "Header");
public static final QName QNAME_ENVELOPE_ENCODINGSTYLE = new QName(URI_ENVELOPE, "encodingStyle");
public static final QName QNAME_SOAP_FAULT = new QName(URI_ENVELOPE, "Fault");
public static final QName QNAME_MUSTUNDERSTAND = new QName(URI_ENVELOPE, "mustUnderstand");
public static final QName QNAME_ROLE = new QName(URI_ENVELOPE, "role");
public static final QName QNAME_NOT_UNDERSTOOD = new QName(URI_ENVELOPE, "NotUnderstood");
//fault
public static final QName QNAME_FAULT_CODE = new QName(URI_ENVELOPE, "Code");
public static final QName QNAME_FAULT_SUBCODE = new QName(URI_ENVELOPE, "Subcode");
public static final QName QNAME_FAULT_VALUE = new QName(URI_ENVELOPE, "Value");
public static final QName QNAME_FAULT_REASON = new QName(URI_ENVELOPE, "Reason");
public static final QName QNAME_FAULT_NODE = new QName(URI_ENVELOPE, "Node");
public static final QName QNAME_FAULT_ROLE = new QName(URI_ENVELOPE, "Role");
public static final QName QNAME_FAULT_DETAIL = new QName(URI_ENVELOPE, "Detail");
public static final QName QNAME_FAULT_REASON_TEXT = new QName(URI_ENVELOPE, "Text");
public final static QName QNAME_UPGRADE = new QName(URI_ENVELOPE, "Upgrade");
public final static QName QNAME_UPGRADE_SUPPORTED_ENVELOPE = new QName(URI_ENVELOPE, "SupportedEnvelope");
//fault codes
public final static QName FAULT_CODE_MUST_UNDERSTAND = new QName(URI_ENVELOPE, "MustUnderstand");
public final static QName FAULT_CODE_MISUNDERSTOOD = new QName(URI_ENVELOPE, "Misunderstood");
public final static QName FAULT_CODE_VERSION_MISMATCH = new QName(URI_ENVELOPE, "VersionMismatch");
public final static QName FAULT_CODE_DATA_ENCODING_UNKNOWN = new QName(URI_ENVELOPE, "DataEncodingUnknown");
public final static QName FAULT_CODE_PROCEDURE_NOT_PRESENT = new QName(URI_ENVELOPE, "ProcedureNotPresent");
public final static QName FAULT_CODE_BAD_ARGUMENTS = new QName(URI_ENVELOPE, "BadArguments");
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2012, 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.soap;
import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants;
import javax.xml.namespace.QName;
/**
*
* @author WS Development Team
*/
public class SOAPConstants {
public static final String URI_ENVELOPE = SOAPNamespaceConstants.ENVELOPE;
public static final String URI_HTTP = SOAPNamespaceConstants.TRANSPORT_HTTP;
public static final String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
public static final String NS_WSDL_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/";
public static final QName QNAME_ENVELOPE_ENCODINGSTYLE = new QName(URI_ENVELOPE, "encodingStyle");
public final static QName QNAME_SOAP_ENVELOPE = new QName(URI_ENVELOPE, "Envelope");
public final static QName QNAME_SOAP_HEADER = new QName(URI_ENVELOPE, "Header");
public static final QName QNAME_MUSTUNDERSTAND = new QName(URI_ENVELOPE, "mustUnderstand");
public static final QName QNAME_ROLE = new QName(URI_ENVELOPE, "actor");
public final static QName QNAME_SOAP_BODY = new QName(URI_ENVELOPE, "Body");
public final static QName QNAME_SOAP_FAULT = new QName(URI_ENVELOPE, "Fault");
public final static QName QNAME_SOAP_FAULT_CODE = new QName("", "faultcode");
public final static QName QNAME_SOAP_FAULT_STRING = new QName("", "faultstring");
public final static QName QNAME_SOAP_FAULT_ACTOR = new QName("", "faultactor");
public final static QName QNAME_SOAP_FAULT_DETAIL = new QName("", "detail");
public final static QName FAULT_CODE_MUST_UNDERSTAND = new QName(URI_ENVELOPE, "MustUnderstand");
public final static QName FAULT_CODE_VERSION_MISMATCH = new QName(URI_ENVELOPE, "VersionMismatch");
public final static QName FAULT_CODE_DATA_ENCODING_UNKNOWN = new QName(URI_ENVELOPE, "DataEncodingUnknown");
public final static QName FAULT_CODE_PROCEDURE_NOT_PRESENT = new QName(URI_ENVELOPE, "ProcedureNotPresent");
public final static QName FAULT_CODE_BAD_ARGUMENTS = new QName(URI_ENVELOPE, "BadArguments");
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1997, 2012, 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.soap;
import com.sun.istack.internal.localization.Localizable;
import com.sun.xml.internal.ws.util.exception.JAXWSExceptionBase;
/**
* SerializationException represents an exception that occurred while
* serializing a Java value as XML.
*
* @see JAXWSExceptionBase
*
* @author WS Development Team
*/
public class SerializationException extends JAXWSExceptionBase {
public SerializationException(String key, Object... args) {
super(key, args);
}
public SerializationException(Localizable arg) {
super("nestedSerializationError", arg);
}
public SerializationException(Throwable throwable) {
super(throwable);
}
public String getDefaultResourceBundleName() {
return "com.sun.xml.internal.ws.resources.encoding";
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 1997, 2012, 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.soap;
/**
*
* @author WS Development Team
*/
public interface SerializerConstants {
public static final boolean ENCODE_TYPE = true;
public static final boolean DONT_ENCODE_TYPE = false;
public static final boolean SERIALIZE_AS_REF = true;
public static final boolean DONT_SERIALIZE_AS_REF = false;
public static final boolean REFERENCEABLE = true;
public static final boolean NOT_REFERENCEABLE = false;
public static final boolean NULLABLE = true;
public static final boolean NOT_NULLABLE = false;
public static final boolean REFERENCED_INSTANCE = true;
public static final boolean UNREFERENCED_INSTANCE = false;
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1997, 2012, 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.soap.streaming;
/**
* @author WS Development Team
*/
public class SOAP12NamespaceConstants {
public static final String XML_NS = "http://www.w3.org/XML/1998/namespace";
public static final String ENVELOPE =
"http://www.w3.org/2003/05/soap-envelope";
public static final String ENCODING =
"http://www.w3.org/2003/05/soap-encoding";
public static final String SOAP_RPC = "http://www.w3.org/2002/06/soap-rpc";
public static final String XSD = "http://www.w3.org/2001/XMLSchema";
public static final String XSI =
"http://www.w3.org/2001/XMLSchema-instance";
public static final String TRANSPORT_HTTP =
"http://www.w3.org/2003/05/soap/bindings/HTTP/";
public static final String ACTOR_NEXT = "http://www.w3.org/2003/05/soap-envelope/role/next";
public static final String ROLE_NEXT =
"http://www.w3.org/2003/05/soap-envelope/role/next";
public static final String ROLE_NONE = "http://www.w3.org/2003/05/soap-envelope/role/none";
public static final String ROLE_ULTIMATE_RECEIVER = "http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver";
public static final String SOAP_UPGRADE =
"http://www.w3.org/2002/06/soap-upgrade";
public static final String TAG_ENVELOPE = "Envelope";
public static final String TAG_HEADER = "Header";
public static final String TAG_BODY = "Body";
public static final String TAG_RESULT = "result";
public static final String TAG_NOT_UNDERSTOOD = "NotUnderstood";
public static final String ATTR_ACTOR = "role";
public static final String ATTR_MUST_UNDERSTAND = "mustUnderstand";
public static final String ATTR_MISUNDERSTOOD = "missUnderstood";
public static final String ATTR_ENCODING_STYLE = "encodingStyle";
public static final String ATTR_NOT_UNDERSTOOD_QNAME = "qname";
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2012, 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.soap.streaming;
/**
* @author WS Development Team
*/
public class SOAPNamespaceConstants {
public static final String NSPREFIX_SOAP_ENVELOPE = "soapenv";
public static final String ENVELOPE = "http://schemas.xmlsoap.org/soap/envelope/";
public static final String ENCODING =
"http://schemas.xmlsoap.org/soap/encoding/";
public static final String XSD = "http://www.w3.org/2001/XMLSchema";
public static final String XSI =
"http://www.w3.org/2001/XMLSchema-instance";
public static final String XMLNS = "http://www.w3.org/XML/1998/namespace";
public static final String TRANSPORT_HTTP =
"http://schemas.xmlsoap.org/soap/http";
public static final String ACTOR_NEXT =
"http://schemas.xmlsoap.org/soap/actor/next";
public static final String TAG_ENVELOPE = "Envelope";
public static final String TAG_HEADER = "Header";
public static final String TAG_BODY = "Body";
public static final String TAG_FAULT = "Fault";
public static final String ATTR_ACTOR = "actor";
public static final String ATTR_MUST_UNDERSTAND = "mustUnderstand";
public static final String ATTR_ENCODING_STYLE = "encodingStyle";
}

View File

@@ -0,0 +1,113 @@
/*
* 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.xml;
import com.sun.xml.internal.ws.api.message.Message;
import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
import com.sun.xml.internal.ws.api.WSBinding;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public final class XMLCodec implements Codec {
public static final String XML_APPLICATION_MIME_TYPE = "application/xml";
public static final String XML_TEXT_MIME_TYPE = "text/xml";
private static final ContentType contentType = new ContentTypeImpl(XML_TEXT_MIME_TYPE);
// private final WSBinding binding;
private WSFeatureList features;
public XMLCodec(WSFeatureList f) {
// this.binding = binding;
features = f;
}
public String getMimeType() {
return XML_APPLICATION_MIME_TYPE;
}
public ContentType getStaticContentType(Packet packet) {
return contentType;
}
public ContentType encode(Packet packet, OutputStream out) {
String encoding = (String) packet.invocationProperties
.get(XMLConstants.OUTPUT_XML_CHARACTER_ENCODING);
XMLStreamWriter writer = null;
if (encoding != null && encoding.length() > 0) {
writer = XMLStreamWriterFactory.create(out, encoding);
} else {
writer = XMLStreamWriterFactory.create(out);
}
try {
if (packet.getMessage().hasPayload()){
writer.writeStartDocument();
packet.getMessage().writePayloadTo(writer);
writer.flush();
}
} catch (XMLStreamException e) {
throw new WebServiceException(e);
}
return contentType;
}
public ContentType encode(Packet packet, WritableByteChannel buffer) {
//TODO: not yet implemented
throw new UnsupportedOperationException();
}
public Codec copy() {
return this;
}
public void decode(InputStream in, String contentType, Packet packet) throws IOException {
Message message = XMLMessage.create(contentType, in, features);
packet.setMessage(message);
}
public void decode(ReadableByteChannel in, String contentType, Packet packet) {
// TODO
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 1997, 2012, 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.xml;
public class XMLConstants {
public static final String OUTPUT_XML_CHARACTER_ENCODING = "com.sun.jaxws.rest.contenttype";
}

View File

@@ -0,0 +1,636 @@
/*
* 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.xml;
import com.sun.istack.internal.NotNull;
import com.sun.xml.internal.bind.api.Bridge;
import com.sun.xml.internal.ws.api.SOAPVersion;
import com.sun.xml.internal.ws.api.WSFeatureList;
import com.sun.xml.internal.ws.api.message.*;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
import com.sun.xml.internal.ws.encoding.ContentType;
import com.sun.xml.internal.ws.encoding.MimeMultipartParser;
import com.sun.xml.internal.ws.encoding.XMLHTTPBindingCodec;
import com.sun.xml.internal.ws.message.AbstractMessageImpl;
import com.sun.xml.internal.ws.message.EmptyMessageImpl;
import com.sun.xml.internal.ws.message.MimeAttachmentSet;
import com.sun.xml.internal.ws.message.source.PayloadSourceMessage;
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
import com.sun.xml.internal.ws.util.StreamUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import javax.activation.DataSource;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
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.stream.StreamSource;
import javax.xml.ws.WebServiceException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
*
* @author Jitendra Kotamraju
*/
public final class XMLMessage {
private static final int PLAIN_XML_FLAG = 1; // 00001
private static final int MIME_MULTIPART_FLAG = 2; // 00010
private static final int FI_ENCODED_FLAG = 16; // 10000
/*
* Construct a message given a content type and an input stream.
*/
public static Message create(final String ct, InputStream in, WSFeatureList f) {
Message data;
try {
in = StreamUtils.hasSomeData(in);
if (in == null) {
return Messages.createEmpty(SOAPVersion.SOAP_11);
}
if (ct != null) {
final ContentType contentType = new ContentType(ct);
final int contentTypeId = identifyContentType(contentType);
if ((contentTypeId & MIME_MULTIPART_FLAG) != 0) {
data = new XMLMultiPart(ct, in, f);
} else if ((contentTypeId & PLAIN_XML_FLAG) != 0) {
data = new XmlContent(ct, in, f);
} else {
data = new UnknownContent(ct, in);
}
} else {
// According to HTTP spec 7.2.1, if the media type remain
// unknown, treat as application/octet-stream
data = new UnknownContent("application/octet-stream", in);
}
} catch(Exception ex) {
throw new WebServiceException(ex);
}
return data;
}
public static Message create(Source source) {
return (source == null) ?
Messages.createEmpty(SOAPVersion.SOAP_11) :
Messages.createUsingPayload(source, SOAPVersion.SOAP_11);
}
public static Message create(DataSource ds, WSFeatureList f) {
try {
return (ds == null) ?
Messages.createEmpty(SOAPVersion.SOAP_11) :
create(ds.getContentType(), ds.getInputStream(), f);
} catch(IOException ioe) {
throw new WebServiceException(ioe);
}
}
public static Message create(Exception e) {
return new FaultMessage(SOAPVersion.SOAP_11);
}
/*
* Get the content type ID from the content type.
*/
private static int getContentId(String ct) {
try {
final ContentType contentType = new ContentType(ct);
return identifyContentType(contentType);
} catch(Exception ex) {
throw new WebServiceException(ex);
}
}
/**
* Return true if the content uses fast infoset.
*/
public static boolean isFastInfoset(String ct) {
return (getContentId(ct) & FI_ENCODED_FLAG) != 0;
}
/*
* Verify a contentType.
*
* @return
* MIME_MULTIPART_FLAG | PLAIN_XML_FLAG
* MIME_MULTIPART_FLAG | FI_ENCODED_FLAG;
* PLAIN_XML_FLAG
* FI_ENCODED_FLAG
*
*/
public static int identifyContentType(ContentType contentType) {
String primary = contentType.getPrimaryType();
String sub = contentType.getSubType();
if (primary.equalsIgnoreCase("multipart") && sub.equalsIgnoreCase("related")) {
String type = contentType.getParameter("type");
if (type != null) {
if (isXMLType(type)) {
return MIME_MULTIPART_FLAG | PLAIN_XML_FLAG;
} else if (isFastInfosetType(type)) {
return MIME_MULTIPART_FLAG | FI_ENCODED_FLAG;
}
}
return 0;
} else if (isXMLType(primary, sub)) {
return PLAIN_XML_FLAG;
} else if (isFastInfosetType(primary, sub)) {
return FI_ENCODED_FLAG;
}
return 0;
}
protected static boolean isXMLType(@NotNull String primary, @NotNull String sub) {
return (primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml"))
|| (primary.equalsIgnoreCase("application") && sub.equalsIgnoreCase("xml"))
|| (primary.equalsIgnoreCase("application") && sub.toLowerCase().endsWith("+xml"));
}
protected static boolean isXMLType(String type) {
String lowerType = type.toLowerCase();
return lowerType.startsWith("text/xml")
|| lowerType.startsWith("application/xml")
|| (lowerType.startsWith("application/") && (lowerType.indexOf("+xml") != -1));
}
protected static boolean isFastInfosetType(String primary, String sub) {
return primary.equalsIgnoreCase("application") && sub.equalsIgnoreCase("fastinfoset");
}
protected static boolean isFastInfosetType(String type) {
return type.toLowerCase().startsWith("application/fastinfoset");
}
/**
* Access a {@link Message} as a {@link DataSource}.
* <p>
* A {@link Message} implementation will implement this if the
* messages is to be access as data source.
* <p>
* TODO: consider putting as part of the API.
*/
public static interface MessageDataSource {
/**
* Check if the data source has been consumed.
* @return true of the data source has been consumed, otherwise false.
*/
boolean hasUnconsumedDataSource();
/**
* Get the data source.
* @return the data source.
*/
DataSource getDataSource();
}
/**
* It's conent-type is some XML type
*
*/
private static class XmlContent extends AbstractMessageImpl implements MessageDataSource {
private final XmlDataSource dataSource;
private boolean consumed;
private Message delegate;
private final HeaderList headerList;
// private final WSBinding binding;
private WSFeatureList features;
public XmlContent(String ct, InputStream in, WSFeatureList f) {
super(SOAPVersion.SOAP_11);
dataSource = new XmlDataSource(ct, in);
this.headerList = new HeaderList(SOAPVersion.SOAP_11);
// this.binding = binding;
features = f;
}
private Message getMessage() {
if (delegate == null) {
InputStream in = dataSource.getInputStream();
assert in != null;
delegate = Messages.createUsingPayload(new StreamSource(in), SOAPVersion.SOAP_11);
consumed = true;
}
return delegate;
}
public boolean hasUnconsumedDataSource() {
return !dataSource.consumed()&&!consumed;
}
public DataSource getDataSource() {
return hasUnconsumedDataSource() ? dataSource :
XMLMessage.getDataSource(getMessage(), features);
}
public boolean hasHeaders() {
return false;
}
public @NotNull MessageHeaders getHeaders() {
return headerList;
}
public String getPayloadLocalPart() {
return getMessage().getPayloadLocalPart();
}
public String getPayloadNamespaceURI() {
return getMessage().getPayloadNamespaceURI();
}
public boolean hasPayload() {
return true;
}
public boolean isFault() {
return false;
}
public Source readEnvelopeAsSource() {
return getMessage().readEnvelopeAsSource();
}
public Source readPayloadAsSource() {
return getMessage().readPayloadAsSource();
}
public SOAPMessage readAsSOAPMessage() throws SOAPException {
return getMessage().readAsSOAPMessage();
}
public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException {
return getMessage().readAsSOAPMessage(packet, inbound);
}
public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
return (T)getMessage().readPayloadAsJAXB(unmarshaller);
}
/** @deprecated */
public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException {
return getMessage().readPayloadAsJAXB(bridge);
}
public XMLStreamReader readPayload() throws XMLStreamException {
return getMessage().readPayload();
}
public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException {
getMessage().writePayloadTo(sw);
}
public void writeTo(XMLStreamWriter sw) throws XMLStreamException {
getMessage().writeTo(sw);
}
public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException {
getMessage().writeTo(contentHandler, errorHandler);
}
public Message copy() {
return getMessage().copy();
}
protected void writePayloadTo(ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException {
throw new UnsupportedOperationException();
}
}
/**
* Data represented as a multi-part MIME message.
* <p>
* The root part may be an XML or an FI document. This class
* parses MIME message lazily.
*/
public static final class XMLMultiPart extends AbstractMessageImpl implements MessageDataSource {
private final DataSource dataSource;
private final StreamingAttachmentFeature feature;
private Message delegate;
private HeaderList headerList;// = new HeaderList();
// private final WSBinding binding;
private final WSFeatureList features;
public XMLMultiPart(final String contentType, final InputStream is, WSFeatureList f) {
super(SOAPVersion.SOAP_11);
headerList = new HeaderList(SOAPVersion.SOAP_11);
dataSource = createDataSource(contentType, is);
this.feature = f.get(StreamingAttachmentFeature.class);
this.features = f;
}
private Message getMessage() {
if (delegate == null) {
MimeMultipartParser mpp;
try {
mpp = new MimeMultipartParser(dataSource.getInputStream(),
dataSource.getContentType(), feature);
} catch(IOException ioe) {
throw new WebServiceException(ioe);
}
InputStream in = mpp.getRootPart().asInputStream();
assert in != null;
delegate = new PayloadSourceMessage(headerList, new StreamSource(in), new MimeAttachmentSet(mpp), SOAPVersion.SOAP_11);
}
return delegate;
}
public boolean hasUnconsumedDataSource() {
return delegate == null;
}
public DataSource getDataSource() {
return hasUnconsumedDataSource() ? dataSource :
XMLMessage.getDataSource(getMessage(), features);
}
public boolean hasHeaders() {
return false;
}
public @NotNull MessageHeaders getHeaders() {
return headerList;
}
public String getPayloadLocalPart() {
return getMessage().getPayloadLocalPart();
}
public String getPayloadNamespaceURI() {
return getMessage().getPayloadNamespaceURI();
}
public boolean hasPayload() {
return true;
}
public boolean isFault() {
return false;
}
public Source readEnvelopeAsSource() {
return getMessage().readEnvelopeAsSource();
}
public Source readPayloadAsSource() {
return getMessage().readPayloadAsSource();
}
public SOAPMessage readAsSOAPMessage() throws SOAPException {
return getMessage().readAsSOAPMessage();
}
public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException {
return getMessage().readAsSOAPMessage(packet, inbound);
}
public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
return (T)getMessage().readPayloadAsJAXB(unmarshaller);
}
public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException {
return getMessage().readPayloadAsJAXB(bridge);
}
public XMLStreamReader readPayload() throws XMLStreamException {
return getMessage().readPayload();
}
public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException {
getMessage().writePayloadTo(sw);
}
public void writeTo(XMLStreamWriter sw) throws XMLStreamException {
getMessage().writeTo(sw);
}
public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException {
getMessage().writeTo(contentHandler, errorHandler);
}
public Message copy() {
return getMessage().copy();
}
protected void writePayloadTo(ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException {
throw new UnsupportedOperationException();
}
@Override
public boolean isOneWay(@NotNull WSDLPort port) {
return false;
}
public @NotNull AttachmentSet getAttachments() {
return getMessage().getAttachments();
}
}
private static class FaultMessage extends EmptyMessageImpl {
public FaultMessage(SOAPVersion version) {
super(version);
}
@Override
public boolean isFault() {
return true;
}
}
/**
* Don't know about this content. It's conent-type is NOT the XML types
* we recognize(text/xml, application/xml, multipart/related;text/xml etc).
*
* This could be used to represent image/jpeg etc
*/
public static class UnknownContent extends AbstractMessageImpl implements MessageDataSource {
private final DataSource ds;
private final HeaderList headerList;
public UnknownContent(final String ct, final InputStream in) {
this(createDataSource(ct,in));
}
public UnknownContent(DataSource ds) {
super(SOAPVersion.SOAP_11);
this.ds = ds;
this.headerList = new HeaderList(SOAPVersion.SOAP_11);
}
/*
* Copy constructor.
*/
private UnknownContent(UnknownContent that) {
super(that.soapVersion);
this.ds = that.ds;
this.headerList = HeaderList.copy(that.headerList);
}
public boolean hasUnconsumedDataSource() {
return true;
}
public DataSource getDataSource() {
assert ds != null;
return ds;
}
protected void writePayloadTo(ContentHandler contentHandler,
ErrorHandler errorHandler, boolean fragment) throws SAXException {
throw new UnsupportedOperationException();
}
public boolean hasHeaders() {
return false;
}
public boolean isFault() {
return false;
}
public MessageHeaders getHeaders() {
return headerList;
}
public String getPayloadLocalPart() {
throw new UnsupportedOperationException();
}
public String getPayloadNamespaceURI() {
throw new UnsupportedOperationException();
}
public boolean hasPayload() {
return false;
}
public Source readPayloadAsSource() {
return null;
}
public XMLStreamReader readPayload() throws XMLStreamException {
throw new WebServiceException("There isn't XML payload. Shouldn't come here.");
}
public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException {
// No XML. Nothing to do
}
public Message copy() {
return new UnknownContent(this);
}
}
public static DataSource getDataSource(Message msg, WSFeatureList f) {
if (msg == null)
return null;
if (msg instanceof MessageDataSource) {
return ((MessageDataSource)msg).getDataSource();
} else {
AttachmentSet atts = msg.getAttachments();
if (atts != null && !atts.isEmpty()) {
final ByteArrayBuffer bos = new ByteArrayBuffer();
try {
Codec codec = new XMLHTTPBindingCodec(f);
Packet packet = new Packet(msg);
com.sun.xml.internal.ws.api.pipe.ContentType ct = codec.getStaticContentType(packet);
codec.encode(packet, bos);
return createDataSource(ct.getContentType(), bos.newInputStream());
} catch(IOException ioe) {
throw new WebServiceException(ioe);
}
} else {
final ByteArrayBuffer bos = new ByteArrayBuffer();
XMLStreamWriter writer = XMLStreamWriterFactory.create(bos);
try {
msg.writePayloadTo(writer);
writer.flush();
} catch (XMLStreamException e) {
throw new WebServiceException(e);
}
return XMLMessage.createDataSource("text/xml", bos.newInputStream());
}
}
}
public static DataSource createDataSource(final String contentType, final InputStream is) {
return new XmlDataSource(contentType, is);
}
private static class XmlDataSource implements DataSource {
private final String contentType;
private final InputStream is;
private boolean consumed;
XmlDataSource(String contentType, final InputStream is) {
this.contentType = contentType;
this.is = is;
}
public boolean consumed() {
return consumed;
}
public InputStream getInputStream() {
consumed = !consumed;
return is;
}
public OutputStream getOutputStream() {
return null;
}
public String getContentType() {
return contentType;
}
public String getName() {
return "";
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2012, 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.xml;
import com.oracle.webservices.internal.api.message.BasePropertySet;
import com.oracle.webservices.internal.api.message.PropertySet;
public class XMLPropertyBag extends BasePropertySet {
private String contentType;
protected PropertyMap getPropertyMap() {
return model;
}
@Property(XMLConstants.OUTPUT_XML_CHARACTER_ENCODING)
public String getXMLContentType(){
return contentType;
}
public void setXMLContentType(String content){
contentType = content;
}
private static final PropertyMap model;
static {
model = parse(XMLPropertyBag.class);
}
}