Author: markt
Date: Thu Apr 22 08:13:08 2010
New Revision: 936646

URL: http://svn.apache.org/viewvc?rev=936646&view=rev
Log:
Add support for loading static resources from /META-INF/resources inside JARs 
bundled with a web application

Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
    tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
    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/WARDirContext.java

Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Thu Apr 22 08:13:08 2010
@@ -1183,5 +1183,11 @@ public interface Context extends Contain
      */
     public JspConfigDescriptor getJspConfigDescriptor();
 
+    /**
+     * Add a URL for a JAR that contains static resources in a
+     * META-INF/resources directory that should be included in the static
+     * resources for this context.
+     */
+    public void addResourceJarUrl(URL url);
 }
 

Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Thu Apr 
22 08:13:08 2010
@@ -115,6 +115,7 @@ standardContext.loginConfig.loginPage=Fo
 standardContext.loginConfig.loginWarning=WARNING: Form login page {0} must 
start with a ''/'' in Servlet 2.4
 standardContext.loginConfig.required=LoginConfig cannot be null
 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.notFound=The requested resource ({0}) is not available.
 standardContext.notReloadable=Reloading is disabled on this Context
 standardContext.notStarted=Context has not yet been started

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=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Apr 22 
08:13:08 2010
@@ -962,6 +962,21 @@ public class StandardContext
 
 
     /**
+     * Add a URL for a JAR that contains static resources in a
+     * META-INF/resources directory that should be included in the static
+     * resources for this context.
+     */
+    public void addResourceJarUrl(URL url) {
+        if (webappResources instanceof BaseDirContext) {
+            ((BaseDirContext) webappResources).addResourcesJar(url);
+        } else {
+            log.error(sm.getString("standardContext.noResourceJar", url,
+                    getPath()));
+        }
+    }
+    
+    
+    /**
      * 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
@@ -2122,11 +2137,13 @@ public class StandardContext
             return;
 
         if (resources instanceof BaseDirContext) {
+            // Caching
             ((BaseDirContext) resources).setCached(isCachingAllowed());
             ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
             ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
             ((BaseDirContext) resources).setCacheObjectMaxSize(
                     getCacheObjectMaxSize());
+            // Alias support
             ((BaseDirContext) resources).setAliases(getAliases());
         }
         if (resources instanceof FileDirContext) {

Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Thu Apr 22 
08:13:08 2010
@@ -38,6 +38,7 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
 
 import javax.servlet.ServletContext;
 
@@ -1237,6 +1238,8 @@ public class ContextConfig
             if (context.getLogEffectiveWebXml()) {
                 log.info("web.xml:\n" + mergedWebXml);
             }
+            
+            processResourceJARs(orderedFragments);
         } else {
             // Apply unmerged web.xml to Context
             webXml.configureContext(context);
@@ -1245,6 +1248,40 @@ public class ContextConfig
 
     
     /**
+     * Scan JARs that contain web-fragment.xml files that will be used to
+     * configure this application to see if they also contain static resources.
+     * If static resources are found, add them to the context. Resources are
+     * added in web-fragment.xml priority order.
+     */
+    protected void processResourceJARs(Set<WebXml> fragments) {
+        for (WebXml fragment : fragments) {
+            URL jarUrl = fragment.getURL();
+            JarFile jarFile = null;
+            try {
+                JarURLConnection conn =
+                    (JarURLConnection) jarUrl.openConnection();
+                jarFile = conn.getJarFile();   
+                ZipEntry entry = jarFile.getEntry("META-INF/resources/");
+                if (entry != null) {
+                    context.addResourceJarUrl(jarUrl);
+                }
+            } catch (IOException ioe) {
+                log.error(sm.getString("contextConfig.resourceJarFail", jarUrl,
+                        context.getPath()));
+            } finally {
+                if (jarFile != null) {
+                    try {
+                        jarFile.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    /**
      * Identify the default web.xml to be used and obtain an input source for
      * it.
      */

Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Thu 
Apr 22 08:13:08 2010
@@ -46,6 +46,7 @@ contextConfig.jar=Unable to process reso
 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.role.auth=WARNING: Security role name {0} used in an 
<auth-constraint> without being defined in a <security-role>
 contextConfig.role.link=WARNING: Security role name {0} used in a <role-link> 
without being defined in a <security-role>
 contextConfig.role.runas=WARNING: Security role name {0} used in a <run-as> 
without being defined in a <security-role>

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=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java (original)
+++ tomcat/trunk/java/org/apache/naming/resources/BaseDirContext.java Thu Apr 
22 08:13:08 2010
@@ -19,11 +19,18 @@
 package org.apache.naming.resources;
 
 import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
 
 import javax.naming.Binding;
 import javax.naming.Context;
@@ -131,10 +138,39 @@ public abstract class BaseDirContext imp
         new HashMap<String,BaseDirContext>();
 
 
+    /**
+     * Alternate / backup DirContexts for static resources. These will be
+     * searched in the order they are added if the requested resource cannot be
+     * found in the primary DirContext. 
+     */
+    protected List<DirContext> altDirContexts = new ArrayList<DirContext>();
+    
+    
     // ------------------------------------------------------------- Properties
 
 
     /**
+     * Add a resources JAR. The contents of /META-INF/resources/ will be used 
if
+     * a requested resource can not be found in the main context.
+     */
+    public void addResourcesJar(URL url) {
+        try {
+            JarURLConnection conn = (JarURLConnection) url.openConnection();
+            JarFile jarFile = conn.getJarFile();   
+            ZipEntry entry = jarFile.getEntry("/");
+            WARDirContext warDirContext = new WARDirContext(jarFile,
+                    new WARDirContext.Entry("/", entry));
+            warDirContext.loadEntries();
+            altDirContexts.add(warDirContext);
+        } catch (IOException ioe) {
+            // TODO: Log failure
+        } finally {
+            // TODO: Clean up
+        }
+    }
+    
+    
+    /**
      * Add an alias.
      */
     public void addAlias(String path, BaseDirContext dirContext) {
@@ -350,7 +386,25 @@ public abstract class BaseDirContext imp
                 return result.dirContext.doGetRealPath(result.aliasName);
             }
         }
-        return doGetRealPath(name);
+        
+        // Next do a standard getRealPath()
+        String path = doGetRealPath(name);
+
+        if (path != null)
+            return path;
+        
+        // Check the alternate locations
+        for (DirContext altDirContext : altDirContexts) {
+            if (altDirContext instanceof BaseDirContext){
+                path = ((BaseDirContext) altDirContext).getRealPath(
+                        "META-INF/resources/" + name);
+                if (path != null)
+                    return path;
+            }
+        }
+        
+        // Really not found
+        return null; 
     }
 
     // -------------------------------------------------------- Context Methods
@@ -380,13 +434,29 @@ public abstract class BaseDirContext imp
      * @exception NamingException if a naming exception is encountered
      */
     public final Object lookup(String name) throws NamingException {
+        // First check for aliases
         if (!aliases.isEmpty()) {
             AliasResult result = findAlias(name);
             if (result.dirContext != null) {
                 return result.dirContext.lookup(result.aliasName);
             }
         }
-        return doLookup(name);
+        
+        // Next do a standard lookup
+        Object obj = doLookup(name);
+
+        if (obj != null)
+            return obj;
+        
+        // Check the alternate locations
+        for (DirContext altDirContext : altDirContexts) {
+            obj = altDirContext.lookup("META-INF/resources/" + name);
+            if (obj != null)
+                return obj;
+        }
+        
+        // Really not found
+        throw new NamingException(sm.getString("resources.notFound", name));
     }
 
     /**
@@ -589,7 +659,31 @@ public abstract class BaseDirContext imp
                 return result.dirContext.listBindings(result.aliasName);
             }
         }
-        return doListBindings(name);
+        
+        // Next do a standard lookup
+        NamingEnumeration<Binding> bindings = doListBindings(name);
+
+        if (bindings != null)
+            return bindings;
+        
+        // Check the alternate locations
+        for (DirContext altDirContext : altDirContexts) {
+            if (altDirContext instanceof BaseDirContext)
+                bindings = ((BaseDirContext) altDirContext).doListBindings(
+                        "META-INF/resources/" + name);
+            else {
+                try {
+                    bindings = altDirContext.listBindings(name);
+                } catch (NamingException ne) {
+                    // Ignore
+                }
+            }
+            if (bindings != null)
+                return bindings;
+        }
+
+        // Really not found
+        throw new NamingException(sm.getString("resources.notFound", name));
     }
 
 
@@ -912,6 +1006,8 @@ public abstract class BaseDirContext imp
      */
     public final Attributes getAttributes(String name, String[] attrIds)
         throws NamingException {
+        
+        // First check for aliases
         if (!aliases.isEmpty()) {
             AliasResult result = findAlias(name);
             if (result.dirContext != null) {
@@ -919,7 +1015,31 @@ public abstract class BaseDirContext imp
                         result.aliasName, attrIds);
             }
         }
-        return doGetAttributes(name, attrIds);
+        
+        // Next do a standard lookup
+        Attributes attrs = doGetAttributes(name, attrIds);
+
+        if (attrs != null)
+            return attrs;
+        
+        // Check the alternate locations
+        for (DirContext altDirContext : altDirContexts) {
+            if (altDirContext instanceof BaseDirContext)
+                attrs = ((BaseDirContext) altDirContext).doGetAttributes(
+                        "META-INF/resources/" + name, attrIds);
+            else {
+                try {
+                    attrs = altDirContext.getAttributes(name, attrIds);
+                } catch (NamingException ne) {
+                    // Ignore
+                }
+            }
+            if (attrs != null)
+                return attrs;
+        }
+        
+        // Really not found
+        throw new NamingException(sm.getString("resources.notFound", name));
     }
 
     /**

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=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java (original)
+++ tomcat/trunk/java/org/apache/naming/resources/FileDirContext.java Thu Apr 
22 08:13:08 2010
@@ -202,8 +202,7 @@ public class FileDirContext extends Base
         File file = file(name);
 
         if (file == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
+            return null;
 
         if (file.isDirectory()) {
             FileDirContext tempContext = new FileDirContext(env);
@@ -326,9 +325,8 @@ public class FileDirContext extends Base
         File file = file(name);
 
         if (file == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
-
+            return null;
+        
         return new NamingContextBindingsEnumeration(list(file).iterator(),
                 this);
 
@@ -432,8 +430,7 @@ public class FileDirContext extends Base
         File file = file(name);
 
         if (file == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
+            return null;
 
         return new FileResourceAttributes(file);
 

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=936646&r1=936645&r2=936646&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java (original)
+++ tomcat/trunk/java/org/apache/naming/resources/WARDirContext.java Thu Apr 22 
08:13:08 2010
@@ -79,7 +79,8 @@ public class WARDirContext extends BaseD
 
 
     /**
-     * Constructor used for returning fake subcontexts.
+     * Constructor used for returning fake sub-contexts or for accessing
+     * META-INF/resources locations in bundled JAR files.
      */
     protected WARDirContext(ZipFile base, Entry entries) {
         this.base = base;
@@ -201,8 +202,8 @@ public class WARDirContext extends BaseD
             return this;
         Entry entry = treeLookup(name);
         if (entry == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
+            return null;
+            
         ZipEntry zipEntry = entry.getEntry();
         if (zipEntry.isDirectory())
             return new WARDirContext(base, entry);
@@ -320,8 +321,8 @@ public class WARDirContext extends BaseD
                     this);
         Entry entry = treeLookup(name);
         if (entry == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
+            return null;
+        
         return new NamingContextBindingsEnumeration(list(entry).iterator(),
                 this);
     }
@@ -441,8 +442,7 @@ public class WARDirContext extends BaseD
         else
             entry = treeLookup(name);
         if (entry == null)
-            throw new NamingException
-                (sm.getString("resources.notFound", name));
+            return null;
         
         ZipEntry zipEntry = entry.getEntry();
 
@@ -841,7 +841,7 @@ public class WARDirContext extends BaseD
     /**
      * Entries structure.
      */
-    protected class Entry implements Comparable<Object> {
+    protected static class Entry implements Comparable<Object> {
 
 
         // -------------------------------------------------------- Constructor



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to