Java tutorial
/** * 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.hadoop.gateway; import com.jayway.restassured.response.Response; import com.mycila.xmltool.XMLDoc; import com.mycila.xmltool.XMLTag; import org.apache.commons.io.FileUtils; import org.apache.directory.server.protocol.shared.transport.TcpTransport; import org.apache.hadoop.gateway.config.GatewayConfig; import org.apache.hadoop.gateway.security.ldap.SimpleLdapDirectoryServer; import org.apache.hadoop.gateway.services.DefaultGatewayServices; import org.apache.hadoop.gateway.services.ServiceLifecycleException; import org.apache.http.HttpStatus; import org.apache.log4j.Appender; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; import static com.jayway.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertThat; public class GatewayDeployFuncTest { private static Class RESOURCE_BASE_CLASS = GatewayDeployFuncTest.class; private static Logger LOG = LoggerFactory.getLogger(GatewayDeployFuncTest.class); public static Enumeration<Appender> appenders; public static GatewayConfig config; public static GatewayServer gateway; public static File gatewayHome; public static String gatewayUrl; public static String clusterUrl; public static SimpleLdapDirectoryServer ldap; public static TcpTransport ldapTransport; @BeforeClass public static void setupSuite() throws Exception { //appenders = NoOpAppender.setUp(); setupLdap(); } @AfterClass public static void cleanupSuite() throws Exception { ldap.stop(true); //FileUtils.deleteQuietly( new File( config.getGatewayHomeDir() ) ); //NoOpAppender.tearDown( appenders ); } public static void setupLdap() throws Exception { URL usersUrl = getResourceUrl("users.ldif"); int port = findFreePort(); ldapTransport = new TcpTransport(port); ldap = new SimpleLdapDirectoryServer("dc=hadoop,dc=apache,dc=org", new File(usersUrl.toURI()), ldapTransport); ldap.start(); LOG.info("LDAP port = " + ldapTransport.getPort()); } @Before public void setupGateway() throws IOException { File targetDir = new File(System.getProperty("user.dir"), "target"); File gatewayDir = new File(targetDir, "gateway-home-" + UUID.randomUUID()); gatewayDir.mkdirs(); gatewayHome = gatewayDir; GatewayTestConfig testConfig = new GatewayTestConfig(); config = testConfig; testConfig.setGatewayHomeDir(gatewayDir.getAbsolutePath()); File topoDir = new File(testConfig.getGatewayTopologyDir()); topoDir.mkdirs(); File deployDir = new File(testConfig.getGatewayDeploymentDir()); deployDir.mkdirs(); DefaultGatewayServices srvcs = new DefaultGatewayServices(); Map<String, String> options = new HashMap<String, String>(); options.put("persist-master", "false"); options.put("master", "password"); try { srvcs.init(testConfig, options); } catch (ServiceLifecycleException e) { e.printStackTrace(); // I18N not required. } gateway = GatewayServer.startGateway(testConfig, srvcs); MatcherAssert.assertThat("Failed to start gateway.", gateway, notNullValue()); LOG.info("Gateway port = " + gateway.getAddresses()[0].getPort()); gatewayUrl = "http://localhost:" + gateway.getAddresses()[0].getPort() + "/" + config.getGatewayPath(); clusterUrl = gatewayUrl + "/test-cluster"; } @After public void cleanupGateway() throws Exception { gateway.stop(); FileUtils.deleteQuietly(gatewayHome); } private static XMLTag createTopology() { XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("gateway") .addTag("provider").addTag("role").addText("authentication").addTag("enabled").addText("true") .addTag("param").addTag("name").addText("main.ldapRealm").addTag("value") .addText("org.apache.shiro.realm.ldap.JndiLdapRealm").gotoParent().addTag("param").addTag("name") .addText("main.ldapRealm.userDnTemplate").addTag("value") .addText("uid={0},ou=people,dc=hadoop,dc=apache,dc=org").gotoParent().addTag("param").addTag("name") .addText("main.ldapRealm.contextFactory.url").addTag("value") .addText("ldap://localhost:" + ldapTransport.getPort()).gotoParent().addTag("param").addTag("name") .addText("main.ldapRealm.contextFactory.authenticationMechanism").addTag("value").addText("simple") .gotoParent().addTag("param").addTag("name").addText("urls./**").addTag("value") .addText("authcBasic").gotoParent().gotoParent().addTag("provider").addTag("role") .addText("identity-assertion").addTag("enabled").addText("true").addTag("name").addText("Pseudo") .gotoParent().addTag("provider").gotoRoot().addTag("service").addTag("role") .addText("test-service-role").gotoRoot(); return xml; } private static int findFreePort() throws IOException { ServerSocket socket = new ServerSocket(0); int port = socket.getLocalPort(); socket.close(); return port; } public static InputStream getResourceStream(String resource) throws IOException { return getResourceUrl(resource).openStream(); } public static URL getResourceUrl(String resource) { URL url = ClassLoader.getSystemResource(getResourceName(resource)); assertThat("Failed to find test resource " + resource, url, Matchers.notNullValue()); return url; } public static String getResourceName(String resource) { return getResourceBaseName() + resource; } public static String getResourceBaseName() { return RESOURCE_BASE_CLASS.getName().replaceAll("\\.", "/") + "/"; } //@Test public void waitForManualTesting() throws IOException { System.in.read(); } @Test(timeout = 30 * 1000) public void testDeployRedeployUndeploy() throws InterruptedException, IOException { long sleep = 200; String username = "guest"; String password = "guest-password"; String serviceUrl = clusterUrl + "/test-service-path/test-service-resource"; long topoTimestampBefore, topoTimestampAfter; File topoDir = new File(config.getGatewayTopologyDir()); File deployDir = new File(config.getGatewayDeploymentDir()); File warDir = null; // Make sure deployment directory is empty. assertThat(topoDir.listFiles().length, is(0)); assertThat(deployDir.listFiles().length, is(0)); File descriptor = writeTestTopology("test-cluster", createTopology()); warDir = waitForFiles(deployDir, "test-cluster.war\\.[0-9A-Fa-f]+", 1, 0, sleep); for (File webInfDir : warDir.listFiles()) { waitForFiles(webInfDir, ".*", 4, 0, sleep); } waitForAccess(serviceUrl, username, password, sleep); // Redeploy and make sure the timestamp is updated. topoTimestampBefore = descriptor.lastModified(); GatewayServer.redeployTopologies(config, null); topoTimestampAfter = descriptor.lastModified(); assertThat(topoTimestampAfter, greaterThan(topoTimestampBefore)); // Check to make sure there are two war directories with the same root. warDir = waitForFiles(deployDir, "test-cluster.war\\.[0-9A-Fa-f]+", 2, 1, sleep); for (File webInfDir : warDir.listFiles()) { waitForFiles(webInfDir, ".*", 4, 0, sleep); } waitForAccess(serviceUrl, username, password, sleep); // Redeploy and make sure the timestamp is updated. topoTimestampBefore = descriptor.lastModified(); GatewayServer.redeployTopologies(config, "test-cluster"); topoTimestampAfter = descriptor.lastModified(); assertThat(topoTimestampAfter, greaterThan(topoTimestampBefore)); // Check to make sure there are two war directories with the same root. warDir = waitForFiles(deployDir, "test-cluster.war\\.[0-9A-Fa-f]+", 3, 2, sleep); for (File webInfDir : warDir.listFiles()) { waitForFiles(webInfDir, ".*", 4, 0, sleep); } waitForAccess(serviceUrl, username, password, sleep); // Delete the test topology. assertThat("Failed to delete the topology file.", descriptor.delete(), is(true)); waitForFiles(deployDir, ".*", 0, -1, sleep); // Wait a bit more to make sure undeployment finished. Thread.sleep(sleep); // Make sure the test topology is not accessible. given().auth().preemptive().basic(username, password).expect().statusCode(HttpStatus.SC_NOT_FOUND).when() .get(serviceUrl); // Make sure deployment directory is empty. assertThat(topoDir.listFiles().length, is(0)); assertThat(deployDir.listFiles().length, is(0)); } private File writeTestTopology(String name, XMLTag xml) throws IOException { // Create the test topology. File tempFile = new File(config.getGatewayTopologyDir(), name + ".xml." + UUID.randomUUID()); FileOutputStream stream = new FileOutputStream(tempFile); xml.toStream(stream); stream.close(); File descriptor = new File(config.getGatewayTopologyDir(), name + ".xml"); tempFile.renameTo(descriptor); return descriptor; } private File waitForFiles(File dir, String pattern, int count, int index, long sleep) throws InterruptedException { RegexDirFilter filter = new RegexDirFilter(pattern); while (true) { File[] files = dir.listFiles(filter); if (files.length == count) { return (index < 0) ? null : files[index]; } Thread.sleep(sleep); } } private void waitForAccess(String url, String username, String password, long sleep) throws InterruptedException { while (true) { Response response = given().auth().preemptive().basic(username, password).when().get(url).andReturn(); if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { Thread.sleep(sleep); continue; } assertThat(response.getContentType(), containsString("text/plain")); assertThat(response.getBody().asString(), is("test-service-response")); break; } } private class RegexDirFilter implements FilenameFilter { Pattern pattern; RegexDirFilter(String regex) { pattern = Pattern.compile(regex); } @Override public boolean accept(File dir, String name) { return pattern.matcher(name).matches(); } } }