Author: markt Date: Mon Nov 25 22:00:13 2013 New Revision: 1545418 URL: http://svn.apache.org/r1545418 Log: Backport automatic deployment changes part 6 Add the first part of the deletion tests for the auto-deployer.
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestHostConfigAutomaticDeployment.java Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1482591,1545416 Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1545418&r1=1545417&r2=1545418&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/HostConfig.java Mon Nov 25 22:00:13 2013 @@ -167,7 +167,8 @@ public class HostConfig /** * The <code>Digester</code> instance used to parse context descriptors. */ - protected static Digester digester = createDigester(); + protected Digester digester = createDigester(contextClass); + private final Object digesterLock = new Object(); /** * The list of Wars in the appBase to be ignored because they are invalid @@ -221,8 +222,14 @@ public class HostConfig */ public void setContextClass(String contextClass) { + String oldContextClass = this.contextClass; this.contextClass = contextClass; + if (oldContextClass != contextClass) { + synchronized (digesterLock) { + digester = createDigester(getContextClass()); + } + } } @@ -391,12 +398,11 @@ public class HostConfig /** * Create the digester which will be used to parse context config files. */ - protected static Digester createDigester() { + protected static Digester createDigester(String contextClassName) { Digester digester = new Digester(); digester.setValidating(false); // Add object creation rule - digester.addObjectCreate("Context", "org.apache.catalina.core.StandardContext", - "className"); + digester.addObjectCreate("Context", contextClassName, "className"); // Set the properties on that object (it doesn't matter if extra // properties are set) digester.addSetProperties("Context"); @@ -612,7 +618,7 @@ public class HostConfig FileInputStream fis = null; try { fis = new FileInputStream(contextXml); - synchronized (digester) { + synchronized (digesterLock) { try { context = (Context) digester.parse(fis); } catch (Exception e) { @@ -906,7 +912,7 @@ public class HostConfig Context context = null; try { if (deployXML && xml.exists()) { - synchronized (digester) { + synchronized (digesterLock) { try { context = (Context) digester.parse(xml); } catch (Exception e) { @@ -920,7 +926,7 @@ public class HostConfig } context.setConfigFile(xml.toURI().toURL()); } else if (deployXML && xmlInWar) { - synchronized (digester) { + synchronized (digesterLock) { try { jar = new JarFile(war); entry = @@ -1067,7 +1073,7 @@ public class HostConfig File xmlCopy = null; try { if (deployXML && xml.exists()) { - synchronized (digester) { + synchronized (digesterLock) { try { context = (Context) digester.parse(xml); } catch (Exception e) { Modified: tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestHostConfigAutomaticDeployment.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestHostConfigAutomaticDeployment.java?rev=1545418&r1=1545417&r2=1545418&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestHostConfigAutomaticDeployment.java (original) +++ tomcat/tc7.0.x/trunk/test/org/apache/catalina/startup/TestHostConfigAutomaticDeployment.java Mon Nov 25 22:00:13 2013 @@ -34,6 +34,7 @@ import org.apache.catalina.Engine; import org.apache.catalina.Globals; import org.apache.catalina.Host; import org.apache.catalina.LifecycleState; +import org.apache.catalina.core.StandardContext; import org.apache.catalina.core.StandardHost; import org.apache.catalina.util.ContextName; import org.apache.tomcat.util.buf.B2CConverter; @@ -56,6 +57,11 @@ public class TestHostConfigAutomaticDepl private static final File DIR_SOURCE = new File("test/deployment/dirNoContext"); + private static final int XML = 1; + private static final int EXT = 2; + private static final int WAR = 3; + private static final int DIR = 4; + private static final String XML_COOKIE_NAME = "XML_CONTEXT"; private static final String WAR_COOKIE_NAME = "WAR_CONTEXT"; private static final String DIR_COOKIE_NAME = "DIR_CONTEXT"; @@ -677,6 +683,187 @@ public class TestHostConfigAutomaticDepl } + /* + * Expected behaviour for deletion of files. + * + * Artifacts present(6) Artifact Artifacts remaining + * XML WAR EXT DIR Removed XML WAR EXT DIR Notes + * N N N Y DIR - - - N + * N Y N N WAR - N - - + * N Y N Y DIR - Y - R 8 + * N Y N Y WAR - N - N + * Y N N N XML N - - - + * Y N N Y DIR Y - - N 2 + * Y N N Y XML N - - N + * Y N Y N EXT Y - N - 2 + * Y N Y N XML N - Y - 9 + * Y N Y Y DIR Y - Y R 10,8 + * Y N Y Y EXT Y - N N 2 + * Y N Y Y XML N - Y N + * Y Y N N WAR Y N - - 2 + * Y Y N N XML N N - - + * Y Y N Y DIR Y Y - R 8 + * Y Y N Y WAR Y N - - 2 + * Y Y N Y XML N N - N + * + * Notes: + */ + @Test + public void testDeleteDirRemoveDir() throws Exception { + doTestDelete(false, false, false, false, true, DIR, false, false, false, + false, null); + } + + @Test + public void testDeleteWarRemoveWar() throws Exception { + doTestDelete(false, false, false, true, false, WAR, false, false, false, + false, null); + } + + @Test + public void testDeleteWarDirRemoveDir() throws Exception { + doTestDelete(false, false, false, true, true, DIR, false, false, true, + true, WAR_COOKIE_NAME); + } + + @Test + public void testDeleteWarDirRemoveWar() throws Exception { + doTestDelete(false, false, false, true, true, WAR, false, false, false, + false, null); + } + + private void doTestDelete(boolean startXml, boolean startExternalWar, + boolean startExternalDir, boolean startWar, boolean startDir, + int toDelete, boolean resultXml, boolean resultExternal, + boolean resultWar, boolean resultDir, String resultCookieName) + throws Exception { + + Tomcat tomcat = getTomcatInstance(); + StandardHost host = (StandardHost) tomcat.getHost(); + + // Init + File xml = null; + File ext = null; + File war = null; + File dir = null; + + if (startXml) { + xml = new File(getConfigBaseFile(host), APP_NAME + ".xml"); + File parent = xml.getParentFile(); + if (!parent.isDirectory()) { + Assert.assertTrue(parent.mkdirs()); + } + Files.copy(XML_SOURCE.toPath(), xml.toPath()); + } + if (startExternalWar) { + // Copy the test WAR file to the external directory + ext = new File(external, "external" + ".war"); + Files.copy(WAR_XML_SOURCE.toPath(), ext.toPath()); + + // Create the XML file + xml = new File(getConfigBaseFile(host), APP_NAME + ".xml"); + File parent = xml.getParentFile(); + if (!parent.isDirectory()) { + Assert.assertTrue(parent.mkdirs()); + } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(xml); + fos.write(("<Context sessionCookieName=\"" + XML_COOKIE_NAME + + "\" docBase=\"" + ext.getAbsolutePath() + + "\" />").getBytes(B2CConverter.ISO_8859_1)); + } finally { + if (fos != null) { + fos.close(); + } + } + } + if (startExternalDir) { + // Copy the test DIR file to the external directory + ext = new File(external, "external"); + recurrsiveCopy(DIR_XML_SOURCE.toPath(), ext.toPath()); + + // Create the XML file + xml = new File(getConfigBaseFile(getTomcatInstance().getHost()), + APP_NAME + ".xml"); + File parent = xml.getParentFile(); + if (!parent.isDirectory()) { + Assert.assertTrue(parent.mkdirs()); + } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(xml); + fos.write(("<Context sessionCookieName=\"" + XML_COOKIE_NAME + + "\" docBase=\"" + ext.getAbsolutePath() + + "\" />").getBytes(B2CConverter.ISO_8859_1)); + } finally { + if (fos != null) { + fos.close(); + } + } + } + if (startWar) { + // Copy the test WAR file to the appBase + war = new File(getAppBaseFile(getTomcatInstance().getHost()), + APP_NAME.getBaseName() + ".war"); + Files.copy(WAR_XML_SOURCE.toPath(), war.toPath()); + } + if (startDir) { + // Copy the test DIR file to the appBase + dir = new File(getAppBaseFile(getTomcatInstance().getHost()), + APP_NAME.getBaseName()); + recurrsiveCopy(DIR_XML_SOURCE.toPath(), dir.toPath()); + } + + if (startWar && !startDir) { + host.setUnpackWARs(false); + // WARDirContext always locks the WAR file so need to use + // anti-resource locking to enable the WAR to be deleted + host.setContextClass(AntiResourceLockingContext.class.getName()); + } + + // Deploy the files we copied + tomcat.start(); + host.backgroundProcess(); + + // Remove the specified file + switch (toDelete) { + case XML: + ExpandWar.delete(xml); + break; + case EXT: + ExpandWar.delete(ext); + break; + case WAR: + ExpandWar.delete(war); + break; + case DIR: + ExpandWar.delete(dir); + break; + default: + Assert.fail(); + } + + // Trigger an auto-deployment cycle + host.backgroundProcess(); + + Context ctxt = (Context) host.findChild(APP_NAME.getName()); + + // Check the results + if (!resultXml && !resultWar && !resultDir) { + // App should have been undeployed + Assert.assertNull(ctxt); + return; + } + + if (resultWar) { + Assert.assertEquals(resultCookieName, ctxt.getSessionCookieName()); + } + } + + private static void recurrsiveCopy(final Path src, final Path dest) throws IOException { @@ -747,4 +934,44 @@ public class TestHostConfigAutomaticDepl return file; } } + + private static class AntiResourceLockingContext extends StandardContext { + + @Override + public boolean getAntiResourceLocking() { + return true; + } + } + + + @Test + public void testSetContextClassName() throws Exception { + + Tomcat tomcat = getTomcatInstance(); + + Host host = tomcat.getHost(); + if (host instanceof StandardHost) { + StandardHost standardHost = (StandardHost) host; + standardHost.setContextClass(TesterContext.class.getName()); + } + + // Copy the WAR file + File war = new File(getAppBaseFile(host), + APP_NAME.getBaseName() + ".war"); + Files.copy(WAR_XML_SOURCE.toPath(), war.toPath()); + + // Deploy the copied war + tomcat.start(); + host.backgroundProcess(); + + // Check the Context class + Context ctxt = (Context) host.findChild(APP_NAME.getName()); + + Assert.assertTrue(ctxt instanceof TesterContext); + } + + + public static class TesterContext extends StandardContext { + // No functional change + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org