Fixed MustUnderstand processing.

This commit is contained in:
Arjen Poutsma
2007-06-14 17:02:48 +00:00
parent 647e623c24
commit da53627bf3
25 changed files with 593 additions and 155 deletions

View File

@@ -20,43 +20,56 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Ordered;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointExceptionResolver;
/**
* Abstract base class for {@link EndpointExceptionResolver EndpointExceptionResolvers}.
*
* <p/>
* <p>Provides a set of mapped endpoints that the resolver should map.
*
* @author Arjen Poutsma
*/
public abstract class AbstractEndpointExceptionResolver implements EndpointExceptionResolver {
public abstract class AbstractEndpointExceptionResolver implements EndpointExceptionResolver, Ordered {
/** Shared {@link Log} for subclasses to use. */
protected final Log logger = LogFactory.getLog(getClass());
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
private Set mappedEndpoints;
/**
* Specify the set of endpoints that this exception resolver should map.
* <p>The exception mappings and the default fault will only apply to the
* specified endpoints.
* Specify the set of endpoints that this exception resolver should map. <p>The exception mappings and the default
* fault will only apply to the specified endpoints.
* <p/>
* If no endpoints are set, both the exception mappings and the default fault
* will apply to all handlers. This means that a specified default fault will
* be used as fallback for all exceptions; any further
* If no endpoints are set, both the exception mappings and the default fault will apply to all handlers. This means
* that a specified default fault will be used as fallback for all exceptions; any further
* <code>EndpointExceptionResolvers</code> in the chain will be ignored in this case.
*/
public void setMappedEndpoints(Set mappedEndpoints) {
this.mappedEndpoints = mappedEndpoints;
}
/**
* Specify the order value for this mapping.
* <p/>
* Default value is {@link Integer#MAX_VALUE}, meaning that it's non-ordered.
*
* @see org.springframework.core.Ordered#getOrder()
*/
public final void setOrder(int order) {
this.order = order;
}
public final int getOrder() {
return order;
}
/**
* Default implementation that checks whether the given <code>endpoint</code>
* is in the set of {@link #setMappedEndpoints mapped endpoints}.
* Default implementation that checks whether the given <code>endpoint</code> is in the set of {@link
* #setMappedEndpoints mapped endpoints}.
*
* @see #resolveExceptionInternal(org.springframework.ws.context.MessageContext,Object,Exception)
*/
@@ -67,10 +80,8 @@ public abstract class AbstractEndpointExceptionResolver implements EndpointExcep
return resolveExceptionInternal(messageContext, endpoint, ex);
}
/**
* Template method for resolving exceptions that is called by
* {@link #resolveException}.
* Template method for resolving exceptions that is called by {@link #resolveException}.
*
* @param messageContext current message context
* @param endpoint the executed endpoint, or <code>null</code> if none chosen at the time of the exception

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.server.endpoint.mapping;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.core.Ordered;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointInvocationChain;
@@ -29,33 +30,14 @@ import org.springframework.ws.server.EndpointMapping;
* @see #getEndpointInternal(org.springframework.ws.context.MessageContext)
* @see org.springframework.ws.server.EndpointInterceptor
*/
public abstract class AbstractEndpointMapping extends ApplicationObjectSupport implements EndpointMapping {
public abstract class AbstractEndpointMapping extends ApplicationObjectSupport implements EndpointMapping, Ordered {
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
private Object defaultEndpoint;
private EndpointInterceptor[] interceptors;
/**
* Returns the default endpoint for this endpoint mapping.
*
* @return the default endpoint mapping, or null if none
*/
protected final Object getDefaultEndpoint() {
return defaultEndpoint;
}
/**
* Sets the default endpoint for this endpoint mapping. This endpoint will be returned if no specific mapping was
* found.
* <p/>
* Default is <code>null</code>, indicating no default endpoint.
*
* @param defaultEndpoint the default endpoint, or null if none
*/
public final void setDefaultEndpoint(Object defaultEndpoint) {
this.defaultEndpoint = defaultEndpoint;
}
/**
* Returns the the endpoint interceptors to apply to all endpoints mapped by this endpoint mapping.
*
@@ -74,6 +56,21 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i
this.interceptors = interceptors;
}
public final int getOrder() {
return order;
}
/**
* Specify the order value for this mapping.
* <p/>
* Default value is {@link Integer#MAX_VALUE}, meaning that it's non-ordered.
*
* @see org.springframework.core.Ordered#getOrder()
*/
public final void setOrder(int order) {
this.order = order;
}
/**
* Look up an endpoint for the given message context, falling back to the default endpoint if no specific one is
* found.
@@ -115,6 +112,27 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i
return new EndpointInvocationChain(endpoint, interceptors);
}
/**
* Returns the default endpoint for this endpoint mapping.
*
* @return the default endpoint mapping, or null if none
*/
protected final Object getDefaultEndpoint() {
return defaultEndpoint;
}
/**
* Sets the default endpoint for this endpoint mapping. This endpoint will be returned if no specific mapping was
* found.
* <p/>
* Default is <code>null</code>, indicating no default endpoint.
*
* @param defaultEndpoint the default endpoint, or null if none
*/
public final void setDefaultEndpoint(Object defaultEndpoint) {
this.defaultEndpoint = defaultEndpoint;
}
/**
* Resolves an endpoint string. If the given string can is a bean name, it is resolved using the application
* context.

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.axiom;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.springframework.util.ObjectUtils;
import org.springframework.ws.soap.soap11.Soap11Header;
/**
* Axiom-specific version of <code>org.springframework.ws.soap.Soap11Header</code>.
*
* @author Arjen Poutsma
*/
class AxiomSoap11Header extends AxiomSoapHeader implements Soap11Header {
AxiomSoap11Header(SOAPHeader axiomHeader, SOAPFactory axiomFactory) {
super(axiomHeader, axiomFactory);
}
public Iterator examineHeaderElementsToProcess(final String[] actors) {
RolePlayer rolePlayer = null;
if (!ObjectUtils.isEmpty(actors)) {
rolePlayer = new RolePlayer() {
public List getRoles() {
return Arrays.asList(actors);
}
public boolean isUltimateDestination() {
return false;
}
};
}
Iterator result = getAxiomHeader().getHeadersToProcess(rolePlayer);
return new AxiomSoapHeaderElementIterator(result);
}
}

View File

@@ -16,16 +16,22 @@
package org.springframework.ws.soap.axiom;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axiom.soap.SOAPProcessingException;
import org.springframework.util.ObjectUtils;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapHeaderException;
import org.springframework.ws.soap.soap12.Soap12Header;
import org.springframework.xml.namespace.QNameUtils;
@@ -69,4 +75,23 @@ class AxiomSoap12Header extends AxiomSoapHeader implements Soap12Header {
throw new AxiomSoapHeaderException(ex);
}
}
public Iterator examineHeaderElementsToProcess(final String[] roles, final boolean isUltimateDestination)
throws SoapHeaderException {
RolePlayer rolePlayer = null;
if (!ObjectUtils.isEmpty(roles)) {
rolePlayer = new RolePlayer() {
public List getRoles() {
return Arrays.asList(roles);
}
public boolean isUltimateDestination() {
return isUltimateDestination;
}
};
}
Iterator result = getAxiomHeader().getHeadersToProcess(rolePlayer);
return new AxiomSoapHeaderElementIterator(result);
}
}

View File

@@ -36,7 +36,7 @@ class AxiomSoapEnvelope extends AxiomSoapElement implements SoapEnvelope {
SOAPHeader axiomHeader = getAxiomEnvelope().getHeader();
String namespaceURI = getAxiomEnvelope().getNamespace().getNamespaceURI();
if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(namespaceURI)) {
return new AxiomSoapHeader(axiomHeader, getAxiomFactory());
return new AxiomSoap11Header(axiomHeader, getAxiomFactory());
}
else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(namespaceURI)) {
return new AxiomSoap12Header(axiomHeader, getAxiomFactory());

View File

@@ -36,7 +36,7 @@ import org.springframework.xml.namespace.QNameUtils;
*
* @author Arjen Poutsma
*/
class AxiomSoapHeader extends AxiomSoapElement implements SoapHeader {
abstract class AxiomSoapHeader extends AxiomSoapElement implements SoapHeader {
AxiomSoapHeader(SOAPHeader axiomHeader, SOAPFactory axiomFactory) {
super(axiomHeader, axiomFactory);
@@ -89,11 +89,11 @@ class AxiomSoapHeader extends AxiomSoapElement implements SoapHeader {
return (SOAPHeader) getAxiomElement();
}
private class AxiomSoapHeaderElementIterator implements Iterator {
protected class AxiomSoapHeaderElementIterator implements Iterator {
private final Iterator axiomIterator;
private AxiomSoapHeaderElementIterator(Iterator axiomIterator) {
protected AxiomSoapHeaderElementIterator(Iterator axiomIterator) {
this.axiomIterator = axiomIterator;
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.saaj;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.soap.soap11.Soap11Header;
/**
* SAAJ-specific implementation of the <code>Soap11Header</code> interface. Wraps a {@link javax.xml.soap.SOAPHeader}.
*
* @author Arjen Poutsma
*/
class SaajSoap11Header extends SaajSoapHeader implements Soap11Header {
SaajSoap11Header(SOAPHeader header) {
super(header);
}
public Iterator examineHeaderElementsToProcess(String[] actors) {
List result = new ArrayList();
Iterator iterator = getImplementation().examineAllHeaderElements(getSaajHeader());
while (iterator.hasNext()) {
SOAPHeaderElement saajHeaderElement = (SOAPHeaderElement) iterator.next();
String headerActor = saajHeaderElement.getActor();
if (shouldProcess(headerActor, actors)) {
result.add(saajHeaderElement);
}
}
return new SaajSoapHeaderElementIterator(result.iterator());
}
private boolean shouldProcess(String headerActor, String[] actors) {
if (!StringUtils.hasLength(headerActor)) {
return true;
}
if (SOAPConstants.URI_SOAP_ACTOR_NEXT.equals(headerActor)) {
return true;
}
if (!ObjectUtils.isEmpty(actors)) {
for (int i = 0; i < actors.length; i++) {
if (actors[i].equals(headerActor)) {
return true;
}
}
}
return false;
}
}

View File

@@ -16,12 +16,19 @@
package org.springframework.ws.soap.saaj;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapHeaderException;
import org.springframework.ws.soap.soap12.Soap12Header;
/**
@@ -56,4 +63,42 @@ class SaajSoap12Header extends SaajSoapHeader implements Soap12Header {
throw new SaajSoapHeaderException(ex);
}
}
public Iterator examineHeaderElementsToProcess(String[] roles, boolean isUltimateDestination)
throws SoapHeaderException {
List result = new ArrayList();
Iterator iterator = getImplementation().examineAllHeaderElements(getSaajHeader());
while (iterator.hasNext()) {
SOAPHeaderElement saajHeaderElement = (SOAPHeaderElement) iterator.next();
String headerRole = saajHeaderElement.getRole();
if (shouldProcess(headerRole, roles, isUltimateDestination)) {
result.add(saajHeaderElement);
}
}
return new SaajSoapHeaderElementIterator(result.iterator());
}
private boolean shouldProcess(String headerRole, String[] roles, boolean isUltimateDestination) {
if (!StringUtils.hasLength(headerRole)) {
return true;
}
if (SOAPConstants.URI_SOAP_1_2_ROLE_NEXT.equals(headerRole)) {
return true;
}
if (SOAPConstants.URI_SOAP_1_2_ROLE_ULTIMATE_RECEIVER.equals(headerRole)) {
return isUltimateDestination;
}
if (SOAPConstants.URI_SOAP_1_2_ROLE_NONE.equals(headerRole)) {
return false;
}
if (!ObjectUtils.isEmpty(roles)) {
for (int i = 0; i < roles.length; i++) {
if (roles[i].equals(headerRole)) {
return true;
}
}
}
return false;
}
}

View File

@@ -68,7 +68,7 @@ class SaajSoapEnvelope extends SaajSoapElement implements SoapEnvelope {
if (saajHeader != null) {
if (getImplementation().getName(saajHeader).getNamespaceURI()
.equals(SoapVersion.SOAP_11.getEnvelopeNamespaceUri())) {
header = new SaajSoapHeader(saajHeader);
header = new SaajSoap11Header(saajHeader);
}
else {
header = new SaajSoap12Header(saajHeader);

View File

@@ -33,7 +33,7 @@ import org.springframework.ws.soap.SoapHeaderException;
*
* @author Arjen Poutsma
*/
class SaajSoapHeader extends SaajSoapElement implements SoapHeader {
abstract class SaajSoapHeader extends SaajSoapElement implements SoapHeader {
SaajSoapHeader(SOAPHeader header) {
super(header);
@@ -67,11 +67,11 @@ class SaajSoapHeader extends SaajSoapElement implements SoapHeader {
return getImplementation().getResult(getSaajHeader());
}
private static class SaajSoapHeaderElementIterator implements Iterator {
protected static class SaajSoapHeaderElementIterator implements Iterator {
private final Iterator iterator;
private SaajSoapHeaderElementIterator(Iterator iterator) {
protected SaajSoapHeaderElementIterator(Iterator iterator) {
Assert.notNull(iterator, "iterator must not be null");
this.iterator = iterator;
}

View File

@@ -32,6 +32,8 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain {
private String[] actorsOrRoles;
private boolean isUltimateReceiver = true;
/**
* Create new <code>SoapEndpointInvocationChain</code>.
*
@@ -54,13 +56,18 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain {
/**
* Create new <code>EndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
* @param interceptors the array of interceptors to apply
* @param actorsOrRoles the array of actorsOrRoles to set
* @param endpoint the endpoint object to invoke
* @param interceptors the array of interceptors to apply
* @param actorsOrRoles the array of actorsOrRoles to set
* @param isUltimateReceiver whether this chain fullfils the SOAP 1.2 Ultimate receiver role
*/
public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors, String[] actorsOrRoles) {
public SoapEndpointInvocationChain(Object endpoint,
EndpointInterceptor[] interceptors,
String[] actorsOrRoles,
boolean isUltimateReceiver) {
super(endpoint, interceptors);
this.actorsOrRoles = actorsOrRoles;
this.isUltimateReceiver = isUltimateReceiver;
}
/**
@@ -72,4 +79,9 @@ public class SoapEndpointInvocationChain extends EndpointInvocationChain {
public String[] getActorsOrRoles() {
return actorsOrRoles;
}
/** Indicates whether this chain fulfills the SOAP 1.2 Ultimate Receiver role. Default is <code>true</code>. */
public boolean isUltimateReceiver() {
return isUltimateReceiver;
}
}

View File

@@ -36,4 +36,6 @@ public interface SoapEndpointMapping extends EndpointMapping {
/** Sets the array of SOAP actors/actorsOrRoles to apply to all endpoints mapped by the delegate endpoint mapping. */
void setActorsOrRoles(String[] actorsOrRoles);
/** Indicates whether this the endpoint fulfills the SOAP 1.2 Ultimate Receiver role. */
void setUltimateReceiver(boolean ultimateReceiver);
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Locale;
import javax.xml.namespace.QName;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
@@ -32,7 +33,7 @@ import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.soap11.Soap11Header;
import org.springframework.ws.soap.soap12.Soap12Header;
/**
@@ -46,33 +47,30 @@ import org.springframework.ws.soap.soap12.Soap12Header;
public class SoapMessageDispatcher extends MessageDispatcher {
/** Default message used when creating a SOAP MustUnderstand fault. */
public static final String DEFAULT_MUST_UNDERSTAND_FAULT =
public static final String DEFAULT_MUST_UNDERSTAND_FAULT_STRING =
"One or more mandatory SOAP header blocks not understood";
private String mustUnderstandFault = DEFAULT_MUST_UNDERSTAND_FAULT;
private String mustUnderstandFaultString = DEFAULT_MUST_UNDERSTAND_FAULT_STRING;
private Locale mustUnderstandFaultLocale = Locale.ENGLISH;
private Locale mustUnderstandFaultStringLocale = Locale.ENGLISH;
/**
* Sets the message used for <code>MustUnderstand</code> fault. Default to <code>DEFAULT_MUST_UNDERSTAND_FAULT</code>.
*
* @see #DEFAULT_MUST_UNDERSTAND_FAULT
* Sets the message used for <code>MustUnderstand</code> fault. Default to {@link
* #DEFAULT_MUST_UNDERSTAND_FAULT_STRING}.
*/
public void setMustUnderstandFault(String mustUnderstandFault) {
this.mustUnderstandFault = mustUnderstandFault;
public void setMustUnderstandFaultString(String mustUnderstandFaultString) {
this.mustUnderstandFaultString = mustUnderstandFaultString;
}
/** Sets the locale of the message used for <code>MustUnderstand</code> fault. Default to {@link Locale#ENGLISH}. */
public void setMustUnderstandFaultStringLocale(Locale mustUnderstandFaultStringLocale) {
this.mustUnderstandFaultStringLocale = mustUnderstandFaultStringLocale;
}
/**
* Sets the locale of the message used for <code>MustUnderstand</code> fault. Default to
* <code>Locale.ENGLISH</code>.
*/
public void setMustUnderstandFaultLocale(Locale mustUnderstandFaultLocale) {
this.mustUnderstandFaultLocale = mustUnderstandFaultLocale;
}
/**
* Process the <code>MustUnderstand</code> headers in the incoming SOAP request message. Iterates over all SOAP
* headers which should be understood, and determines whether these are supported. Generates a SOAP MustUnderstand
* Process the headers targeted at the actor or role fullfilled by the endpoint. Also processed the
* <code>MustUnderstand</code> headers in the incoming SOAP request message. Iterates over all SOAP headers which
* should be understood for this role, and determines whether these are supported. Generates a SOAP MustUnderstand
* fault if a header is not understood.
*
* @param mappedEndpoint the mapped EndpointInvocationChain
@@ -83,41 +81,59 @@ public class SoapMessageDispatcher extends MessageDispatcher {
*/
protected boolean handleRequest(EndpointInvocationChain mappedEndpoint, MessageContext messageContext) {
if (messageContext.getRequest() instanceof SoapMessage) {
SoapMessage soapRequest = (SoapMessage) messageContext.getRequest();
if (soapRequest.getSoapHeader() == null) {
// no headers to process
return true;
}
String[] roles = getRoles(mappedEndpoint, soapRequest.getVersion());
if (logger.isDebugEnabled()) {
logger.debug("Handling MustUnderstand headers for actors/roles [" +
StringUtils.arrayToCommaDelimitedString(roles) + "]");
}
for (int i = 0; i < roles.length; i++) {
if (!handleRequestForRole(mappedEndpoint, messageContext, roles[i])) {
return false;
}
String[] actorsOrRoles = null;
boolean isUltimateReceiver = true;
if (mappedEndpoint instanceof SoapEndpointInvocationChain) {
SoapEndpointInvocationChain soapChain = (SoapEndpointInvocationChain) mappedEndpoint;
actorsOrRoles = soapChain.getActorsOrRoles();
isUltimateReceiver = soapChain.isUltimateReceiver();
}
return handleHeaders(mappedEndpoint, messageContext, actorsOrRoles, isUltimateReceiver);
}
return true;
}
/**
* Determines the roles for a specific SOAP invocation chain. Gets the roles specified on the chain, and adds the
* SOAP-version specific 'next' role to it.
*
* @see org.springframework.ws.soap.SoapVersion#getNextActorOrRoleUri()
*/
protected String[] getRoles(EndpointInvocationChain mappedEndpoint, SoapVersion version) {
String[] mappedRoles = null;
if (mappedEndpoint instanceof SoapEndpointInvocationChain) {
SoapEndpointInvocationChain soapEndpoint = (SoapEndpointInvocationChain) mappedEndpoint;
mappedRoles = soapEndpoint.getActorsOrRoles();
private boolean handleHeaders(EndpointInvocationChain mappedEndpoint,
MessageContext messageContext,
String[] actorsOrRoles,
boolean isUltimateReceiver) {
SoapMessage soapRequest = (SoapMessage) messageContext.getRequest();
SoapHeader soapHeader = soapRequest.getSoapHeader();
if (soapHeader == null) {
return true;
}
if (mappedRoles == null) {
mappedRoles = new String[0];
Iterator headerIterator;
if (soapHeader instanceof Soap11Header) {
headerIterator = ((Soap11Header) soapHeader).examineHeaderElementsToProcess(actorsOrRoles);
}
else {
headerIterator =
((Soap12Header) soapHeader).examineHeaderElementsToProcess(actorsOrRoles, isUltimateReceiver);
}
List notUnderstoodHeaderNames = new ArrayList();
while (headerIterator.hasNext()) {
SoapHeaderElement headerElement = (SoapHeaderElement) headerIterator.next();
QName headerName = headerElement.getName();
if (logger.isDebugEnabled()) {
if (!headerElement.getMustUnderstand()) {
logger.debug("Handling header " + headerName);
}
else {
logger.debug("Handling MustUnderstand header " + headerName);
}
}
if (headerElement.getMustUnderstand() && !headerUnderstood(mappedEndpoint, headerElement)) {
notUnderstoodHeaderNames.add(headerName);
}
}
if (notUnderstoodHeaderNames.isEmpty()) {
return true;
}
else {
SoapMessage response = (SoapMessage) messageContext.getResponse();
createMustUnderstandFault(response, notUnderstoodHeaderNames, actorsOrRoles);
return false;
}
return StringUtils.addStringToArray(mappedRoles, version.getNextActorOrRoleUri());
}
/**
@@ -128,52 +144,39 @@ public class SoapMessageDispatcher extends MessageDispatcher {
*
* @see SoapEndpointInterceptor#understands(org.springframework.ws.soap.SoapHeaderElement)
*/
private boolean handleRequestForRole(EndpointInvocationChain mappedEndpoint,
MessageContext messageContext,
String actorOrRole) {
SoapHeader requestHeader = ((SoapMessage) messageContext.getRequest()).getSoapHeader();
List notUnderstoodHeaderNames = new ArrayList();
for (Iterator iterator = requestHeader.examineMustUnderstandHeaderElements(actorOrRole); iterator.hasNext();) {
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
QName headerName = headerElement.getName();
if (logger.isDebugEnabled()) {
logger.debug(
"Received mustUnderstand header [" + headerName + "] for actor/role [" + actorOrRole + "]");
}
boolean understood = false;
for (int i = 0; i < mappedEndpoint.getInterceptors().length; i++) {
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
if (interceptor instanceof SoapEndpointInterceptor &&
((SoapEndpointInterceptor) interceptor).understands(headerElement)) {
understood = true;
break;
}
}
if (!understood) {
notUnderstoodHeaderNames.add(headerName);
private boolean headerUnderstood(EndpointInvocationChain mappedEndpoint, SoapHeaderElement headerElement) {
EndpointInterceptor[] interceptors = mappedEndpoint.getInterceptors();
for (int i = 0; i < interceptors.length; i++) {
EndpointInterceptor interceptor = interceptors[i];
if (interceptor instanceof SoapEndpointInterceptor &&
((SoapEndpointInterceptor) interceptor).understands(headerElement)) {
return true;
}
}
if (notUnderstoodHeaderNames.isEmpty()) {
return true;
return false;
}
private void createMustUnderstandFault(SoapMessage soapResponse,
List notUnderstoodHeaderNames,
String[] actorsOrRoles) {
if (logger.isWarnEnabled()) {
logger.warn("Could not handle mustUnderstand headers: " +
StringUtils.collectionToCommaDelimitedString(notUnderstoodHeaderNames) + ". Returning fault");
}
else {
if (logger.isWarnEnabled()) {
logger.warn("Could not handle mustUnderstand headers: " +
StringUtils.collectionToCommaDelimitedString(notUnderstoodHeaderNames) + ". Returning fault");
SoapBody responseBody = soapResponse.getSoapBody();
SoapFault fault =
responseBody.addMustUnderstandFault(mustUnderstandFaultString, mustUnderstandFaultStringLocale);
if (!ObjectUtils.isEmpty(actorsOrRoles)) {
fault.setFaultActorOrRole(actorsOrRoles[0]);
}
SoapHeader header = soapResponse.getSoapHeader();
if (header instanceof Soap12Header) {
Soap12Header soap12Header = (Soap12Header) header;
for (Iterator iterator = notUnderstoodHeaderNames.iterator(); iterator.hasNext();) {
QName headerName = (QName) iterator.next();
soap12Header.addNotUnderstoodHeaderElement(headerName);
}
SoapMessage soapResponse = (SoapMessage) messageContext.getResponse();
SoapBody responseBody = soapResponse.getSoapBody();
SoapFault fault = responseBody.addMustUnderstandFault(mustUnderstandFault, mustUnderstandFaultLocale);
fault.setFaultActorOrRole(actorOrRole);
SoapHeader header = soapResponse.getSoapHeader();
if (header instanceof Soap12Header) {
Soap12Header soap12Header = (Soap12Header) header;
for (Iterator iterator = notUnderstoodHeaderNames.iterator(); iterator.hasNext();) {
QName headerName = (QName) iterator.next();
soap12Header.addNotUnderstoodHeaderElement(headerName);
}
}
return false;
}
}
}

View File

@@ -46,6 +46,8 @@ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndp
private String[] actorsOrRoles;
private boolean isUltimateReceiver = true;
/** Sets the delegate <code>EndpointMapping</code> to resolve the endpoint with. */
public void setDelegate(EndpointMapping delegate) {
this.delegate = delegate;
@@ -61,6 +63,10 @@ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndp
this.actorsOrRoles = actorsOrRoles;
}
public final void setUltimateReceiver(boolean ultimateReceiver) {
isUltimateReceiver = ultimateReceiver;
}
/**
* Creates a new <code>SoapEndpointInvocationChain</code> based on the delegate endpoint, the delegate interceptors,
* and set actors/roles.
@@ -70,7 +76,7 @@ public class DelegatingSoapEndpointMapping implements InitializingBean, SoapEndp
public EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
EndpointInvocationChain delegateChain = delegate.getEndpoint(messageContext);
return new SoapEndpointInvocationChain(delegateChain.getEndpoint(), delegateChain.getInterceptors(),
actorsOrRoles);
actorsOrRoles, isUltimateReceiver);
}
public void afterPropertiesSet() throws Exception {

View File

@@ -53,6 +53,8 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i
private String[] actorsOrRoles;
private boolean isUltimateReceiver = true;
public final void setActorOrRole(String actorOrRole) {
Assert.notNull(actorOrRole, "actorOrRole must not be null");
actorsOrRoles = new String[]{actorOrRole};
@@ -63,6 +65,10 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i
this.actorsOrRoles = actorsOrRoles;
}
public final void setUltimateReceiver(boolean ultimateReceiver) {
isUltimateReceiver = ultimateReceiver;
}
/**
* Creates a new <code>SoapEndpointInvocationChain</code> based on the given endpoint, and the set interceptors, and
* actors/roles.
@@ -76,7 +82,7 @@ public class SoapActionEndpointMapping extends AbstractMapBasedEndpointMapping i
protected final EndpointInvocationChain createEndpointInvocationChain(MessageContext messageContext,
Object endpoint,
EndpointInterceptor[] interceptors) {
return new SoapEndpointInvocationChain(endpoint, interceptors, actorsOrRoles);
return new SoapEndpointInvocationChain(endpoint, interceptors, actorsOrRoles, isUltimateReceiver);
}
protected String getLookupKeyForMessage(MessageContext messageContext) throws Exception {

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.soap11;
import java.util.Iterator;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapHeaderException;
/**
* Subinterface of <code>SoapHeader</code> that exposes SOAP 1.1 functionality.
*
* @author Arjen Poutsma
*/
public interface Soap11Header extends SoapHeader {
/**
* Returns an <code>Iterator</code> over all the {@link SoapHeaderElement header elements} that should be processed
* for the given actors. Headers target to the "next" actor or role will always be included.
*
* @param actors an array of actors to search for
* @return an iterator over all the header elements that contain the specified actors
* @throws SoapHeaderException if the headers cannot be returned
* @see SoapHeaderElement
*/
Iterator examineHeaderElementsToProcess(String[] actors) throws SoapHeaderException;
}

View File

@@ -16,10 +16,12 @@
package org.springframework.ws.soap.soap12;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapHeaderException;
/**
* Subinterface of <code>SoapHeader</code> that exposes SOAP 1.2 functionality.
@@ -48,4 +50,18 @@ public interface Soap12Header extends SoapHeader {
*/
SoapHeaderElement addUpgradeHeaderElement(java.lang.String[] supportedSoapUris);
/**
* Returns an <code>Iterator</code> over all the {@link SoapHeaderElement header elements} that should be processed
* for the given roles. Headers target to the "next" role will always be included, and those targeted to "none" will
* never be included.
*
* @param roles an array of roles to search for
* @param isUltimateReceiver whether to search for headers for the ultimate receiver
* @return an iterator over all the header elements that contain the specified roles
* @throws SoapHeaderException if the headers cannot be returned
* @see SoapHeaderElement
*/
Iterator examineHeaderElementsToProcess(String[] roles, boolean isUltimateReceiver) throws SoapHeaderException;
}

View File

@@ -37,6 +37,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.OrderComparator;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -123,6 +124,7 @@ public class DefaultStrategiesHelper {
else {
result = Collections.EMPTY_LIST;
}
Collections.sort(result, new OrderComparator());
return result;
}
catch (ClassNotFoundException ex) {

View File

@@ -26,6 +26,10 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest
protected SoapHeader soapHeader;
protected static final String NAMESPACE = "http://www.springframework.org";
protected static final String PREFIX = "spring";
protected final SoapElement createSoapElement() throws Exception {
soapHeader = createSoapHeader();
return soapHeader;
@@ -34,7 +38,7 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest
protected abstract SoapHeader createSoapHeader() throws Exception;
public void testAddHeaderElement() throws Exception {
QName qName = new QName("http://www.springframework.org", "localName", "spring");
QName qName = new QName(NAMESPACE, "localName", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
assertNotNull("No SoapHeaderElement returned", headerElement);
assertEquals("Invalid qName for element", qName, headerElement.getName());
@@ -45,7 +49,7 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest
}
public void testExamineAllHeaderElement() throws Exception {
QName qName = new QName("http://www.springframework.org", "localName", "spring");
QName qName = new QName(NAMESPACE, "localName", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
assertEquals("Invalid qName for element", qName, headerElement.getName());
assertNotNull("No SoapHeaderElement returned", headerElement);
@@ -65,11 +69,11 @@ public abstract class AbstractSoapHeaderTestCase extends AbstractSoapElementTest
}
public void testExamineMustUnderstandHeaderElements() throws Exception {
QName qName1 = new QName("http://www.springframework.org", "localName1", "spring");
QName qName1 = new QName(NAMESPACE, "localName1", PREFIX);
SoapHeaderElement headerElement1 = soapHeader.addHeaderElement(qName1);
headerElement1.setMustUnderstand(true);
headerElement1.setActorOrRole("role1");
QName qName2 = new QName("http://www.springframework.org", "localName2", "spring");
QName qName2 = new QName(NAMESPACE, "localName2", PREFIX);
SoapHeaderElement headerElement2 = soapHeader.addHeaderElement(qName2);
headerElement2.setMustUnderstand(true);
headerElement2.setActorOrRole("role2");

View File

@@ -28,6 +28,6 @@ public class SaajSoap11HeaderTest extends AbstractSoap11HeaderTestCase {
protected SoapHeader createSoapHeader() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage saajMessage = messageFactory.createMessage();
return new SaajSoapHeader(saajMessage.getSOAPPart().getEnvelope().getHeader());
return new SaajSoap11Header(saajMessage.getSOAPPart().getEnvelope().getHeader());
}
}

View File

@@ -121,10 +121,9 @@ public class SoapMessageDispatcherTest extends TestCase {
Soap11Fault fault = (Soap11Fault) responseBody.getFault();
assertEquals("Invalid fault code", new QName(SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE, "MustUnderstand"),
fault.getFaultCode());
assertEquals("Invalid fault string", SoapMessageDispatcher.DEFAULT_MUST_UNDERSTAND_FAULT,
assertEquals("Invalid fault string", SoapMessageDispatcher.DEFAULT_MUST_UNDERSTAND_FAULT_STRING,
fault.getFaultStringOrReason());
assertEquals("Invalid fault string locale", Locale.ENGLISH, fault.getFaultStringLocale());
assertEquals("Invalid fault actor", SOAPConstants.URI_SOAP_ACTOR_NEXT, fault.getFaultActorOrRole());
interceptorControl.verify();
}
@@ -154,9 +153,8 @@ public class SoapMessageDispatcherTest extends TestCase {
Soap12Fault fault = (Soap12Fault) responseBody.getFault();
assertEquals("Invalid fault code", new QName(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE, "MustUnderstand"),
fault.getFaultCode());
assertEquals("Invalid fault string", SoapMessageDispatcher.DEFAULT_MUST_UNDERSTAND_FAULT,
assertEquals("Invalid fault string", SoapMessageDispatcher.DEFAULT_MUST_UNDERSTAND_FAULT_STRING,
fault.getFaultReasonText(Locale.ENGLISH));
assertEquals("Invalid fault actor", SOAPConstants.URI_SOAP_1_2_ROLE_NEXT, fault.getFaultActorOrRole());
SoapHeader responseHeader = response.getSoapHeader();
Iterator iterator = responseHeader.examineAllHeaderElements();
assertTrue("Response header has no elements", iterator.hasNext());
@@ -182,7 +180,7 @@ public class SoapMessageDispatcherTest extends TestCase {
interceptorControl.replay();
SoapEndpointInvocationChain chain = new SoapEndpointInvocationChain(new Object(),
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{headerActor});
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{headerActor}, true);
boolean result = dispatcher.handleRequest(chain, context);
assertTrue("actor-specific header not understood", result);
@@ -205,7 +203,7 @@ public class SoapMessageDispatcherTest extends TestCase {
interceptorControl.replay();
SoapEndpointInvocationChain chain = new SoapEndpointInvocationChain(new Object(),
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{headerRole});
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{headerRole}, true);
boolean result = dispatcher.handleRequest(chain, context);
assertTrue("role-specific header not understood", result);
@@ -221,7 +219,7 @@ public class SoapMessageDispatcherTest extends TestCase {
interceptorControl.replay();
SoapEndpointInvocationChain chain = new SoapEndpointInvocationChain(new Object(),
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{"role"});
new SoapEndpointInterceptor[]{interceptorMock}, new String[]{"role"}, true);
boolean result = dispatcher.handleRequest(chain, context);
assertTrue("Invalid result", result);

View File

@@ -29,6 +29,10 @@ import org.springframework.xml.transform.StringSource;
public abstract class AbstractSoap11BodyTestCase extends AbstractSoapBodyTestCase {
public void testGetType() {
assertTrue("Invalid type returned", soapBody instanceof Soap11Body);
}
public void testGetName() throws Exception {
assertEquals("Invalid qualified name", SoapVersion.SOAP_11.getBodyName(), soapBody.getName());
}

View File

@@ -16,17 +16,24 @@
package org.springframework.ws.soap.soap11;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.springframework.ws.soap.AbstractSoapHeaderTestCase;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.xml.transform.StringResult;
public abstract class AbstractSoap11HeaderTestCase extends AbstractSoapHeaderTestCase {
private static final String PREFIX = "spring";
public void testGetType() {
assertTrue("Invalid type returned", soapHeader instanceof Soap11Header);
}
public void testGetName() throws Exception {
assertEquals("Invalid qualified name",
new QName(SoapVersion.SOAP_11.getEnvelopeNamespaceUri(), "Header"),
assertEquals("Invalid qualified name", new QName(SoapVersion.SOAP_11.getEnvelopeNamespaceUri(), "Header"),
soapHeader.getName());
}
@@ -34,8 +41,51 @@ public abstract class AbstractSoap11HeaderTestCase extends AbstractSoapHeaderTes
StringResult result = new StringResult();
transformer.transform(soapHeader.getSource(), result);
assertXMLEqual("Invalid contents of header",
"<SOAP-ENV:Header xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />",
result.toString());
"<SOAP-ENV:Header xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />", result.toString());
}
public void testExamineHeaderElementsToProcessActors() throws Exception {
QName qName = new QName(NAMESPACE, "localName1", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role1");
qName = new QName(NAMESPACE, "localName2", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role2");
qName = new QName(NAMESPACE, "localName3", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole(SoapVersion.SOAP_11.getNextActorOrRoleUri());
Iterator iterator = ((Soap11Header) soapHeader).examineHeaderElementsToProcess(new String[]{"role1"});
assertNotNull("header element iterator is null", iterator);
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertFalse("header element iterator has too many elements", iterator.hasNext());
}
public void testExamineHeaderElementsToProcessNoActors() throws Exception {
QName qName = new QName(NAMESPACE, "localName1", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("");
qName = new QName(NAMESPACE, "localName2", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role1");
qName = new QName(NAMESPACE, "localName3", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole(SoapVersion.SOAP_11.getNextActorOrRoleUri());
Iterator iterator = ((Soap11Header) soapHeader).examineHeaderElementsToProcess(new String[0]);
assertNotNull("header element iterator is null", iterator);
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertFalse("header element iterator has too many elements", iterator.hasNext());
}
private void checkHeaderElement(SoapHeaderElement headerElement) {
QName name = headerElement.getName();
assertTrue("Invalid name on header element", new QName(NAMESPACE, "localName1", PREFIX).equals(name) ||
new QName(NAMESPACE, "localName3", PREFIX).equals(name));
}
}

View File

@@ -30,6 +30,10 @@ import org.springframework.xml.transform.StringSource;
public abstract class AbstractSoap12BodyTestCase extends AbstractSoapBodyTestCase {
public void testGetType() {
assertTrue("Invalid type returned", soapBody instanceof Soap12Body);
}
public void testGetName() throws Exception {
assertEquals("Invalid qualified name", new QName(SoapVersion.SOAP_12.getEnvelopeNamespaceUri(), "Body"),
soapBody.getName());

View File

@@ -16,6 +16,7 @@
package org.springframework.ws.soap.soap12;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.springframework.ws.soap.AbstractSoapHeaderTestCase;
@@ -25,6 +26,10 @@ import org.springframework.xml.transform.StringResult;
public abstract class AbstractSoap12HeaderTestCase extends AbstractSoapHeaderTestCase {
public void testGetType() {
assertTrue("Invalid type returned", soapHeader instanceof Soap12Header);
}
public void testGetName() throws Exception {
assertEquals("Invalid qualified name", new QName(SoapVersion.SOAP_12.getEnvelopeNamespaceUri(), "Header"),
soapHeader.getName());
@@ -67,4 +72,60 @@ public abstract class AbstractSoap12HeaderTestCase extends AbstractSoapHeaderTes
*/
}
public void testExamineHeaderElementsToProcessActors() throws Exception {
QName qName = new QName(NAMESPACE, "localName1", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role1");
qName = new QName(NAMESPACE, "localName2", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role2");
qName = new QName(NAMESPACE, "localName3", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole(SoapVersion.SOAP_12.getNextActorOrRoleUri());
Iterator iterator = ((Soap12Header) soapHeader).examineHeaderElementsToProcess(new String[]{"role1"}, false);
assertNotNull("header element iterator is null", iterator);
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertFalse("header element iterator has too many elements", iterator.hasNext());
}
public void testExamineHeaderElementsToProcessNoActors() throws Exception {
QName qName = new QName(NAMESPACE, "localName1", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("");
qName = new QName(NAMESPACE, "localName2", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole("role1");
qName = new QName(NAMESPACE, "localName3", PREFIX);
headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole(SoapVersion.SOAP_12.getNextActorOrRoleUri());
Iterator iterator = ((Soap12Header) soapHeader).examineHeaderElementsToProcess(new String[0], false);
assertNotNull("header element iterator is null", iterator);
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertTrue("header element iterator has no elements", iterator.hasNext());
checkHeaderElement((SoapHeaderElement) iterator.next());
assertFalse("header element iterator has too many elements", iterator.hasNext());
}
public void testExamineHeaderElementsToProcessUltimateDestination() throws Exception {
QName qName = new QName(NAMESPACE, "localName", PREFIX);
SoapHeaderElement headerElement = soapHeader.addHeaderElement(qName);
headerElement.setActorOrRole(SoapVersion.SOAP_12.getUltimateReceiverRoleUri());
Iterator iterator = ((Soap12Header) soapHeader).examineHeaderElementsToProcess(new String[]{"role"}, true);
assertNotNull("header element iterator is null", iterator);
headerElement = (SoapHeaderElement) iterator.next();
assertEquals("Invalid name on header element", new QName(NAMESPACE, "localName", PREFIX),
headerElement.getName());
assertFalse("header element iterator has too many elements", iterator.hasNext());
}
private void checkHeaderElement(SoapHeaderElement headerElement) {
QName name = headerElement.getName();
assertTrue("Invalid name on header element", new QName(NAMESPACE, "localName1", PREFIX).equals(name) ||
new QName(NAMESPACE, "localName3", PREFIX).equals(name));
}
}