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 2010/01/21 03:57:29 UTC

svn commit: r901507 - in /tomcat/trunk: java/org/apache/catalina/ java/org/apache/catalina/core/ java/org/apache/catalina/deploy/ test/org/apache/catalina/deploy/

Author: markt
Date: Thu Jan 21 02:57:10 2010
New Revision: 901507

URL: http://svn.apache.org/viewvc?rev=901507&view=rev
Log:
Servlet 3.0 implementation
Implement some more of the new ServletContext methods

Added:
    tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java
    tomcat/trunk/test/org/apache/catalina/deploy/TestSecurityConstraint.java
Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/Wrapper.java
    tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java
    tomcat/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.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/core/StandardWrapper.java
    tomcat/trunk/java/org/apache/catalina/deploy/FilterDef.java
    tomcat/trunk/java/org/apache/catalina/deploy/SecurityCollection.java
    tomcat/trunk/java/org/apache/catalina/deploy/SecurityConstraint.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=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Thu Jan 21 02:57:10 2010
@@ -451,6 +451,108 @@
     public void setWrapperClass(String wrapperClass);
 
 
+    /**
+     * Get the server.xml <context> attribute's xmlNamespaceAware.
+     * @return true if namespace awareness is enabled.
+     *
+     */
+    public boolean getXmlNamespaceAware();
+
+
+    /**
+     * Get the server.xml <context> attribute's xmlValidation.
+     * @return true if validation is enabled.
+     *
+     */
+    public boolean getXmlValidation();
+
+
+    /**
+     * Set the validation feature of the XML parser used when
+     * parsing xml instances.
+     * @param xmlValidation true to enable xml instance validation
+     */
+    public void setXmlValidation(boolean xmlValidation);
+
+
+   /**
+     * Set the namespace aware feature of the XML parser used when
+     * parsing xml instances.
+     * @param xmlNamespaceAware true to enable namespace awareness
+     */
+    public void setXmlNamespaceAware(boolean xmlNamespaceAware);
+    /**
+     * Get the server.xml <context> attribute's xmlValidation.
+     * @return true if validation is enabled.
+     */
+     
+
+    /**
+     * Set the validation feature of the XML parser used when
+     * parsing tlds files. 
+     * @param tldValidation true to enable xml instance validation
+     */
+    public void setTldValidation(boolean tldValidation);
+
+
+    /**
+     * Get the server.xml <context> attribute's webXmlValidation.
+     * @return true if validation is enabled.
+     *
+     */
+    public boolean getTldValidation();
+
+
+    /**
+     * Get the server.xml &lt;host&gt; attribute's xmlNamespaceAware.
+     * @return true if namespace awareness is enabled.
+     */
+    public boolean getTldNamespaceAware();
+
+
+    /**
+     * Set the namespace aware feature of the XML parser used when
+     * parsing xml instances.
+     * @param tldNamespaceAware true to enable namespace awareness
+     */
+    public void setTldNamespaceAware(boolean tldNamespaceAware);
+
+    /**
+     * Get the Jar Scanner to be used to scan for JAR resources for this
+     * context.
+     * @return  The Jar Scanner configured for this context.
+     */
+    public JarScanner getJarScanner();
+
+    /**
+     * Set the Jar Scanner to be used to scan for JAR resources for this
+     * context.
+     * @param jarScanner    The Jar Scanner to be used for this context.
+     */
+    public void setJarScanner(JarScanner jarScanner);
+
+    /**
+     * Obtain the {@link Authenticator} that is used by this context or
+     * <code>null</code> if none is used.
+     */
+    public Authenticator getAuthenticator();
+    
+    /**
+     * Set whether or not the effective web.xml for this context should be
+     * logged on context start.
+     */
+    public void setLogEffectiveWebXml(boolean logEffectiveWebXml);
+    
+    /**
+     * Should the effective web.xml for this context be logged on context start?
+     */
+    public boolean getLogEffectiveWebXml();
+    
+    /**
+     * Has this context been initialized?
+     */
+    public boolean isInitialized();
+
     // --------------------------------------------------------- Public Methods
 
 
@@ -1020,108 +1122,11 @@
 
 
     /**
-     * Get the server.xml <context> attribute's xmlNamespaceAware.
-     * @return true if namespace awareness is enabled.
-     *
-     */
-    public boolean getXmlNamespaceAware();
-
-
-    /**
-     * Get the server.xml <context> attribute's xmlValidation.
-     * @return true if validation is enabled.
-     *
-     */
-    public boolean getXmlValidation();
-
-
-    /**
-     * Set the validation feature of the XML parser used when
-     * parsing xml instances.
-     * @param xmlValidation true to enable xml instance validation
-     */
-    public void setXmlValidation(boolean xmlValidation);
-
-
-   /**
-     * Set the namespace aware feature of the XML parser used when
-     * parsing xml instances.
-     * @param xmlNamespaceAware true to enable namespace awareness
-     */
-    public void setXmlNamespaceAware(boolean xmlNamespaceAware);
-    /**
-     * Get the server.xml <context> attribute's xmlValidation.
-     * @return true if validation is enabled.
-     */
-     
-
-    /**
-     * Set the validation feature of the XML parser used when
-     * parsing tlds files. 
-     * @param tldValidation true to enable xml instance validation
-     */
-    public void setTldValidation(boolean tldValidation);
-
-
-    /**
-     * Get the server.xml <context> attribute's webXmlValidation.
-     * @return true if validation is enabled.
-     *
-     */
-    public boolean getTldValidation();
-
-
-    /**
-     * Get the server.xml &lt;host&gt; attribute's xmlNamespaceAware.
-     * @return true if namespace awareness is enabled.
-     */
-    public boolean getTldNamespaceAware();
-
-
-    /**
-     * Set the namespace aware feature of the XML parser used when
-     * parsing xml instances.
-     * @param tldNamespaceAware true to enable namespace awareness
-     */
-    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);
-
-    /**
-     * Get the Jar Scanner to be used to scan for JAR resources for this
-     * context.
-     * @return  The Jar Scanner configured for this context.
-     */
-    public JarScanner getJarScanner();
-
-    /**
-     * Set the Jar Scanner to be used to scan for JAR resources for this
-     * context.
-     * @param jarScanner    The Jar Scanner to be used for this context.
-     */
-    public void setJarScanner(JarScanner jarScanner);
-
-    /**
-     * Obtain the {@link Authenticator} that is used by this context or
-     * <code>null</code> if none is used.
-     */
-    public Authenticator getAuthenticator();
-    
-    /**
-     * Set whether or not the effective web.xml for this context should be
-     * logged on context start.
-     */
-    public void setLogEffectiveWebXml(boolean logEffectiveWebXml);
-    
-    /**
-     * Should the effective web.xml for this context be logged on context start?
-     */
-    public boolean getLogEffectiveWebXml();
 }
 

Modified: tomcat/trunk/java/org/apache/catalina/Wrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Wrapper.java?rev=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Wrapper.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Wrapper.java Thu Jan 21 02:57:10 2010
@@ -151,6 +151,17 @@
      */
     public boolean isUnavailable();
 
+    
+    /**
+     * Return the associated servlet instance.
+     */
+    public Servlet getServlet();
+    
+
+    /**
+     * Set the associated servlet instance
+     */
+    public void setServlet(Servlet servlet);
 
     // --------------------------------------------------------- Public Methods
 
@@ -219,12 +230,6 @@
 
 
     /**
-     * Return the associated servlet instance.
-     */
-    public Servlet getServlet();
-    
-    
-    /**
      * Return the value for the specified initialization parameter name,
      * if any; otherwise return <code>null</code>.
      *

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=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationContext.java Thu Jan 21 02:57:10 2010
@@ -20,6 +20,7 @@
 
 
 import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -816,9 +817,59 @@
     }
 
 
+    /**
+     * Add filter to context.
+     * @param   filterName  Name of filter to add
+     * @param   filterClass Name of filter class
+     * @returns <code>null</code> if the filter has already been fully defined,
+     *          else a {@link FilterRegistration.Dynamic} object that can be
+     *          used to further configure the filter
+     * @throws IllegalStateException if the context has already been initialised
+     * @throws UnsupportedOperationException - TODO SERVLET3
+     */
     public FilterRegistration.Dynamic addFilter(String filterName,
             String filterClass) throws IllegalStateException {
         
+        return addFilter(filterName, filterClass, null);
+    }
+
+    
+    /**
+     * Add filter to context.
+     * @param   filterName  Name of filter to add
+     * @param   filter      Filter to add
+     * @returns <code>null</code> if the filter has already been fully defined,
+     *          else a {@link FilterRegistration.Dynamic} object that can be
+     *          used to further configure the filter
+     * @throws IllegalStateException if the context has already been initialised
+     * @throws UnsupportedOperationException - TODO SERVLET3
+     */
+    public FilterRegistration.Dynamic addFilter(String filterName,
+            Filter filter) throws IllegalStateException {
+        
+        return addFilter(filterName, null, filter);
+    }
+
+    
+    /**
+     * Add filter to context.
+     * @param   filterName  Name of filter to add
+     * @param   filterClass Class of filter to add
+     * @returns <code>null</code> if the filter has already been fully defined,
+     *          else a {@link FilterRegistration.Dynamic} object that can be
+     *          used to further configure the filter
+     * @throws IllegalStateException if the context has already been initialised
+     * @throws UnsupportedOperationException - TODO SERVLET3
+     */
+    public FilterRegistration.Dynamic addFilter(String filterName,
+            Class<? extends Filter> filterClass) throws IllegalStateException {
+        
+        return addFilter(filterName, filterClass.getName(), null);
+    }
+
+    private FilterRegistration.Dynamic addFilter(String filterName,
+            String filterClass, Filter filter) throws IllegalStateException {
+        
         if (context.initialized) {
             //TODO Spec breaking enhancement to ignore this restriction
             throw new IllegalStateException(
@@ -840,103 +891,78 @@
         }
 
         // Name must already be set
-        filterDef.setFilterClass(filterClass);
-        
-        return new ApplicationFilterRegistration(filterDef, context);
-    }
-
-    
-    public FilterRegistration.Dynamic addFilter(String filterName,
-            Filter filter) throws IllegalStateException {
-        
-        if (context.initialized) {
-            //TODO Spec breaking enhancement to ignore this restriction
-            throw new IllegalStateException(
-                    sm.getString("applicationContext.addFilter.ise",
-                            getContextPath()));
-        }
-        
-        if (context.findFilterDef(filterName) != null) {
-            return null;
-        }
-
-        // TODO SERVLET3
-        return null;
-    }
-
-    
-    public FilterRegistration.Dynamic addFilter(String filterName,
-            Class<? extends Filter> filterClass) throws IllegalStateException {
-        
-        if (context.initialized) {
-            //TODO Spec breaking enhancement to ignore this restriction
-            throw new IllegalStateException(
-                    sm.getString("applicationContext.addFilter.ise",
-                            getContextPath()));
+        if (filter == null) {
+            filterDef.setFilterClass(filterClass);
+        } else {
+            filterDef.setFilterClass(filter.getClass().getName());
+            filterDef.setFilter(filter);
         }
         
-        if (context.findFilterDef(filterName) != null) {
-            return null;
-        }
-
-        // TODO SERVLET3
-        return null;
-    }
-
+        return new ApplicationFilterRegistration(filterDef, context);
+    } 
     
     public <T extends Filter> T createFilter(Class<T> c)
     throws ServletException {
-        // TODO SERVLET3
-        return null;
+        try {
+            @SuppressWarnings("unchecked")
+            T filter = (T) context.getInstanceManager().newInstance(c.getName());
+            return filter;
+        } catch (IllegalAccessException e) {
+            throw new ServletException(e);
+        } catch (InvocationTargetException e) {
+            throw new ServletException(e);
+        } catch (NamingException e) {
+            throw new ServletException(e);
+        } catch (InstantiationException e) {
+            throw new ServletException(e);
+        } catch (ClassNotFoundException e) {
+            throw new ServletException(e);
+        }
     }
 
 
     public FilterRegistration getFilterRegistration(String filterName) {
-        // TODO SERVLET3
-        return null;
+        FilterDef filterDef = context.findFilterDef(filterName);
+        if (filterDef == null) {
+            return null;
+        }
+        
+        return new ApplicationFilterRegistration(filterDef, context);
     }
     
+    /**
+     * Add servlet to context.
+     * @param   servletName  Name of filter to add
+     * @param   servletClass Name of filter class
+     * @returns <code>null</code> if the servlet has already been fully defined,
+     *          else a {@link ServletRegistration.Dynamic} object that can be
+     *          used to further configure the servlet
+     * @throws IllegalStateException if the context has already been initialised
+     * @throws UnsupportedOperationException - TODO SERVLET3
+     */
     public ServletRegistration.Dynamic addServlet(String servletName,
-            String className) throws IllegalStateException {
+            String servletClass) throws IllegalStateException {
         
-        if (context.initialized) {
-            //TODO Spec breaking enhancement to ignore this restriction
-            throw new IllegalStateException(
-                    sm.getString("applicationContext.addServlet.ise",
-                            getContextPath()));
-        }
-
-        if (context.findChild(servletName) != null) {
-            return null;
-        }
-
-        // TODO SERVLET3
-        return null;
+        return addServlet(servletName, servletClass, null);
     }
 
 
     public ServletRegistration.Dynamic addServlet(String servletName,
             Servlet servlet) throws IllegalStateException {
-        
-        if (context.initialized) {
-            //TODO Spec breaking enhancement to ignore this restriction
-            throw new IllegalStateException(
-                    sm.getString("applicationContext.addServlet.ise",
-                            getContextPath()));
-        }
-
-        if (context.findChild(servletName) != null) {
-            return null;
-        }
 
-        // TODO SERVLET3
-        return null;
+        return addServlet(servletName, null, servlet);
     }
 
     
     public ServletRegistration.Dynamic addServlet(String servletName,
             Class <? extends Servlet> servletClass)
     throws IllegalStateException {
+
+        return addServlet(servletName, servletClass.getName(), null);
+    }
+
+    private ServletRegistration.Dynamic addServlet(String servletName,
+            String servletClass, Servlet servlet) throws IllegalStateException {
         
         if (context.initialized) {
             //TODO Spec breaking enhancement to ignore this restriction
@@ -944,26 +970,59 @@
                     sm.getString("applicationContext.addServlet.ise",
                             getContextPath()));
         }
-
-        if (context.findChild(servletName) != null) {
-            return null;
+        
+        Wrapper wrapper = (Wrapper) context.findChild(servletName);
+        
+        // Assume a 'complete' FilterRegistration is one that has a class and
+        // a name
+        if (wrapper == null) {
+            wrapper = context.createWrapper();
+        } else {
+            if (wrapper.getName() != null &&
+                    wrapper.getServletClass() != null) {
+                return null;
+            }
         }
 
-        // TODO SERVLET3
-        return null;
-    }
+        // Name must already be set
+        if (servlet == null) {
+            wrapper.setServletClass(servletClass);
+        } else {
+            wrapper.setServletClass(servlet.getClass().getName());
+            wrapper.setServlet(servlet);
+       }
+        
+        return new ApplicationServletRegistration(wrapper, context);
+    } 
 
 
     public <T extends Servlet> T createServlet(Class<T> c)
     throws ServletException {
-        // TODO SERVLET3
-        return null;
+        try {
+            @SuppressWarnings("unchecked")
+            T servlet = (T) context.getInstanceManager().newInstance(c.getName());
+            return servlet;
+        } catch (IllegalAccessException e) {
+            throw new ServletException(e);
+        } catch (InvocationTargetException e) {
+            throw new ServletException(e);
+        } catch (NamingException e) {
+            throw new ServletException(e);
+        } catch (InstantiationException e) {
+            throw new ServletException(e);
+        } catch (ClassNotFoundException e) {
+            throw new ServletException(e);
+        }
     }
 
 
     public ServletRegistration getServletRegistration(String servletName) {
-        // TODO SERVLET3
-        return null;
+        Wrapper wrapper = (Wrapper) context.findChild(servletName);
+        if (wrapper == null) {
+            return null;
+        }
+        
+        return new ApplicationServletRegistration(wrapper, context);
     }
     
 
@@ -1058,8 +1117,12 @@
 
     @Override
     public boolean setInitParameter(String name, String value) {
-        // TODO SERVLET3
-        return false;
+        if (parameters.containsKey(name)) {
+            return false;
+        }
+        
+        parameters.put(name, value);
+        return true;
     }
     
     
@@ -1091,14 +1154,50 @@
 
     @Override
     public void declareRoles(String... roleNames) {
-        // TODO SERVLET3
+        
+        if (context.initialized) {
+            //TODO Spec breaking enhancement to ignore this restriction
+            throw new IllegalStateException(
+                    sm.getString("applicationContext.addRole.ise",
+                            getContextPath()));
+        }
+        
+        if (roleNames == null) {
+            throw new IllegalArgumentException(
+                    sm.getString("applicationContext.roles.iae",
+                            getContextPath()));
+        }
+        
+        for (String role : roleNames) {
+            if (role == null || "".equals(role)) {
+                throw new IllegalArgumentException(
+                        sm.getString("applicationContext.role.iae",
+                                getContextPath()));
+            }
+            context.addSecurityRole(role);
+        }
     }
 
 
     @Override
     public ClassLoader getClassLoader() {
-        // TODO SERVLET3
-        return null;
+        ClassLoader result = context.getLoader().getClassLoader();
+        if (Globals.IS_SECURITY_ENABLED) {
+            ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+            ClassLoader parent = result;
+            while (parent != null) {
+                if (parent == tccl) {
+                    break;
+                }
+                parent = parent.getParent();
+            }
+            if (parent == null) {
+                System.getSecurityManager().checkPermission(
+                        new RuntimePermission("getClassLoader"));
+            }
+        }
+        
+        return result;
     }
 
 
@@ -1250,10 +1349,15 @@
      * Get full path, based on the host name and the context path.
      */
     private static String getJNDIUri(String hostName, String path) {
-        if (!path.startsWith("/"))
-            return "/" + hostName + "/" + path;
-        else
-            return "/" + hostName + path;
+        String result;
+        
+        if (path.startsWith("/")) {
+            result = "/" + hostName + path;
+        } else {
+            result = "/" + hostName + "/" + path;
+        }
+        
+        return result;
     }
 
 

Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java?rev=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java Thu Jan 21 02:57:10 2010
@@ -57,6 +57,7 @@
 
 public final class ApplicationFilterConfig implements FilterConfig, Serializable {
 
+    private static final long serialVersionUID = 1L;
 
     protected static final StringManager sm =
         StringManager.getManager(Constants.Package);
@@ -95,7 +96,11 @@
 
         this.context = context;
         setFilterDef(filterDef);
-
+        if (filterDef.getFilter() != null) {
+            this.filter = filterDef.getFilter();
+            getInstanceManager().newInstance(filter);
+            initFilter();
+        }
     }
 
 
@@ -156,10 +161,11 @@
     public String getInitParameter(String name) {
 
         Map<String,String> map = filterDef.getParameterMap();
-        if (map == null)
+        if (map == null) {
             return (null);
-        else
-            return map.get(name);
+        }
+
+        return map.get(name);
 
     }
 
@@ -171,10 +177,11 @@
     public Enumeration<String> getInitParameterNames() {
         Map<String,String> map = filterDef.getParameterMap();
         
-        if (map == null)
+        if (map == null) {
             return (new Enumerator<String>(new ArrayList<String>()));
-        else
-            return (new Enumerator<String>(map.keySet()));
+        }
+
+        return new Enumerator<String>(map.keySet());
 
     }
 
@@ -184,7 +191,7 @@
      */
     public ServletContext getServletContext() {
 
-        return (this.context.getServletContext());
+        return this.context.getServletContext();
 
     }
 
@@ -239,16 +246,23 @@
         // Identify the class loader we will be using
         String filterClass = filterDef.getFilterClass();
         this.filter = (Filter) getInstanceManager().newInstance(filterClass);
+        
+        initFilter();
+        
+        return (this.filter);
+
+    }
 
+    private void initFilter() throws ServletException {
         if (context instanceof StandardContext &&
                 context.getSwallowOutput()) {
             try {
                 SystemLogHandler.startCapture();
                 filter.init(this);
             } finally {
-                String log = SystemLogHandler.stopCapture();
-                if (log != null && log.length() > 0) {
-                    getServletContext().log(log);
+                String capturedlog = SystemLogHandler.stopCapture();
+                if (capturedlog != null && capturedlog.length() > 0) {
+                    getServletContext().log(capturedlog);
                 }
             }
         } else {
@@ -257,12 +271,8 @@
         
         // Expose filter via JMX
         registerJMX();
-        
-        return (this.filter);
-
     }
 
-
     /**
      * Return the filter definition we are configured for.
      */

Added: 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=901507&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java (added)
+++ tomcat/trunk/java/org/apache/catalina/core/ApplicationServletRegistration.java Thu Jan 21 02:57:10 2010
@@ -0,0 +1,261 @@
+/*
+ * 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.core;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.HttpMethodConstraintElement;
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletRegistration;
+import javax.servlet.ServletSecurityElement;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.deploy.SecurityCollection;
+import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.catalina.util.ParameterMap;
+import org.apache.tomcat.util.res.StringManager;
+
+public class ApplicationServletRegistration
+        implements ServletRegistration.Dynamic {
+
+    /**
+     * The string manager for this package.
+     */
+    private static final StringManager sm =
+      StringManager.getManager(Constants.Package);
+    
+    private Wrapper wrapper;
+    private Context context;
+    
+    public ApplicationServletRegistration(Wrapper wrapper,
+            Context context) {
+        this.wrapper = wrapper;
+        this.context = context;
+        
+    }
+
+    @Override
+    public String getClassName() {
+        return wrapper.getServletClass();
+   }
+
+    @Override
+    public String getInitParameter(String name) {
+        return wrapper.getServlet().getServletConfig().getInitParameter(name);
+    }
+
+    @Override
+    public Map<String, String> getInitParameters() {
+        ParameterMap<String,String> result = new ParameterMap<String,String>();
+        ServletConfig servletConfig =  wrapper.getServlet().getServletConfig(); 
+        Enumeration<String> parameterNames =
+            servletConfig.getInitParameterNames();
+        
+        while (parameterNames.hasMoreElements()) {
+            String parameterName = parameterNames.nextElement();
+            result.put(parameterName,
+                    servletConfig.getInitParameter(parameterName));
+        }
+        result.setLocked(true);
+        return result;
+    }
+
+    @Override
+    public String getName() {
+        return wrapper.getName();
+    }
+
+    @Override
+    public boolean setInitParameter(String name, String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException(
+                    sm.getString("applicationFilterRegistration.nullInitParam",
+                            name, value));
+        }
+        if (getInitParameter(name) != null) {
+            return false;
+        }
+        
+        wrapper.addInitParameter(name, value);
+
+        return true;
+    }
+
+    @Override
+    public Set<String> setInitParameters(Map<String, String> initParameters) {
+        
+        Set<String> conflicts = new HashSet<String>();
+        
+        for (Map.Entry<String, String> entry : initParameters.entrySet()) {
+            if (entry.getKey() == null || entry.getValue() == null) {
+                throw new IllegalArgumentException(sm.getString(
+                        "applicationFilterRegistration.nullInitParams",
+                                entry.getKey(), entry.getValue()));
+            }
+            if (getInitParameter(entry.getKey()) != null) {
+                conflicts.add(entry.getKey());
+            }
+        }
+
+        // Have to add in a separate loop since spec requires no updates at all
+        // if there is an issue
+        for (Map.Entry<String, String> entry : initParameters.entrySet()) {
+            setInitParameter(entry.getKey(), entry.getValue());
+        }
+        
+        return conflicts;
+    }
+
+    @Override
+    public void setAsyncSupported(boolean asyncSupported) {
+        wrapper.setAsyncSupported(asyncSupported);
+    }
+
+    @Override
+    public void setLoadOnStartup(int loadOnStartup) {
+        wrapper.setLoadOnStartup(loadOnStartup);
+    }
+
+    @Override
+    public void setMultipartConfig(MultipartConfigElement multipartConfig) {
+        wrapper.setMultipartConfigElement(multipartConfig);
+    }
+
+    @Override
+    public void setRunAsRole(String roleName) {
+        wrapper.setRunAs(roleName);
+    }
+
+    @Override
+    public Set<String> setServletSecurity(ServletSecurityElement constraint) {
+        if (constraint == null) {
+            throw new IllegalArgumentException(sm.getString(
+                    "applicationServletRegistration.setServletSecurity.iae",
+                    getName(), context.getPath()));
+        }
+        
+        if (context.isInitialized()) {
+            throw new IllegalStateException(sm.getString(
+                    "applicationServletRegistration.setServletSecurity.ise",
+                    getName(), context.getPath()));
+        }
+
+        Set<String> conflicts = new HashSet<String>();
+
+        Collection<String> urlPatterns = getMappings();
+        for (String urlPattern : urlPatterns) {
+            boolean foundConflict = false;
+            
+            SecurityConstraint[] securityConstraints =
+                context.findConstraints();
+            for (SecurityConstraint securityConstraint : securityConstraints) {
+                
+                SecurityCollection[] collections =
+                    securityConstraint.findCollections();
+                for (SecurityCollection collection : collections) {
+                    if (collection.findPattern(urlPattern)) {
+                        // First pattern found will indicate if there is a
+                        // conflict since for any given pattern all matching
+                        // constraints will be from either the descriptor or
+                        // not. It is not permitted to have a mixture
+                        if (collection.isFromDescriptor()) {
+                            // Skip this pattern
+                            foundConflict = true;
+                        } else {
+                            // Need to overwrite constraint for this pattern
+                            // so remove every pattern found
+                            context.removeConstraint(securityConstraint);
+                        }
+                    }
+                    if (foundConflict) {
+                        break;
+                    }
+                }
+                if (foundConflict) {
+                    break;
+                }
+            }
+            if (!foundConflict) {
+                SecurityConstraint[] newSecurityConstraints =
+                        SecurityConstraint.createConstraints(constraint,
+                                urlPattern);
+                for (SecurityConstraint securityConstraint :
+                        newSecurityConstraints) {
+                    context.addConstraint(securityConstraint);
+                }
+            }
+        }
+        
+        return conflicts;
+    }
+
+
+    @Override
+    public Set<String> addMapping(String... urlPatterns) {
+        if (urlPatterns == null) {
+            return Collections.emptySet();
+        }
+        
+        Set<String> conflicts = new HashSet<String>();
+        
+        for (String urlPattern : urlPatterns) {
+            if (context.findServletMapping(urlPattern) != null) {
+                conflicts.add(urlPattern);
+            }
+        }
+
+        if (!conflicts.isEmpty()) {
+            return conflicts;
+        }
+        
+        for (String urlPattern : urlPatterns) {
+            context.addServletMapping(urlPattern, wrapper.getName());
+        }
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Collection<String> getMappings() {
+
+        Set<String> result = new HashSet<String>();
+        String servletName = wrapper.getName();
+        
+        String[] urlPatterns = context.findServletMappings();
+        for (String urlPattern : urlPatterns) {
+            String name = context.findServletMapping(urlPattern);
+            if (name.equals(servletName)) {
+                result.add(urlPattern);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String getRunAsRole() {
+        return wrapper.getRunAs();
+    }
+    
+}

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=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Thu Jan 21 02:57:10 2010
@@ -14,11 +14,14 @@
 # limitations under the License.
 
 applicationContext.addFilter.ise=Filters can not be added to context {0} as the context has been initialised
+applicationContext.addRole.ise=Roles can not be added to context {0} as the context has been initialised
 applicationContext.addServlet.ise=Servlets can not be added to context {0} as the context has been initialised
 applicationContext.attributeEvent=Exception thrown by attributes event listener
 applicationContext.mapping.error=Error during mapping
 applicationContext.requestDispatcher.iae=Path {0} does not start with a "/" character
 applicationContext.resourcePaths.iae=Path {0} does not start with a "/" character
+applicationContext.role.iae=An individual role to declare for context [{0}] may not be null nor the empty string
+applicationContext.roles.iae=Array of roles to declare for context [{0}] cannot be null
 applicationContext.setAttribute.namenull=Name cannot be null
 applicationContext.addSessionCookieConfig.ise=Session Cookie configuration cannot be set for context {0} as the context has been initialised
 applicationContext.setSessionTracking.ise=The session tracking modes for context {0} cannot be set whilst the context is running
@@ -42,6 +45,8 @@
 applicationRequest.badRequest=Request is not a javax.servlet.ServletRequestWrapper
 applicationResponse.badParent=Cannot locate parent Response implementation
 applicationResponse.badResponse=Response is not a javax.servlet.ServletResponseWrapper
+applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with path [{1}]
+applicationServletRegistration.setServletSecurity.ise=Security constraints can't be added to servlet [{0}] deployed to context with path [{1}] as the context has already been initialised
 aprListener.aprInit=The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: {0}
 aprListener.tcnInvalid=An incompatible version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat requires version {1} 
 aprListener.tcnVersion=An older version {0} of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of {1}

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=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Jan 21 02:57:10 2010
@@ -2154,6 +2154,13 @@
     }
 
 
+    /**
+     * Has this context been initialized?
+     */
+    public boolean isInitialized() {
+        return initialized;
+    }
+
     // -------------------------------------------------------- Context Methods
 
 
@@ -5842,20 +5849,6 @@
         start();
     }
     
-    public int getState() {
-        if( started ) {
-            return 1; // RUNNING
-        }
-        if( initialized ) {
-            return 0; // starting ? 
-        }
-        if( ! available ) { 
-            return 4; //FAILED
-        }
-        // 2 - STOPPING
-        return 3; // STOPPED
-    }
-    
     /**
      * The J2EE Server ObjectName this module is deployed on.
      */     

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=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardWrapper.java Thu Jan 21 02:57:10 2010
@@ -648,6 +648,21 @@
     }
 
 
+    /**
+     * Return the associated servlet instance.
+     */
+    public Servlet getServlet() {
+        return instance;
+    }
+    
+    
+    /**
+     * Set the associated servlet instance.
+     */
+    public void setServlet(Servlet servlet) {
+        instance = servlet;
+    }
+
     // --------------------------------------------------------- Public Methods
 
 
@@ -765,14 +780,6 @@
 
 
     /**
-     * Return the associated servlet instance.
-     */
-    public Servlet getServlet() {
-        return instance;
-    }
-    
-    
-    /**
      * Allocate an initialized instance of this Servlet that is ready to have
      * its <code>service()</code> method called.  If the servlet class does
      * not implement <code>SingleThreadModel</code>, the (only) initialized

Modified: tomcat/trunk/java/org/apache/catalina/deploy/FilterDef.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/FilterDef.java?rev=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/FilterDef.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/FilterDef.java Thu Jan 21 02:57:10 2010
@@ -23,6 +23,8 @@
 import java.util.Map;
 import java.io.Serializable;
 
+import javax.servlet.Filter;
+
 
 /**
  * Representation of a filter definition for a web application, as represented
@@ -66,7 +68,21 @@
         this.displayName = displayName;
     }
 
+    
+    /**
+     * The filter instance associated with this definition
+     */
+    private Filter filter = null;
+    
+    public Filter getFilter() {
+        return filter;
+    }
 
+    public void setFilter(Filter filter) {
+        this.filter = filter;
+    }
+    
+    
     /**
      * The fully qualified name of the Java class that implements this filter.
      */

Modified: tomcat/trunk/java/org/apache/catalina/deploy/SecurityCollection.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/SecurityCollection.java?rev=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/SecurityCollection.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/SecurityCollection.java Thu Jan 21 02:57:10 2010
@@ -115,6 +115,12 @@
     private String patterns[] = new String[0];
 
 
+    /**
+     * This security collection was established by a deployment descriptor.
+     * Defaults to <code>true</code>.
+     */
+    private boolean isFromDescriptor = true;
+
     // ------------------------------------------------------------- Properties
 
 
@@ -162,6 +168,22 @@
     }
 
 
+    /**
+     * Return if this constraint was defined in a deployment descriptor.
+     */
+    public boolean isFromDescriptor() {
+        return isFromDescriptor;
+    }
+
+
+    /**
+     * Set if this constraint was defined in a deployment descriptor.
+     */
+    public void setFromDescriptor(boolean isFromDescriptor) {
+        this.isFromDescriptor = isFromDescriptor;
+    }
+
+
     // --------------------------------------------------------- Public Methods
 
 

Modified: tomcat/trunk/java/org/apache/catalina/deploy/SecurityConstraint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/SecurityConstraint.java?rev=901507&r1=901506&r2=901507&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/SecurityConstraint.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/SecurityConstraint.java Thu Jan 21 02:57:10 2010
@@ -19,6 +19,16 @@
 package org.apache.catalina.deploy;
 
 import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.servlet.HttpConstraintElement;
+import javax.servlet.HttpMethodConstraintElement;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
 
 
 /**
@@ -459,4 +469,81 @@
     }
 
 
+    /**
+     * Convert a {@link ServletSecurityElement} to an array of
+     * {@link SecurityConstraint}(s).
+     * 
+     * @param element       The element to be converted
+     * @param urlPattern    The url pattern that the element should be applied
+     *                      to
+     * @return              The (possibly zero length) array of constraints that
+     *                      are the equivalent to the input
+     */
+    public static SecurityConstraint[] createConstraints(
+            ServletSecurityElement element, String urlPattern) {
+        Set<SecurityConstraint> result = new HashSet<SecurityConstraint>();
+        
+        // Add the per method constraints
+        Collection<HttpMethodConstraintElement> methods =
+            element.getHttpMethodConstraints();
+        Iterator<HttpMethodConstraintElement> methodIter = methods.iterator();
+        while (methodIter.hasNext()) {
+            HttpMethodConstraintElement methodElement = methodIter.next();
+            SecurityConstraint constraint =
+                createConstraint(methodElement, urlPattern, true);
+            // There will always be a single collection
+            SecurityCollection collection = constraint.findCollections()[0];
+            collection.addMethod(methodElement.getMethodName());
+            result.add(constraint);
+        }
+        
+        // Add the constraint for all the other methods
+        SecurityConstraint constraint = createConstraint(element, urlPattern, false);
+        if (constraint != null) {
+            // There will always be a single collection
+            SecurityCollection collection = constraint.findCollections()[0];
+            Iterator<String> ommittedMethod = element.getMethodNames().iterator();
+            while (ommittedMethod.hasNext()) {
+                collection.addOmittedMethod(ommittedMethod.next());
+            }
+            
+            result.add(constraint);
+            
+        }
+        
+        return result.toArray(new SecurityConstraint[result.size()]);
+    }
+    
+    private static SecurityConstraint createConstraint(
+            HttpConstraintElement element, String urlPattern, boolean alwaysCreate) {
+
+        SecurityConstraint constraint = new SecurityConstraint();
+        SecurityCollection collection = new SecurityCollection();
+        boolean create = alwaysCreate;
+        
+        if (element.getTransportGuarantee() !=
+                ServletSecurity.TransportGuarantee.NONE) {
+            constraint.setUserConstraint(element.getTransportGuarantee().name());
+            create = true;
+        }
+        if (element.getRolesAllowed().length > 0) {
+            String[] roles = element.getRolesAllowed();
+            for (String role : roles) {
+                constraint.addAuthRole(role);
+            }
+            create = true;
+        }
+        if (element.getEmptyRoleSemantic() != EmptyRoleSemantic.PERMIT) {
+            constraint.setAuthConstraint(true);
+            create = true;
+        }
+        
+        if (create) {
+            collection.addPattern(urlPattern);
+            constraint.addCollection(collection);
+            return constraint;
+        }
+        
+        return null;
+    }
 }

Added: tomcat/trunk/test/org/apache/catalina/deploy/TestSecurityConstraint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/deploy/TestSecurityConstraint.java?rev=901507&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/deploy/TestSecurityConstraint.java (added)
+++ tomcat/trunk/test/org/apache/catalina/deploy/TestSecurityConstraint.java Thu Jan 21 02:57:10 2010
@@ -0,0 +1,193 @@
+package org.apache.catalina.deploy;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.HttpConstraintElement;
+import javax.servlet.HttpMethodConstraintElement;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
+
+import junit.framework.TestCase;
+
+public class TestSecurityConstraint extends TestCase {
+
+    private static final String URL_PATTERN = "/test";
+    private static final String ROLE1 = "R1";
+
+    /**
+     * Uses the examples in SRV.13.4 as the basis for these tests
+     */
+    public void testCreateConstraints() {
+        
+        ServletSecurityElement element;
+        SecurityConstraint[] result;
+        Set<HttpMethodConstraintElement> hmces =
+            new HashSet<HttpMethodConstraintElement>();
+        
+        // Example 13-1
+        // @ServletSecurity 
+        element = new ServletSecurityElement();
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+
+        assertEquals(0, result.length);
+
+        // Example 13-2
+        // @ServletSecurity(
+        //     @HttpConstraint(
+        //         transportGuarantee = TransportGuarantee.CONFIDENTIAL))
+        element = new ServletSecurityElement(
+                new HttpConstraintElement(
+                        ServletSecurity.TransportGuarantee.CONFIDENTIAL));
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+
+        assertEquals(1, result.length);
+        assertEquals(false, result[0].getAuthConstraint());
+        assertEquals(true,
+                result[0].findCollections()[0].findPattern(URL_PATTERN));
+        assertEquals(0, result[0].findCollections()[0].findMethods().length);
+        assertEquals(ServletSecurity.TransportGuarantee.CONFIDENTIAL.name(),
+                result[0].getUserConstraint());
+        
+        // Example 13-3
+        // @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY)) 
+        element = new ServletSecurityElement(
+                new HttpConstraintElement(EmptyRoleSemantic.DENY));
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+
+        assertEquals(1, result.length);
+        assertEquals(true, result[0].getAuthConstraint());
+        assertEquals(true,
+                result[0].findCollections()[0].findPattern(URL_PATTERN));
+        assertEquals(0, result[0].findCollections()[0].findMethods().length);
+        assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
+                result[0].getUserConstraint());
+        
+        // Example 13-4
+        // @ServletSecurity(@HttpConstraint(rolesAllowed = "R1")) 
+        element = new ServletSecurityElement(new HttpConstraintElement(
+                ServletSecurity.TransportGuarantee.NONE, ROLE1));
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+
+        assertEquals(1, result.length);
+        assertEquals(true, result[0].getAuthConstraint());
+        assertEquals(1, result[0].findAuthRoles().length);
+        assertEquals(true, result[0].findAuthRole(ROLE1));
+        assertEquals(true,
+                result[0].findCollections()[0].findPattern(URL_PATTERN));
+        assertEquals(0, result[0].findCollections()[0].findMethods().length);
+        assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
+                result[0].getUserConstraint());
+
+        // Example 13-5
+        // @ServletSecurity((httpMethodConstraints = { 
+        //     @HttpMethodConstraint(value = "GET", rolesAllowed = "R1"), 
+        //     @HttpMethodConstraint(value = "POST", rolesAllowed = "R1", 
+        //     transportGuarantee = TransportGuarantee.CONFIDENTIAL) 
+        // })
+        hmces.clear();
+        hmces.add(new HttpMethodConstraintElement("GET",
+                new HttpConstraintElement(
+                        ServletSecurity.TransportGuarantee.NONE, ROLE1)));
+        hmces.add(new HttpMethodConstraintElement("POST",
+                new HttpConstraintElement(
+                        ServletSecurity.TransportGuarantee.CONFIDENTIAL,
+                        ROLE1)));
+        element = new ServletSecurityElement(hmces);
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+        
+        assertEquals(2, result.length);
+        for (int i = 0; i < 2; i++) {
+            assertEquals(true, result[i].getAuthConstraint());
+            assertEquals(1, result[i].findAuthRoles().length);
+            assertEquals(true, result[i].findAuthRole(ROLE1));
+            assertEquals(true,
+                    result[i].findCollections()[0].findPattern(URL_PATTERN));
+            assertEquals(1, result[i].findCollections()[0].findMethods().length);
+            String method = result[i].findCollections()[0].findMethods()[0];
+            if ("GET".equals(method)) {
+                assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
+                        result[i].getUserConstraint());
+            } else if ("POST".equals(method)) {
+                assertEquals(ServletSecurity.TransportGuarantee.CONFIDENTIAL.name(),
+                        result[i].getUserConstraint());
+            } else {
+                fail("Unexpected method :[" + method + "]");
+            }
+        }
+        
+        // Example 13-6
+        // @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"), 
+        //     httpMethodConstraints = @HttpMethodConstraint("GET"))
+        hmces.clear();
+        hmces.add(new HttpMethodConstraintElement("GET"));
+        element = new ServletSecurityElement(
+                new HttpConstraintElement(
+                        ServletSecurity.TransportGuarantee.NONE,
+                        ROLE1),
+                hmces);
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+        
+        assertEquals(2, result.length);
+        for (int i = 0; i < 2; i++) {
+            assertEquals(true,
+                    result[i].findCollections()[0].findPattern(URL_PATTERN));
+            if (result[i].findCollections()[0].findMethods().length == 1) {
+                assertEquals("GET",
+                        result[i].findCollections()[0].findMethods()[0]);
+                assertEquals(false, result[i].getAuthConstraint());
+            } else if (result[i].findCollections()[0].findOmittedMethods().length == 1) {
+                assertEquals("GET",
+                        result[i].findCollections()[0].findOmittedMethods()[0]);
+                assertEquals(true, result[i].getAuthConstraint());
+                assertEquals(1, result[i].findAuthRoles().length);
+                assertEquals(ROLE1, result[i].findAuthRoles()[0]);
+            } else {
+                fail("Unexpected number of methods defined");
+            }
+            assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
+                    result[i].getUserConstraint());
+        }
+        
+        // Example 13-7
+        // @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"), 
+        //     httpMethodConstraints = @HttpMethodConstraint(value="TRACE", 
+        //         emptyRoleSemantic = EmptyRoleSemantic.DENY))
+        hmces.clear();
+        hmces.add(new HttpMethodConstraintElement("TRACE",
+                new HttpConstraintElement(EmptyRoleSemantic.DENY)));
+        element = new ServletSecurityElement(
+                new HttpConstraintElement(
+                        ServletSecurity.TransportGuarantee.NONE,
+                        ROLE1),
+                hmces);
+        result = SecurityConstraint.createConstraints(element, URL_PATTERN);
+        
+        assertEquals(2, result.length);
+        for (int i = 0; i < 2; i++) {
+            assertEquals(true,
+                    result[i].findCollections()[0].findPattern(URL_PATTERN));
+            if (result[i].findCollections()[0].findMethods().length == 1) {
+                assertEquals("TRACE",
+                        result[i].findCollections()[0].findMethods()[0]);
+                assertEquals(true, result[i].getAuthConstraint());
+                assertEquals(0, result[i].findAuthRoles().length);
+            } else if (result[i].findCollections()[0].findOmittedMethods().length == 1) {
+                assertEquals("TRACE",
+                        result[i].findCollections()[0].findOmittedMethods()[0]);
+                assertEquals(true, result[i].getAuthConstraint());
+                assertEquals(1, result[i].findAuthRoles().length);
+                assertEquals(ROLE1, result[i].findAuthRoles()[0]);
+            } else {
+                fail("Unexpected number of methods defined");
+            }
+            assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
+                    result[i].getUserConstraint());
+        }
+        
+        // Example 13-8 is the same as 13-4
+        // Example 13-9 is the same as 13-7
+    }
+
+}



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