You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2011/06/02 17:54:27 UTC

svn commit: r1130618 - in /tomcat/trunk: java/org/apache/catalina/ java/org/apache/catalina/core/ java/org/apache/catalina/deploy/ java/org/apache/catalina/startup/ test/org/apache/catalina/startup/ test/webapp-3.0/ webapps/docs/

Author: markt
Date: Thu Jun  2 15:54:26 2011
New Revision: 1130618

URL: http://svn.apache.org/viewvc?rev=1130618&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=51278
Allow ServletContainerInitializers to override settings in the global default web.xml and the host web.xml. 

Added:
    tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java   (with props)
    tomcat/trunk/test/webapp-3.0/index.html   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/Wrapper.java
    tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java
    tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java
    tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java
    tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java
    tomcat/trunk/java/org/apache/catalina/deploy/WebXml.java
    tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/Wrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Wrapper.java?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Wrapper.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Wrapper.java Thu Jun  2 15:54:26 2011
@@ -386,4 +386,14 @@ public interface Wrapper extends Contain
      * Servlet associated with this wrapper.
      */
     public void servletSecurityAnnotationScan() throws ServletException;
+    
+    /**
+     * Is the Servlet overridable by a ServletContainerInitializer?
+     */
+    public boolean isOverridable();
+
+    /**
+     * Sets the overridable attribute for this Servlet.
+     */
+    public void setOverridable(boolean overridable);
 }

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=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java Thu Jun  2 15:54:26 2011
@@ -1102,7 +1102,7 @@ public class ApplicationContext
 
         Wrapper wrapper = (Wrapper) context.findChild(servletName);
         
-        // Assume a 'complete' FilterRegistration is one that has a class and
+        // Assume a 'complete' ServletRegistration is one that has a class and
         // a name
         if (wrapper == null) {
             wrapper = context.createWrapper();
@@ -1111,7 +1111,11 @@ public class ApplicationContext
         } else {
             if (wrapper.getName() != null &&
                     wrapper.getServletClass() != null) {
-                return null;
+                if (wrapper.isOverridable()) {
+                    wrapper.setOverridable(false);
+                } else {
+                    return null;
+                }
             }
         }
 

Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java Thu Jun  2 15:54:26 2011
@@ -171,8 +171,16 @@ public class ApplicationServletRegistrat
         Set<String> conflicts = new HashSet<String>();
         
         for (String urlPattern : urlPatterns) {
-            if (context.findServletMapping(urlPattern) != null) {
-                conflicts.add(urlPattern);
+            String wrapperName = context.findServletMapping(urlPattern);
+            if (wrapperName != null) {
+                Wrapper wrapper = (Wrapper) context.findChild(wrapperName);
+                if (wrapper.isOverridable()) {
+                    // Some Wrappers (from global and host web.xml) may be
+                    // overridden rather than generating a conflict
+                    context.removeServletMapping(urlPattern);
+                } else {
+                    conflicts.add(urlPattern);
+                }
             }
         }
 

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java Thu Jun  2 15:54:26 2011
@@ -276,6 +276,8 @@ public class StandardWrapper extends Con
 
     protected volatile boolean servletSecurityAnnotationScanRequired = false;
 
+    private boolean overridable = false;
+    
     /**
      * Static class array used when the SecurityManager is turned on and 
      * <code>Servlet.init</code> is invoked.
@@ -294,6 +296,15 @@ public class StandardWrapper extends Con
 
     // ------------------------------------------------------------- Properties
 
+    @Override
+    public boolean isOverridable() {
+        return overridable;
+    }
+
+    @Override
+    public void setOverridable(boolean overridable) {
+        this.overridable = overridable;
+    }
 
     /**
      * Return the available date/time for this servlet, in milliseconds since

Modified: tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java Thu Jun  2 15:54:26 2011
@@ -264,4 +264,19 @@ public class ServletDef implements Seria
     public void setEnabled(String enabled) {
         this.enabled = Boolean.valueOf(enabled);
     }
+
+    
+    /**
+     * Can this ServletDef be overridden by an SCI?
+     */
+    private boolean overridable = false;
+    
+    public boolean isOverridable() {
+        return overridable;
+    }
+
+    public void setOverridable(boolean overridable) {
+        this.overridable = overridable;
+    }
+
 }

Modified: tomcat/trunk/java/org/apache/catalina/deploy/WebXml.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/WebXml.java?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/WebXml.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/WebXml.java Thu Jun  2 15:54:26 2011
@@ -61,7 +61,18 @@ public class WebXml {
 
     private static final org.apache.juli.logging.Log log=
         org.apache.juli.logging.LogFactory.getLog(WebXml.class);
-    
+
+    // Global defaults are overridable but Servlets and Servlet mappings need to
+    // be unique. Duplicates normally trigger an error. This flag indicates if
+    // newly added Servlet elements are marked as overridable.
+    private boolean overridable = false;
+    public boolean isOverridable() {
+        return overridable;
+    }
+    public void setOverridable(boolean overridable) {
+        this.overridable = overridable;
+    }
+
     // web.xml only elements
     // Absolute Ordering
     private Set<String> absoluteOrdering = null;
@@ -305,6 +316,9 @@ public class WebXml {
     private Map<String,ServletDef> servlets = new HashMap<String,ServletDef>();
     public void addServlet(ServletDef servletDef) {
         servlets.put(servletDef.getServletName(), servletDef);
+        if (overridable) {
+            servletDef.setOverridable(overridable);
+        }
     }
     public Map<String,ServletDef> getServlets() { return servlets; }
     
@@ -1268,6 +1282,7 @@ public class WebXml {
                 wrapper.setAsyncSupported(
                         servlet.getAsyncSupported().booleanValue());
             }
+            wrapper.setOverridable(servlet.isOverridable());
             context.addChild(wrapper);
         }
         for (Entry<String, String> entry : servletMappings.entrySet()) {

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=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Thu Jun  2 15:54:26 2011
@@ -1186,6 +1186,15 @@ public class ContextConfig
      */
     protected void webConfig() {
         WebXml webXml = createWebXml();
+        /* Anything and everything can override the global and host defaults.
+         * This is implemented in two parts
+         * - Handle as a web fragment that gets added after everything else so
+         *   everything else takes priority
+         * - Mark Servlets as overridable so SCI configuration can replace
+         *   configuration from the defaults
+         */ 
+        WebXml webXmlDefaultFragment = createWebXml();
+        webXmlDefaultFragment.setOverridable(true);
 
         // Parse global web.xml if present
         InputSource globalWebXml = getGlobalWebXmlSource();
@@ -1193,17 +1202,19 @@ public class ContextConfig
             // This is unusual enough to log
             log.info(sm.getString("contextConfig.defaultMissing"));
         } else {
-            parseWebXml(globalWebXml, webXml, false);
+            parseWebXml(globalWebXml, webXmlDefaultFragment, false);
         }
 
         // Parse host level web.xml if present
         // Additive apart from welcome pages
         webXml.setReplaceWelcomeFiles(true);
         InputSource hostWebXml = getHostWebXmlSource();
-        parseWebXml(hostWebXml, webXml, false);
+        parseWebXml(hostWebXml, webXmlDefaultFragment, false);
+        
+        Set<WebXml> defaults = new HashSet<WebXml>();
+        defaults.add(webXmlDefaultFragment);
         
         // Parse context level web.xml
-        webXml.setReplaceWelcomeFiles(true);
         InputSource contextWebXml = getContextWebXmlSource();
         parseWebXml(contextWebXml, webXml, false);
         
@@ -1260,16 +1271,19 @@ public class ContextConfig
                     ok = webXml.merge(orderedFragments);
                 }
     
-                // Step 6.5 Convert explicitly mentioned jsps to servlets
+                // Step 7. Convert explicitly mentioned jsps to servlets
                 if (!false) {
                     convertJsps(webXml);
                 }
-    
-                // Step 7. Apply merged web.xml to Context
+
+                // Step 8. Apply global defaults
+                webXml.merge(defaults);
+                
+                // Step 9. Apply merged web.xml to Context
                 if (ok) {
                     webXml.configureContext(context);
     
-                    // Step 7a. Make the merged web.xml available to other
+                    // Step 9a. Make the merged web.xml available to other
                     // components, specifically Jasper, to save those components
                     // from having to re-generate it.
                     // TODO Use a ServletContainerInitializer for Jasper
@@ -1282,11 +1296,12 @@ public class ContextConfig
                     }
                 }
             } else {
+                webXml.merge(defaults);
                 webXml.configureContext(context);
             }
             
             // Always need to look for static resources
-            // Step 8. Look for static resources packaged in JARs
+            // Step 10. Look for static resources packaged in JARs
             if (ok) {
                 // Spec does not define an order.
                 // Use ordered JARs followed by remaining JARs
@@ -1309,7 +1324,7 @@ public class ContextConfig
             // Only look for ServletContainerInitializer if metadata is not
             // complete
             if (!webXml.isMetadataComplete()) {
-                // Step 9. Apply the ServletContainerInitializer config to the
+                // Step 11. Apply the ServletContainerInitializer config to the
                 // context
                 if (ok) {
                     for (Map.Entry<ServletContainerInitializer,
@@ -1328,6 +1343,7 @@ public class ContextConfig
         } else {
             // Apply unmerged web.xml to Context
             convertJsps(webXml);
+            webXml.merge(defaults);
             webXml.configureContext(context);
         }
     }

Added: tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java?rev=1130618&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java (added)
+++ tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java Thu Jun  2 15:54:26 2011
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package org.apache.catalina.startup;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Set;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.core.StandardContext;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TestContextConfig extends TomcatBaseTest {
+
+    public void testOverrideWithSCIDefaultName() throws Exception {
+        doTestOverrideDefaultServletWithSCI("default");
+    }
+
+    public void testOverrideWithSCIDefaultMapping() throws Exception {
+        doTestOverrideDefaultServletWithSCI("anything");
+    }
+
+    private void doTestOverrideDefaultServletWithSCI(String servletName)
+            throws Exception{
+
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp-3.0");
+        StandardContext ctxt = (StandardContext) tomcat.addContext(null,
+                "/test", appDir.getAbsolutePath());
+        ctxt.setDefaultWebXml(new File("conf/web.xml").getAbsolutePath());
+        ctxt.addLifecycleListener(new ContextConfig());
+        
+        ctxt.addServletContainerInitializer(
+                new CustomDefaultServletSCI(servletName), null);
+
+        tomcat.start();
+
+        ByteChunk res = new ByteChunk();
+        
+        int rc =getUrl("http://localhost:" + getPort() + "/test", res, null);
+
+        // Check return code
+        assertEquals(HttpServletResponse.SC_OK, rc);
+        
+        // Check context
+        assertEquals("OK - Custom default Servlet", res.toString());
+    }
+
+    private static class CustomDefaultServletSCI
+            implements ServletContainerInitializer {
+
+        private String servletName;
+        
+        public CustomDefaultServletSCI(String servletName) {
+            this.servletName = servletName;
+        }
+
+        @Override
+        public void onStartup(Set<Class<?>> c, ServletContext ctx)
+                throws ServletException {
+            Servlet s = new CustomDefaultServlet();
+            ServletRegistration.Dynamic r = ctx.addServlet(servletName, s);
+            r.addMapping("/");
+        }
+        
+    }
+
+    private static class CustomDefaultServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+            resp.setContentType("text/plain");
+            resp.getWriter().print("OK - Custom default Servlet");
+        }
+    }
+}

Propchange: tomcat/trunk/test/org/apache/catalina/startup/TestContextConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/test/webapp-3.0/index.html
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp-3.0/index.html?rev=1130618&view=auto
==============================================================================
--- tomcat/trunk/test/webapp-3.0/index.html (added)
+++ tomcat/trunk/test/webapp-3.0/index.html Thu Jun  2 15:54:26 2011
@@ -0,0 +1,8 @@
+<html>
+  <head>
+    <title>Index page</title>
+  </head>
+  <body>
+   <p>This is the index page served by the default Servlet.</p>
+  </body>
+</html>
\ No newline at end of file

Propchange: tomcat/trunk/test/webapp-3.0/index.html
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1130618&r1=1130617&r2=1130618&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Jun  2 15:54:26 2011
@@ -78,6 +78,10 @@
         with an incomplete FORM authentication configuration. (markt)
       </fix>
       <fix>
+        <bug>51278</bug>: Allow ServletContainerInitializers to override
+        settings in the global default web.xml and the host web.xml. (markt)
+      </fix>
+      <fix>
         <bug>51310</bug>: When stopping the Server object on shutdown call
         destroy() after calling stop(). (markt)
       </fix>



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