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

Reply via email to