private String webappVersion = "";
+ private boolean addWebinfClassesResources = false;
+
// ----------------------------------------------------- Context Properties
+ public void setAddWebinfClassesResources(
+ boolean addWebinfClassesResources) {
+ this.addWebinfClassesResources = addWebinfClassesResources;
+ }
+
+
+ public boolean getAddWebinfClassesResources() {
+ return addWebinfClassesResources;
+ }
+
+
@Override
public void setWebappVersion(String webappVersion) {
if (null == webappVersion) {
((BaseDirContext) webappResources).allocate();
// Alias support
((BaseDirContext) webappResources).setAliases(getAliases());
+
+ if (effectiveMajorVersion >=3 && addWebinfClassesResources) {
+ try {
+ DirContext webInfCtx =
+ (DirContext) webappResources.lookup(
+ "/WEB-INF/classes");
+ // Do the lookup to make sure it exists
+ webInfCtx.lookup("META-INF/resources");
+ ((BaseDirContext) webappResources).addAltDirContext(
+ webInfCtx);
+ } catch (NamingException e) {
+ // Doesn't exist - ignore and carry on
+ }
+ }
}
// Register the cache in JMX
if (isCachingAllowed()) {
}
}
processResourceJARs(resourceJars);
+ // See also StandardContext.resourcesStart() for
+ // WEB-INF/classes/META-INF/resources configuration
}
// Only look for ServletContainerInitializer if metadata is not
}
}
-
+
+ /**
+ * Add an alternative DirContext (must contain META-INF/resources) directly.
+ */
+ public void addAltDirContext(DirContext altDirContext) {
+ altDirContexts.add(altDirContext);
+ }
+
+
/**
* Add an alias.
*/
"<p>resourceD.jsp in resources.jar</p>");
assertPageContains("/test/folder/resourceE.jsp",
"<p>resourceE.jsp in the web application</p>");
+ assertPageContains("/test/resourceG.jsp",
+ "<p>resourceG.jsp in WEB-INF/classes</p>", 404);
+ }
+
+ public void testResourcesWebInfClasses() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ // app dir is relative to server home
+ File appDir = new File("test/webapp-3.0-fragments");
+
+ // Need to cast to be able to set StandardContext specific attribute
+ StandardContext ctxt = (StandardContext)
+ tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+ ctxt.setAddWebinfClassesResources(true);
+
+ tomcat.start();
+
+ assertPageContains("/test/resourceA.jsp",
+ "<p>resourceA.jsp in the web application</p>");
+ assertPageContains("/test/resourceB.jsp",
+ "<p>resourceB.jsp in resources.jar</p>");
+ assertPageContains("/test/folder/resourceC.jsp",
+ "<p>resourceC.jsp in the web application</p>");
+ assertPageContains("/test/folder/resourceD.jsp",
+ "<p>resourceD.jsp in resources.jar</p>");
+ assertPageContains("/test/folder/resourceE.jsp",
+ "<p>resourceE.jsp in the web application</p>");
+ assertPageContains("/test/resourceG.jsp",
+ "<p>resourceG.jsp in WEB-INF/classes</p>");
}
public void testResourcesAbsoluteOrdering() throws Exception {
}
}
- private void assertPageContains(String pageUrl, String expected)
+ private void assertPageContains(String pageUrl, String expectedBody)
throws IOException {
- ByteChunk res = getUrl("http://localhost:" + getPort() + pageUrl);
- String result = res.toString();
- assertTrue(result, result.indexOf(expected) > 0);
+ assertPageContains(pageUrl, expectedBody, 200);
+ }
+
+ private void assertPageContains(String pageUrl, String expectedBody,
+ int expectedStatus) throws IOException {
+ ByteChunk res = new ByteChunk();
+ int sc = getUrl("http://localhost:" + getPort() + pageUrl, res, null);
+
+ assertEquals(expectedStatus, sc);
+
+ if (expectedStatus == 200) {
+ String result = res.toString();
+ assertTrue(result, result.indexOf(expectedBody) > 0);
+ }
}
}
--- /dev/null
+<%--
+ 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.
+--%>
+<%--
+ Resource file that is present both in the web application and in the
+ WEB-INF/lib/resources.jar file. The one in the web application should win.
+--%>
+<p>resourceG.jsp in WEB-INF/classes</p>
<attributes>
+ <attribute name="addWebinfClassesResources" required="false">
+ <p>This attribute controls if, in addition to static resources being
+ served from <code>META-INF/resources</code> inside web application JAR
+ files, static resources are also served from
+ <code>WEB-INF/classes/META-INF/resources</code>. This only applies to
+ web applications with a major version of 3 or higher. Since this is a
+ proprietary extension to the Servlet 3 specification, it is disabled by
+ default. To enable this feature, set the attribute to <code>true</code>.
+ </p>
+ </attribute>
+
<attribute name="aliases" required="false">
<p>This attribute provides a list of external locations from which to
load resources for this context. The list of aliases should be of