blob: 5227f0ae42333b2d32cd862ef8f5ce0c88e7c7dc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.axis2.jaxws.handler;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.jaxws.description.DescriptionFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.description.xml.handler.HandlerChainType;
import org.apache.axis2.jaxws.description.xml.handler.HandlerChainsType;
import org.apache.axis2.jaxws.description.xml.handler.HandlerType;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.PortInfo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
/**
* Test Role (SOAP 1.2 terminology) or Actor (SOAP 1.1 terminology) mustUndertand processing.
*/
public class RoleBasedMustUndertandTests extends TestCase {
private SOAPFactory soap11Factory;
private SOAPFactory soap12Factory;
private OMFactory omFactory;
private String namespace = "http://RoleBasedMustUnderstandTest/good/namespace";
private String soap11Namespace = "http://schemas.xmlsoap.org/soap/envelope/";
private String header_ultimateReceiver = "header_ultimateReceiver";
private String header_ultimateReceiver_processed = "header_ultmiateReceiver_processed";
private String header_rolePlayed = "header_rolePlayed";
private String header_roleNotPlayed = "header_roleNotPlayed";
private String header_bindingAdded = "header_bindingAdded";
private String header_SoapNext = "header_SoapNext";
private String rolePlayed1 = "http://Role/Played/role1";
private String roleNotPlayed = "http://Role/Not/Played/role1";
private String roleBindingAdded = "http://Role/Added/By/Binding";
private String roleNoHeaders = "http://Role/Played/No/Headers";
private String roleHandlerAdded = "http://org/apache/axis2/jaxws/handler/AddedRole";
private String roleHandlerAdded2 = "http://org/apache/axis2/jaxws/handler/AddedRole2";
private String roleSoap11Next = "http://schemas.xmlsoap.org/soap/actor/next";
public RoleBasedMustUndertandTests(String testName) {
super(testName);
soap11Factory = OMAbstractFactory.getSOAP11Factory();
soap12Factory = OMAbstractFactory.getSOAP12Factory();
omFactory = OMAbstractFactory.getOMFactory();
}
/**
* Validate that handler information can be cached on the ServiceDescritpion on the server side.
*/
public void testCachingOnServer() {
ServiceDescription serviceDesc = DescriptionFactory.createServiceDescription(RoleBasedMUServiceImpl.class);
HandlerResolverImpl handlerResolver1 = new HandlerResolverImpl(serviceDesc);
HandlerResolverImpl handlerResolver2 = new HandlerResolverImpl(serviceDesc);
EndpointDescription epDesc = serviceDesc.getEndpointDescriptions()[0];
PortInfo portInfo = epDesc.getPortInfo();
List<String> roles1 = handlerResolver1.getRoles(portInfo);
List<String> roles2 = handlerResolver2.getRoles(portInfo);
assertNotNull(roles1);
assertNotNull(roles2);
assertTrue(roles1 == roles2);
}
/**
* Validate that handler information can NOT be cached on the client. That is because the client
* can specify handler information per instance of a service delegate. Those service
* delegates could share a ServiceDescription, but since each service delegate could specify
* unique handler information, we can't use common handler information stored on the
* ServiceDescription
*/
public void testCachingOnClient() {
ServiceDescription serviceDesc = DescriptionFactory.createServiceDescription(RoleBasedMUServiceImpl.class);
HandlerResolverImpl handlerResolver1 = new HandlerResolverImpl(serviceDesc, "sd1");
HandlerResolverImpl handlerResolver2 = new HandlerResolverImpl(serviceDesc, "sd2");
EndpointDescription epDesc = serviceDesc.getEndpointDescriptions()[0];
PortInfo portInfo = epDesc.getPortInfo();
List<String> roles1 = handlerResolver1.getRoles(portInfo);
List<String> roles2 = handlerResolver2.getRoles(portInfo);
assertNotNull(roles1);
assertNotNull(roles2);
assertTrue(roles1 != roles2);
}
/**
* The JAXWS Spec, section 10, says roles can be set on the SOAP binding. Verify that a
* mustUnderstand header which is not processed for a role added by the SOAPBinding causes
* a Not Understood fault
*/
public void testRoleAddedToSoapBinding() {
RolePlayer rolePlayer = new UltimateDestinationRoles();
MessageContext mscCtx11 = createMessageContext(soap11Factory);
// Note that since this role is UltimateReceiver, all unprocessed headers will be set
// on the message context
setUnprocessedHeaders(mscCtx11, rolePlayer);
// Indicate we understand (e.g. via handlers) the headers for Ultimate Receiver and the
// role we are acting in. We don't indicate we understand the header that the SOAPBinding
// added, so that should cause an exception
List<QName> understoodHeaders = new ArrayList<QName>();
understoodHeaders.add(new QName(namespace, header_ultimateReceiver));
understoodHeaders.add(new QName(namespace, header_rolePlayed));
// Create a list of additional roles that acted in (e.g. one played by a JAXWS
// handler)
List<String> headerRolesPlayed = bindingAddedRole();
try {
HandlerUtils.checkMustUnderstand(mscCtx11, understoodHeaders, headerRolesPlayed);
fail("Should have gotten NotUnderstood fault for header for role added by binding: " + header_bindingAdded);
} catch (AxisFault af) {
// Expected path; should get exception for ultimate receiver not processed.
String checkFault = af.toString();
if (!checkFault.contains("Must Understand check failed")
|| !checkFault.contains(header_bindingAdded)) {
fail("Did not get expected NotUnderstood AxisFault. Unexpected fault " + af);
}
} catch (Exception e) {
fail("Caught unexpected exception + e");
}
}
/**
* Test where there are no previous non-understood headers on the MessageContext and there's an
* additional Role added by a JAXWS handler
*/
public void testOnlySoapBindingRole() {
MessageContext mscCtx11 = createMessageContext(soap11Factory);
// Note that we are not putting any non-understood headers on the message context
// Create a list of additional roles (e.g. one played by a JAXWS
// handler
List<String> headerRolesPlayed = bindingAddedRole();
try {
HandlerUtils.checkMustUnderstand(mscCtx11, null, headerRolesPlayed);
fail("Should have gotten NotUnderstood fault for header for role added by binding: " + header_bindingAdded);
} catch (AxisFault af) {
// Expected path; should get exception for ultimate receiver not processed.
String checkFault = af.toString();
if (!checkFault.contains("Must Understand check failed")
|| !checkFault.contains(header_bindingAdded)) {
fail("Did not get expected NotUnderstood AxisFault. Unexpected fault " + af);
}
} catch (Exception e) {
fail("Caught unexpected exception + e");
}
}
/**
* Test that adding a role for headers that does not exist does not cause any fault
*/
public void testNoHeadersForSoapBindingRole() {
MessageContext mscCtx11 = createMessageContext(soap11Factory);
List<String> headerRolesPlayed = noHeadersRole();
try {
HandlerUtils.checkMustUnderstand(mscCtx11, null, headerRolesPlayed);
} catch (AxisFault af) {
fail("Unexpected AxisFault "+ af);
} catch (Exception e) {
fail("Caught unexpected exception + e");
}
}
/**
* A mustUnderstand header for a role not being acted in should NOT cause a notUnderstood
* fault.
*/
public void testRoleNotActingIn() {
RolePlayer rolePlayer = new UltimateDestinationRoles();
MessageContext mscCtx11 = createMessageContext(soap11Factory);
// Note that since this role is UltimateReceiver, all unprocessed headers will be set
// on the message context
setUnprocessedHeaders(mscCtx11, rolePlayer);
// Indicate we understand (e.g. via handlers) the headers for Ultimate Receiver and the
// role we are acting in. This leaves the mustUnderstand header for the role we are not
// acting in, which should not cause an exception.
List<QName> understoodHeaders = new ArrayList<QName>();
understoodHeaders.add(new QName(namespace, header_ultimateReceiver));
understoodHeaders.add(new QName(namespace, header_rolePlayed));
try {
HandlerUtils.checkMustUnderstand(mscCtx11, understoodHeaders, null);
} catch (AxisFault e) {
fail("Should not have caught an AxisFault " + e);
}
}
/**
* Test mustUnderstand processing for Ultimate Receiver with an understood header list
* passed to the mustUnderstand checking
*/
public void testUltimateReceiverRoles() {
RolePlayer rolePlayer = new UltimateDestinationRoles();
MessageContext mscCtx11 = createMessageContext(soap11Factory);
setUnprocessedHeaders(mscCtx11, rolePlayer);
// Indicate we understand (e.g. via handlers) all the headers.
List<QName> understoodHeaders = new ArrayList<QName>();
understoodHeaders.add(new QName(namespace, header_ultimateReceiver));
understoodHeaders.add(new QName(namespace, header_rolePlayed));
try {
HandlerUtils.checkMustUnderstand(mscCtx11, understoodHeaders, null);
} catch (AxisFault e) {
fail("Should not have caught an AxisFault " + e);
}
}
/**
* Verify that an Ultimate Receiver with no roles only yields the header with no role specified
* as unprocessed and that passing a list of understood headers including just that one causes
* the mustUnderstand checks to pass.
*/
public void testUltimateReceiver() {
RolePlayer rolePlayer = new UltimateDestinationNoRoles();
MessageContext msgCtx = createMessageContext(soap11Factory);
// Indicate the must understand header without an explicit role will be understood.
// The other headers, with explicit roles, should not cause an error.
setUnprocessedHeaders(msgCtx, rolePlayer);
List<QName> understoodHeaders = new ArrayList<QName>();
understoodHeaders.add(new QName(namespace, header_ultimateReceiver));
try {
HandlerUtils.checkMustUnderstand(msgCtx, understoodHeaders, null);
} catch (AxisFault e) {
fail("Should not have caught and AxisFault " + e);
}
}
/**
* Test mustUnderstand processing for Ultimate Receiver without additional understood headers
* being passed to the checker. This should cause a notUnderstood fault
*/
public void testUltimateReceiverNoRoles() {
RolePlayer rolePlayer = new UltimateDestinationNoRoles();
MessageContext messageContext11 = createMessageContext(soap11Factory);
setUnprocessedHeaders(messageContext11, rolePlayer);
try {
HandlerUtils.checkMustUnderstand(messageContext11, null, null);
fail("Should have gotten MustUnderstand Header Not Understood fault");
} catch (AxisFault af) {
// Expected path; should get exception for ultimate receiver not processed.
String checkFault = af.toString();
if (!checkFault.contains("Must Understand check failed")
|| !checkFault.contains(header_ultimateReceiver)) {
fail("Did not get expected NotUnderstood AxisFault. Unexpected fault " + af);
}
} catch (Exception e) {
fail("Caught unexpected exception + e");
}
MessageContext messageContext12 = createMessageContext(soap12Factory);
setUnprocessedHeaders(messageContext12, rolePlayer);
try {
HandlerUtils.checkMustUnderstand(messageContext12, null, null);
fail("Should have gotten MustUnderstand Header Not Understood fault");
} catch (AxisFault af) {
// Expected path; should get exception for ultimate receiver not processed.
if (!af.toString().contains("Must Understand check failed")) {
fail("Did not get expected NotUnderstood AxisFault. Unexpected fault " + af);
}
} catch (Exception e) {
fail("Caught unexpected exception + e");
}
}
/**
* Test a RolePlayer that is not an ultimate receiver and does not act in any roles
* corresponding to headers. There should be no faults cause by the mustUnderstand headers
*/
public void testNotUltimateReceiverNoRoles() {
RolePlayer rolePlayer = new NotUltimateDestinationNoRoles();
MessageContext msgCtx11 = createMessageContext(soap11Factory);
setUnprocessedHeaders(msgCtx11, rolePlayer);
try {
HandlerUtils.checkMustUnderstand(msgCtx11, null, null);
} catch (AxisFault e) {
fail("Should not have caught and AxisFault");
}
MessageContext msgCtx12 = createMessageContext(soap12Factory);
setUnprocessedHeaders(msgCtx12, rolePlayer);
try {
HandlerUtils.checkMustUnderstand(msgCtx12, null, null);
} catch (AxisFault e) {
fail("Should not have caught and AxisFault");
}
}
/**
* Test that the HandlerResolverImpl returns the correct roles defined in the handler config
* file <soap-role> elements.
*/
public void testHandlerResolverGetRoles() {
ServiceDescription serviceDesc = DescriptionFactory.createServiceDescription(RoleBasedMUServiceImpl.class);
HandlerResolverImpl handlerResolver = new HandlerResolverImpl(serviceDesc);
EndpointDescription epDesc = serviceDesc.getEndpointDescriptions()[0];
// Make sure the role information is specified in the handler config file
HandlerChainsType epHandlerChains = epDesc.getHandlerChain();
assertNotNull(epHandlerChains);
List<HandlerChainType> epHandlerChain = epHandlerChains.getHandlerChain();
assertEquals(1, epHandlerChain.size());
List<HandlerType> epHandler = epHandlerChain.get(0).getHandler();
assertEquals(1, epHandler.size());
HandlerType handlerType = epHandler.get(0);
List<org.apache.axis2.jaxws.description.xml.handler.String> soapRoles =
handlerType.getSoapRole();
assertNotNull(soapRoles);
assertEquals(1, soapRoles.size());
String addedRole = soapRoles.get(0).getValue();
assertEquals(roleHandlerAdded, addedRole);
// Now verify the role information in the handler config file correctly affects the
// roles played returned from the Resolver
PortInfo portInfo = epDesc.getPortInfo();
List<String> handlerRoles = handlerResolver.getRoles(portInfo);
assertNotNull(handlerRoles);
assertEquals(1, handlerRoles.size());
assertEquals(roleHandlerAdded, handlerRoles.get(0));
List<Handler> handlerChain = handlerResolver.getHandlerChain(portInfo);
assertNotNull(handlerChain);
assertEquals(1, handlerChain.size());
}
/**
* Test that multiple <soap-role> elements in the handler config file work correctly.
*/
public void testHandlerResolverGerRoles2() {
ServiceDescription serviceDesc = DescriptionFactory.createServiceDescription(RoleBasedMUServiceImpl2.class);
HandlerResolverImpl handlerResolver = new HandlerResolverImpl(serviceDesc);
EndpointDescription epDesc = serviceDesc.getEndpointDescriptions()[0];
// Make sure the role information is specified in the handler config file
HandlerChainsType epHandlerChains = epDesc.getHandlerChain();
assertNotNull(epHandlerChains);
List<HandlerChainType> epHandlerChain = epHandlerChains.getHandlerChain();
assertEquals(1, epHandlerChain.size());
List<HandlerType> epHandler = epHandlerChain.get(0).getHandler();
assertEquals(1, epHandler.size());
HandlerType handlerType = epHandler.get(0);
List<org.apache.axis2.jaxws.description.xml.handler.String> soapRoles =
handlerType.getSoapRole();
assertNotNull(soapRoles);
assertEquals(2, soapRoles.size());
ArrayList<String> checkRoles = new ArrayList<String>();
checkRoles.add(soapRoles.get(0).getValue());
checkRoles.add(soapRoles.get(1).getValue());
assertTrue(checkRoles.contains(roleHandlerAdded));
assertTrue(checkRoles.contains(roleHandlerAdded2));
// Now verify the role information in the handler config file correctly affects the
// roles played returned from the Resolver
PortInfo portInfo = epDesc.getPortInfo();
List<String> handlerRoles = handlerResolver.getRoles(portInfo);
assertNotNull(handlerRoles);
assertEquals(2, handlerRoles.size());
ArrayList<String> checkResolverRoles = new ArrayList<String>();
checkResolverRoles.add((String) handlerRoles.get(0));
checkResolverRoles.add((String) handlerRoles.get(1));
assertTrue(checkResolverRoles.contains(roleHandlerAdded));
assertTrue(checkResolverRoles.contains(roleHandlerAdded2));
List<Handler> handlerChain = handlerResolver.getHandlerChain(portInfo);
assertNotNull(handlerChain);
assertEquals(1, handlerChain.size());
}
/**
* Test that a RolePlayer with no roles doesn't cause any problems in the mustUnderstand
* checking.
*/
public void testHandlerResolverEmptyRolesPlayed() {
RolePlayer rolePlayer = new UltimateDestinationRoles();
MessageContext msgCtx11 = createMessageContext(soap11Factory);
setUnprocessedHeaders(msgCtx11, rolePlayer);
// Indicate we understand (e.g. via handlers) all the headers.
List<QName> understoodHeaders = new ArrayList<QName>();
understoodHeaders.add(new QName(namespace, header_ultimateReceiver));
understoodHeaders.add(new QName(namespace, header_rolePlayed));
List<String> handlerRolePlayer = new ArrayList<String>();
try {
HandlerUtils.checkMustUnderstand(msgCtx11, understoodHeaders, handlerRolePlayer);
} catch (AxisFault e) {
fail("Should not have caught and AxisFault");
}
}
// =============================================================================================
// Utility methods
// =============================================================================================
private MessageContext createMessageContext(SOAPFactory soapFactory) {
MessageContext messageContext = null;
AxisService as1 = new AxisService("Service1");
ConfigurationContext cc = null;
try {
cc = ConfigurationContextFactory.createEmptyConfigurationContext();
AxisConfiguration ac = cc.getAxisConfiguration();
ac.addService(as1);
messageContext = cc.createMessageContext();
messageContext.setAxisService(as1);
SOAPEnvelope se = soapFactory.createSOAPEnvelope();
SOAPHeader sh = soapFactory.createSOAPHeader(se);
SOAPHeaderBlock shb1 = sh.addHeaderBlock(header_ultimateReceiver,
omFactory.createOMNamespace(namespace, header_ultimateReceiver));
// Since no role was set on the shb1, default is ultimate receiver
shb1.setMustUnderstand(true);
SOAPHeaderBlock shb2 = sh.addHeaderBlock(header_rolePlayed,
omFactory.createOMNamespace(namespace, header_rolePlayed));
shb2.setRole(rolePlayed1);
shb2.setMustUnderstand(true);
SOAPHeaderBlock shb3 = sh.addHeaderBlock(header_roleNotPlayed,
omFactory.createOMNamespace(namespace, header_roleNotPlayed));
shb3.setRole(roleNotPlayed);
shb3.setMustUnderstand(true);
SOAPHeaderBlock shb4 = sh.addHeaderBlock(header_bindingAdded,
omFactory.createOMNamespace(namespace, header_bindingAdded));
shb4.setRole(roleBindingAdded);
shb4.setMustUnderstand(true);
// This header is destined for the ulmiate receiver, but it is already processed
// so it shouldn't cause mustUnderstand fault
SOAPHeaderBlock shb5 = sh.addHeaderBlock(header_ultimateReceiver_processed,
omFactory.createOMNamespace(namespace, header_ultimateReceiver_processed));
// Since no role was set on the shb1, default is ultimate receiver
shb5.setMustUnderstand(true);
shb5.setProcessed();
// Header targeted for SOAP11 role of Next, not set to MustUnderstand
SOAPHeaderBlock shb6 = sh.addHeaderBlock(header_SoapNext,
omFactory.createOMNamespace(soap11Namespace, header_SoapNext));
shb6.setRole(roleSoap11Next);
messageContext.setEnvelope(se);
} catch (AxisFault e) {
fail("Caught unexpected exception creating message context" + e);
}
return messageContext;
}
private void setUnprocessedHeaders(MessageContext messageContext, RolePlayer rolePlayer) {
SOAPEnvelope envelope = messageContext.getEnvelope();
Iterator headerBlocks = envelope.getHeader().getHeadersToProcess(rolePlayer);
List<QName> unprocessedHeaders = new ArrayList<QName>();
while (headerBlocks.hasNext()) {
SOAPHeaderBlock headerBlock = (SOAPHeaderBlock) headerBlocks.next();
QName headerName = headerBlock.getQName();
// if this header block has been processed or mustUnderstand isn't
// turned on then its cool
if (headerBlock.isProcessed() || !headerBlock.getMustUnderstand()) {
continue;
} else {
unprocessedHeaders.add(headerName);
}
}
if(unprocessedHeaders !=null && unprocessedHeaders.size()>0){
messageContext.setProperty(Constants.UNPROCESSED_HEADER_QNAMES, unprocessedHeaders);
}
}
private List<String> bindingAddedRole() {
List<String> roles = new ArrayList<String>();
roles.add(roleBindingAdded);
return roles;
}
private List<String> noHeadersRole() {
List<String> roles = new ArrayList<String>();
roles.add(roleNoHeaders);
return roles;
}
// =============================================================================================
// Inner Test Classes
// =============================================================================================
class UltimateDestinationNoRoles implements RolePlayer {
public List getRoles() {
return null;
}
public boolean isUltimateDestination() {
return true;
}
}
class NotUltimateDestinationNoRoles implements RolePlayer {
public List getRoles() {
return null;
}
public boolean isUltimateDestination() {
return false;
}
}
class UltimateDestinationRoles implements RolePlayer {
List<String> roles = new ArrayList<String>();
public UltimateDestinationRoles() {
roles.add(rolePlayed1);
}
public List getRoles() {
return roles;
}
public boolean isUltimateDestination() {
return true;
}
}
@WebService
@HandlerChain(file="RoleBasedMustUnderstandTests.xml")
class RoleBasedMUServiceImpl {
}
@WebService
@HandlerChain(file="RoleBasedMustUnderstandTests2.xml")
class RoleBasedMUServiceImpl2 {
}
}