Author: markt Date: Thu Jul 16 19:34:49 2009 New Revision: 794798 URL: http://svn.apache.org/viewvc?rev=794798&view=rev Log: More GSOC work from Xie Xiadong Initial implementation of RemoteHost and RemoteAddr filters.
Added: tomcat/trunk/java/org/apache/catalina/filters/Constants.java (with props) tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java (with props) tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties (with props) tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties (with props) tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties (with props) tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java (with props) tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java (with props) tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java (with props) Added: tomcat/trunk/java/org/apache/catalina/filters/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/Constants.java?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/Constants.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/Constants.java Thu Jul 16 19:34:49 2009 @@ -0,0 +1,34 @@ +/* + * 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.filters; + + +/** + * Manifest constants for this Java package. + * + * + * @author Craig R. McClanahan + * @version $Revision$ $Date$ + */ + +public final class Constants { + + public static final String Package = "org.apache.catalina.filters"; + +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/Constants.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/Constants.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java Thu Jul 16 19:34:49 2009 @@ -0,0 +1,92 @@ +/* + * 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.filters; + +import java.util.Enumeration; + +import javax.servlet.Filter; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.juli.logging.Log; +import org.apache.tomcat.util.IntrospectionUtils; +import org.apache.tomcat.util.res.StringManager; + +/** + * Base class for filters that provide some utility methods. + * + * @author xxd + * + */ +public abstract class FilterBase implements Filter { + + protected static final StringManager sm = + StringManager.getManager(Constants.Package); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Enumeration<String> paramNames = filterConfig.getInitParameterNames(); + while (paramNames.hasMoreElements()) { + String paramName = paramNames.nextElement(); + if (!IntrospectionUtils.setProperty(this, paramName, + filterConfig.getInitParameter(paramName))) { + getLogger().warn(sm.getString("filterbase.noSuchProperty", + paramName, this.getClass().getName())); + } + } + } + + /** + * Whether the request object is an HttpServletRequest or not. + * + * @param request + * @return + */ + protected boolean isHttpServletRequest(ServletRequest request) { + return request instanceof HttpServletRequest; + } + + /** + * Whether the response object is an HttpServletResponse or not. + * + * @param response + * @return + */ + protected boolean isHttpServletResponse(ServletResponse response) { + return response instanceof HttpServletResponse; + } + + /** + * Whether the corresponding Servlet is an HttpServlet or not. + * + * @param request + * @param response + * @return + */ + protected boolean isHttpServlet(ServletRequest request, + ServletResponse response) { + return isHttpServletRequest(request) && isHttpServletResponse(response); + } + + protected abstract Log getLogger(); + +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/FilterBase.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties (added) +++ tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties Thu Jul 16 19:34:49 2009 @@ -0,0 +1,18 @@ +# 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. + +filterbase.noSuchProperty=The property "{0}" is not defined for filters of type "{1}" + +http.403=Access to the specified resource ({0}) has been forbidden. Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings.properties ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties (added) +++ tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties Thu Jul 16 19:34:49 2009 @@ -0,0 +1,16 @@ +# 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. + +http.403=El acceso al recurso especificado ({0}) ha sido prohibido. Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_es.properties ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties (added) +++ tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties Thu Jul 16 19:34:49 2009 @@ -0,0 +1,16 @@ +# 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. + +http.403=L''acc\u00e8s \u00e0 la ressource demand\u00e9e ({0}) a \u00e9t\u00e9 interdit. Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/LocalStrings_fr.properties ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java Thu Jul 16 19:34:49 2009 @@ -0,0 +1,79 @@ +/* + * 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.filters; + + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + + +/** + * Concrete implementation of <code>RequestFilterFilter</code> that filters + * based on the string representation of the remote client's IP address. + * + * @author Craig R. McClanahan + * + */ + +public final class RemoteAddrFilter + extends RequestFilter { + + // ----------------------------------------------------- Instance Variables + private static Log log = LogFactory.getLog(RemoteAddrFilter.class); + + + // ------------------------------------------------------------- Properties + + + + // --------------------------------------------------------- Public Methods + + + /** + * Extract the desired request property, and pass it (along with the + * specified request and response objects) to the protected + * <code>process()</code> method to perform the actual filtering. + * This method must be implemented by a concrete subclass. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * + * @exception IOException if an input/output error occurs + * @exception ServletException if a servlet error occurs + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + process(request.getRemoteAddr(), request, response, chain); + + } + + protected Log getLogger() { + return log; + } + +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/RemoteAddrFilter.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java Thu Jul 16 19:34:49 2009 @@ -0,0 +1,79 @@ +/* + * 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.filters; + + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + + +/** + * Concrete implementation of <code>RequestFilterFilter</code> that filters + * based on the remote client's host name. + * + * @author Craig R. McClanahan + * + */ + +public final class RemoteHostFilter + extends RequestFilter { + + + // ----------------------------------------------------- Instance Variables + private static Log log = LogFactory.getLog(RemoteHostFilter.class); + + + // ------------------------------------------------------------- Properties + + + + // --------------------------------------------------------- Public Methods + + + /** + * Extract the desired request property, and pass it (along with the + * specified request and response objects) to the protected + * <code>process()</code> method to perform the actual filtering. + * This method must be implemented by a concrete subclass. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * + * @exception IOException if an input/output error occurs + * @exception ServletException if a servlet error occurs + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + process(request.getRemoteHost(), request, response, chain); + + } + + protected Log getLogger() { + return log; + } +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/RemoteHostFilter.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java?rev=794798&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java (added) +++ tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java Thu Jul 16 19:34:49 2009 @@ -0,0 +1,304 @@ +/* + * 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.filters; + + +import java.io.IOException; +import java.util.ArrayList; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tomcat.util.res.StringManager; + +/** + * Implementation of a Filter that performs filtering based on comparing the + * appropriate request property (selected based on which subclass you choose + * to configure into your Container's pipeline) against a set of regular + * expressions configured for this Filter. + * <p> + * This filter is configured by setting the <code>allow</code> and/or + * <code>deny</code> properties to a comma-delimited list of regular + * expressions (in the syntax supported by the jakarta-regexp library) to + * which the appropriate request property will be compared. Evaluation + * proceeds as follows: + * <ul> + * <li>The subclass extracts the request property to be filtered, and + * calls the common <code>process()</code> method. + * <li>If there are any deny expressions configured, the property will + * be compared to each such expression. If a match is found, this + * request will be rejected with a "Forbidden" HTTP response.</li> + * <li>If there are any allow expressions configured, the property will + * be compared to each such expression. If a match is found, this + * request will be allowed to pass through to the next filter in the + * current pipeline.</li> + * <li>If one or more deny expressions was specified but no allow expressions, + * allow this request to pass through (because none of the deny + * expressions matched it). + * <li>The request will be rejected with a "Forbidden" HTTP response.</li> + * </ul> + * <p> + * This Filter may be attached to any Container, depending on the granularity + * of the filtering you wish to perform. + * + * @author Craig R. McClanahan + * + */ + +public abstract class RequestFilter + extends FilterBase { + + + // ----------------------------------------------------- Class Variables + + + /** + * The StringManager for this package. + */ + protected static StringManager sm = + StringManager.getManager(Constants.Package); + + + // ----------------------------------------------------- Instance Variables + + /** + * The comma-delimited set of <code>allow</code> expressions. + */ + protected String allow = null; + + + /** + * The set of <code>allow</code> regular expressions we will evaluate. + */ + protected Pattern allows[] = new Pattern[0]; + + + /** + * The set of <code>deny</code> regular expressions we will evaluate. + */ + protected Pattern denies[] = new Pattern[0]; + + + /** + * The comma-delimited set of <code>deny</code> expressions. + */ + protected String deny = null; + + /** + * mime type -- "text/plain" + */ + private static final String PLAIN_TEXT_MIME_TYPE = "text/plain"; + + + // ------------------------------------------------------------- Properties + + + /** + * Return a comma-delimited set of the <code>allow</code> expressions + * configured for this Filter, if any; otherwise, return <code>null</code>. + */ + public String getAllow() { + + return (this.allow); + + } + + + /** + * Set the comma-delimited set of the <code>allow</code> expressions + * configured for this Filter, if any. + * + * @param allow The new set of allow expressions + */ + public void setAllow(String allow) { + + this.allow = allow; + this.allows = precalculate(allow); + + } + + + /** + * Return a comma-delimited set of the <code>deny</code> expressions + * configured for this Filter, if any; otherwise, return <code>null</code>. + */ + public String getDeny() { + + return (this.deny); + + } + + + /** + * Set the comma-delimited set of the <code>deny</code> expressions + * configured for this Filter, if any. + * + * @param deny The new set of deny expressions + */ + public void setDeny(String deny) { + + + this.deny = deny; + this.denies = precalculate(deny); + + } + + + // --------------------------------------------------------- Public Methods + + + /* (non-Javadoc) + * @see javax.servlet.Filter#destroy() + */ + @Override + public void destroy() { + // NOOP + } + + /** + * Extract the desired request property, and pass it (along with the + * specified request and response objects) to the protected + * <code>process()</code> method to perform the actual filtering. + * This method must be implemented by a concrete subclass. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * @param chain The filter chain + * + * @exception IOException if an input/output error occurs + * @exception ServletException if a servlet error occurs + */ + @Override + public abstract void doFilter(ServletRequest request, + ServletResponse response, FilterChain chain) throws IOException, + ServletException; + + + // ------------------------------------------------------ Protected Methods + + + /** + * Return an array of regular expression objects initialized from the + * specified argument, which must be <code>null</code> or a comma-delimited + * list of regular expression patterns. + * + * @param list The comma-separated list of patterns + * + * @exception IllegalArgumentException if one of the patterns has + * invalid syntax + */ + protected Pattern[] precalculate(String list) { + + if (list == null) + return (new Pattern[0]); + list = list.trim(); + if (list.length() < 1) + return (new Pattern[0]); + list += ","; + + ArrayList<Pattern> reList = new ArrayList<Pattern>(); + while (list.length() > 0) { + int comma = list.indexOf(','); + if (comma < 0) + break; + String pattern = list.substring(0, comma).trim(); + try { + reList.add(Pattern.compile(pattern)); + } catch (PatternSyntaxException e) { + IllegalArgumentException iae = new IllegalArgumentException + (sm.getString("requestFilterFilter.syntax", pattern)); + iae.initCause(e); + throw iae; + } + list = list.substring(comma + 1); + } + + Pattern reArray[] = new Pattern[reList.size()]; + return reList.toArray(reArray); + + } + + + /** + * Perform the filtering that has been configured for this Filter, matching + * against the specified request property. + * + * @param property The request property on which to filter + * @param request The servlet request to be processed + * @param response The servlet response to be processed + * + * @exception IOException if an input/output error occurs + * @exception ServletException if a servlet error occurs + */ + protected void process(String property, ServletRequest request, + ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + // Check the deny patterns, if any + for (int i = 0; i < this.denies.length; i++) { + if (this.denies[i].matcher(property).matches()) { + if (isHttpServletResponse(response)) { + ((HttpServletResponse) response) + .sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } else { + sendErrorWhenNotHttp(response); + return; + } + } + } + + // Check the allow patterns, if any + for (int i = 0; i < this.allows.length; i++) { + if (this.allows[i].matcher(property).matches()) { + chain.doFilter(request, response); + return; + } + } + + // Allow if denies specified but not allows + if ((this.denies.length > 0) && (this.allows.length == 0)) { + chain.doFilter(request, response); + return; + } + + // Deny this request + if (isHttpServletResponse(response)) { + ((HttpServletResponse) response) + .sendError(HttpServletResponse.SC_FORBIDDEN); + } else { + sendErrorWhenNotHttp(response); + } + } + + + private void sendErrorWhenNotHttp(ServletResponse response) + throws IOException { + response.setContentType(PLAIN_TEXT_MIME_TYPE); + response.getWriter().write(sm.getString("http.403")); + response.getWriter().flush(); + } + + +} Propchange: tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/filters/RequestFilter.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org