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 <host> 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 <host> 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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org