You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2014/12/11 12:59:03 UTC
cxf git commit: Missing files from last commit
Repository: cxf
Updated Branches:
refs/heads/master 94585ae07 -> e34329f6f
Missing files from last commit
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/e34329f6
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/e34329f6
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/e34329f6
Branch: refs/heads/master
Commit: e34329f6fa0ed306d43a239f462ce277b4d60b46
Parents: 94585ae
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Thu Dec 11 11:58:52 2014 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Thu Dec 11 11:58:52 2014 +0000
----------------------------------------------------------------------
.../org/apache/cxf/systest/https/BusServer.java | 73 ++
.../cxf/systest/https/HTTPSConduitTest.java | 755 +++++++++++++++++++
.../https/HTTPSProxyAuthConduitTest.java | 111 +++
.../systest/https/HTTPSProxyConduitTest.java | 100 +++
.../org/apache/cxf/systest/https/Server.java | 100 +++
.../org/apache/cxf/systest/https/Mortimer.cxf | 47 ++
.../org/apache/cxf/systest/https/greeting.wsdl | 166 ++++
7 files changed, 1352 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/java/org/apache/cxf/systest/https/BusServer.java
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/BusServer.java b/systests/transports/src/test/java/org/apache/cxf/systest/https/BusServer.java
new file mode 100644
index 0000000..09df754
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/BusServer.java
@@ -0,0 +1,73 @@
+/**
+ * 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.cxf.systest.https;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.testutil.common.TestUtil;
+
+/**
+ * This server just instantiates a Bus, full stop.
+ * Everything else is designed to be spring-loaded.
+ */
+public class BusServer extends AbstractBusTestServerBase {
+ public static final Map<String, String> PORTMAP = new HashMap<String, String>();
+ public static void resetPortMap() {
+ PORTMAP.clear();
+ for (int x = 0; x < 9; x++) {
+ PORTMAP.put("PORT" + x, TestUtil.getNewPortNumber(BusServer.class, x));
+ }
+ }
+ public static String getPort(int x) {
+ if (PORTMAP.isEmpty()) {
+ for (int y = 0; y < 9; y++) {
+ PORTMAP.put("PORT" + y, TestUtil.getPortNumber(BusServer.class, y));
+ }
+ }
+ return PORTMAP.get("PORT" + x);
+ }
+
+
+ protected void run() {
+ //
+ // Just instantiate the Bus; services will be instantiated
+ // and published automatically through Spring
+ //
+ final BusFactory factory = BusFactory.newInstance();
+ Bus bus = factory.createBus();
+ setBus(bus);
+ BusFactory.setDefaultBus(bus);
+ BusFactory.setThreadDefaultBus(bus);
+ }
+
+ public static void main(String[] args) {
+ try {
+ BusServer s = new BusServer();
+ s.start();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(-1);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSConduitTest.java
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSConduitTest.java b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSConduitTest.java
new file mode 100644
index 0000000..c375e7e
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSConduitTest.java
@@ -0,0 +1,755 @@
+/**
+ * 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.cxf.systest.https;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.BusApplicationContext;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.MessageTrustDecider;
+import org.apache.cxf.transport.http.URLConnectionInfo;
+import org.apache.cxf.transport.http.UntrustedURLConnectionIOException;
+import org.apache.cxf.transport.http.auth.HttpAuthHeader;
+import org.apache.cxf.transport.http.auth.HttpAuthSupplier;
+import org.apache.cxf.transport.https.HttpsURLConnectionInfo;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.services.SOAPService;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * This class tests several issues and Conduit policies based
+ * on a set up of redirecting servers.
+ * <pre>
+ *
+ * Http Redirection:
+ *
+ * Poltim(https:9005) ----> Mortimer (http:9000)
+ *
+ * HttpS redirection/Trust:
+ *
+ * Tarpin(https:9003) ----> Gordy(https:9001) ----> Bethal(https:9002)
+ *
+ * Hostname Verifier Test
+ *
+ * Morpit (https:9008)
+ *
+ * </pre>HTTPConduitTest
+ * The Bethal server issues 401 with differing realms depending on the
+ * User name given in the authorization header.
+ * <p>
+ * The Morpit has a CN that is not equal to "localhost" to kick in
+ * the Hostname Verifier.
+ */
+public class HTTPSConduitTest extends AbstractBusClientServerTestBase {
+ private static final boolean IN_PROCESS = true;
+
+ private static TLSClientParameters tlsClientParameters = new TLSClientParameters();
+ private static List<String> servers = new ArrayList<String>();
+
+ private static Map<String, String> addrMap = new TreeMap<String, String>();
+
+ static {
+ try {
+ //System.setProperty("javax.net.debug", "all");
+ URL key = Server.class.getResource("../../../../../keys/Morpit.jks");
+ String keystore = new File(key.toURI()).getAbsolutePath();
+ //System.out.println("Keystore: " + keystore);
+ KeyManager[] kmgrs = getKeyManagers(getKeyStore("JKS", keystore, "password"), "password");
+
+ key = Server.class.getResource("../../../../../keys/Truststore.jks");
+
+ String truststore = new File(key.toURI()).getAbsolutePath();
+ //System.out.println("Truststore: " + truststore);
+ TrustManager[] tmgrs = getTrustManagers(getKeyStore("JKS", truststore, "password"));
+
+ tlsClientParameters.setKeyManagers(kmgrs);
+ tlsClientParameters.setTrustManagers(tmgrs);
+ } catch (Exception e) {
+ throw new RuntimeException("Static initialization failed", e);
+ }
+ }
+
+ private final QName serviceName =
+ new QName("http://apache.org/hello_world", "SOAPService");
+ private final QName bethalQ =
+ new QName("http://apache.org/hello_world", "Bethal");
+ private final QName gordyQ =
+ new QName("http://apache.org/hello_world", "Gordy");
+ private final QName tarpinQ =
+ new QName("http://apache.org/hello_world", "Tarpin");
+ private final QName poltimQ =
+ new QName("http://apache.org/hello_world", "Poltim");
+
+ public HTTPSConduitTest() {
+ }
+
+
+ public static String getPort(String s) {
+ return BusServer.PORTMAP.get(s);
+ }
+
+ @BeforeClass
+ public static void allocatePorts() {
+ BusServer.resetPortMap();
+ addrMap.clear();
+ addrMap.put("Mortimer", "http://localhost:" + getPort("PORT0") + "/");
+ addrMap.put("Tarpin", "https://localhost:" + getPort("PORT1") + "/");
+ addrMap.put("Poltim", "https://localhost:" + getPort("PORT2") + "/");
+ addrMap.put("Gordy", "https://localhost:" + getPort("PORT3") + "/");
+ addrMap.put("Bethal", "https://localhost:" + getPort("PORT4") + "/");
+ addrMap.put("Morpit", "https://localhost:" + getPort("PORT5") + "/");
+ tlsClientParameters.setDisableCNCheck(true);
+ servers.clear();
+ }
+
+
+ /**
+ * This function is used to start up a server. It only "starts" a
+ * server if it hasn't been started before, hence its static nature.
+ * <p>
+ * This approach is used to start the needed servers for a particular test
+ * instead of starting them all in "startServers". This single needed
+ * server approach allieviates the pain in starting them all just to run
+ * a particular test in the debugger.
+ */
+ public synchronized boolean startServer(String name) {
+ if (servers.contains(name)) {
+ return true;
+ }
+ Bus bus = BusFactory.getThreadDefaultBus(false);
+ URL serverC =
+ Server.class.getResource(name + ".cxf");
+ BusFactory.setDefaultBus(null);
+ BusFactory.setThreadDefaultBus(null);
+ boolean server = launchServer(Server.class, null,
+ new String[] {
+ name,
+ addrMap.get(name),
+ serverC.toString() },
+ IN_PROCESS);
+ if (server) {
+ servers.add(name);
+ }
+ BusFactory.setDefaultBus(null);
+ BusFactory.setThreadDefaultBus(bus);
+ return server;
+ }
+
+ @AfterClass
+ public static void cleanUp() {
+ Bus b = BusFactory.getDefaultBus(false);
+ if (b != null) {
+ b.shutdown(true);
+ }
+ b = BusFactory.getThreadDefaultBus(false);
+ if (b != null) {
+ b.shutdown(true);
+ }
+ }
+
+ public static KeyStore getKeyStore(String ksType, String file, String ksPassword)
+ throws GeneralSecurityException,
+ IOException {
+
+ String type = ksType != null
+ ? ksType
+ : KeyStore.getDefaultType();
+
+ char[] password = ksPassword != null
+ ? ksPassword.toCharArray()
+ : null;
+
+ // We just use the default Keystore provider
+ KeyStore keyStore = KeyStore.getInstance(type);
+
+ keyStore.load(new FileInputStream(file), password);
+
+ return keyStore;
+ }
+
+ public static KeyManager[] getKeyManagers(KeyStore keyStore, String keyPassword)
+ throws GeneralSecurityException,
+ IOException {
+ // For tests, we just use the default algorithm
+ String alg = KeyManagerFactory.getDefaultAlgorithm();
+
+ char[] keyPass = keyPassword != null
+ ? keyPassword.toCharArray()
+ : null;
+
+ // For tests, we just use the default provider.
+ KeyManagerFactory fac = KeyManagerFactory.getInstance(alg);
+
+ fac.init(keyStore, keyPass);
+
+ return fac.getKeyManagers();
+ }
+
+ public static TrustManager[] getTrustManagers(KeyStore keyStore)
+ throws GeneralSecurityException,
+ IOException {
+ // For tests, we just use the default algorithm
+ String alg = TrustManagerFactory.getDefaultAlgorithm();
+
+ // For tests, we just use the default provider.
+ TrustManagerFactory fac = TrustManagerFactory.getInstance(alg);
+
+ fac.init(keyStore);
+
+ return fac.getTrustManagers();
+ }
+
+ //methods that a subclass can override to inject a Proxy into the flow
+ //and assert the proxy was appropriately called
+ public void configureProxy(Client c) {
+ }
+ public void resetProxyCount() {
+ }
+ public void assertProxyRequestCount(int i) {
+ }
+
+ /**
+ * We use this class to reset the default bus.
+ * Note: This may not always work in the future.
+ * I was lucky in that "defaultBus" is actually a
+ * protected static.
+ */
+ class DefaultBusFactory extends SpringBusFactory {
+ public Bus createBus(URL config) {
+ Bus bus = super.createBus(config, true);
+ BusFactory.setDefaultBus(bus);
+ BusFactory.setThreadDefaultBus(bus);
+ return bus;
+ }
+ }
+
+ /**
+ * This methods tests a basic https connection to Bethal.
+ * It supplies an authorization policy with preemptive user/pass
+ * to avoid the 401.
+ */
+ @Test
+ public void testHttpsBasicConnectionWithConfig() throws Exception {
+ startServer("Bethal");
+
+ URL config = getClass().getResource("BethalClientConfig.cxf");
+
+ // We go through the back door, setting the default bus.
+ new DefaultBusFactory().createBus(config);
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter bethal = service.getPort(bethalQ, Greeter.class);
+
+ assertNotNull("Port is null", bethal);
+ updateAddressPort(bethal, getPort("PORT4"));
+ verifyBethalClient(bethal);
+ }
+
+ @Test
+ public void testGetClientFromSpringContext() throws Exception {
+ startServer("Bethal");
+
+ BusFactory.setDefaultBus(null);
+ // The client bean configuration file
+ URL beans = getClass().getResource("BethalClientBeans.xml");
+ // We go through the back door, setting the default bus.
+ Bus bus = new DefaultBusFactory().createBus(beans);
+
+ ApplicationContext context = bus.getExtension(BusApplicationContext.class);
+ Greeter bethal = (Greeter)context.getBean("Bethal");
+ updateAddressPort(bethal, getPort("PORT4"));
+ // verify the client side's setting
+ verifyBethalClient(bethal);
+ }
+
+ // we just verify the configurations are loaded successfully
+ private void verifyBethalClient(Greeter bethal) {
+ Client client = ClientProxy.getClient(bethal);
+
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = http.getClient();
+ assertEquals("the httpClientPolicy's autoRedirect should be true",
+ true, httpClientPolicy.isAutoRedirect());
+ TLSClientParameters tlsParameters = http.getTlsClientParameters();
+ assertNotNull("the http conduit's tlsParameters should not be null", tlsParameters);
+
+
+ // If we set any name, but Edward, Mary, or George,
+ // and a password of "password" we will get through
+ // Bethal.
+ AuthorizationPolicy authPolicy = http.getAuthorization();
+ assertEquals("Set the wrong user name from the configuration",
+ "Betty", authPolicy.getUserName());
+ assertEquals("Set the wrong pass word form the configuration",
+ "password", authPolicy.getPassword());
+
+ configureProxy(ClientProxy.getClient(bethal));
+
+ String answer = bethal.sayHi();
+ answer = bethal.sayHi();
+ answer = bethal.sayHi();
+ answer = bethal.sayHi();
+ answer = bethal.sayHi();
+ assertTrue("Unexpected answer: " + answer,
+ "Bonjour from Bethal".equals(answer));
+
+ //With HTTPS, it will just be a CONNECT to the proxy and all the
+ //data is encrypted. Thus, the proxy cannot distinquish the requests
+ assertProxyRequestCount(0);
+ }
+
+ /**
+ * This methods tests a basic https connection to Bethal.
+ * It supplies an authorization policy with premetive user/pass
+ * to avoid the 401.
+ */
+ @Test
+ public void testHttpsBasicConnection() throws Exception {
+ startServer("Bethal");
+
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter bethal = service.getPort(bethalQ, Greeter.class);
+ assertNotNull("Port is null", bethal);
+ updateAddressPort(bethal, getPort("PORT4"));
+
+ // Okay, I'm sick of configuration files.
+ // This also tests dynamic configuration of the conduit.
+ Client client = ClientProxy.getClient(bethal);
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+
+ httpClientPolicy.setAutoRedirect(false);
+ // If we set any name, but Edward, Mary, or George,
+ // and a password of "password" we will get through
+ // Bethal.
+ AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+ authPolicy.setUserName("Betty");
+ authPolicy.setPassword("password");
+
+ http.setClient(httpClientPolicy);
+ http.setTlsClientParameters(tlsClientParameters);
+ http.setAuthorization(authPolicy);
+
+ configureProxy(client);
+ String answer = bethal.sayHi();
+ assertTrue("Unexpected answer: " + answer,
+ "Bonjour from Bethal".equals(answer));
+ assertProxyRequestCount(0);
+ }
+
+
+ @Test
+ public void testHttpsRedirectToHttpFail() throws Exception {
+ startServer("Mortimer");
+ startServer("Poltim");
+
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter poltim = service.getPort(poltimQ, Greeter.class);
+ assertNotNull("Port is null", poltim);
+ updateAddressPort(poltim, getPort("PORT2"));
+
+ // Okay, I'm sick of configuration files.
+ // This also tests dynamic configuration of the conduit.
+ Client client = ClientProxy.getClient(poltim);
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+
+ httpClientPolicy.setAutoRedirect(true);
+
+ http.setClient(httpClientPolicy);
+ http.setTlsClientParameters(tlsClientParameters);
+ configureProxy(client);
+ poltim.sayHi();
+ //client -> poltim is https and thus not recorded but then redirected to mortimer
+ //client -> mortimer is http and recoreded
+ assertProxyRequestCount(1);
+ }
+
+ class MyHttpsTrustDecider extends MessageTrustDecider {
+
+ private String[] trustName;
+ private int called;
+
+ MyHttpsTrustDecider(String name) {
+ trustName = new String[] {name};
+ }
+
+ MyHttpsTrustDecider(String[] name) {
+ trustName = name;
+ }
+
+ public int wasCalled() {
+ return called;
+ }
+
+ public void establishTrust(
+ String conduitName,
+ URLConnectionInfo cinfo,
+ Message message
+ ) throws UntrustedURLConnectionIOException {
+
+ called++;
+
+ HttpsURLConnectionInfo ci = (HttpsURLConnectionInfo) cinfo;
+ boolean trusted = false;
+ for (int i = 0; i < trustName.length; i++) {
+ trusted = trusted
+ || ci.getPeerPrincipal()
+ .toString().contains("OU=" + trustName[i]);
+ }
+ if (!trusted) {
+ throw new UntrustedURLConnectionIOException(
+ "Peer Principal \""
+ + ci.getPeerPrincipal()
+ + "\" does not contain "
+ + getTrustNames());
+ }
+ }
+
+ private String getTrustNames() {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < trustName.length; i++) {
+ sb.append("\"OU=");
+ sb.append(trustName[i]);
+ sb.append("\"");
+ if (i < trustName.length - 1) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+ }
+
+ @Test
+ public void testHttpsTrust() throws Exception {
+ startServer("Bethal");
+
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter bethal = service.getPort(bethalQ, Greeter.class);
+ assertNotNull("Port is null", bethal);
+ updateAddressPort(bethal, getPort("PORT4"));
+
+ // Okay, I'm sick of configuration files.
+ // This also tests dynamic configuration of the conduit.
+ Client client = ClientProxy.getClient(bethal);
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+
+ httpClientPolicy.setAutoRedirect(false);
+ // If we set any name, but Edward, Mary, or George,
+ // and a password of "password" we will get through
+ // Bethal.
+ AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+ authPolicy.setUserName("Betty");
+ authPolicy.setPassword("password");
+
+ http.setClient(httpClientPolicy);
+ http.setTlsClientParameters(tlsClientParameters);
+ http.setAuthorization(authPolicy);
+
+ // Our expected server should be OU=Bethal
+ http.setTrustDecider(new MyHttpsTrustDecider("Bethal"));
+
+ configureProxy(client);
+ String answer = bethal.sayHi();
+ assertTrue("Unexpected answer: " + answer,
+ "Bonjour from Bethal".equals(answer));
+ assertProxyRequestCount(0);
+
+
+ // Nobody will not equal OU=Bethal
+ MyHttpsTrustDecider trustDecider =
+ new MyHttpsTrustDecider("Nobody");
+ http.setTrustDecider(trustDecider);
+ try {
+ answer = bethal.sayHi();
+ fail("Unexpected answer from Bethal: " + answer);
+ } catch (Exception e) {
+ //e.printStackTrace();
+ //assertTrue("Trust Decider was not called",
+ // 0 > trustDecider.wasCalled());
+ }
+ assertProxyRequestCount(0);
+ }
+
+ @Test
+ public void testHttpsTrustRedirect() throws Exception {
+ startServer("Tarpin");
+ startServer("Gordy");
+ startServer("Bethal");
+
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter tarpin = service.getPort(tarpinQ, Greeter.class);
+ assertNotNull("Port is null", tarpin);
+ updateAddressPort(tarpin, getPort("PORT1"));
+
+ // Okay, I'm sick of configuration files.
+ // This also tests dynamic configuration of the conduit.
+ Client client = ClientProxy.getClient(tarpin);
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+
+ httpClientPolicy.setAutoRedirect(true);
+ // If we set any name, but Edward, Mary, or George,
+ // and a password of "password" we will get through
+ // Bethal.
+ AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+ authPolicy.setUserName("Betty");
+ authPolicy.setPassword("password");
+
+ http.setClient(httpClientPolicy);
+ http.setTlsClientParameters(tlsClientParameters);
+ http.setAuthorization(authPolicy);
+
+ // We get redirected from Tarpin, to Gordy, to Bethal.
+ MyHttpsTrustDecider trustDecider =
+ new MyHttpsTrustDecider(
+ new String[] {"Tarpin", "Gordy", "Bethal"});
+ http.setTrustDecider(trustDecider);
+
+ // We actually get our answer from Bethal at the end of the
+ // redirects.
+ configureProxy(ClientProxy.getClient(tarpin));
+ String answer = tarpin.sayHi();
+ assertProxyRequestCount(0);
+
+ assertTrue("Trust Decider wasn't called correctly",
+ 3 == trustDecider.wasCalled());
+ assertTrue("Unexpected answer: " + answer,
+ "Bonjour from Bethal".equals(answer));
+
+ // Limit the redirects to 1, since there are two, this should fail.
+ http.getClient().setMaxRetransmits(1);
+
+ try {
+ answer = tarpin.sayHi();
+ fail("Unexpected answer from Tarpin: " + answer);
+ } catch (Exception e) {
+ //e.printStackTrace();
+ }
+ assertProxyRequestCount(0);
+
+ // Set back to unlimited.
+ http.getClient().setMaxRetransmits(-1);
+
+ // Effectively we will not trust Gordy in the middle.
+ trustDecider =
+ new MyHttpsTrustDecider(
+ new String[] {"Tarpin", "Bethal"});
+ http.setTrustDecider(trustDecider);
+
+ try {
+ answer = tarpin.sayHi();
+ fail("Unexpected answer from Tarpin: " + answer);
+ } catch (Exception e) {
+ //e.printStackTrace();
+ assertTrue("Trust Decider wasn't called correctly",
+ 2 == trustDecider.wasCalled());
+ }
+ assertProxyRequestCount(0);
+ }
+
+ public class MyBasicAuthSupplier implements HttpAuthSupplier {
+
+ String realm;
+ String user;
+ String pass;
+
+ /**
+ * This will loop from Cronus, to Andromeda, to Zorantius
+ */
+ MyBasicAuthSupplier() {
+ }
+
+ MyBasicAuthSupplier(String r, String u, String p) {
+ realm = r;
+ user = u;
+ pass = p;
+ }
+
+ /**
+ * If we don't have the realm set, then we loop
+ * through the realms.
+ */
+ public String getAuthorization(
+ AuthorizationPolicy authPolicy,
+ URI currentURI,
+ Message message,
+ String fullHeader
+ ) {
+ String reqestedRealm = new HttpAuthHeader(fullHeader).getRealm();
+ if (realm != null && realm.equals(reqestedRealm)) {
+ return createUserPass(user, pass);
+ }
+ if ("Andromeda".equals(reqestedRealm)) {
+ // This will get us another 401 to Zorantius
+ return createUserPass("Edward", "password");
+ }
+ if ("Zorantius".equals(reqestedRealm)) {
+ // George will get us another 401 to Cronus
+ return createUserPass("George", "password");
+ }
+ if ("Cronus".equals(reqestedRealm)) {
+ // Mary will get us another 401 to Andromeda
+ return createUserPass("Mary", "password");
+ }
+ return null;
+ }
+
+ private String createUserPass(String usr, String pwd) {
+ String userpass = usr + ":" + pwd;
+ String token = Base64Utility.encode(userpass.getBytes());
+ return "Basic " + token;
+ }
+
+ public boolean requiresRequestCaching() {
+ return false;
+ }
+
+ }
+
+ /**
+ * This tests redirects through Gordy to Bethal. Bethal will
+ * supply a series of 401s. See PushBack401.
+ */
+ @Test
+ public void testHttpsRedirect401Response() throws Exception {
+ startServer("Gordy");
+ startServer("Bethal");
+
+ URL wsdl = getClass().getResource("greeting.wsdl");
+ assertNotNull("WSDL is null", wsdl);
+
+ SOAPService service = new SOAPService(wsdl, serviceName);
+ assertNotNull("Service is null", service);
+
+ Greeter gordy = service.getPort(gordyQ, Greeter.class);
+ assertNotNull("Port is null", gordy);
+ updateAddressPort(gordy, getPort("PORT3"));
+
+ // Okay, I'm sick of configuration files.
+ // This also tests dynamic configuration of the conduit.
+ Client client = ClientProxy.getClient(gordy);
+ HTTPConduit http =
+ (HTTPConduit) client.getConduit();
+
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+
+ httpClientPolicy.setAutoRedirect(true);
+ http.setClient(httpClientPolicy);
+ http.setTlsClientParameters(tlsClientParameters);
+
+ // We get redirected from Gordy, to Bethal.
+ http.setTrustDecider(
+ new MyHttpsTrustDecider(
+ new String[] {"Gordy", "Bethal"}));
+
+ // Without preemptive user/pass Bethal returns a
+ // 401 for realm Cronus. If we supply any name other
+ // than Edward, George, or Mary, with the pass of "password"
+ // we should succeed.
+ http.setAuthSupplier(
+ new MyBasicAuthSupplier("Cronus", "Betty", "password"));
+
+ // We actually get our answer from Bethal at the end of the
+ // redirects.
+ String answer = gordy.sayHi();
+ assertTrue("Unexpected answer: " + answer,
+ "Bonjour from Bethal".equals(answer));
+
+ // The loop auth supplier,
+ // We should die with looping realms.
+ http.setAuthSupplier(new MyBasicAuthSupplier());
+
+ try {
+ answer = gordy.sayHi();
+ fail("Unexpected answer from Gordy: " + answer);
+ } catch (Exception e) {
+ //e.printStackTrace();
+ }
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyAuthConduitTest.java
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyAuthConduitTest.java b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyAuthConduitTest.java
new file mode 100644
index 0000000..2750f21
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyAuthConduitTest.java
@@ -0,0 +1,111 @@
+/**
+ * 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.cxf.systest.https;
+
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+
+import org.jboss.netty.handler.codec.http.HttpRequest;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import org.littleshoot.proxy.DefaultHttpProxyServer;
+import org.littleshoot.proxy.HttpFilter;
+import org.littleshoot.proxy.HttpRequestFilter;
+import org.littleshoot.proxy.ProxyAuthorizationHandler;
+
+
+/**
+ *
+ */
+public class HTTPSProxyAuthConduitTest extends HTTPSConduitTest {
+ static final int PROXY_PORT = Integer.parseInt(allocatePort(HTTPSProxyAuthConduitTest.class));
+ static DefaultHttpProxyServer proxy;
+ static CountingFilter requestFilter = new CountingFilter();
+
+ static class CountingFilter implements HttpRequestFilter {
+ AtomicInteger count = new AtomicInteger();
+ public void filter(HttpRequest httpRequest) {
+ count.incrementAndGet();
+ }
+
+ public void reset() {
+ count.set(0);
+ }
+ public int getCount() {
+ return count.get();
+ }
+ }
+
+ public HTTPSProxyAuthConduitTest() {
+ }
+
+
+ @AfterClass
+ public static void stopProxy() {
+ proxy.stop();
+ proxy = null;
+ }
+
+ @BeforeClass
+ public static void startProxy() {
+ proxy = new DefaultHttpProxyServer(PROXY_PORT, requestFilter, new HashMap<String, HttpFilter>());
+ proxy.addProxyAuthenticationHandler(new ProxyAuthorizationHandler() {
+ public boolean authenticate(String userName, String password) {
+ return "password".equals(password) && "CXF".equals(userName);
+ }
+ });
+ proxy.start();
+ }
+ @Before
+ public void resetCount() {
+ requestFilter.reset();
+ }
+
+ public void configureProxy(Client client) {
+ HTTPConduit cond = (HTTPConduit)client.getConduit();
+ HTTPClientPolicy pol = cond.getClient();
+ if (pol == null) {
+ pol = new HTTPClientPolicy();
+ cond.setClient(pol);
+ }
+ pol.setProxyServer("localhost");
+ pol.setProxyServerPort(PROXY_PORT);
+ ProxyAuthorizationPolicy auth = new ProxyAuthorizationPolicy();
+ auth.setUserName("CXF");
+ auth.setPassword("password");
+ cond.setProxyAuthorization(auth);
+ }
+
+ public void resetProxyCount() {
+ requestFilter.reset();
+ }
+ public void assertProxyRequestCount(int i) {
+ assertEquals("Unexpected request count", i, requestFilter.getCount());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyConduitTest.java
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyConduitTest.java b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyConduitTest.java
new file mode 100644
index 0000000..8171576
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/HTTPSProxyConduitTest.java
@@ -0,0 +1,100 @@
+/**
+ * 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.cxf.systest.https;
+
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+
+import org.jboss.netty.handler.codec.http.HttpRequest;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import org.littleshoot.proxy.DefaultHttpProxyServer;
+import org.littleshoot.proxy.HttpFilter;
+import org.littleshoot.proxy.HttpRequestFilter;
+
+
+/**
+ *
+ */
+public class HTTPSProxyConduitTest extends HTTPSConduitTest {
+ static final int PROXY_PORT = Integer.parseInt(allocatePort(HTTPSProxyConduitTest.class));
+ static DefaultHttpProxyServer proxy;
+ static CountingFilter requestFilter = new CountingFilter();
+
+ static class CountingFilter implements HttpRequestFilter {
+ AtomicInteger count = new AtomicInteger();
+ public void filter(HttpRequest httpRequest) {
+ count.incrementAndGet();
+ }
+
+ public void reset() {
+ count.set(0);
+ }
+ public int getCount() {
+ return count.get();
+ }
+ }
+
+ public HTTPSProxyConduitTest() {
+ }
+
+
+ @AfterClass
+ public static void stopProxy() {
+ proxy.stop();
+ proxy = null;
+ }
+
+ @BeforeClass
+ public static void startProxy() {
+ proxy = new DefaultHttpProxyServer(PROXY_PORT, requestFilter, new HashMap<String, HttpFilter>());
+ proxy.start();
+ }
+ @Before
+ public void resetCount() {
+ requestFilter.reset();
+ }
+
+ public void configureProxy(Client client) {
+ HTTPConduit cond = (HTTPConduit)client.getConduit();
+ HTTPClientPolicy pol = cond.getClient();
+ if (pol == null) {
+ pol = new HTTPClientPolicy();
+ cond.setClient(pol);
+ }
+ pol.setProxyServer("localhost");
+ pol.setProxyServerPort(PROXY_PORT);
+ }
+
+ public void resetProxyCount() {
+ requestFilter.reset();
+ }
+ public void assertProxyRequestCount(int i) {
+ assertEquals("Unexpected request count", i, requestFilter.getCount());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/java/org/apache/cxf/systest/https/Server.java
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/Server.java b/systests/transports/src/test/java/org/apache/cxf/systest/https/Server.java
new file mode 100644
index 0000000..12f3bbd
--- /dev/null
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/Server.java
@@ -0,0 +1,100 @@
+/**
+ * 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.cxf.systest.https;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.apache.cxf.systest.http.GreeterImpl;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class Server extends AbstractBusTestServerBase {
+ public static final String PORT = allocatePort(Server.class);
+
+ private String name;
+ private String address;
+ private URL configFileURL;
+ private EndpointImpl ep;
+
+ public Server(String[] args) throws Exception {
+ this(args[0], args[1], args[2]);
+ }
+
+ public Server(String n, String addr, String conf) throws Exception {
+ name = n;
+ address = addr;
+ configFileURL = new URL(conf);
+ //System.out.println("Starting " + name
+ // + " Server at " + address
+ // + " with config " + configFileURL);
+
+ }
+ public void tearDown() throws Exception {
+ if (ep != null) {
+ ep.stop();
+ ep = null;
+ }
+ }
+
+ protected void run() {
+ // We use a null binding id in the call to EndpointImpl
+ // constructor. Why?
+ final String nullBindingID = null;
+
+ // We need to specify to use defaults on constructing the
+ // bus, because our configuration file doesn't have
+ // everything needed.
+ final boolean useDefaults = true;
+
+ // We configure a new bus for this server.
+ setBus(new SpringBusFactory().createBus(configFileURL, useDefaults));
+
+ // This impl class must have the appropriate annotations
+ // to match the WSDL file that we are using.
+ Object implementor = new GreeterImpl(name);
+
+ // I don't know why this works.
+ ep =
+ new EndpointImpl(
+ getBus(),
+ implementor,
+ nullBindingID,
+ this.getClass().getResource("greeting.wsdl").toString());
+ // How the hell do I know what the name of the
+ // http-destination is from using this call?
+ ep.setEndpointName(new QName("http://apache.org/hello_world", name));
+ ep.publish(address);
+ }
+
+
+ public static void main(String[] args) {
+ try {
+ Server s = new Server(args);
+ s.start();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(-1);
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/resources/org/apache/cxf/systest/https/Mortimer.cxf
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/https/Mortimer.cxf b/systests/transports/src/test/resources/org/apache/cxf/systest/https/Mortimer.cxf
new file mode 100644
index 0000000..4a26c85
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/https/Mortimer.cxf
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<!--
+ ** This file configures the Mortimer Server.
+ ** It is an http server.
+ -->
+
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sec="http://cxf.apache.org/configuration/security"
+ xmlns:http="http://cxf.apache.org/transports/http/configuration"
+ xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+ xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+ xsi:schemaLocation="
+ http://cxf.apache.org/configuration/security
+ http://cxf.apache.org/schemas/configuration/security.xsd
+ http://cxf.apache.org/transports/http/configuration
+ http://cxf.apache.org/schemas/configuration/http-conf.xsd
+ http://cxf.apache.org/transports/http-jetty/configuration
+ http://cxf.apache.org/schemas/configuration/http-jetty.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <http:destination name="{http://apache.org/hello_world}Mortimer.http-destination">
+ <!-- Nothing to Configure here for Mortimer -->
+ </http:destination>
+
+</beans>
http://git-wip-us.apache.org/repos/asf/cxf/blob/e34329f6/systests/transports/src/test/resources/org/apache/cxf/systest/https/greeting.wsdl
----------------------------------------------------------------------
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/https/greeting.wsdl b/systests/transports/src/test/resources/org/apache/cxf/systest/https/greeting.wsdl
new file mode 100644
index 0000000..c12bdfe
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/https/greeting.wsdl
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://apache.org/hello_world" xmlns:x1="http://apache.org/hello_world/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloWorld" targetNamespace="http://apache.org/hello_world">
+ <wsdl:types>
+ <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://apache.org/hello_world/types" targetNamespace="http://apache.org/hello_world/types" elementFormDefault="qualified">
+ <simpleType name="MyStringType">
+ <restriction base="string">
+ <maxLength value="30"/>
+ </restriction>
+ </simpleType>
+ <element name="sayHi">
+ <complexType/>
+ </element>
+ <element name="sayHiResponse">
+ <complexType>
+ <sequence>
+ <element name="responseType" type="string"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="greetMe">
+ <complexType>
+ <sequence>
+ <element name="requestType" type="tns:MyStringType"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="greetMeResponse">
+ <complexType>
+ <sequence>
+ <element name="responseType" type="string"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="pingMe">
+ <complexType/>
+ </element>
+ <element name="pingMeResponse">
+ <complexType/>
+ </element>
+ <element name="faultDetail">
+ <complexType>
+ <sequence>
+ <element name="minor" type="short"/>
+ <element name="major" type="short"/>
+ </sequence>
+ </complexType>
+ </element>
+ </schema>
+ </wsdl:types>
+ <wsdl:message name="sayHiRequest">
+ <wsdl:part element="x1:sayHi" name="in"/>
+ </wsdl:message>
+ <wsdl:message name="sayHiResponse">
+ <wsdl:part element="x1:sayHiResponse" name="out"/>
+ </wsdl:message>
+ <wsdl:message name="greetMeRequest">
+ <wsdl:part element="x1:greetMe" name="in"/>
+ </wsdl:message>
+ <wsdl:message name="greetMeResponse">
+ <wsdl:part element="x1:greetMeResponse" name="out"/>
+ </wsdl:message>
+ <wsdl:message name="pingMeRequest">
+ <wsdl:part name="in" element="x1:pingMe"/>
+ </wsdl:message>
+ <wsdl:message name="pingMeResponse">
+ <wsdl:part name="out" element="x1:pingMeResponse"/>
+ </wsdl:message>
+ <wsdl:message name="pingMeFault">
+ <wsdl:part name="faultDetail" element="x1:faultDetail"/>
+ </wsdl:message>
+ <wsdl:portType name="Greeter">
+ <wsdl:operation name="sayHi">
+ <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
+ <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="greetMe">
+ <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
+ <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="pingMe">
+ <wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/>
+ <wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/>
+ <wsdl:fault name="pingMeFault" message="tns:pingMeFault"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
+ <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="sayHi">
+ <soap:operation soapAction="" style="document"/>
+ <wsdl:input name="sayHiRequest">
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="sayHiResponse">
+ <soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="greetMe">
+ <soap:operation soapAction="" style="document"/>
+ <wsdl:input name="greetMeRequest">
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="greetMeResponse">
+ <soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="pingMe">
+ <soap:operation style="document"/>
+ <wsdl:input>
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="pingMeFault">
+ <soap:fault name="pingMeFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="SOAPService">
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Mortimer">
+ <soap:address location="http://localhost:9000/Mortimer"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Tarpin">
+ <soap:address location="https://localhost:9003/Tarpin"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Rethwel">
+ <soap:address location="http://localhost:9004/Rethwel"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Gordy">
+ <soap:address location="https://localhost:9001/Gordy"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Bethal">
+ <soap:address location="https://localhost:9002/Bethal"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Hurlon">
+ <soap:address location="http://localhost:9006/Hurlon"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Poltim">
+ <soap:address location="https://localhost:9005/Poltim"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Abost">
+ <soap:address location="https://localhost:9007/Abost"/>
+ </wsdl:port>
+ <wsdl:port binding="tns:Greeter_SOAPBinding" name="Morpit">
+ <soap:address location="https://localhost:9008/Morpit"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>