SWS-525 - SaajSoapMessage can get wrong SAAJ version
This commit is contained in:
@@ -36,6 +36,8 @@ class SaajSoapElement implements SoapElement {
|
||||
|
||||
private final SOAPElement element;
|
||||
|
||||
private SaajImplementation implementation;
|
||||
|
||||
SaajSoapElement(SOAPElement element) {
|
||||
Assert.notNull(element, "element must not be null");
|
||||
this.element = element;
|
||||
@@ -94,17 +96,20 @@ class SaajSoapElement implements SoapElement {
|
||||
}
|
||||
|
||||
protected final SaajImplementation getImplementation() {
|
||||
if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_13) {
|
||||
return Saaj13Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
|
||||
return Saaj12Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) {
|
||||
return Saaj11Implementation.getInstance();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Could not find SAAJ on the classpath");
|
||||
if (implementation == null) {
|
||||
if (SaajUtils.getSaajVersion(element) == SaajUtils.SAAJ_13) {
|
||||
implementation = Saaj13Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion(element) == SaajUtils.SAAJ_12) {
|
||||
implementation = Saaj12Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion(element) == SaajUtils.SAAJ_11) {
|
||||
implementation = Saaj11Implementation.getInstance();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Could not find SAAJ on the classpath");
|
||||
}
|
||||
}
|
||||
return implementation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ public class SaajSoapMessage extends AbstractSoapMessage {
|
||||
|
||||
private final boolean langAttributeOnSoap11FaulString;
|
||||
|
||||
private SaajImplementation implementation;
|
||||
|
||||
/**
|
||||
* Create a new <code>SaajSoapMessage</code> based on the given SAAJ <code>SOAPMessage</code>.
|
||||
*
|
||||
@@ -77,12 +79,12 @@ public class SaajSoapMessage extends AbstractSoapMessage {
|
||||
*/
|
||||
public SaajSoapMessage(SOAPMessage soapMessage, boolean langAttributeOnSoap11FaulString) {
|
||||
Assert.notNull(soapMessage, "soapMessage must not be null");
|
||||
saajMessage = soapMessage;
|
||||
this.langAttributeOnSoap11FaulString = langAttributeOnSoap11FaulString;
|
||||
MimeHeaders headers = getImplementation().getMimeHeaders(soapMessage);
|
||||
if (ObjectUtils.isEmpty(headers.getHeader(TransportConstants.HEADER_SOAP_ACTION))) {
|
||||
headers.addHeader(TransportConstants.HEADER_SOAP_ACTION, "\"\"");
|
||||
}
|
||||
saajMessage = soapMessage;
|
||||
this.langAttributeOnSoap11FaulString = langAttributeOnSoap11FaulString;
|
||||
}
|
||||
|
||||
/** Return the SAAJ <code>SOAPMessage</code> that this <code>SaajSoapMessage</code> is based on. */
|
||||
@@ -169,7 +171,7 @@ public class SaajSoapMessage extends AbstractSoapMessage {
|
||||
}
|
||||
|
||||
public boolean isXopPackage() {
|
||||
if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
|
||||
if (SaajUtils.getSaajVersion(saajMessage) >= SaajUtils.SAAJ_13) {
|
||||
SOAPPart saajPart = saajMessage.getSOAPPart();
|
||||
String[] contentTypes = saajPart.getMimeHeader(TransportConstants.HEADER_CONTENT_TYPE);
|
||||
for (int i = 0; i < contentTypes.length; i++) {
|
||||
@@ -182,7 +184,7 @@ public class SaajSoapMessage extends AbstractSoapMessage {
|
||||
}
|
||||
|
||||
public boolean convertToXopPackage() {
|
||||
if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
|
||||
if (SaajUtils.getSaajVersion(saajMessage) >= SaajUtils.SAAJ_13) {
|
||||
convertMessageToXop();
|
||||
convertPartToXop();
|
||||
return true;
|
||||
@@ -244,19 +246,22 @@ public class SaajSoapMessage extends AbstractSoapMessage {
|
||||
return new SaajAttachment(saajAttachment);
|
||||
}
|
||||
|
||||
protected SaajImplementation getImplementation() {
|
||||
if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_13) {
|
||||
return Saaj13Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
|
||||
return Saaj12Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) {
|
||||
return Saaj11Implementation.getInstance();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Could not find SAAJ on the classpath");
|
||||
protected final SaajImplementation getImplementation() {
|
||||
if (implementation == null) {
|
||||
if (SaajUtils.getSaajVersion(saajMessage) == SaajUtils.SAAJ_13) {
|
||||
implementation = Saaj13Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion(saajMessage) == SaajUtils.SAAJ_12) {
|
||||
implementation = Saaj12Implementation.getInstance();
|
||||
}
|
||||
else if (SaajUtils.getSaajVersion(saajMessage) == SaajUtils.SAAJ_11) {
|
||||
implementation = Saaj11Implementation.getInstance();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Could not find SAAJ on the classpath");
|
||||
}
|
||||
}
|
||||
return implementation;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
@@ -18,7 +18,12 @@ package org.springframework.ws.soap.saaj.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.MimeHeaders;
|
||||
@@ -29,13 +34,16 @@ import javax.xml.soap.SOAPEnvelope;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Collection of generic utility methods to work with SAAJ. Includes conversion from SAAJ {@link Name} objects to {@link
|
||||
@@ -48,6 +56,11 @@ import org.w3c.dom.Element;
|
||||
*/
|
||||
public abstract class SaajUtils {
|
||||
|
||||
// The exception message thrown by WebLogic 9
|
||||
private static final String WEBLOGIC_9_SAAJ_EXCEPTION_MESSAGE = "This class does not support SAAJ 1.1";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SaajUtils.class);
|
||||
|
||||
public static final int SAAJ_11 = 0;
|
||||
|
||||
public static final int SAAJ_12 = 1;
|
||||
@@ -56,6 +69,9 @@ public abstract class SaajUtils {
|
||||
|
||||
private static final String SAAJ_13_CLASS_NAME = "javax.xml.soap.SAAJMetaFactory";
|
||||
|
||||
// Maps SOAPElement class names to Integer SAAJ versions (SAAJ_11, SAAJ_12, SAAJ_13)
|
||||
private static final Map saajVersions = Collections.synchronizedMap(new HashMap());
|
||||
|
||||
private static int saajVersion = SAAJ_12;
|
||||
|
||||
static {
|
||||
@@ -127,6 +143,112 @@ public abstract class SaajUtils {
|
||||
return saajVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SAAJ version for the specified {@link SOAPMessage}.
|
||||
*
|
||||
* @return a code comparable to the SAAJ_XX codes in this class
|
||||
* @see #SAAJ_11
|
||||
* @see #SAAJ_12
|
||||
* @see #SAAJ_13
|
||||
*/
|
||||
public static int getSaajVersion(SOAPMessage soapMessage) {
|
||||
Assert.notNull(soapMessage, "'soapMessage' must not be null");
|
||||
try {
|
||||
return getSaajVersion(soapMessage.getSOAPPart().getEnvelope());
|
||||
}
|
||||
catch (SOAPException e) {
|
||||
return SAAJ_11;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SAAJ version for the specified {@link javax.xml.soap.SOAPElement}.
|
||||
*
|
||||
* @return a code comparable to the SAAJ_XX codes in this class
|
||||
* @see #SAAJ_11
|
||||
* @see #SAAJ_12
|
||||
* @see #SAAJ_13
|
||||
*/
|
||||
public static int getSaajVersion(SOAPElement soapElement) {
|
||||
Assert.notNull(soapElement, "'soapElement' must not be null");
|
||||
Class soapElementClass = soapElement.getClass();
|
||||
Integer saajVersion = (Integer) saajVersions.get(soapElementClass.getName());
|
||||
if (saajVersion == null) {
|
||||
if (isSaaj12(soapElement)) {
|
||||
if (isSaaj13(soapElement)) {
|
||||
saajVersion = new Integer(SAAJ_13);
|
||||
}
|
||||
else {
|
||||
saajVersion = new Integer(SAAJ_12);
|
||||
}
|
||||
} else {
|
||||
saajVersion = new Integer(SAAJ_11);
|
||||
}
|
||||
saajVersions.put(soapElementClass.getName(), saajVersion);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("SOAPElement [" + soapElement.getClass().getName() + "] implements " +
|
||||
getSaajVersionString(saajVersion.intValue()));
|
||||
}
|
||||
}
|
||||
return saajVersion.intValue();
|
||||
}
|
||||
|
||||
private static boolean isSaaj13(SOAPElement soapElement) {
|
||||
try {
|
||||
Method m = soapElement.getClass().getMethod("getElementQName", new Class[0]);
|
||||
// we might be using the SAAJ 1.3 API, while the impl is 1.2
|
||||
// let's see if the method is not abstract
|
||||
if (Modifier.isAbstract(m.getModifiers())) {
|
||||
logger.warn("Detected SAAJ API version 1.3, while implementation provides version 1.2. " +
|
||||
"Please replace the SAAJ API jar with a version that corresponds to your runtime" +
|
||||
" implementation (which might be provided by your app server).");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
// getElementQName not found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we can find a SAAJ 1.2 implementation, being aware of the broken WebLogic 9 SAAJ implementation.
|
||||
* <p/>
|
||||
* WebLogic 9 does implement SAAJ 1.2, but throws UnsupportedOperationExceptions when a SAAJ 1.2 method is called.
|
||||
*/
|
||||
private static boolean isSaaj12(SOAPElement soapElement) {
|
||||
try {
|
||||
Method m = soapElement.getClass().getMethod("getPrefix", new Class[0]);
|
||||
// we might be using the SAAJ 1.2 API, while the impl is 1.1
|
||||
// let's see if the method is not abstract
|
||||
if (Modifier.isAbstract(m.getModifiers())) {
|
||||
logger.warn("Detected SAAJ API version 1.2, while implementation provides version 1.1. " +
|
||||
"Please replace the SAAJ API jar with a version that corresponds to your runtime " +
|
||||
"implementation (which might be provided by your app server).");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
soapElement.getPrefix();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
// getPrefix not found
|
||||
return false;
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// getPrefix results in UOE, let's see if we're dealing with WL 9
|
||||
if (WEBLOGIC_9_SAAJ_EXCEPTION_MESSAGE.equals(ex.getMessage())) {
|
||||
return false;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SAAJ version as a String. The returned string will be "<code>SAAJ 1.3</code>", "<code>SAAJ
|
||||
* 1.2</code>", or "<code>SAAJ 1.1</code>".
|
||||
@@ -135,6 +257,10 @@ public abstract class SaajUtils {
|
||||
* @see #getSaajVersion()
|
||||
*/
|
||||
public static String getSaajVersionString() {
|
||||
return getSaajVersionString(saajVersion);
|
||||
}
|
||||
|
||||
private static String getSaajVersionString(int saajVersion) {
|
||||
if (saajVersion >= SaajUtils.SAAJ_13) {
|
||||
return "SAAJ 1.3";
|
||||
}
|
||||
@@ -166,7 +292,7 @@ public abstract class SaajUtils {
|
||||
}
|
||||
else if (StringUtils.hasLength(qName.getNamespaceURI())) {
|
||||
Iterator prefixes;
|
||||
if (getSaajVersion() == SAAJ_11) {
|
||||
if (getSaajVersion(resolveElement) == SAAJ_11) {
|
||||
prefixes = resolveElement.getNamespacePrefixes();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -25,9 +25,10 @@ import javax.xml.soap.SOAPEnvelope;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
|
||||
import org.custommonkey.xmlunit.XMLTestCase;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class SaajUtilsTest extends XMLTestCase {
|
||||
|
||||
@@ -114,4 +115,5 @@ public class SaajUtilsTest extends XMLTestCase {
|
||||
public void testGetSaajVersion() throws Exception {
|
||||
assertEquals("Invalid SAAJ version", SaajUtils.SAAJ_13, SaajUtils.getSaajVersion());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user