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: [email protected]
For additional commands, e-mail: [email protected]