Repository: geode Updated Branches: refs/heads/develop f78fc7126 -> 6e8676238
http://git-wip-us.apache.org/repos/asf/geode/blob/6e867623/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatClientServerTest.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatClientServerTest.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatClientServerTest.java index 15de541..817428b 100644 --- a/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatClientServerTest.java +++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatClientServerTest.java @@ -14,17 +14,18 @@ */ package org.apache.geode.session.tests; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.util.CommandStringBuilder; -import org.apache.geode.test.dunit.DUnitEnv; -import org.apache.geode.test.dunit.rules.GfshShellConnectionRule; -import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; +import java.io.File; + import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; -import java.io.File; +import org.apache.geode.management.internal.cli.i18n.CliStrings; +import org.apache.geode.management.internal.cli.util.CommandStringBuilder; +import org.apache.geode.test.dunit.DUnitEnv; +import org.apache.geode.test.dunit.rules.GfshShellConnectionRule; +import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; /** * Setup class for Tomcat Client Server tests @@ -53,8 +54,8 @@ public abstract class TomcatClientServerTest extends CargoTestBase { @Before public void startServer() throws Exception { TomcatInstall install = (TomcatInstall) getInstall(); - String libDirJars = install.getInstallPath() + "/lib/*"; - String binDirJars = install.getInstallPath() + "/bin/*"; + String libDirJars = install.getHome() + "/lib/*"; + String binDirJars = install.getHome() + "/bin/*"; CommandStringBuilder command = new CommandStringBuilder(CliStrings.START_SERVER); serverName = getClass().getSimpleName().concat("_").concat(getTestMethodName()); http://git-wip-us.apache.org/repos/asf/geode/blob/6e867623/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatContainer.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatContainer.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatContainer.java new file mode 100644 index 0000000..0edf0b3 --- /dev/null +++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatContainer.java @@ -0,0 +1,154 @@ +/* + * 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.geode.session.tests; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +import org.apache.commons.io.FileUtils; +import org.codehaus.cargo.container.configuration.FileConfig; +import org.codehaus.cargo.container.configuration.StandaloneLocalConfiguration; +import org.codehaus.cargo.container.tomcat.TomcatPropertySet; +import org.codehaus.cargo.util.XmlReplacement; + +/** + * Container for a tomcat installation + * + * Extends {@link ServerContainer} to form a basic container which sets up and configures a Tomcat + * container. + */ +public class TomcatContainer extends ServerContainer { + + private File contextXMLFile; + private File serverXMLFile; + + public static final String DEFAULT_TOMCAT_CONFIG_XML_DIR = "conf/"; + + public static final String DEFAULT_TOMCAT_XML_REPLACEMENT_DIR = + DEFAULT_TOMCAT_CONFIG_XML_DIR + "Catalina/localhost/"; + public static final String DEFAULT_TOMCAT_CONTEXT_XML_REPLACEMENT_NAME = "context.xml.default"; + + /** + * Setup the Tomcat container + * + * Sets up a configuration for the container using the specified installation and configuration + * home. Finds and sets up the server.xml and context.xml files needed to specify container + * properties, deploys the session testing WAR file to the Cargo container, and sets various + * container properties (i.e. locator, local cache, etc.) + */ + public TomcatContainer(TomcatInstall install, File containerConfigHome, + String containerDescriptors) throws IOException { + super(install, containerConfigHome, containerDescriptors); + + // Modify the cargo configuration to load off of the installation's context.xml + setConfigFile(DEFAULT_CONF_DIR + "context.xml", "conf", "context.xml"); + // Setup container specific XML files + contextXMLFile = new File(logDir.getAbsolutePath() + "/context.xml"); + serverXMLFile = new File(DEFAULT_CONF_DIR + "server.xml"); + + FileUtils.copyFile(new File(DEFAULT_CONF_DIR + "context.xml"), contextXMLFile); + setConfigFile(contextXMLFile.getAbsolutePath(), DEFAULT_TOMCAT_XML_REPLACEMENT_DIR, + DEFAULT_TOMCAT_CONTEXT_XML_REPLACEMENT_NAME); + + // Default properties + setCacheProperty("enableLocalCache", "false"); + setCacheProperty("className", install.getContextSessionManagerClass()); + + // Deploy war file to container configuration + deployWar(); + // Setup the default installations locators + setLocator(install.getDefaultLocatorAddress(), install.getDefaultLocatorPort()); + } + + /** + * Get the AJP port of this container using {@link #getPort()} with the argument + * {@link TomcatPropertySet#AJP_PORT} + */ + public String getAJPPort() { + return getPort(TomcatPropertySet.AJP_PORT); + } + + /** + * Implements the {@link ServerContainer#writeSettings()} function in order to write the proper + * settings to the container + * + * Method uses the {@link ContainerInstall#editXMLFile(String, String, String, String, HashMap)} + * to edit the {@link #contextXMLFile} with the {@link #cacheProperties}. Method uses + * {@link #writePropertiesToConfig(StandaloneLocalConfiguration, String, String, HashMap)} to + * write the {@link #systemProperties} to the {@link #serverXMLFile} using the container's + * configuration (obtained from {@link #getConfiguration()}). + */ + @Override + public void writeSettings() throws IOException { + StandaloneLocalConfiguration config = (StandaloneLocalConfiguration) getConfiguration(); + + // Edit the context XML file + ContainerInstall.editXMLFile(contextXMLFile.getAbsolutePath(), "Tomcat", "Manager", "Context", + cacheProperties); + writePropertiesToConfig(config, DEFAULT_TOMCAT_CONFIG_XML_DIR + "/" + serverXMLFile.getName(), + "//Server/Listener[@className='" + getInstall().getServerLifeCycleListenerClass() + "']", + systemProperties); + } + + /** + * Edits the container's configuration so that the file's XML element specified by the XPath + * parameter contains the given XML attributes + * + * Uses {@link XmlReplacement} instances to add XML attributes to the specified XML node without + * actively updating the original XML file. + * + * This function is used to edit the system properties that need to be placed in the server.xml + * file. Adding these replacement XML pieces to the container's configuration allows the + * configuration to modify the server.xml file only when creating the standalone container + * configuration. This means that the server.xml file located in the installation's 'conf' folder + * remains static, which resolves possible concurrency issues that might arise if more than one + * container is modifying the server.xml file. + * + * @param file The path to the XML file that will be edited + * @param XPath The path within XML file that leads to the node that should be changed + * @param attributes The attributes to add to the node + */ + private void writePropertiesToConfig(StandaloneLocalConfiguration config, String file, + String XPath, HashMap<String, String> attributes) { + for (String key : attributes.keySet()) { + XmlReplacement property = new XmlReplacement(); + property.setFile(file); + property.setXpathExpression(XPath); + property.setAttributeName(key); + property.setValue(attributes.get(key)); + config.addXmlReplacement(property); + } + } + + /** + * Sets a configuration file property for the container's configuration + * + * This function is currently only used to specify a different context.xml file from the one + * located in the installations 'conf' folder. + * + * @param filePath The path to the new configuration file + * @param configDirDest The name of the directory that the configuration file be placed in + * @param configFileDestName The name of destination file for the new configuration file + */ + private void setConfigFile(String filePath, String configDirDest, String configFileDestName) { + FileConfig configFile = new FileConfig(); + + configFile.setFile(filePath); + configFile.setToDir(configDirDest); + configFile.setToFile(configFileDestName); + getConfiguration().setConfigFileProperty(configFile); + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/6e867623/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatInstall.java ---------------------------------------------------------------------- diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatInstall.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatInstall.java index fe00cd3..6a6f2df 100644 --- a/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatInstall.java +++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/TomcatInstall.java @@ -22,16 +22,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.regex.Pattern; -import org.codehaus.cargo.container.configuration.FileConfig; -import org.codehaus.cargo.container.configuration.LocalConfiguration; - /** * Tomcat specific container installation class * - * Provides logic for installation and setup of the tomcat container, including editing the - * properties needed to switch between cache types. - * - * This makes the modifications to the tomcat install as described in <a href= + * Provides logic for installation of tomcat. This makes the modifications to the tomcat install as + * described in <a href= * "https://geode.apache.org/docs/guide/latest/tools_modules/http_session_mgmt/session_mgmt_tomcat.html"> * the geode docs</a>. */ @@ -61,99 +56,50 @@ public class TomcatInstall extends ContainerInstall { this.downloadURL = downloadURL; } - public String downloadURL() { - return downloadURL; - } - - public int toInteger() { - return version; - } - /** - * Name of the property that can be set to speed up container startup + * Converts the version to an integer * - * Tomcat versions have different property names for the property that, when set, causes the - * container to skip over the specified jars when scanning jars on startup. Similar to - * {@link GenericAppServerInstall.Server} but specifically built for Tomcat installations. - * - * @throws IllegalArgumentException if given a tomcat version is not expected + * This differs from {@link #getVersion()} in that this does not always return the version + * number. For Tomcat 9, there is no DeltaSession manager, so it must use the session manager + * from Tomcat 8. Thus, this function returns 8 when asked for the Tomcat 9 version number. */ - public String jarSkipPropertyName() { + public int toInteger() { switch (this) { case TOMCAT6: - return null; case TOMCAT7: - return "tomcat.util.scan.DefaultJarScanner.jarsToSkip"; case TOMCAT8: + return getVersion(); case TOMCAT9: - return "tomcat.util.scan.StandardJarScanFilter.jarsToSkip"; + return 8; default: throw new IllegalArgumentException("Illegal tomcat version option"); } } - /** - * XML required DeltaSessionManager attribute - * - * This XML attribute changes based on the Tomcat version. - * - * @return HashMap whose key is the name of the attribute ('className') and value is the value - * of the attribute. - */ - public HashMap<String, String> getRequiredXMLAttributes() { - HashMap<String, String> attributes = new HashMap<>(); - - int sessionManagerNum; - switch (this) { - case TOMCAT9: - sessionManagerNum = 8; - break; - default: - sessionManagerNum = this.toInteger(); - } - attributes.put("className", "org.apache.geode.modules.session.catalina.Tomcat" - + sessionManagerNum + "DeltaSessionManager"); - return attributes; + public int getVersion() { + return version; } - } - /** - * Tomcat cache type configuration for this installation - * - * Contains the XML needed for each cache type. Similar to - * {@link GenericAppServerInstall.CacheType} but specifically built for Tomcat installations. - */ - public enum TomcatConfig { - PEER_TO_PEER("org.apache.geode.modules.session.catalina.PeerToPeerCacheLifecycleListener", - "cache-peer.xml"), - CLIENT_SERVER("org.apache.geode.modules.session.catalina.ClientServerCacheLifecycleListener", - "cache-client.xml"); - - private final String XMLClassName; - private final String XMLFile; - - TomcatConfig(String XMLClassName, String XMLFile) { - this.XMLClassName = XMLClassName; - this.XMLFile = XMLFile; + public String getContainerId() { + return "tomcat" + getVersion() + "x"; } - /** - * Name of XML file associated with this type of cache - */ - public String getXMLFile() { - return XMLFile; + public String getDownloadURL() { + return downloadURL; } - /** - * Required XML attribute associated with this type of cache - * - * @return HashMap whose key is the name of the attribute ('className') and value is the value - * of the attribute. - */ - public HashMap<String, String> getRequiredXMLAttributes() throws IOException { - HashMap<String, String> attributes = new HashMap<>(); - attributes.put("className", XMLClassName); - return attributes; + public String jarSkipPropertyName() { + switch (this) { + case TOMCAT6: + return null; + case TOMCAT7: + return "tomcat.util.scan.DefaultJarScanner.jarsToSkip"; + case TOMCAT8: + case TOMCAT9: + return "tomcat.util.scan.StandardJarScanFilter.jarsToSkip"; + default: + throw new IllegalArgumentException("Illegal tomcat version option"); + } } } @@ -162,41 +108,40 @@ public class TomcatInstall extends ContainerInstall { "geode-modules-tomcat8", "javax.transaction-api", "jgroups", "log4j-api", "log4j-core", "log4j-jul", "shiro-core", "slf4j-api", "slf4j-jdk14", "commons-validator"}; - private TomcatConfig config; private final TomcatVersion version; - private final String tomcatModulePath; public TomcatInstall(TomcatVersion version) throws Exception { - this(version, TomcatConfig.PEER_TO_PEER, DEFAULT_INSTALL_DIR); + this(version, ConnectionType.PEER_TO_PEER, DEFAULT_INSTALL_DIR); } public TomcatInstall(TomcatVersion version, String installDir) throws Exception { - this(version, TomcatConfig.PEER_TO_PEER, installDir); + this(version, ConnectionType.PEER_TO_PEER, installDir); } - public TomcatInstall(TomcatVersion version, TomcatConfig config) throws Exception { - this(version, config, DEFAULT_INSTALL_DIR); + public TomcatInstall(TomcatVersion version, ConnectionType connType) throws Exception { + this(version, connType, DEFAULT_INSTALL_DIR); } - public TomcatInstall(TomcatVersion version, TomcatConfig config, String installDir) + /** + * Download and setup an installation tomcat using the {@link ContainerInstall} constructor and + * some extra functions this class provides + * + * Specifically, this function uses {@link #copyTomcatGeodeReqFiles(String)} to install geode + * session into Tomcat, {@link #setupDefaultSettings()} to modify the context and server XML files + * within the installation's 'conf' folder, and {@link #updateProperties()} to set the jar + * skipping properties needed to speedup container startup. + */ + public TomcatInstall(TomcatVersion version, ConnectionType connType, String installDir) throws Exception { // Does download and install from URL - super(installDir, version.downloadURL()); + super(installDir, version.getDownloadURL(), connType, "tomcat"); - this.config = config; this.version = version; - // Get tomcat module path - tomcatModulePath = findAndExtractModule(GEODE_BUILD_HOME, "tomcat"); - // Set the cache XML file by copying the XML file in the build dir - setCacheXMLFile(tomcatModulePath + "/conf/" + config.getXMLFile(), - "cargo_logs/XMLs/" + getContainerDescription() + "_" + System.nanoTime() + ".xml"); - - // Default properties - setCacheProperty("enableLocalCache", "false"); - // Install geode sessions into tomcat install copyTomcatGeodeReqFiles(GEODE_BUILD_HOME + "/lib/"); + // Set some default XML attributes in server and cache XMLs + setupDefaultSettings(); // Add required jars copied to jar skips so container startup is faster if (version.jarSkipPropertyName() != null) { @@ -205,16 +150,91 @@ public class TomcatInstall extends ContainerInstall { } /** - * Copies jars specified by {@link #tomcatRequiredJars} from the {@link #tomcatModulePath} and the - * specified other directory passed to the function. - * - * @throws IOException if the {@link #tomcatModulePath}, installation lib directory, or extra + * Modifies the context and server XML files in the installation's 'conf' directory so that they + * contain the session manager class ({@link #getContextSessionManagerClass()}) and life cycle + * listener class ({@link #getServerLifeCycleListenerClass()}) respectively + */ + public void setupDefaultSettings() { + HashMap<String, String> attributes = new HashMap<>(); + + attributes.put("className", getContextSessionManagerClass()); + editXMLFile(getDefaultContextXMLFile().getAbsolutePath(), "Tomcat", "Manager", "Context", + attributes); + + attributes.put("className", getServerLifeCycleListenerClass()); + editXMLFile(getDefaultServerXMLFile().getAbsolutePath(), "Tomcat", "Listener", "Server", + attributes); + } + + /** + * Location of the context XML file in the installation's 'conf' directory + */ + public File getDefaultContextXMLFile() { + return new File(getHome() + "/conf/context.xml"); + } + + /** + * Location of the server XML file in the installation's 'conf' directory + */ + public File getDefaultServerXMLFile() { + return new File(getHome() + "/conf/server.xml"); + } + + /** + * Implements {@link ContainerInstall#getContextSessionManagerClass()} + * + * Gets the TomcatDeltaSessionManager class associated with this {@link #version}. Use's the + * {@link #version}'s toInteger function to do so. + */ + @Override + public String getContextSessionManagerClass() { + return "org.apache.geode.modules.session.catalina.Tomcat" + version.toInteger() + + "DeltaSessionManager"; + } + + /** + * Implementation of {@link ContainerInstall#generateContainer(File, String)}, which generates a + * Tomcat specific container + * + * Creates a {@link TomcatContainer} instance off of this installation. + * + * @param containerDescriptors Additional descriptors used to identify a container + */ + @Override + public TomcatContainer generateContainer(File containerConfigHome, String containerDescriptors) + throws IOException { + return new TomcatContainer(this, containerConfigHome, containerDescriptors); + } + + /** + * The cargo specific installation id needed to setup a cargo container + * + * Based on the installation's {@link #version}. + */ + @Override + public String getInstallId() { + return version.getContainerId(); + } + + /** + * @see ContainerInstall#getInstallDescription() + */ + @Override + public String getInstallDescription() { + return version.name() + "_" + getConnectionType().getName(); + } + + /** + * Copies jars specified by {@link #tomcatRequiredJars} from the {@link #getModulePath()} and the + * specified other directory passed to the function + * + * @throws IOException if the {@link #getModulePath()}, installation lib directory, or extra * directory passed in contain no files. */ private void copyTomcatGeodeReqFiles(String extraJarsPath) throws IOException { ArrayList<File> requiredFiles = new ArrayList<>(); // The library path for the current tomcat installation - String tomcatLibPath = getInstallPath() + "/lib/"; + String tomcatLibPath = getHome() + "/lib/"; // List of required jars and form version regexps from them String versionRegex = "-[0-9]+.*\\.jar"; @@ -237,7 +257,7 @@ public class TomcatInstall extends ContainerInstall { // Find all the required jars in the tomcatModulePath try { - for (File file : (new File(tomcatModulePath + "/lib/")).listFiles()) { + for (File file : (new File(getModulePath() + "/lib/")).listFiles()) { for (Pattern pattern : patterns) { if (pattern.matcher(file.getName()).find()) { requiredFiles.add(file); @@ -248,7 +268,7 @@ public class TomcatInstall extends ContainerInstall { } } catch (NullPointerException e) { throw new IOException( - "No files found in tomcat module directory " + tomcatModulePath + "/lib/"); + "No files found in tomcat module directory " + getModulePath() + "/lib/"); } // Find all the required jars in the extraJarsPath @@ -285,115 +305,7 @@ public class TomcatInstall extends ContainerInstall { for (String jarName : tomcatRequiredJars) jarsToSkip += "," + jarName + "*.jar"; - editPropertyFile(getInstallPath() + "/conf/catalina.properties", version.jarSkipPropertyName(), + editPropertyFile(getHome() + "/conf/catalina.properties", version.jarSkipPropertyName(), jarsToSkip, true); } - - /** - * Build a HashMap with server property attributes for the server.xml file - * - * Server properties are obtained by iterating through {@link ContainerInstall#systemProperties} - */ - private HashMap<String, String> buildServerXMLAttributes() throws IOException { - HashMap<String, String> attributes = config.getRequiredXMLAttributes(); - - for (String property : systemProperties.keySet()) - attributes.put(property, systemProperties.get(property)); - - return attributes; - } - - /** - * Build a HashMap with cache property attributes for the context.xml file - * - * Cache properties are obtained by iterating through {@link ContainerInstall#cacheProperties} - */ - private HashMap<String, String> buildContextXMLAttributes() { - HashMap<String, String> attributes = version.getRequiredXMLAttributes(); - - for (String property : cacheProperties.keySet()) - attributes.put(property, cacheProperties.get(property)); - - return attributes; - } - - /** - * Update the server and context XML files - * - * Uses the {@link #buildContextXMLAttributes()} and {@link #buildServerXMLAttributes()} methods - * to update to the proper attributes and values - */ - private void updateXMLFiles() throws IOException { - editXMLFile(getInstallPath() + "/conf/server.xml", "Tomcat", "Listener", "Server", - buildServerXMLAttributes()); - editXMLFile(getInstallPath() + "/conf/context.xml", "Tomcat", "Manager", "Context", - buildContextXMLAttributes()); - } - - /** - * Tomcat specific property updater - * - * Overrides {@link ContainerInstall#writeProperties}. Most properties for Tomcat installs are - * changed within the server.xml and context.xml files so this runs {@link #updateXMLFiles}. - */ - @Override - public void writeProperties() throws Exception { - updateXMLFiles(); - } - - /** - * Sets the address and port of the locator for this tomcat installation - * - * For Client Server installations the cache-client.xml file is updated within the installations - * conf folder. For Peer to Peer installations the server.xml file is updated using - * {@link #updateXMLFiles()} when the container is started. - */ - @Override - public void setLocator(String address, int port) throws Exception { - if (config == TomcatConfig.CLIENT_SERVER) { - HashMap<String, String> attributes = new HashMap<>(); - attributes.put("host", address); - attributes.put("port", Integer.toString(port)); - - editXMLFile(getSystemProperty("cache-xml-file"), "locator", "pool", attributes, true); - - } else { - setSystemProperty("locators", address + "[" + port + "]"); - } - - logger.info("Set locator for Tomcat install to " + address + "[" + port + "]"); - } - - public TomcatVersion getVersion() { - return version; - } - - /** - * @see ContainerInstall#getContainerId() - */ - @Override - public String getContainerId() { - return "tomcat" + version.toInteger() + "x"; - } - - /** - * @see ContainerInstall#getContainerDescription() - */ - @Override - public String getContainerDescription() { - return version.name() + "_" + config.name(); - } - - /** - * Modifies the tomcat configuration so that this points to the correct context.xml file when - * setup and run using Cargo. - */ - @Override - public void modifyConfiguration(LocalConfiguration configuration) { - // Copy context.xml file for actual server to get DeltaSessionManager as manager - FileConfig contextConfigFile = new FileConfig(); - contextConfigFile.setToDir("conf"); - contextConfigFile.setFile(getInstallPath() + "/conf/context.xml"); - configuration.setConfigFileProperty(contextConfigFile); - } }
