Author: markt Date: Fri Jun 12 11:38:29 2009 New Revision: 784083 URL: http://svn.apache.org/viewvc?rev=784083&view=rev Log: Implement alias resources. Key features: - configured at the context level in the same way as the other resource related attributes - maps paths to directories or WAR files (single files not supported)
Implementation notes: - Correct results for getRealPath() required this to be pushed down to the BaseDirContext as the short-cuts previously used needed to take account of any aliases. This in turn meant an addition to the Context interface - Thanks to Tim F. The configuration format is all his idea Modified: tomcat/trunk/java/org/apache/catalina/Context.java tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java tomcat/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java tomcat/trunk/java/org/apache/naming/resources/LocalStrings.properties tomcat/trunk/java/org/apache/naming/resources/VirtualDirContext.java tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java tomcat/trunk/webapps/docs/config/context.xml Modified: tomcat/trunk/java/org/apache/catalina/Context.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Context.java (original) +++ tomcat/trunk/java/org/apache/catalina/Context.java Fri Jun 12 11:38:29 2009 @@ -1073,6 +1073,13 @@ */ public void setTldNamespaceAware(boolean tldNamespaceAware); + /** + * Return the real path for a given virtual path, if possible; otherwise + * return <code>null</code>. + * + * @param path The path to the desired resource + */ + public String getRealPath(String path); } Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java Fri Jun 12 11:38:29 2009 @@ -371,17 +371,7 @@ * @param path The path to the desired resource */ public String getRealPath(String path) { - - if (!context.isFilesystemBased()) - return null; - - if (path == null) { - return null; - } - - File file = new File(basePath, path); - return (file.getAbsolutePath()); - + return context.getRealPath(path); } Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Fri Jun 12 11:38:29 2009 @@ -670,6 +670,12 @@ /** + * List of resource aliases. + */ + protected String aliases = null; + + + /** * Non proxied resources. */ private DirContext webappResources = null; @@ -848,6 +854,25 @@ /** + * Return the list of resource aliases. + */ + public String getAliases() { + return this.aliases; + } + + + /** + * Set the current alias configuration. The list of aliases should be of the + * form "/aliasPath1=docBase1,/aliasPath2=docBase2" where aliasPathN must + * include a leading '/' and docBaseN must be an absolute path to either a + * .war file or a directory. + */ + public void setAliases(String aliases) { + this.aliases = aliases; + } + + + /** * Return the "follow standard delegation model" flag used to configure * our ClassLoader. */ @@ -1908,6 +1933,7 @@ ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize()); ((BaseDirContext) resources).setCacheObjectMaxSize( getCacheObjectMaxSize()); + ((BaseDirContext) resources).setAliases(getAliases()); } if (resources instanceof FileDirContext) { filesystemBased = true; @@ -3815,6 +3841,19 @@ } + /** + * Return the real path for a given virtual path, if possible; otherwise + * return <code>null</code>. + * + * @param path The path to the desired resource + */ + public String getRealPath(String path) { + if (webappResources instanceof BaseDirContext) { + return ((BaseDirContext) webappResources).getRealPath(path); + } + return null; + } + // --------------------------------------------------------- Public Methods Modified: tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml (original) +++ tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml Fri Jun 12 11:38:29 2009 @@ -45,6 +45,10 @@ description="Object that creates and destroys servlets, filters, and listeners. Include dependency injection and postConstruct/preDestory handling" type="org.apache.catalina.instanceManagement.InstanceManager" /> + <attribute name="aliases" + description="List of resource aliases" + type="java.lang.String" /> + <attribute name="antiJARLocking" description="Take care to not lock jar files" type="boolean" /> Modified: tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java (original) +++ tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java Fri Jun 12 11:38:29 2009 @@ -18,7 +18,12 @@ package org.apache.naming.resources; +import java.io.File; +import java.util.HashMap; import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; import javax.naming.Binding; import javax.naming.Context; @@ -119,10 +124,98 @@ protected int cacheObjectMaxSize = 512; // 512 K + /** + * Aliases allow content to be included from other locations. + */ + protected Map<String,BaseDirContext> aliases = + new HashMap<String,BaseDirContext>(); + + // ------------------------------------------------------------- Properties /** + * Add an alias. + */ + public void addAlias(String path, BaseDirContext dirContext) { + if (!path.startsWith("/")) { + throw new IllegalArgumentException( + sm.getString("resources.invalidAliasPath", path)); + } + aliases.put(path, dirContext); + } + + + /** + * Remove an alias. + */ + public void removeAlias(String path) { + if (!path.startsWith("/")) { + throw new IllegalArgumentException( + sm.getString("resources.invalidAliasPath", path)); + } + aliases.remove(path); + } + + + /** + * Get the current alias configuration in String form. If no aliases are + * configured, an empty string will be returned. + */ + public String getAliases() { + StringBuilder result = new StringBuilder(); + Iterator<Entry<String,BaseDirContext>> iter = + aliases.entrySet().iterator(); + boolean first = true; + while (iter.hasNext()) { + if (first) { + first = false; + } else { + result.append(','); + } + Entry<String,BaseDirContext> entry = iter.next(); + result.append(entry.getKey()); + result.append('='); + result.append(entry.getValue().getDocBase()); + } + return result.toString(); + } + + + /** + * Set the current alias configuration from a String. The String should be + * of the form "/aliasPath1=docBase1,/aliasPath2=docBase2" where aliasPathN + * must include a leading '/' and docBaseN must be an absolute path to + * either a .war file or a directory. Any call to this method will replace + * the current set of aliases. + */ + public void setAliases(String theAliases) { + // Overwrite whatever is currently set + aliases.clear(); + + if (theAliases == null || theAliases.length() == 0) + return; + + String[] kvps = theAliases.split(","); + for (String kvp : kvps) { + String[] kv = kvp.split("="); + if (kv.length != 2 || kv[0].length() == 0 || kv[1].length() == 0) + throw new IllegalArgumentException( + sm.getString("resources.invalidAliasMapping", kvp)); + + BaseDirContext context; + if (kv[1].endsWith(".war") && !(new File(kv[1]).isDirectory())) { + context = new WARDirContext(); + } else { + context = new FileDirContext(); + } + context.setDocBase(kv[1]); + addAlias(kv[0], context); + } + } + + + /** * Return the document root for this component. */ public String getDocBase() { @@ -235,6 +328,22 @@ // No action taken by the default implementation } + + /** + * Return the real path for a given virtual path, if possible; otherwise + * return <code>null</code>. + * + * @param path The path to the desired resource + */ + public String getRealPath(String name) { + if (!aliases.isEmpty()) { + AliasResult result = findAlias(name); + if (result.dirContext != null) { + return result.dirContext.doGetRealPath(result.aliasName); + } + } + return doGetRealPath(name); + } // -------------------------------------------------------- Context Methods @@ -262,9 +371,15 @@ * @return the object bound to name * @exception NamingException if a naming exception is encountered */ - public abstract Object lookup(String name) - throws NamingException; - + public final Object lookup(String name) throws NamingException { + if (!aliases.isEmpty()) { + AliasResult result = findAlias(name); + if (result.dirContext != null) { + return result.dirContext.lookup(result.aliasName); + } + } + return doLookup(name); + } /** * Binds a name to an object. All intermediate contexts and the target @@ -779,9 +894,17 @@ * indicates that none should be retrieved * @exception NamingException if a naming exception is encountered */ - public abstract Attributes getAttributes(String name, String[] attrIds) - throws NamingException; - + public final Attributes getAttributes(String name, String[] attrIds) + throws NamingException { + if (!aliases.isEmpty()) { + AliasResult result = findAlias(name); + if (result.dirContext != null) { + return result.dirContext.getAttributes( + result.aliasName, attrIds); + } + } + return doGetAttributes(name, attrIds); + } /** * Modifies the attributes associated with a named object. The order of @@ -1229,6 +1352,37 @@ // ------------------------------------------------------ Protected Methods + protected abstract Attributes doGetAttributes(String name, String[] attrIds) + throws NamingException; + + protected abstract Object doLookup(String name) throws NamingException; + protected abstract String doGetRealPath(String name); + + // -------------------------------------------------------- Private Methods + private AliasResult findAlias(String name) { + AliasResult result = new AliasResult(); + + String searchName = name; + + result.dirContext = aliases.get(searchName); + while (result.dirContext == null) { + int slash = searchName.lastIndexOf('/'); + if (slash < 0) + break; + searchName = searchName.substring(0, slash); + result.dirContext = aliases.get(searchName); + } + + if (result.dirContext != null) + result.aliasName = name.substring(searchName.length()); + + return result; + } + + private static class AliasResult { + BaseDirContext dirContext; + String aliasName; + } } Modified: tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java (original) +++ tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java Fri Jun 12 11:38:29 2009 @@ -193,6 +193,17 @@ } + /** + * Return the real path for a given virtual path, if possible; otherwise + * return <code>null</code>. + * + * @param path The path to the desired resource + */ + protected String doGetRealPath(String path) { + File file = new File(getDocBase(), path); + return file.getAbsolutePath(); + } + // -------------------------------------------------------- Context Methods @@ -203,7 +214,7 @@ * @return the object bound to name * @exception NamingException if a naming exception is encountered */ - public Object lookup(String name) + protected Object doLookup(String name) throws NamingException { Object result = null; File file = file(name); @@ -425,7 +436,7 @@ * indicates that none should be retrieved * @exception NamingException if a naming exception is encountered */ - public Attributes getAttributes(String name, String[] attrIds) + protected Attributes doGetAttributes(String name, String[] attrIds) throws NamingException { // Building attribute list Modified: tomcat/trunk/java/org/apache/naming/resources/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/resources/LocalStrings.properties?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/resources/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/naming/resources/LocalStrings.properties Fri Jun 12 11:38:29 2009 @@ -28,6 +28,8 @@ resources.alreadyBound=Name {0} is already bound in this Context resources.bindFailed=Bind failed: {0} resources.unbindFailed=Unbind failed: {0} +resources.invalidAliasPath=The alias path ''{0}'' must start with ''/'' +resources.invalidAliasMapping=The alias mapping ''{0}'' is not valid standardResources.alreadyStarted=Resources has already been started standardResources.directory=File base {0} is not a directory standardResources.exists=File base {0} does not exist Modified: tomcat/trunk/java/org/apache/naming/resources/VirtualDirContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/resources/VirtualDirContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/resources/VirtualDirContext.java (original) +++ tomcat/trunk/java/org/apache/naming/resources/VirtualDirContext.java Fri Jun 12 11:38:29 2009 @@ -160,7 +160,7 @@ } @Override - public Object lookup(String name) throws NamingException { + protected Object doLookup(String name) throws NamingException { // handle "virtual" tlds if (name.startsWith("/WEB-INF/") && name.endsWith(".tld")) { Modified: tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java (original) +++ tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java Fri Jun 12 11:38:29 2009 @@ -167,6 +167,16 @@ } + /** + * Return the real path for a given virtual path, if possible; otherwise + * return <code>null</code>. + * + * @param path The path to the desired resource + */ + protected String doGetRealPath(String path) { + return null; + } + // -------------------------------------------------------- Context Methods @@ -178,7 +188,7 @@ * @return the object bound to name * @exception NamingException if a naming exception is encountered */ - public Object lookup(String name) + protected Object doLookup(String name) throws NamingException { return lookup(new CompositeName(name)); } @@ -423,7 +433,7 @@ * indicates that none should be retrieved * @exception NamingException if a naming exception is encountered */ - public Attributes getAttributes(String name, String[] attrIds) + protected Attributes doGetAttributes(String name, String[] attrIds) throws NamingException { return getAttributes(new CompositeName(name), attrIds); } Modified: tomcat/trunk/webapps/docs/config/context.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=784083&r1=784082&r2=784083&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/context.xml (original) +++ tomcat/trunk/webapps/docs/config/context.xml Fri Jun 12 11:38:29 2009 @@ -251,6 +251,16 @@ <attributes> + <attribute name="alises" required="false"> + <p>This attribute provides a list of external locations from which to + load resources for this context. These external locations will not be + emptied if the context is un-deployed. The list of aliases should be of + the form <code>"/aliasPath1=docBase1,/aliasPath2=docBase2"</code> where + <code>aliasPathN</code> must include a leading '/' and + <code>docBaseN</code> must be an absolute path to either a .war file or + a directory.</p> + </attribute> + <attribute name="allowLinking" required="false"> <p>If the value of this flag is <code>true</code>, symlinks will be allowed inside the web application, pointing to resources outside the --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org