/* * JBoss, Home of Professional Open Source. * Copyright 2013, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.test.manualmode.ws; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_RUNTIME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATION_REQUIRES_RELOAD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ATTRIBUTE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RECURSIVE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESPONSE_HEADERS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UNDEFINE_ATTRIBUTE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION; import static org.junit.Assert.fail; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import org.jboss.arquillian.container.test.api.ContainerController; import org.jboss.arquillian.container.test.api.Deployer; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.as.arquillian.container.ManagementClient; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.as.controller.client.OperationBuilder; import org.jboss.as.test.shared.TestSuiteEnvironment; import org.jboss.dmr.ModelNode; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; /** * Some tests on changes to the model that are applied immediately to the runtime * when there's no WS deployment on the server. * * @author <a href="mailto:alessio.soldano@jboss.com">Alessio Soldano</a> * @author <a href="mailto:ema@redhat.com">Jim Ma</a> */ @RunWith(Arquillian.class) @RunAsClient public class WSAttributesChangesTestCase { private static final String DEFAULT_JBOSSAS = "default-jbossas"; private static final String DEP_1 = "jaxws-manual-pojo-1"; private static final String DEP_2 = "jaxws-manual-pojo-2"; @ArquillianResource ContainerController containerController; @ArquillianResource Deployer deployer; @Deployment(name = DEP_1, testable = false, managed = false) public static WebArchive deployment1() { WebArchive pojoWar = ShrinkWrap.create(WebArchive.class, DEP_1 + ".war").addClasses( EndpointIface.class, PojoEndpoint.class); return pojoWar; } @Deployment(name = DEP_2, testable = false, managed = false) public static WebArchive deployment2() { WebArchive pojoWar = ShrinkWrap.create(WebArchive.class, DEP_2 + ".war").addClasses( EndpointIface.class, PojoEndpoint.class); return pojoWar; } @Before public void startContainer() throws Exception { containerController.start(DEFAULT_JBOSSAS); } @Test public void testWsdlHostChanges() throws Exception { performWsdlHostAttributeTest(false); performWsdlHostAttributeTest(true); } private void performWsdlHostAttributeTest(boolean checkUpdateWithDeployedEndpoint) throws Exception { Assert.assertTrue(containerController.isStarted(DEFAULT_JBOSSAS)); ManagementClient managementClient = new ManagementClient(TestSuiteEnvironment.getModelControllerClient(), TestSuiteEnvironment.getServerAddress(), TestSuiteEnvironment.getServerPort(), "http-remoting"); ModelControllerClient client = managementClient.getControllerClient(); String initialWsdlHost = null; try { initialWsdlHost = getAttribute("wsdl-host", client); final String hostnameA = "foo-host-a"; ModelNode op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-host"); op.get(VALUE).set(hostnameA); applyUpdate(client, op, false); //update successful, no need to reload //now we deploy an endpoint... deployer.deploy(DEP_1); //verify the updated wsdl host is used... URL wsdlURL = new URL(managementClient.getWebUri().toURL(), '/' + DEP_1 + "/POJOService?wsdl"); checkWsdl(wsdlURL, hostnameA); if (checkUpdateWithDeployedEndpoint) { final String hostnameB = "foo-host-b"; ModelNode opB = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); opB.get(NAME).set("wsdl-host"); opB.get(VALUE).set(hostnameB); applyUpdate(client, opB, true); //update again, but we'll need to reload, as there's an active deployment //check the wsdl host is still the one we updated to before checkWsdl(wsdlURL, hostnameA); //and check that still applies even if we undeploy and redeploy the endpoint deployer.undeploy(DEP_1); deployer.deploy(DEP_1); checkWsdl(wsdlURL, hostnameA); } } finally { try { deployer.undeploy(DEP_1); } catch (Throwable t) { //ignore } try { if (initialWsdlHost != null) { ModelNode op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-host"); op.get(VALUE).set(initialWsdlHost); applyUpdate(client, op, checkUpdateWithDeployedEndpoint); } } finally { managementClient.close(); } } } @Test public void testWsdlPortChanges() throws Exception { performWsdlPortAttributeTest(false); performWsdlPortAttributeTest(true); } private void performWsdlPortAttributeTest(boolean checkUpdateWithDeployedEndpoint) throws Exception { Assert.assertTrue(containerController.isStarted(DEFAULT_JBOSSAS)); ManagementClient managementClient = new ManagementClient(TestSuiteEnvironment.getModelControllerClient(), TestSuiteEnvironment.getServerAddress(), TestSuiteEnvironment.getServerPort(), "http-remoting"); ModelControllerClient client = managementClient.getControllerClient(); try { final String portA = "55667"; ModelNode op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-port"); op.get(VALUE).set(portA); applyUpdate(client, op, false); //update successful, no need to reload //now we deploy an endpoint... deployer.deploy(DEP_2); //verify the updated wsdl port is used... URL wsdlURL = new URL(managementClient.getWebUri().toURL(), '/' + DEP_2 + "/POJOService?wsdl"); checkWsdl(wsdlURL, portA); if (checkUpdateWithDeployedEndpoint) { final String portB = "55668"; ModelNode opB = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); opB.get(NAME).set("wsdl-port"); opB.get(VALUE).set(portB); applyUpdate(client, opB, true); //update again, but we'll need to reload, as there's an active deployment //check the wsdl port is still the one we updated to before checkWsdl(wsdlURL, portA); //and check that still applies even if we undeploy and redeploy the endpoint deployer.undeploy(DEP_2); deployer.deploy(DEP_2); checkWsdl(wsdlURL, portA); } } finally { try { deployer.undeploy(DEP_2); } catch (Throwable t) { //ignore } try { ModelNode op = createOpNode("subsystem=webservices/", UNDEFINE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-port"); applyUpdate(client, op, checkUpdateWithDeployedEndpoint); } finally { managementClient.close(); } } } @Test public void testWsdlUriSchemeChanges() throws Exception { performWsdlUriSchemeAttributeTest(false); performWsdlUriSchemeAttributeTest(true); } private void performWsdlUriSchemeAttributeTest(boolean checkUpdateWithDeployedEndpoint) throws Exception { Assert.assertTrue(containerController.isStarted(DEFAULT_JBOSSAS)); ManagementClient managementClient = new ManagementClient(TestSuiteEnvironment.getModelControllerClient(), TestSuiteEnvironment.getServerAddress(), TestSuiteEnvironment.getServerPort(), "http-remoting"); ModelControllerClient client = managementClient.getControllerClient(); String initialWsdlUriScheme = null; try { //save initial wsdl-uri-schema value to restore later initialWsdlUriScheme = getAttribute("wsdl-uri-scheme", client, false); //set wsdl-uri-scheme value to https ModelNode op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-uri-scheme"); op.get(VALUE).set("https"); applyUpdate(client, op, false); deployer.deploy(DEP_1); //check if it works for the deployed endpoint url checkWSDLUriScheme(client, DEP_1 + ".war", "https"); deployer.undeploy(DEP_1); //set wsdl-uri-scheme value to http ModelNode op2 = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op2.get(NAME).set("wsdl-uri-scheme"); op2.get(VALUE).set("http"); applyUpdate(client, op2, false); deployer.deploy(DEP_1); //check if the uri scheme of soap address is modified to http checkWSDLUriScheme(client, DEP_1 + ".war", "http"); if (checkUpdateWithDeployedEndpoint) { //set wsdl-uri-schema value to http ModelNode opB = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); opB.get(NAME).set("wsdl-uri-scheme"); opB.get(VALUE).set("https"); applyUpdate(client, opB, true); //check this doesn't apply to endpointed which are deployed before this change checkWSDLUriScheme(client, DEP_1 + ".war", "http"); deployer.undeploy(DEP_1); deployer.deploy(DEP_1); //check this will take effect to redeployed endpoint checkWSDLUriScheme(client, DEP_1 + ".war", "http"); } } finally { try { deployer.undeploy(DEP_1); } catch (Throwable t) { //ignore } try { //restore the value of wsdl-uri-scheme attribute ModelNode op = null; if ("undefined".equals(initialWsdlUriScheme)) { op = createOpNode("subsystem=webservices/", UNDEFINE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-uri-scheme"); } else { op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-uri-scheme"); op.get(VALUE).set(initialWsdlUriScheme); } applyUpdate(client, op, checkUpdateWithDeployedEndpoint); } finally { managementClient.close(); } } } @Test public void testWsdlPathRewriteRuleChanges() throws Exception { performWsdlPathRewriteRuleAttributeTest(false); performWsdlPathRewriteRuleAttributeTest(true); } private void performWsdlPathRewriteRuleAttributeTest(boolean checkUpdateWithDeployedEndpoint) throws Exception { Assert.assertTrue(containerController.isStarted(DEFAULT_JBOSSAS)); ManagementClient managementClient = new ManagementClient(TestSuiteEnvironment.getModelControllerClient(), TestSuiteEnvironment.getServerAddress(), TestSuiteEnvironment.getServerPort(), "http-remoting"); ModelControllerClient client = managementClient.getControllerClient(); try { final String expectedContext = "xx/jaxws-manual-pojo-1"; final String sedCmdA = "s/jaxws-manual-pojo-1/xx\\/jaxws-manual-pojo-1/g"; ModelNode op = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-path-rewrite-rule"); op.get(VALUE).set(sedCmdA); applyUpdate(client, op, false); //update successful, no need to reload //now we deploy an endpoint... deployer.deploy(DEP_1); //verify the updated wsdl host is used... URL wsdlURL = new URL(managementClient.getWebUri().toURL(), '/' + DEP_1 + "/POJOService?wsdl"); checkWsdl(wsdlURL, expectedContext); if (checkUpdateWithDeployedEndpoint) { //final String hostnameB = "foo-host-b"; final String sedCmdB = "s/jaxws-manual-pojo-1/FOO\\/jaxws-manual-pojo-1/g"; ModelNode opB = createOpNode("subsystem=webservices/", WRITE_ATTRIBUTE_OPERATION); opB.get(NAME).set("wsdl-path-rewrite-rule"); opB.get(VALUE).set(sedCmdB); applyUpdate(client, opB, true); //update again, but we'll need to reload, as there's an active deployment //check the wsdl host is still the one we updated to before checkWsdl(wsdlURL, expectedContext); //and check that still applies even if we undeploy and redeploy the endpoint deployer.undeploy(DEP_1); deployer.deploy(DEP_1); checkWsdl(wsdlURL, expectedContext); } } finally { try { deployer.undeploy(DEP_1); } catch (Throwable t) { //ignore } try { ModelNode op = createOpNode("subsystem=webservices/", UNDEFINE_ATTRIBUTE_OPERATION); op.get(NAME).set("wsdl-path-rewrite-rule"); applyUpdate(client, op, checkUpdateWithDeployedEndpoint); } finally { managementClient.close(); } } } @After public void stopContainer() { if (containerController.isStarted(DEFAULT_JBOSSAS)) { containerController.stop(DEFAULT_JBOSSAS); } } private String getAttribute(final String attribute, final ModelControllerClient client) throws Exception { return getAttribute(attribute, client, true); } private String getAttribute(final String attribute, final ModelControllerClient client, final boolean checkDefined) throws Exception { ModelNode op = createOpNode("subsystem=webservices/", READ_ATTRIBUTE_OPERATION); op.get(NAME).set(attribute); final ModelNode result = client.execute(new OperationBuilder(op).build()); if (result.hasDefined(OUTCOME) && SUCCESS.equals(result.get(OUTCOME).asString())) { if (checkDefined) { Assert.assertTrue(result.hasDefined(RESULT)); } return result.get(RESULT).asString(); } else if (result.hasDefined(FAILURE_DESCRIPTION)) { throw new Exception(result.get(FAILURE_DESCRIPTION).toString()); } else { throw new Exception("Operation not successful; outcome = " + result.get(OUTCOME)); } } private static ModelNode createOpNode(String address, String operation) { ModelNode op = new ModelNode(); // set address ModelNode list = op.get(ADDRESS).setEmptyList(); if (address != null) { String[] pathSegments = address.split("/"); for (String segment : pathSegments) { String[] elements = segment.split("="); list.add(elements[0], elements[1]); } } op.get("operation").set(operation); return op; } private static ModelNode applyUpdate(final ModelControllerClient client, final ModelNode update, final boolean expectReloadRequired) throws Exception { final ModelNode result = client.execute(new OperationBuilder(update).build()); if (result.hasDefined(OUTCOME) && SUCCESS.equals(result.get(OUTCOME).asString())) { if (expectReloadRequired) { Assert.assertTrue(result.hasDefined(RESPONSE_HEADERS)); ModelNode responseHeaders = result.get(RESPONSE_HEADERS); Assert.assertTrue(responseHeaders.hasDefined(OPERATION_REQUIRES_RELOAD)); Assert.assertEquals("true", responseHeaders.get(OPERATION_REQUIRES_RELOAD).asString()); } else { Assert.assertFalse(result.hasDefined(RESPONSE_HEADERS)); } return result; } else if (result.hasDefined(FAILURE_DESCRIPTION)) { throw new Exception(result.get(FAILURE_DESCRIPTION).toString()); } else { throw new Exception("Operation not successful; outcome = " + result.get(OUTCOME)); } } private void checkWsdl(URL wsdlURL, String hostOrPort) throws IOException { HttpURLConnection connection = (HttpURLConnection) wsdlURL.openConnection(); try { connection.connect(); Assert.assertEquals(200, connection.getResponseCode()); connection.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { if (line.contains("address location")) { Assert.assertTrue(line.contains(hostOrPort)); return; } } fail("Could not check soap:address!"); } finally { connection.disconnect(); } } private void checkWSDLUriScheme(final ModelControllerClient managementClient, String deploymentName, String expectedScheme) throws Exception { final ModelNode address = new ModelNode(); address.add(DEPLOYMENT, deploymentName); address.add(SUBSYSTEM, "webservices"); address.add("endpoint", "*"); // get all endpoints final ModelNode operation = new ModelNode(); operation.get(OP).set(READ_RESOURCE_OPERATION); operation.get(OP_ADDR).set(address); operation.get(INCLUDE_RUNTIME).set(true); operation.get(RECURSIVE).set(true); ModelNode result = managementClient.execute(operation); Assert.assertEquals(SUCCESS, result.get(OUTCOME).asString()); for (final ModelNode endpointResult : result.get("result").asList()) { final ModelNode endpoint = endpointResult.get("result"); final URL wsdlURL = new URL(endpoint.get("wsdl-url").asString()); HttpURLConnection connection = (HttpURLConnection) wsdlURL.openConnection(); try { connection.connect(); Assert.assertEquals(200, connection.getResponseCode()); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { if (line.contains("address location")) { if ("https".equals(expectedScheme)) { Assert.assertTrue(line, line.contains("https")); return; } else { Assert.assertTrue(line, line.contains("http") && !line.contains("https")); return; } } } fail(line + " Could not check soap:address!"); } finally { connection.disconnect(); } } } }