From 4a27eaa1bffdc10167d6166654951578eea80935 Mon Sep 17 00:00:00 2001 From: markt Date: Mon, 1 Nov 2010 02:04:53 +0000 Subject: [PATCH] Parallel deployment - More work separating Context.name & Context.path - Review use of Context.getName() and Context.getPath() and use the correct one - Start to add webappVersion property to Context (many components not version aware - e.g. Manager app) - Set version when deploying apps if version is specified - Include version in Context.name if version is specified - New ContextName util class to handle all path/name/version etc translations In most cases the behaviour is unchanged if the version is not specified. The one exception is JMX ObjectNames that used to contain a key value pair "path=...". Since context path is no longer unique when using versions, this has been changed to "context=..." and the context name used which is unique. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1029527 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/catalina/Context.java | 20 +++ .../apache/catalina/connector/MapperListener.java | 81 +++++----- .../catalina/core/ApplicationFilterConfig.java | 4 +- .../core/ApplicationServletRegistration.java | 4 +- java/org/apache/catalina/core/ContainerBase.java | 2 + .../apache/catalina/core/LocalStrings.properties | 11 +- .../catalina/core/NamingContextListener.java | 8 +- java/org/apache/catalina/core/StandardContext.java | 85 ++++++----- java/org/apache/catalina/core/StandardWrapper.java | 7 +- .../apache/catalina/core/mbeans-descriptors.xml | 14 ++ .../apache/catalina/ha/deploy/FarmWarDeployer.java | 33 +---- java/org/apache/catalina/loader/WebappLoader.java | 32 ++-- .../catalina/manager/HTMLManagerServlet.java | 26 ++-- .../apache/catalina/manager/ManagerServlet.java | 135 +++++++---------- java/org/apache/catalina/mbeans/MBeanFactory.java | 20 +-- java/org/apache/catalina/mbeans/MBeanUtils.java | 87 ++++++----- java/org/apache/catalina/realm/JAASRealm.java | 5 +- java/org/apache/catalina/session/JDBCStore.java | 3 + java/org/apache/catalina/session/ManagerBase.java | 12 +- .../org/apache/catalina/startup/ContextConfig.java | 43 ++---- java/org/apache/catalina/startup/Embedded.java | 2 +- java/org/apache/catalina/startup/HostConfig.java | 165 +++++++-------------- .../catalina/startup/LocalStrings.properties | 5 +- java/org/apache/catalina/startup/TldConfig.java | 3 +- java/org/apache/catalina/util/ContextName.java | 132 +++++++++++++++++ .../apache/catalina/util/ExtensionValidator.java | 2 +- 26 files changed, 496 insertions(+), 445 deletions(-) create mode 100644 java/org/apache/catalina/util/ContextName.java diff --git a/java/org/apache/catalina/Context.java b/java/org/apache/catalina/Context.java index cfb77bb80..33c03a237 100644 --- a/java/org/apache/catalina/Context.java +++ b/java/org/apache/catalina/Context.java @@ -1275,5 +1275,25 @@ public interface Context extends Container { * otherwise false */ public boolean isResourceOnlyServlet(String servletName); + + /** + * Return the base name to use for WARs, directories or context.xml files + * for this context. + */ + public String getBaseName(); + + /** + * Set the version of this web application - used to differentiate + * different versions of the same web application when using parallel + * deployment. + */ + public void setWebappVersion(String webappVersion); + + /** + * Set the version of this web application - used to differentiate + * different versions of the same web application when using parallel + * deployment. If not specified, defaults to the empty string. + */ + public String getWebappVersion(); } diff --git a/java/org/apache/catalina/connector/MapperListener.java b/java/org/apache/catalina/connector/MapperListener.java index 6fc53675b..5c44e8a1f 100644 --- a/java/org/apache/catalina/connector/MapperListener.java +++ b/java/org/apache/catalina/connector/MapperListener.java @@ -157,70 +157,70 @@ public class MapperListener implements ContainerListener, LifecycleListener { // Handle dynamically adding wrappers Wrapper wrapper = (Wrapper) event.getSource(); Context context = (Context) wrapper.getParent(); - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } String hostName = context.getParent().getName(); String wrapperName = wrapper.getName(); String mapping = (String) event.getData(); boolean jspWildCard = ("jsp".equals(wrapperName) && mapping.endsWith("/*")); - mapper.addWrapper(hostName, contextName, mapping, wrapper, + mapper.addWrapper(hostName, contextPath, mapping, wrapper, jspWildCard, context.isResourceOnlyServlet(wrapperName)); } else if (event.getType() == Wrapper.REMOVE_MAPPING_EVENT) { // Handle dynamically removing wrappers Wrapper wrapper = (Wrapper) event.getSource(); - String contextName = wrapper.getParent().getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = ((Context) wrapper.getParent()).getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } String hostName = wrapper.getParent().getParent().getName(); String mapping = (String) event.getData(); - mapper.removeWrapper(hostName, contextName, mapping); + mapper.removeWrapper(hostName, contextPath, mapping); } else if (event.getType() == Context.ADD_WELCOME_FILE_EVENT) { // Handle dynamically adding welcome files Context context = (Context) event.getSource(); String hostName = context.getParent().getName(); - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } String welcomeFile = (String) event.getData(); - mapper.addWelcomeFile(hostName, contextName, welcomeFile); + mapper.addWelcomeFile(hostName, contextPath, welcomeFile); } else if (event.getType() == Context.REMOVE_WELCOME_FILE_EVENT) { // Handle dynamically removing welcome files Context context = (Context) event.getSource(); String hostName = context.getParent().getName(); - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } String welcomeFile = (String) event.getData(); - mapper.removeWelcomeFile(hostName, contextName, welcomeFile); + mapper.removeWelcomeFile(hostName, contextPath, welcomeFile); } else if (event.getType() == Context.CLEAR_WELCOME_FILES_EVENT) { // Handle dynamically clearing welcome files Context context = (Context) event.getSource(); String hostName = context.getParent().getName(); - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } - mapper.clearWelcomeFiles(hostName, contextName); + mapper.clearWelcomeFiles(hostName, contextPath); } } @@ -301,23 +301,23 @@ public class MapperListener implements ContainerListener, LifecycleListener { */ private void unregisterWrapper(Wrapper wrapper) { - String contextName = wrapper.getParent().getName(); + String contextPath = ((Context) wrapper.getParent()).getPath(); String wrapperName = wrapper.getName(); - if ("/".equals(contextName)) { - contextName = ""; + if ("/".equals(contextPath)) { + contextPath = ""; } String hostName = wrapper.getParent().getParent().getName(); String[] mappings = wrapper.findMappings(); for (String mapping : mappings) { - mapper.removeWrapper(hostName, contextName, mapping); + mapper.removeWrapper(hostName, contextPath, mapping); } if(log.isDebugEnabled()) { log.debug(sm.getString("mapperListener.unregisterWrapper", - wrapperName, contextName, connector)); + wrapperName, contextPath, connector)); } } @@ -327,16 +327,16 @@ public class MapperListener implements ContainerListener, LifecycleListener { */ private void registerContext(Context context) { - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } Container host = context.getParent(); javax.naming.Context resources = context.getResources(); String[] welcomeFiles = context.findWelcomeFiles(); - mapper.addContext(host.getName(), host, contextName, context, + mapper.addContext(host.getName(), host, contextPath, context, welcomeFiles, resources); for (Container container : context.findChildren()) { @@ -345,7 +345,7 @@ public class MapperListener implements ContainerListener, LifecycleListener { if(log.isDebugEnabled()) { log.debug(sm.getString("mapperListener.registerContext", - contextName, connector)); + contextPath, connector)); } } @@ -360,17 +360,17 @@ public class MapperListener implements ContainerListener, LifecycleListener { return; } - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } String hostName = context.getParent().getName(); if(log.isDebugEnabled()) log.debug(sm.getString("mapperListener.unregisterContext", - contextName, connector)); + contextPath, connector)); - mapper.removeContext(hostName, contextName); + mapper.removeContext(hostName, contextPath); } @@ -381,10 +381,11 @@ public class MapperListener implements ContainerListener, LifecycleListener { String wrapperName = wrapper.getName(); Context context = (Context) wrapper.getParent(); - String contextName = context.getName(); - if ("/".equals(contextName)) { - contextName = ""; + String contextPath = context.getPath(); + if ("/".equals(contextPath)) { + contextPath = ""; } + String hostName = context.getParent().getName(); String[] mappings = wrapper.findMappings(); @@ -392,14 +393,14 @@ public class MapperListener implements ContainerListener, LifecycleListener { for (String mapping : mappings) { boolean jspWildCard = (wrapperName.equals("jsp") && mapping.endsWith("/*")); - mapper.addWrapper(hostName, contextName, mapping, wrapper, + mapper.addWrapper(hostName, contextPath, mapping, wrapper, jspWildCard, context.isResourceOnlyServlet(wrapperName)); } if(log.isDebugEnabled()) { log.debug(sm.getString("mapperListener.registerWrapper", - wrapperName, contextName, connector)); + wrapperName, contextPath, connector)); } } diff --git a/java/org/apache/catalina/core/ApplicationFilterConfig.java b/java/org/apache/catalina/core/ApplicationFilterConfig.java index b9238cc7b..d34b08562 100644 --- a/java/org/apache/catalina/core/ApplicationFilterConfig.java +++ b/java/org/apache/catalina/core/ApplicationFilterConfig.java @@ -394,7 +394,9 @@ public final class ApplicationFilterConfig implements FilterConfig, Serializable private void registerJMX() { String parentName = context.getName(); - parentName = ("".equals(parentName)) ? "/" : parentName; + if (!parentName.startsWith("/")) { + parentName = "/" + parentName; + } String hostName = context.getParent().getName(); hostName = (hostName == null) ? "DEFAULT" : hostName; diff --git a/java/org/apache/catalina/core/ApplicationServletRegistration.java b/java/org/apache/catalina/core/ApplicationServletRegistration.java index 748005fe8..c4bb9fd25 100644 --- a/java/org/apache/catalina/core/ApplicationServletRegistration.java +++ b/java/org/apache/catalina/core/ApplicationServletRegistration.java @@ -149,13 +149,13 @@ public class ApplicationServletRegistration if (constraint == null) { throw new IllegalArgumentException(sm.getString( "applicationServletRegistration.setServletSecurity.iae", - getName(), context.getPath())); + getName(), context.getName())); } if (!context.getState().equals(LifecycleState.STARTING_PREP)) { throw new IllegalStateException(sm.getString( "applicationServletRegistration.setServletSecurity.ise", - getName(), context.getPath())); + getName(), context.getName())); } return context.addServletSecurity(this, constraint); diff --git a/java/org/apache/catalina/core/ContainerBase.java b/java/org/apache/catalina/core/ContainerBase.java index e1d53298f..04206b3e0 100644 --- a/java/org/apache/catalina/core/ContainerBase.java +++ b/java/org/apache/catalina/core/ContainerBase.java @@ -1269,6 +1269,8 @@ public abstract class ContainerBase extends LifecycleMBeanBase String name = current.getName(); if ((name == null) || (name.equals(""))) { name = "/"; + } else if (name.startsWith("##")) { + name = "/" + name; } loggerName = "[" + name + "]" + ((loggerName != null) ? ("." + loggerName) : ""); diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index dd447e0c9..0adb4654c 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -50,8 +50,8 @@ applicationRequest.badParent=Cannot locate parent Request implementation applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper applicationResponse.badParent=Cannot locate parent Response implementation applicationResponse.badResponse=Response is not a javax.servlet.ServletResponseWrapper -applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with path [{1}] -applicationServletRegistration.setServletSecurity.ise=Security constraints can't be added to servlet [{0}] deployed to context with path [{1}] as the context has already been initialised +applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with name [{1}] +applicationServletRegistration.setServletSecurity.ise=Security constraints can't be added to servlet [{0}] deployed to context with name [{1}] as the context has already been initialised aprListener.aprInit=The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: {0} aprListener.tcnInvalid=An incompatible version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat requires version {1} aprListener.tcnVersion=An older version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of {1} @@ -121,16 +121,16 @@ standardContext.loginConfig.loginWarning=WARNING: Form login page {0} must start standardContext.loginConfig.required=LoginConfig cannot be null standardContext.manager=Configured a manager of class [{0}] standardContext.mappingError=MAPPING configuration error for relative URI {0} -standardContext.noResourceJar=Resource JARs are not supported. The JAR found at [{0}] will no be used to provide static content for context with path [{1}] +standardContext.noResourceJar=Resource JARs are not supported. The JAR found at [{0}] will not be used to provide static content for context with name [{1}] standardContext.notFound=The requested resource ({0}) is not available. standardContext.notReloadable=Reloading is disabled on this Context standardContext.notStarted=Context has not yet been started standardContext.notWrapper=Child of a Context must be a Wrapper standardContext.parameter.duplicate=Duplicate context initialization parameter {0} standardContext.parameter.required=Both parameter name and parameter value are required -standardContext.reloadingCompleted=Reloading Context with path [{0}] is completed +standardContext.reloadingCompleted=Reloading Context with name [{0}] is completed standardContext.reloadingFailed=Reloading this Context failed due to previous errors -standardContext.reloadingStarted=Reloading Context with path [{0}] has started +standardContext.reloadingStarted=Reloading Context with name [{0}] has started standardContext.resourcesStart=Error starting static Resources standardContext.securityConstraint.mixHttpMethod=It is not permitted to mix and in the same web resource collection standardContext.securityConstraint.pattern=Invalid {0} in security constraint @@ -148,6 +148,7 @@ standardContext.stoppingWrapper=Exception stopping Wrapper for servlet {0} standardContext.urlDecode=Cannot URL decode request path {0} standardContext.urlPattern.patternWarning=WARNING: URL pattern {0} must start with a ''/'' in Servlet 2.4 standardContext.urlValidate=Cannot validate URL decoded request path {0} +standardContext.workPath=Exception obtaining work path for context [{0}] standardContext.wrapper.error=JSP file {0} must start with a ''/' standardContext.wrapper.warning=WARNING: JSP file {0} must start with a ''/'' in Servlet 2.4 standardEngine.alreadyStarted=Engine has already been started diff --git a/java/org/apache/catalina/core/NamingContextListener.java b/java/org/apache/catalina/core/NamingContextListener.java index f459c9b5f..1e2ff4eca 100644 --- a/java/org/apache/catalina/core/NamingContextListener.java +++ b/java/org/apache/catalina/core/NamingContextListener.java @@ -720,12 +720,12 @@ public class NamingContextListener ",class=" + resource.getType() + ",name=" + quotedResourceName); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) + contextName = "/" + contextName; Host host = (Host) ((Context)container).getParent(); name = new ObjectName(domain + ":type=DataSource" + - ",path=" + path + + ",context=" + contextName + ",host=" + host.getName() + ",class=" + resource.getType() + ",name=" + quotedResourceName); diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java index d08fb7854..76880ab46 100644 --- a/java/org/apache/catalina/core/StandardContext.java +++ b/java/org/apache/catalina/core/StandardContext.java @@ -100,6 +100,7 @@ import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.session.StandardManager; import org.apache.catalina.startup.TldConfig; import org.apache.catalina.util.CharsetMapper; +import org.apache.catalina.util.ContextName; import org.apache.catalina.util.ExtensionValidator; import org.apache.catalina.util.RequestUtil; import org.apache.catalina.util.URLEncoder; @@ -812,9 +813,29 @@ public class StandardContext extends ContainerBase private Set resourceOnlyServlets = new HashSet(); + private String webappVersion; // ----------------------------------------------------- Context Properties + + @Override + public void setWebappVersion(String webappVersion) { + this.webappVersion = webappVersion; + } + + + @Override + public String getWebappVersion() { + return webappVersion; + } + + + @Override + public String getBaseName() { + return new ContextName(path, webappVersion).getBaseName(); + } + + @Override public String getResourceOnlyServlets() { StringBuilder result = new StringBuilder(); @@ -1029,7 +1050,7 @@ public class StandardContext extends ContainerBase ((BaseDirContext) webappResources).addResourcesJar(url); } else { log.error(sm.getString("standardContext.noResourceJar", url, - getPath())); + getName())); } } @@ -1872,7 +1893,7 @@ public class StandardContext extends ContainerBase return (path); } - + /** * Set the context path for this Context. * @@ -2335,7 +2356,8 @@ public class StandardContext extends ContainerBase workDir = new File(catalinaHomePath, getWorkDir()); } catch (IOException e) { - log.warn("Exception obtaining work path for " + getPath()); + log.warn(sm.getString("standardContext.workPath", getName()), + e); } } return workDir.getAbsolutePath(); @@ -3627,17 +3649,9 @@ public class StandardContext extends ContainerBase throw new IllegalStateException (sm.getString("containerBase.notStarted", logName())); - String path = getPath(); - if (path.length() == 0) { - path = "/"; - } - - // Make sure reloading is enabled - // if (!reloadable) - // throw new IllegalStateException - // (sm.getString("standardContext.notReloadable")); if(log.isInfoEnabled()) - log.info(sm.getString("standardContext.reloadingStarted", path)); + log.info(sm.getString("standardContext.reloadingStarted", + getName())); // Stop accepting requests temporarily setPaused(true); @@ -3657,7 +3671,8 @@ public class StandardContext extends ContainerBase setPaused(false); if(log.isInfoEnabled()) - log.info(sm.getString("standardContext.reloadingCompleted", path)); + log.info(sm.getString("standardContext.reloadingCompleted", + getName())); } @@ -4644,10 +4659,13 @@ public class StandardContext extends ContainerBase } // Register the cache in JMX if (isCachingAllowed()) { + String contextName = getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } ObjectName resourcesName = new ObjectName(this.getDomain() + ":type=Cache,host=" - + getHostname() + ",path=" - + (("".equals(getPath()))?"/":getPath())); + + getHostname() + ",context=" + contextName); Registry.getRegistry(null, null).registerComponent (proxyDirContext.getCache(), resourcesName, null); } @@ -4680,12 +4698,15 @@ public class StandardContext extends ContainerBase } // Unregister the cache in JMX if (isCachingAllowed()) { + String contextName = getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } ObjectName resourcesName = new ObjectName(this.getDomain() + ":type=Cache,host=" - + getHostname() + ",path=" - + (("".equals(getPath()))?"/" - :getPath())); + + getHostname() + ",context=" + + contextName); Registry.getRegistry(null, null) .unregisterComponent(resourcesName); } @@ -4758,7 +4779,7 @@ public class StandardContext extends ContainerBase protected synchronized void startInternal() throws LifecycleException { if(log.isDebugEnabled()) - log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName())); + log.debug("Starting " + getBaseName()); // Send j2ee.state.starting notification if (this.getObjectName() != null) { @@ -5592,21 +5613,6 @@ public class StandardContext extends ContainerBase /** - * Given a context path, get the config file name. - */ - protected String getDefaultConfigFile() { - String basename = null; - String path = getPath(); - if (path.equals("")) { - basename = "ROOT"; - } else { - basename = path.substring(1).replace('/', '#'); - } - return (basename + ".xml"); - } - - - /** * Get naming context full name. */ private String getNamingContextName() { @@ -5786,7 +5792,7 @@ public class StandardContext extends ContainerBase if ((engineName == null) || (engineName.length() < 1)) engineName = "_"; - String temp = getPath(); + String temp = getName(); if (temp.startsWith("/")) temp = temp.substring(1); temp = temp.replace('/', '_'); @@ -5963,12 +5969,11 @@ public class StandardContext extends ContainerBase result.append(hostname); } - String pathName = getName(); - if ("".equals(pathName)) { + String contextName = getName(); + if (!contextName.startsWith("/")) { result.append('/'); - } else { - result.append(pathName); } + result.append(contextName); return result.toString(); } diff --git a/java/org/apache/catalina/core/StandardWrapper.java b/java/org/apache/catalina/core/StandardWrapper.java index e18b67a31..7bd1284fe 100644 --- a/java/org/apache/catalina/core/StandardWrapper.java +++ b/java/org/apache/catalina/core/StandardWrapper.java @@ -1725,12 +1725,11 @@ public class StandardWrapper extends ContainerBase keyProperties.append(hostName); } - String pathName = ((Context) getParent()).getPath(); - if ("".equals(pathName)) { + String contextName = ((Context) getParent()).getName(); + if (!contextName.startsWith("/")) { keyProperties.append('/'); - } else { - keyProperties.append(pathName); } + keyProperties.append(contextName); StandardContext ctx = null; if (parent instanceof StandardContext) { diff --git a/java/org/apache/catalina/core/mbeans-descriptors.xml b/java/org/apache/catalina/core/mbeans-descriptors.xml index 995961068..ed12dc406 100644 --- a/java/org/apache/catalina/core/mbeans-descriptors.xml +++ b/java/org/apache/catalina/core/mbeans-descriptors.xml @@ -86,6 +86,11 @@ description="Take care to not lock resources" type="boolean" /> + + @@ -237,6 +242,10 @@ description="The default context.xml override flag for this web application" type="boolean"/> + + @@ -365,6 +374,11 @@ is="true" type="boolean"/> + + = 2) { log("Uploading WAR file to " + localWar); } // Copy WAR to appBase try { - if (!isServiced(path)) { - addServiced(path); + if (!isServiced(name)) { + addServiced(name); try { // Upload WAR uploadWar(request, localWar); // Copy WAR and XML to the host app base if needed if (tag != null) { deployedPath = deployed; - File localWarCopy = new File(deployedPath, basename + ".war"); + File localWarCopy = new File(deployedPath, baseName + ".war"); copy(localWar, localWarCopy); localWar = localWarCopy; - copy(localWar, new File(getAppBase(), basename + ".war")); + copy(localWar, new File(getAppBase(), baseName + ".war")); } // Perform new deployment - check(path); + check(name); } finally { - removeServiced(path); + removeServiced(name); } } } catch (Exception e) { @@ -664,7 +666,7 @@ public class ManagerServlet return; } - context = (Context) host.findChild(path); + context = (Context) host.findChild(name); if (context != null && context.getConfigured()) { writer.println(smClient.getString( "managerServlet.deployed", displayPath)); @@ -695,9 +697,10 @@ public class ManagerServlet return; } String displayPath = path; - if( path.equals("/") ) - path = ""; - + ContextName cn = new ContextName(path, null); + String baseName = cn.getBaseName(); + String name = cn.getName(); + // Calculate the base path File deployedPath = versioned; if (tag != null) { @@ -705,24 +708,24 @@ public class ManagerServlet } // Find the local WAR file - File localWar = new File(deployedPath, getDocBase(path) + ".war"); + File localWar = new File(deployedPath, baseName + ".war"); // Check if app already exists, or undeploy it if updating - Context context = (Context) host.findChild(path); + Context context = (Context) host.findChild(name); if (context != null) { undeploy(writer, displayPath, smClient); } // Copy WAR to appBase try { - if (!isServiced(path)) { - addServiced(path); + if (!isServiced(name)) { + addServiced(name); try { - copy(localWar, new File(getAppBase(), getDocBase(path) + ".war")); + copy(localWar, new File(getAppBase(), baseName + ".war")); // Perform new deployment - check(path); + check(name); } finally { - removeServiced(path); + removeServiced(name); } } } catch (Exception e) { @@ -732,7 +735,7 @@ public class ManagerServlet return; } - context = (Context) host.findChild(path); + context = (Context) host.findChild(name); if (context != null && context.getConfigured()) { writer.println(smClient.getString("managerServlet.deployed", displayPath)); @@ -790,17 +793,17 @@ public class ManagerServlet return; } String displayPath = path; - if("/".equals(path)) { - path = ""; - } + ContextName cn = new ContextName(path, null); + String name = cn.getName(); + String baseName = cn.getBaseName(); // Check if app already exists, or undeploy it if updating - Context context = (Context) host.findChild(path); + Context context = (Context) host.findChild(name); if (update) { if (context != null) { undeploy(writer, displayPath, smClient); } - context = (Context) host.findChild(path); + context = (Context) host.findChild(name); } if (context != null) { writer.println(smClient.getString("managerServlet.alreadyContext", @@ -816,30 +819,30 @@ public class ManagerServlet } try { - if (!isServiced(path)) { - addServiced(path); + if (!isServiced(name)) { + addServiced(name); try { if (config != null) { configBase.mkdirs(); copy(new File(config), - new File(configBase, getConfigFile(path) + ".xml")); + new File(configBase, baseName + ".xml")); } if (war != null) { if (war.endsWith(".war")) { copy(new File(war), - new File(getAppBase(), getDocBase(path) + ".war")); + new File(getAppBase(), baseName + ".war")); } else { copy(new File(war), - new File(getAppBase(), getDocBase(path))); + new File(getAppBase(), baseName)); } } // Perform new deployment - check(path); + check(name); } finally { - removeServiced(path); + removeServiced(name); } } - context = (Context) host.findChild(path); + context = (Context) host.findChild(name); if (context != null && context.getConfigured() && context.getAvailable()) { writer.println(smClient.getString( "managerServlet.deployed", displayPath)); @@ -928,7 +931,7 @@ public class ManagerServlet return; } // It isn't possible for the manager to reload itself - if (context.getPath().equals(this.context.getPath())) { + if (context.getName().equals(this.context.getName())) { writer.println(smClient.getString("managerServlet.noSelf")); return; } @@ -1335,7 +1338,7 @@ public class ManagerServlet return; } // It isn't possible for the manager to stop itself - if (context.getPath().equals(this.context.getPath())) { + if (context.getName().equals(this.context.getName())) { writer.println(smClient.getString("managerServlet.noSelf")); return; } @@ -1370,27 +1373,28 @@ public class ManagerServlet return; } String displayPath = path; - if( path.equals("/") ) - path = ""; + ContextName cn = new ContextName(path, null); + String name = cn.getName(); + String baseName = cn.getBaseName(); try { // Validate the Context of the specified application - Context context = (Context) host.findChild(path); + Context context = (Context) host.findChild(name); if (context == null) { writer.println(smClient.getString("managerServlet.noContext", RequestUtil.filter(displayPath))); return; } - if (!isDeployed(path)) { + if (!isDeployed(name)) { writer.println(smClient.getString("managerServlet.notDeployed", RequestUtil.filter(displayPath))); return; } - if (!isServiced(path)) { - addServiced(path); + if (!isServiced(name)) { + addServiced(name); try { // Try to stop the context first to be nicer context.stop(); @@ -1398,12 +1402,9 @@ public class ManagerServlet ExceptionUtils.handleThrowable(t); } try { - if (path.lastIndexOf('/') > 0) { - path = "/" + path.substring(1).replace('/','#'); - } - File war = new File(getAppBase(), getDocBase(path) + ".war"); - File dir = new File(getAppBase(), getDocBase(path)); - File xml = new File(configBase, getConfigFile(path) + ".xml"); + File war = new File(getAppBase(), baseName + ".war"); + File dir = new File(getAppBase(), baseName); + File xml = new File(configBase, baseName + ".xml"); if (war.exists()) { war.delete(); } else if (dir.exists()) { @@ -1412,9 +1413,9 @@ public class ManagerServlet xml.delete(); } // Perform new deployment - check(path.replace('#', '/')); + check(name); } finally { - removeServiced(path.replace('#','/')); + removeServiced(name); } } writer.println(smClient.getString("managerServlet.undeployed", @@ -1433,34 +1434,6 @@ public class ManagerServlet /** - * Given a context path, get the config file name. - */ - protected String getConfigFile(String path) { - String basename = null; - if (path.equals("")) { - basename = "ROOT"; - } else { - basename = path.substring(1).replace('/', '#'); - } - return (basename); - } - - - /** - * Given a context path, get the doc base. - */ - protected String getDocBase(String path) { - String basename = null; - if (path.equals("")) { - basename = "ROOT"; - } else { - basename = path.substring(1).replace('/', '#'); - } - return (basename); - } - - - /** * Return a File object representing the "application root" directory * for our associated Host. */ diff --git a/java/org/apache/catalina/mbeans/MBeanFactory.java b/java/org/apache/catalina/mbeans/MBeanFactory.java index fae8d30b6..43183b91f 100644 --- a/java/org/apache/catalina/mbeans/MBeanFactory.java +++ b/java/org/apache/catalina/mbeans/MBeanFactory.java @@ -548,18 +548,6 @@ public class MBeanFactory { false, false); } - /** - * Given a context path, get the config file name. - */ - private String getConfigFile(String path) { - String basename = null; - if (path.equals("")) { - basename = "ROOT"; - } else { - basename = path.substring(1).replace('/', '#'); - } - return (basename); - } /** * Create a new StandardContext. @@ -598,20 +586,20 @@ public class MBeanFactory { ":type=Deployer,host="+ pname.getKeyProperty("host")); if(mserver.isRegistered(deployer)) { - String contextPath = context.getPath(); + String contextName = context.getName(); mserver.invoke(deployer, "addServiced", - new Object [] {contextPath}, + new Object [] {contextName}, new String [] {"java.lang.String"}); String configPath = (String)mserver.getAttribute(deployer, "configBaseName"); - String baseName = getConfigFile(contextPath); + String baseName = context.getBaseName(); File configFile = new File(new File(configPath), baseName+".xml"); context.setConfigFile(configFile.toURI().toURL()); mserver.invoke(deployer, "manageApp", new Object[] {context}, new String[] {"org.apache.catalina.Context"}); mserver.invoke(deployer, "removeServiced", - new Object [] {contextPath}, + new Object [] {contextName}, new String [] {"java.lang.String"}); } else { log.warn("Deployer not found for "+pname.getKeyProperty("host")); diff --git a/java/org/apache/catalina/mbeans/MBeanUtils.java b/java/org/apache/catalina/mbeans/MBeanUtils.java index 66ee9d488..c14a32c42 100644 --- a/java/org/apache/catalina/mbeans/MBeanUtils.java +++ b/java/org/apache/catalina/mbeans/MBeanUtils.java @@ -495,12 +495,12 @@ public class MBeanUtils { ObjectName name = null; Host host = (Host)context.getParent(); - String path = context.getPath(); - if (path.length() < 1) - path = "/"; - // FIXME + String contextName = context.getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } name = new ObjectName(domain + ":j2eeType=WebModule,name=//" + - host.getName()+ path + + host.getName()+ contextName + ",J2EEApplication=none,J2EEServer=none"); return (name); @@ -528,12 +528,14 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=Environment" + ",resourcetype=Global,name=" + environment.getName()); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } + Host host = (Host) ((Context)container).getParent(); name = new ObjectName(domain + ":type=Environment" + - ",resourcetype=Context,path=" + path + + ",resourcetype=Context,context=" + contextName + ",host=" + host.getName() + ",name=" + environment.getName()); } @@ -603,12 +605,14 @@ public class MBeanUtils { ",resourcetype=Global" + ",name=" + quotedResourceLinkName); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } + Host host = (Host) ((Context)container).getParent(); name = new ObjectName(domain + ":type=ResourceLink" + - ",resourcetype=Context,path=" + path + + ",resourcetype=Context,context=" + contextName + ",host=" + host.getName() + ",name=" + quotedResourceLinkName); } @@ -703,13 +707,13 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=Loader,host=" + container.getName()); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) { - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; } Host host = (Host) container.getParent(); - name = new ObjectName(domain + ":type=Loader,path=" + path + - ",host=" + host.getName()); + name = new ObjectName(domain + ":type=Loader,context=" + + contextName + ",host=" + host.getName()); } return (name); @@ -739,13 +743,13 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=Manager,host=" + container.getName()); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) { - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; } Host host = (Host) container.getParent(); - name = new ObjectName(domain + ":type=Manager,path=" + path + - ",host=" + host.getName()); + name = new ObjectName(domain + ":type=Manager,context=" + + contextName + ",host=" + host.getName()); } return (name); @@ -772,12 +776,13 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=NamingResources" + ",resourcetype=Global"); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } Host host = (Host) ((Context)container).getParent(); name = new ObjectName(domain + ":type=NamingResources" + - ",resourcetype=Context,path=" + path + + ",resourcetype=Context,context=" + contextName + ",host=" + host.getName()); } @@ -828,13 +833,13 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=Realm,host=" + container.getName()); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) { - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; } Host host = (Host) container.getParent(); - name = new ObjectName(domain + ":type=Realm,path=" + path + - ",host=" + host.getName()); + name = new ObjectName(domain + ":type=Realm,context=" + + contextName + ",host=" + host.getName()); } return (name); @@ -999,12 +1004,12 @@ public class MBeanUtils { name = new ObjectName(domain + ":type=Valve,name=" + className + ext + local ); } else if (container instanceof Context) { - String path = ((Context)container).getPath(); - if (path.length() < 1) { - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; } Host host = (Host) container.getParent(); - String local=",path=" + path + ",host=" + + String local=",context=" + contextName + ",host=" + host.getName(); int seq = getSeq(local); String ext=""; @@ -1694,12 +1699,12 @@ public class MBeanUtils { keyProperties.append(",servlet="); keyProperties.append(c.getName()); } else if (c instanceof Context) { - String path = ((Context)c).getPath(); - if (path.length() < 1) { - path = "/"; + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; } - keyProperties.append(",path="); - keyProperties.append(path); + keyProperties.append(",context="); + keyProperties.append(contextName); } else if (c instanceof Host) { keyProperties.append(",host="); keyProperties.append(c.getName()); diff --git a/java/org/apache/catalina/realm/JAASRealm.java b/java/org/apache/catalina/realm/JAASRealm.java index c676f943d..2d52be54b 100644 --- a/java/org/apache/catalina/realm/JAASRealm.java +++ b/java/org/apache/catalina/realm/JAASRealm.java @@ -218,7 +218,10 @@ public class JAASRealm super.setContainer(container); if( appName==null ) { - String name=container.getName(); + String name = container.getName(); + if (!name.startsWith("/")) { + name = "/" + name; + } name = makeLegalForJAAS(name); appName=name; diff --git a/java/org/apache/catalina/session/JDBCStore.java b/java/org/apache/catalina/session/JDBCStore.java index 995c1dfcc..8a8943e15 100644 --- a/java/org/apache/catalina/session/JDBCStore.java +++ b/java/org/apache/catalina/session/JDBCStore.java @@ -188,6 +188,9 @@ public class JDBCStore extends StoreBase { if (name == null) { Container container = manager.getContainer(); String contextName = container.getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } String hostName = ""; String engineName = ""; diff --git a/java/org/apache/catalina/session/ManagerBase.java b/java/org/apache/catalina/session/ManagerBase.java index 053abca45..ffecc84dd 100644 --- a/java/org/apache/catalina/session/ManagerBase.java +++ b/java/org/apache/catalina/session/ManagerBase.java @@ -1355,14 +1355,14 @@ public abstract class ManagerBase extends LifecycleMBeanBase StringBuilder name = new StringBuilder("type=Manager"); if (container instanceof Context) { - name.append(",path="); + name.append(",context="); Context context = (Context) container; - String path = context.getPath(); - if (path.equals("")) { - path = "/"; - } - name.append(path); + String contextName = ((Context)container).getName(); + if (!contextName.startsWith("/")) { + contextName = "/" + contextName; + } + name.append(contextName); name.append(",host="); name.append(context.getParent().getName()); diff --git a/java/org/apache/catalina/startup/ContextConfig.java b/java/org/apache/catalina/startup/ContextConfig.java index 1872a3499..32d375148 100644 --- a/java/org/apache/catalina/startup/ContextConfig.java +++ b/java/org/apache/catalina/startup/ContextConfig.java @@ -73,6 +73,7 @@ import org.apache.catalina.deploy.LoginConfig; import org.apache.catalina.deploy.SecurityConstraint; import org.apache.catalina.deploy.ServletDef; import org.apache.catalina.deploy.WebXml; +import org.apache.catalina.util.ContextName; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.naming.resources.DirContextURLConnection; @@ -683,15 +684,8 @@ public class ContextConfig if (path == null) { return; } - if (path.equals("")) { - docBase = "ROOT"; - } else { - if (path.startsWith("/")) { - docBase = path.substring(1).replace('/', '#'); - } else { - docBase = path.replace('/', '#'); - } - } + ContextName cn = new ContextName(path, context.getWebappVersion()); + docBase = cn.getBaseName(); } File file = new File(docBase); @@ -703,13 +697,10 @@ public class ContextConfig file = new File(docBase); String origDocBase = docBase; - String pathName = context.getPath(); - if (pathName.equals("")) { - pathName = "ROOT"; - } else { - // Context path must start with '/' - pathName = pathName.substring(1).replace('/', '#'); - } + ContextName cn = new ContextName(context.getPath(), + context.getWebappVersion()); + String pathName = cn.getBaseName(); + if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory() && unpackWARs) { URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() + "!/"); docBase = ExpandWar.expand(host, war, pathName); @@ -788,18 +779,12 @@ public class ContextConfig if (path == null) { return; } - if (path.equals("")) { - docBase = "ROOT"; - } else { - if (path.startsWith("/")) { - docBase = path.substring(1); - } else { - docBase = path; - } - } + ContextName cn = new ContextName(path, context.getWebappVersion()); + docBase = cn.getBaseName(); File file = null; if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war")) { + // TODO - This is never executed. Bug or code to delete? file = new File(System.getProperty("java.io.tmpdir"), deploymentCount++ + "-" + docBase + ".war"); } else { @@ -808,7 +793,7 @@ public class ContextConfig } if (log.isDebugEnabled()) - log.debug("Anti locking context[" + context.getPath() + log.debug("Anti locking context[" + context.getName() + "] setting docBase to " + file); // Cleanup just in case an old deployment is lying around @@ -844,7 +829,7 @@ public class ContextConfig fixDocBase(); } catch (IOException e) { log.error(sm.getString( - "contextConfig.fixDocBase", context.getPath()), e); + "contextConfig.fixDocBase", context.getName()), e); } } @@ -1397,7 +1382,7 @@ public class ContextConfig } catch (IOException ioe) { log.error(sm.getString( "contextConfig.servletContainerInitializerFail", url, - context.getPath())); + context.getName())); return false; } finally { if (is != null) { @@ -1514,7 +1499,7 @@ public class ContextConfig } } catch (IOException ioe) { log.error(sm.getString("contextConfig.resourceJarFail", url, - context.getPath())); + context.getName())); } finally { if (jarFile != null) { try { diff --git a/java/org/apache/catalina/startup/Embedded.java b/java/org/apache/catalina/startup/Embedded.java index 6cbd92fcd..e957e9f21 100644 --- a/java/org/apache/catalina/startup/Embedded.java +++ b/java/org/apache/catalina/startup/Embedded.java @@ -595,7 +595,7 @@ public class Embedded extends StandardService { public synchronized void removeContext(Context context) { if( log.isDebugEnabled() ) - log.debug("Removing context[" + context.getPath() + "]"); + log.debug("Removing context[" + context.getName() + "]"); // Is this Context actually among those that are defined? boolean found = false; diff --git a/java/org/apache/catalina/startup/HostConfig.java b/java/org/apache/catalina/startup/HostConfig.java index 0a986a42d..40a4a49b8 100644 --- a/java/org/apache/catalina/startup/HostConfig.java +++ b/java/org/apache/catalina/startup/HostConfig.java @@ -48,6 +48,7 @@ import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; import org.apache.catalina.core.ContainerBase; import org.apache.catalina.core.StandardHost; +import org.apache.catalina.util.ContextName; import org.apache.catalina.util.IOTools; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -450,46 +451,6 @@ public class HostConfig return configBase().getAbsolutePath(); } - /** - * Given a context path, get the base name for WARs, directories and - * context.xml files. - */ - protected String getBaseName(String path) { - String basename = null; - if (path.equals("")) { - basename = "ROOT"; - } else { - basename = path.substring(1).replace('/', '#'); - } - return (basename); - } - - - /** - * Given the name of a WAR file, directory of context.xml file, determine - * the context path. - */ - protected String getContextPath(String filename, boolean stripExtension) { - String contextPath; - - // Remove any file extension - if (stripExtension) { - contextPath = filename.substring(0, filename.length() -4); - } else { - contextPath = filename; - } - - if ("ROOT".equals(contextPath)) { - // Handle special case of ROOT - contextPath = ""; - } else { - // Prepend / and otherwise # -> / replacement - contextPath = '/' + contextPath.replace('#', '/'); - } - - return contextPath; - } - /** * Deploy applications for any directories or WAR files that are found @@ -517,20 +478,21 @@ public class HostConfig File appBase = appBase(); File configBase = configBase(); - String baseName = getBaseName(name); + ContextName cn = new ContextName(name); + String baseName = cn.getBaseName(); // Deploy XML descriptors from configBase File xml = new File(configBase, baseName + ".xml"); if (xml.exists()) - deployDescriptor(name, xml, baseName + ".xml"); + deployDescriptor(cn, xml, baseName + ".xml"); // Deploy WARs, and loop if additional descriptors are found File war = new File(appBase, baseName + ".war"); if (war.exists()) - deployWAR(name, war, baseName + ".war"); + deployWAR(cn, war, baseName + ".war"); // Deploy expanded folders File dir = new File(appBase, baseName); if (dir.exists()) - deployDirectory(name, dir, baseName); + deployDirectory(cn, dir, baseName); } @@ -547,14 +509,15 @@ public class HostConfig File contextXml = new File(configBase, files[i]); if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".xml")) { - String contextPath = getContextPath(files[i], true); + ContextName cn = new ContextName(files[i]); + String name = cn.getName(); - if (isServiced(contextPath)) + if (isServiced(name)) continue; String file = files[i]; - deployDescriptor(contextPath, contextXml, file); + deployDescriptor(cn, contextXml, file); } } } @@ -565,12 +528,12 @@ public class HostConfig * @param contextXml * @param file */ - protected void deployDescriptor(String contextPath, File contextXml, String file) { - if (deploymentExists(contextPath)) { + protected void deployDescriptor(ContextName cn, File contextXml, String file) { + if (deploymentExists(cn.getName())) { return; } - DeployedApplication deployedApp = new DeployedApplication(contextPath); + DeployedApplication deployedApp = new DeployedApplication(cn.getName()); // Assume this is a configuration descriptor and deploy it if(log.isInfoEnabled()) { @@ -599,7 +562,9 @@ public class HostConfig context.addLifecycleListener(listener); context.setConfigFile(contextXml.toURI().toURL()); - context.setPath(contextPath); + context.setName(cn.getName()); + context.setPath(cn.getPath()); + context.setWebappVersion(cn.getVersion()); // Add the associated docBase to the redeployed list if it's a WAR boolean isExternalWar = false; boolean isExternal = false; @@ -628,19 +593,9 @@ public class HostConfig } host.addChild(context); // Get paths for WAR and expanded WAR in appBase - String name = null; - String path = context.getPath(); - if (path.equals("")) { - name = "ROOT"; - } else { - if (path.startsWith("/")) { - name = path.substring(1); - } else { - name = path; - } - } + // default to appBase dir + name - File expandedDocBase = new File(appBase(), name); + File expandedDocBase = new File(appBase(), cn.getBaseName()); if (context.getDocBase() != null) { // first assume docBase is absolute expandedDocBase = new File(context.getDocBase()); @@ -687,7 +642,7 @@ public class HostConfig } if (context != null && host.findChild(context.getName()) != null) { - deployed.put(contextPath, deployedApp); + deployed.put(context.getName(), deployedApp); } } @@ -710,22 +665,22 @@ public class HostConfig if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".war") && dir.isFile() && !invalidWars.contains(files[i]) ) { - String contextPath = getContextPath(files[i], true); + ContextName cn = new ContextName(files[i]); // Check for WARs with /../ /./ or similar sequences in the name - if (!validateContextPath(appBase, contextPath)) { + if (!validateContextPath(appBase, cn.getBaseName())) { log.error(sm.getString( "hostConfig.illegalWarName", files[i])); invalidWars.add(files[i]); continue; } - if (isServiced(contextPath)) + if (isServiced(cn.getName())) continue; String file = files[i]; - deployWAR(contextPath, dir, file); + deployWAR(cn, dir, file); } } } @@ -772,9 +727,9 @@ public class HostConfig * @param war * @param file */ - protected void deployWAR(String contextPath, File war, String file) { + protected void deployWAR(ContextName cn, File war, String file) { - if (deploymentExists(contextPath)) + if (deploymentExists(cn.getName())) return; // Checking for a nested /META-INF/context.xml @@ -844,7 +799,7 @@ public class HostConfig } } - DeployedApplication deployedApp = new DeployedApplication(contextPath); + DeployedApplication deployedApp = new DeployedApplication(cn.getName()); // Deploy the application in this WAR file if(log.isInfoEnabled()) @@ -929,14 +884,15 @@ public class HostConfig (LifecycleListener) clazz.newInstance(); context.addLifecycleListener(listener); - context.setPath(contextPath); + context.setName(cn.getName()); + context.setPath(cn.getPath()); + context.setWebappVersion(cn.getVersion()); context.setDocBase(file); host.addChild(context); // If we're unpacking WARs, the docBase will be mutated after // starting the context if (unpackWARs && (context.getDocBase() != null)) { - String name = getBaseName(context.getPath()); - File docBase = new File(appBase(), name); + File docBase = new File(appBase(), cn.getBaseName()); deployedApp.redeployResources.put(docBase.getAbsolutePath(), new Long(docBase.lastModified())); addWatchedResources(deployedApp, docBase.getAbsolutePath(), @@ -949,7 +905,7 @@ public class HostConfig log.error(sm.getString("hostConfig.deployWar.error", file), t); } - deployed.put(contextPath, deployedApp); + deployed.put(cn.getName(), deployedApp); } @@ -969,12 +925,12 @@ public class HostConfig continue; File dir = new File(appBase, files[i]); if (dir.isDirectory()) { - String contextPath = getContextPath(files[i], false); + ContextName cn = new ContextName(files[i]); - if (isServiced(contextPath)) + if (isServiced(cn.getName())) continue; - deployDirectory(contextPath, dir, files[i]); + deployDirectory(cn, dir, files[i]); } } } @@ -985,12 +941,13 @@ public class HostConfig * @param dir * @param file */ - protected void deployDirectory(String contextPath, File dir, String file) { - DeployedApplication deployedApp = new DeployedApplication(contextPath); + protected void deployDirectory(ContextName cn, File dir, String file) { - if (deploymentExists(contextPath)) + if (deploymentExists(cn.getName())) return; + DeployedApplication deployedApp = new DeployedApplication(cn.getName()); + // Deploy the application in this directory if( log.isInfoEnabled() ) log.info(sm.getString("hostConfig.deployDir", file)); @@ -1046,7 +1003,9 @@ public class HostConfig (LifecycleListener) clazz.newInstance(); context.addLifecycleListener(listener); - context.setPath(contextPath); + context.setName(cn.getName()); + context.setPath(cn.getPath()); + context.setWebappVersion(cn.getVersion()); context.setDocBase(file); host.addChild(context); deployedApp.redeployResources.put(dir.getAbsolutePath(), @@ -1061,18 +1020,18 @@ public class HostConfig log.error(sm.getString("hostConfig.deployDir.error", file), t); } - deployed.put(contextPath, deployedApp); + deployed.put(cn.getName(), deployedApp); } /** * Check if a webapp is already deployed in this host. * - * @param contextPath of the context which will be checked + * @param contextName of the context which will be checked */ - protected boolean deploymentExists(String contextPath) { - return (deployed.containsKey(contextPath) || - (host.findChild(contextPath) != null)); + protected boolean deploymentExists(String contextName) { + return (deployed.containsKey(contextName) || + (host.findChild(contextName) != null)); } @@ -1384,12 +1343,12 @@ public class HostConfig */ public void manageApp(Context context) { - String contextPath = context.getPath(); + String contextName = context.getName(); - if (deployed.containsKey(contextPath)) + if (deployed.containsKey(contextName)) return; - DeployedApplication deployedApp = new DeployedApplication(contextPath); + DeployedApplication deployedApp = new DeployedApplication(contextName); // Add the associated docBase to the redeployed list if it's a WAR boolean isWar = false; @@ -1408,38 +1367,24 @@ public class HostConfig // Add the eventual unpacked WAR and all the resources which will be // watched inside it if (isWar && unpackWARs) { - String name = null; - String path = context.getPath(); - if (path.equals("")) { - name = "ROOT"; - } else { - if (path.startsWith("/")) { - name = path.substring(1); - } else { - name = path; - } - } - File docBase = new File(name); - if (!docBase.isAbsolute()) { - docBase = new File(appBase(), name); - } + File docBase = new File(appBase(), context.getBaseName()); deployedApp.redeployResources.put(docBase.getAbsolutePath(), new Long(docBase.lastModified())); addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); } else { addWatchedResources(deployedApp, null, context); } - deployed.put(contextPath, deployedApp); + deployed.put(contextName, deployedApp); } /** * Remove a webapp from our control. * Entry point for the admin webapp, and other JMX Context controllers. */ - public void unmanageApp(String contextPath) { - if(isServiced(contextPath)) { - deployed.remove(contextPath); - host.removeChild(host.findChild(contextPath)); + public void unmanageApp(String contextName) { + if(isServiced(contextName)) { + deployed.remove(contextName); + host.removeChild(host.findChild(contextName)); } } diff --git a/java/org/apache/catalina/startup/LocalStrings.properties b/java/org/apache/catalina/startup/LocalStrings.properties index 695cc7edf..8898e1d58 100644 --- a/java/org/apache/catalina/startup/LocalStrings.properties +++ b/java/org/apache/catalina/startup/LocalStrings.properties @@ -48,10 +48,11 @@ contextConfig.jar=Unable to process resource [{0}] for annotations contextConfig.jndiUrl=Unable to process JNDI URL [{0}] for annotations contextConfig.jndiUrlNotDirContextConn=The connection created for URL [{0}] was not a DirContextURLConnection contextConfig.missingRealm=No Realm has been configured to authenticate against -contextConfig.resourceJarFail=Failed to processes JAR found at URL [{0}] for static resources to be included in context with path [{0}] +contextConfig.resourceJarFail=Failed to processes JAR found at URL [{0}] for static resources to be included in context with name [{0}] contextConfig.role.auth=WARNING: Security role name {0} used in an without being defined in a contextConfig.role.link=WARNING: Security role name {0} used in a without being defined in a contextConfig.role.runas=WARNING: Security role name {0} used in a without being defined in a +contextConfig.servletContainerInitializerFail=Failed to process JAR found at URL [{0}] for ServletContainerInitializers for context with name [{1}] contextConfig.start=ContextConfig: Processing START contextConfig.stop=ContextConfig: Processing STOP contextConfig.unavailable=Marking this application unavailable due to previous error(s) @@ -103,7 +104,7 @@ tldConfig.addListeners=Adding {0} listeners from TLD files tldConfig.cce=Lifecycle event data object {0} is not a Context tldConfig.dirFail=Failed to process directory [{0}] for TLD files tldConfig.dirScan=Scanning for TLD files in directory [{0}] -tldConfig.execute=Error processing TLD files for context path {0} +tldConfig.execute=Error processing TLD files for context with name [{0}] tldConfig.jarFail=Failed to process JAR [{0}] for TLD files tldConfig.webinfFail=Failed to process TLD found at [{0}] tldConfig.webinfScan=Scanning WEB-INF for TLD files in [{0}] diff --git a/java/org/apache/catalina/startup/TldConfig.java b/java/org/apache/catalina/startup/TldConfig.java index 064fbd4c1..4f2f9e337 100644 --- a/java/org/apache/catalina/startup/TldConfig.java +++ b/java/org/apache/catalina/startup/TldConfig.java @@ -568,6 +568,7 @@ public final class TldConfig implements LifecycleListener { } } + @Override public void lifecycleEvent(LifecycleEvent event) { // Identify the context we are associated with try { @@ -584,7 +585,7 @@ public final class TldConfig implements LifecycleListener { execute(); } catch (Exception e) { log.error(sm.getString( - "tldConfig.execute", context.getPath()), e); + "tldConfig.execute", context.getName()), e); } } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { taglibUris.clear(); diff --git a/java/org/apache/catalina/util/ContextName.java b/java/org/apache/catalina/util/ContextName.java new file mode 100644 index 000000000..7a1aa3eaa --- /dev/null +++ b/java/org/apache/catalina/util/ContextName.java @@ -0,0 +1,132 @@ +/* + * 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.catalina.util; + +import java.util.Locale; + +/** + * Utility class to manage context names so there is one place where the + * conversions between baseName, path and version take place. + */ +public final class ContextName { + private final String ROOT_NAME = "ROOT"; + private final String VERSION_MARKER = "##"; + private final String FWD_SLASH_REPLACEMENT = "#"; + + private final String baseName; + private final String path; + private final String version; + private final String name; + + /** + * Creates an instance from a base name, directory name, WAR name or + * context.xml name. + * + * @param name The name to use as the basis for this object + */ + public ContextName(String name) { + // Remove file extension, if any + if (name.toLowerCase(Locale.ENGLISH).endsWith(".war") || + name.toLowerCase(Locale.ENGLISH).endsWith(".xml")) { + baseName = name.substring(0, name.length() -4); + } else { + baseName = name; + } + + // Extract version number + int versionIndex = baseName.indexOf(VERSION_MARKER); + if (versionIndex > -1) { + version = baseName.substring(versionIndex + 2); + } else { + version = ""; + } + + if (ROOT_NAME.equals(baseName)) { + path = ""; + } else if (versionIndex > -1) { + path = "/" + baseName.substring(0, versionIndex).replaceAll( + FWD_SLASH_REPLACEMENT, "/"); + } else { + path = "/" + baseName.replaceAll(FWD_SLASH_REPLACEMENT, "/"); + } + + if (versionIndex > -1) { + this.name = path + VERSION_MARKER + version; + } else { + this.name = path; + } + } + + /** + * Construct and instance from a path and version. + * + * @param path Context path to use + * @param version Context version to use + */ + public ContextName(String path, String version) { + // Path should never be null or '/' + if (path == null || "/".equals(path)) { + this.path = ""; + } else { + this.path = path; + } + + // Version should never be null + if (version == null) { + this.version = ""; + } else { + this.version = version; + } + + // Name is path + version + if ("".equals(this.version)) { + name = this.path; + } else { + name = this.path + VERSION_MARKER + this.version; + } + + // Base name is converted path + version + StringBuilder tmp = new StringBuilder(); + if ("".equals(path)) { + tmp.append(ROOT_NAME); + } else { + tmp.append(this.path.substring(1).replaceAll("/", + FWD_SLASH_REPLACEMENT)); + } + if (this.version.length() > 0) { + tmp.append(VERSION_MARKER); + tmp.append(this.version); + } + this.baseName = tmp.toString(); + } + + public String getBaseName() { + return baseName; + } + + public String getPath() { + return path; + } + + public String getVersion() { + return version; + } + + public String getName() { + return name; + } +} diff --git a/java/org/apache/catalina/util/ExtensionValidator.java b/java/org/apache/catalina/util/ExtensionValidator.java index 68546f728..c8a77bfdd 100644 --- a/java/org/apache/catalina/util/ExtensionValidator.java +++ b/java/org/apache/catalina/util/ExtensionValidator.java @@ -137,7 +137,7 @@ public final class ExtensionValidator { Context context) throws IOException { - String appName = context.getPath(); + String appName = context.getName(); ArrayList appManifestResources = new ArrayList(); // If the application context is null it does not exist and -- 2.11.0