blob: 867724277a5b8bdd1c6cdb2440f9f4172463074b [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.spi;
import junit.framework.TestCase;
import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
import org.apache.axis2.jaxws.description.impl.DescriptionUtils;
import org.apache.axis2.jaxws.description.xml.handler.HandlerChainsType;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.soap.SOAPBinding;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Verify that handler chains specified using the HandlerChainsType in a sparse
* composite are correctly applied to Services and Ports on the client requester.
*/
public class ClientMetadataHandlerChainTest extends TestCase {
static String namespaceURI = "http://www.apache.org/test/namespace";
static String svcLocalPart = "DummyService";
static private String portLocalPart = "DummyPort";
private static int uniqueService = 0;
/**
* Test creating a service without a sparse composite. This verifies pre-existing default
* behavior.
*/
public void testServiceAndPortNoComposite() {
QName serviceQName = new QName(namespaceURI, svcLocalPart);
QName portQName = new QName(namespaceURI, portLocalPart);
Service service = Service.create(serviceQName);
HandlerResolver resolver = service.getHandlerResolver();
assertNotNull(resolver);
PortInfo pi = new DummyPortInfo();
List<Handler> list = resolver.getHandlerChain(pi);
assertEquals(0, list.size());
ClientMetadataHandlerChainTestSEI port = service.getPort(portQName, ClientMetadataHandlerChainTestSEI.class);
// Verify that ports created under the service have no handlers from the sparse composite
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(0, portHandlers.size());
}
/**
* Test creating a service with a sparse composite that contains handler configuration
* information for this service delegate. Verify that the handlers are included in the
* chain.
*/
public void testServiceWithComposite() {
QName serviceQName = new QName(namespaceURI, svcLocalPart);
QName portQName = new QName(namespaceURI, portLocalPart);
// Create a composite with a JAXB Handler Config
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setServiceMetadata(sparseComposite);
Service service = Service.create(serviceQName);
ClientMetadataHandlerChainTestSEI port = service.getPort(portQName, ClientMetadataHandlerChainTestSEI.class);
// Verify the HandlerResolver on the service knows about the handlers in the sparse composite
HandlerResolver resolver = service.getHandlerResolver();
assertNotNull(resolver);
PortInfo pi = new DummyPortInfo();
List<Handler> list = resolver.getHandlerChain(pi);
assertEquals(2, list.size());
// Verify that ports created under the service have handlers
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(2, portHandlers.size());
assertTrue(containSameHandlers(portHandlers, list));
// Verify that a subsequent port are different and that they also gets the correct handlers
ClientMetadataHandlerChainTestSEI port2 = service.getPort(portQName, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider2 = (BindingProvider) port2;
Binding binding2 = (Binding) bindingProvider2.getBinding();
List<Handler> portHandlers2 = binding2.getHandlerChain();
assertNotSame(port, port2);
assertEquals(2, portHandlers2.size());
assertTrue(containSameHandlers(portHandlers2, list));
}
/**
* Set a sparse composite on a specific Port. Verify that instances of that Port have the
* correct handlers associated and other Ports do not.
*/
public void testPortWithComposite() {
QName serviceQName = new QName(namespaceURI, svcLocalPart);
QName portQName = new QName(namespaceURI, portLocalPart);
Service service = Service.create(serviceQName);
// Create a composite with a JAXB Handler Config
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setPortMetadata(sparseComposite);
ClientMetadataHandlerChainTestSEI port = service.getPort(portQName, ClientMetadataHandlerChainTestSEI.class);
// Verify the HandlerResolver on the service knows about the handlers in the sparse composite
HandlerResolver resolver = service.getHandlerResolver();
assertNotNull(resolver);
PortInfo pi = new DummyPortInfo();
List<Handler> list = resolver.getHandlerChain(pi);
assertEquals(2, list.size());
// Verify that the port created with the sparse metadata has those handlers
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(2, portHandlers.size());
assertTrue(containSameHandlers(portHandlers, list));
// Verify that a creating another instance of the same port also gets those handlers
ClientMetadataHandlerChainTestSEI port2 = service.getPort(portQName, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider2 = (BindingProvider) port2;
Binding binding2 = (Binding) bindingProvider2.getBinding();
List<Handler> portHandlers2 = binding2.getHandlerChain();
assertNotSame(port, port2);
assertEquals(2, portHandlers2.size());
assertTrue(containSameHandlers(portHandlers2, list));
// Verify that createing a different port doesn't get the handlers
QName portQName3 = new QName(namespaceURI, portLocalPart + "3");
ClientMetadataHandlerChainTestSEI port3 = service.getPort(portQName3, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider3 = (BindingProvider) port3;
Binding binding3 = (Binding) bindingProvider3.getBinding();
List<Handler> portHandlers3 = binding3.getHandlerChain();
assertEquals(0, portHandlers3.size());
// Verify setting the metadata on a different port (a different QName) will get handlers.
QName portQName4 = new QName(namespaceURI, portLocalPart + "4");
ServiceDelegate.setPortMetadata(sparseComposite);
ClientMetadataHandlerChainTestSEI port4 = service.getPort(portQName4, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider4 = (BindingProvider) port4;
Binding binding4 = (Binding) bindingProvider4.getBinding();
List<Handler> portHandlers4 = binding4.getHandlerChain();
assertEquals(2, portHandlers4.size());
// Verify the service handler resolver knows about boths sets of handlers
// attached to the two different port QNames and none are attached for the third port
List<Handler> listForPort = resolver.getHandlerChain(pi);
assertEquals(2, listForPort.size());
PortInfo pi4 = new DummyPortInfo(portQName4);
List<Handler> listForPort4 = resolver.getHandlerChain(pi4);
assertEquals(2, listForPort4.size());
PortInfo pi3 = new DummyPortInfo(portQName3);
List<Handler> listForPort3 = resolver.getHandlerChain(pi3);
assertEquals(0, listForPort3.size());
}
/**
* Verify that handlers specified in a sparse compoiste on the service are only associated with
* that specific service delegate (i.e. Service instance), even if the QNames are the same
* across two instances of a Service.
*/
public void testMultipleServiceDelgatesServiceComposite() {
try {
// Need to cache the ServiceDescriptions so that they are shared
// across the two instances of the same Service.
ClientMetadataTest.installCachingFactory();
QName serviceQName = new QName(namespaceURI, svcLocalPart);
PortInfo pi = new DummyPortInfo();
// Create a Service specifying a sparse composite and verify the
// ports under that service get the correct handlers associated.
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setServiceMetadata(sparseComposite);
Service service1 = Service.create(serviceQName);
// Create a second instance of the same Service, but without
// metadata. Ports created under that service should not get handler's associated.
Service service2 = Service.create(serviceQName);
// No ports created yet, so there should be no relevant handler
// chains.
HandlerResolver resolver1 = service1.getHandlerResolver();
List<Handler> list1 = resolver1.getHandlerChain(pi);
assertEquals(0, list1.size());
// Create the port, it should get handlers.
QName portQName1 = new QName(namespaceURI, portLocalPart);
ClientMetadataHandlerChainTestSEI port1 =
service1.getPort(portQName1, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider1 = (BindingProvider) port1;
Binding binding1 = (Binding) bindingProvider1.getBinding();
List<Handler> portHandlers1 = binding1.getHandlerChain();
assertEquals(2, portHandlers1.size());
// Refresh the handler list from the resolver after the port is created
list1 = resolver1.getHandlerChain(pi);
assertTrue(containSameHandlers(portHandlers1, list1));
// Make sure the 2nd Service instance doesn't have handlers
// associated with it
HandlerResolver resolver2 = service2.getHandlerResolver();
List<Handler> list2 = resolver2.getHandlerChain(pi);
assertEquals(0, list2.size());
// Make sure the same port created under the 2nd service also
// doesn't have handlers
ClientMetadataHandlerChainTestSEI port2 =
service2.getPort(portQName1, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider2 = (BindingProvider) port2;
Binding binding2 = (Binding) bindingProvider2.getBinding();
List<Handler> portHandlers2 = binding2.getHandlerChain();
assertEquals(0, portHandlers2.size());
}
finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Verify that handlers specified in a sparse compoiste on the port are only associated with
* that port on that specific service delegate (i.e. Service instance), even if the QNames are the same
* across two instances of a Service.
*/
public void testMultipleServiceDelgatesPortComposite() {
try {
// Need to cache the ServiceDescriptions so that they are shared
// across the two instances of the same Service.
ClientMetadataTest.installCachingFactory();
QName serviceQName = new QName(namespaceURI, svcLocalPart);
PortInfo pi = new DummyPortInfo();
// Create two instances of the same Service
Service service1 = Service.create(serviceQName);
Service service2 = Service.create(serviceQName);
// No ports created yet, so there should be no relevant handler
// chains.
HandlerResolver resolver1 = service1.getHandlerResolver();
List<Handler> list1 = resolver1.getHandlerChain(pi);
assertEquals(0, list1.size());
// Create a Port specifying a sparse composite and verify the
// port gets the correct handlers associated.
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setPortMetadata(sparseComposite);
QName portQName1 = new QName(namespaceURI, portLocalPart);
ClientMetadataHandlerChainTestSEI port1 =
service1.getPort(portQName1, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider1 = (BindingProvider) port1;
Binding binding1 = (Binding) bindingProvider1.getBinding();
List<Handler> portHandlers1 = binding1.getHandlerChain();
assertEquals(2, portHandlers1.size());
// Refresh the handler list from the resolver after the port is created
list1 = resolver1.getHandlerChain(pi);
assertTrue(containSameHandlers(portHandlers1, list1));
// Make sure the 2nd Service instance doesn't have handlers
// associated with it
HandlerResolver resolver2 = service2.getHandlerResolver();
List<Handler> list2 = resolver2.getHandlerChain(pi);
assertEquals(0, list2.size());
// Make sure the same port created under the 2nd service also
// doesn't have handlers
ClientMetadataHandlerChainTestSEI port2 =
service2.getPort(portQName1, ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider2 = (BindingProvider) port2;
Binding binding2 = (Binding) bindingProvider2.getBinding();
List<Handler> portHandlers2 = binding2.getHandlerChain();
assertEquals(0, portHandlers2.size());
}
finally {
ClientMetadataTest.restoreOriginalFactory();
}
}
/**
* Verify that the original functionality of specifying a HandlerChain annotation with a
* file member works as it should.
*/
public void testHandlerChainOnSEI() {
QName serviceQN = new QName(namespaceURI, svcLocalPart);
Service service = Service.create(serviceQN);
ClientMetadataHandlerChainTestSEIWithHC port = service.getPort(ClientMetadataHandlerChainTestSEIWithHC.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(1, portHandlers.size());
assertTrue(containsHandlerChainAnnotationHandlers(portHandlers));
}
/**
* Verify that handler information in a sparse composite on the Port will override any handler chain
* annotation on the SEI.
*/
public void testSEIHandlerChainOverrideOnPort() {
QName serviceQN = new QName(namespaceURI, svcLocalPart + uniqueService++);
Service service = Service.create(serviceQN);
// The SEI has a HandlerChain annotation, but the sparse metadata should override it
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setPortMetadata(sparseComposite);
ClientMetadataHandlerChainTestSEIWithHC port = service.getPort(ClientMetadataHandlerChainTestSEIWithHC.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(2, portHandlers.size());
assertTrue(containsSparseCompositeHandlers(portHandlers));
}
/**
* Verify that handler information in a sparse composite on the Service will override any handler chain
* annotation on the SEI.
*/
public void testSEIHandlerChainOverrideOnService() {
QName serviceQN = new QName(namespaceURI, svcLocalPart + uniqueService++);
// The SEI has a HandlerChain annotation, but the sparse metadata should override it
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setServiceMetadata(sparseComposite);
Service service = Service.create(serviceQN);
ClientMetadataHandlerChainTestSEIWithHC port = service.getPort(ClientMetadataHandlerChainTestSEIWithHC.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(2, portHandlers.size());
assertTrue(containsSparseCompositeHandlers(portHandlers));
}
/**
* Set different composites on the Service and the Port that specify different
* HandlerChainsType values.
*/
public void testCompositeOnServiceAndPort() {
QName serviceQN = new QName(namespaceURI, svcLocalPart + uniqueService++);
// Create a service with a composite specifying handlers
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setServiceMetadata(sparseComposite);
Service service = Service.create(serviceQN);
// Create a port with a composite specifying different handlers
DescriptionBuilderComposite portComposite = new DescriptionBuilderComposite();
HandlerChainsType portHandlerChainsType = getHandlerChainsType("ClientMetadataHandlerChainTest.xml");
portComposite.setHandlerChainsType(portHandlerChainsType);
ServiceDelegate.setPortMetadata(portComposite);
ClientMetadataHandlerChainTestSEI port = service.getPort(ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
// If there is a HandlerChainsType composite specified on both the Service and the Port,
// then the composite specified on the Port should be the one used to associate the
// handlers for that Port.
assertEquals(1, portHandlers.size());
assertTrue(containsHandlerChainAnnotationHandlers(portHandlers));
}
/**
* Verfiy that a HandlerChain annotation on the Service is associated with the Port
*/
public void testGeneratedServiceWithHC() {
ClientMetadataHandlerChainTestServiceWithHC service = new ClientMetadataHandlerChainTestServiceWithHC();
ClientMetadataHandlerChainTestSEI port = service.getPort(ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(1, portHandlers.size());
assertTrue(containsHandlerChainAnnotationHandlers(portHandlers));
}
/**
* Verfiy that given a HandlerChain annotation on the Service and a Port and a sparse composite
* on the Port associates the handlers from the sparse composite on the Port.
*/
public void testGeneratedServiceWithHCPortOverride() {
ClientMetadataHandlerChainTestServiceWithHC service = new ClientMetadataHandlerChainTestServiceWithHC();
// Set a HandlerChainsType on the sparse composite for the Port creation; it should override the
// HandlerChain annotation on the Service.
DescriptionBuilderComposite sparseComposite = new DescriptionBuilderComposite();
HandlerChainsType handlerChainsType = getHandlerChainsType();
sparseComposite.setHandlerChainsType(handlerChainsType);
ServiceDelegate.setPortMetadata(sparseComposite);
ClientMetadataHandlerChainTestSEI port = service.getPort(ClientMetadataHandlerChainTestSEI.class);
BindingProvider bindingProvider = (BindingProvider) port;
Binding binding = (Binding) bindingProvider.getBinding();
List<Handler> portHandlers = binding.getHandlerChain();
assertEquals(2, portHandlers.size());
assertTrue(containsSparseCompositeHandlers(portHandlers));
}
// =============================================================================================
// Helper methods and classes
// =============================================================================================
private boolean containsSparseCompositeHandlers(List<Handler> handlerList) {
List<Class> inputHandlerClasses = handlerClasses(handlerList);
// These are the handlers defined in the HandlerChainsType placed on the sparse composite
List<Class> compositeHandlerClasses = new ArrayList<Class>();
compositeHandlerClasses.add(org.apache.axis2.jaxws.spi.handler.DummySOAPHandler.class);
compositeHandlerClasses.add(org.apache.axis2.jaxws.spi.handler.DummyLogicalHandler.class);
if (inputHandlerClasses.size() != compositeHandlerClasses.size()) {
return false;
}
if (inputHandlerClasses.containsAll(compositeHandlerClasses)) {
return true;
} else {
return false;
}
}
/**
* Answer if the List contains the same handlers as defined in the SEI
* via the HandlerChain.file annotation memeber.
*
* @param portHandlers List of handlers
* @return true if the list matches what was defined on the SEI via the
* HandlerChain annotation; false otherwise.
*/
private boolean containsHandlerChainAnnotationHandlers(List<Handler> portHandlers) {
List<Class> portHandlerClasses = handlerClasses(portHandlers);
List<Class> seiHandlerClasses = new ArrayList<Class>();
seiHandlerClasses.add(ClientMetadataHandlerChainHandler.class);
if (portHandlerClasses.size() != seiHandlerClasses.size()) {
return false;
}
if (portHandlerClasses.containsAll(seiHandlerClasses)) {
return true;
} else {
return false;
}
}
/**
* Answer if two List<Handler> arguments contain the same handler Class files.
* @param list1
* @param list2
* @return
*/
private boolean containSameHandlers(List<Handler> list1, List<Handler> list2) {
if (list1.size() != list2.size()) {
return false;
}
List<Class> list1HandlerClasses = handlerClasses(list1);
List<Class> list2HandlerClasses = handlerClasses(list2);
if (list1HandlerClasses.containsAll(list2HandlerClasses)) {
return true;
} else {
return false;
}
}
private List<Class> handlerClasses(List<Handler> listOfHandlers) {
List<Class> handlerClasses = new ArrayList<Class>();
Iterator<Handler> handlerIterator = listOfHandlers.iterator();
while (handlerIterator.hasNext()) {
handlerClasses.add(handlerIterator.next().getClass());
}
return handlerClasses;
}
private HandlerChainsType getHandlerChainsType() {
return getHandlerChainsType("handler.xml");
}
private HandlerChainsType getHandlerChainsType(String fileName) {
InputStream is = getXMLFileStream(fileName);
assertNotNull(is);
HandlerChainsType returnHCT = DescriptionUtils.loadHandlerChains(is, this.getClass().getClassLoader());
assertNotNull(returnHCT);
return returnHCT;
}
private InputStream getXMLFileStream(String fileName) {
InputStream is = null;
String configLoc = null;
try {
String sep = "/";
configLoc = sep + "test-resources" + sep + "configuration" + sep + "handlers" + sep + fileName;
String baseDir = new File(System.getProperty("basedir",".")).getCanonicalPath();
is = new File(baseDir + configLoc).toURL().openStream();
}
catch(Exception e) {
e.printStackTrace();
}
return is;
}
public class DummyPortInfo implements PortInfo {
private QName portQN;
private QName serviceQN;
public DummyPortInfo() {
this.portQN = new QName("http://www.apache.org/test/namespace", "DummyPort");
this.serviceQN = new QName("http://www.apache.org/test/namespace", "DummyService");
}
public DummyPortInfo(QName portQN) {
this();
this.portQN = portQN;
}
public String getBindingID() {
return SOAPBinding.SOAP11HTTP_BINDING;
}
public QName getPortName() {
return portQN;
}
public QName getServiceName() {
return serviceQN;
}
}
}
@WebService
interface ClientMetadataHandlerChainTestSEI {
public String echo(String toEcho);
}
@WebService
@HandlerChain(file="ClientMetadataHandlerChainTest.xml")
interface ClientMetadataHandlerChainTestSEIWithHC {
public String echo(String toEcho);
}
@WebServiceClient
@HandlerChain(file="ClientMetadataHandlerChainTest.xml")
class ClientMetadataHandlerChainTestServiceWithHC extends javax.xml.ws.Service {
public ClientMetadataHandlerChainTestServiceWithHC() {
super(null,
new QName(ClientMetadataHandlerChainTest.namespaceURI, ClientMetadataHandlerChainTest.svcLocalPart));
}
public ClientMetadataHandlerChainTestServiceWithHC(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
}