Author: remm Date: Tue Apr 4 15:34:09 2006 New Revision: 391432 URL: http://svn.apache.org/viewcvs?rev=391432&view=rev Log: - Add support for multiple servlet and filter mappings. - Fix a bug I found by accident where application listeners are not reinitialized when reloading. - That's all folks, all the useful Servlet 2.5 features are done. Now the annotations ... (sigh) - Reuse the ignoreAnnotations field name from the patch submitted by Fabien Carrion.
Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/Context.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterFactory.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/deploy/FilterMap.java tomcat/tc6.0.x/trunk/java/org/apache/catalina/startup/WebRuleSet.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/digester/CallMethodRule.java Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/Context.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/Context.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/Context.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/Context.java Tue Apr 4 15:34:09 2006 @@ -259,6 +259,21 @@ /** + * Return the boolean on the annotations parsing. + */ + public boolean getIgnoreAnnotations(); + + + /** + * Set the boolean on the annotations parsing for this web + * application. + * + * @param ignoreAnnotations The boolean on the annotations parsing + */ + public void setIgnoreAnnotations(boolean ignoreAnnotations); + + + /** * Return the login configuration descriptor for this web application. */ public LoginConfig getLoginConfig(); Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterFactory.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterFactory.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterFactory.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterFactory.java Tue Apr 4 15:34:09 2006 @@ -212,7 +212,30 @@ return (false); // Match on context relative request path - String testPath = filterMap.getURLPattern(); + String[] testPaths = filterMap.getURLPatterns(); + + for (int i = 0; i < testPaths.length; i++) { + if (matchFiltersURL(testPaths[i], requestPath)) { + return (true); + } + } + + // No match + return (false); + + } + + + /** + * Return <code>true</code> if the context-relative request path + * matches the requirements of the specified filter mapping; + * otherwise, return <code>false</code>. + * + * @param testPath URL mapping being checked + * @param requestPath Context-relative request path of this request + */ + private boolean matchFiltersURL(String testPath, String requestPath) { + if (testPath == null) return (false); @@ -268,11 +291,13 @@ if (servletName == null) { return (false); } else { - if (servletName.equals(filterMap.getServletName())) { - return (true); - } else { - return false; + String[] servletNames = filterMap.getServletNames(); + for (int i = 0; i < servletNames.length; i++) { + if (servletName.equals(servletNames[i])) { + return (true); + } } + return false; } } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java Tue Apr 4 15:34:09 2006 @@ -301,7 +301,7 @@ private boolean delegate = false; - /** + /** * The display name of this web application. */ private String displayName = null; @@ -360,6 +360,12 @@ /** + * Ignore annotations. + */ + private boolean ignoreAnnotations = false; + + + /** * The set of classnames of InstanceListeners that will be added * to each newly created Wrapper by <code>createWrapper()</code>. */ @@ -1301,6 +1307,28 @@ /** + * Return the boolean on the annotations parsing. + */ + public boolean getIgnoreAnnotations() { + return this.ignoreAnnotations; + } + + + /** + * Set the boolean on the annotations parsing for this web + * application. + * + * @param ignoreAnnotations The boolean on the annotations parsing + */ + public void setIgnoreAnnotations(boolean ignoreAnnotations) { + boolean oldIgnoreAnnotations = this.ignoreAnnotations; + this.ignoreAnnotations = ignoreAnnotations; + support.firePropertyChange("ignoreAnnotations", Boolean.valueOf(oldIgnoreAnnotations), + Boolean.valueOf(this.ignoreAnnotations)); + } + + + /** * Return the login configuration descriptor for this web application. */ public LoginConfig getLoginConfig() { @@ -2061,23 +2089,29 @@ // Validate the proposed filter mapping String filterName = filterMap.getFilterName(); - String servletName = filterMap.getServletName(); - String urlPattern = filterMap.getURLPattern(); + String[] servletNames = filterMap.getServletNames(); + String[] urlPatterns = filterMap.getURLPatterns(); if (findFilterDef(filterName) == null) throw new IllegalArgumentException (sm.getString("standardContext.filterMap.name", filterName)); - if ((servletName == null) && (urlPattern == null)) + if ((servletNames.length == 0) && (urlPatterns.length == 0)) throw new IllegalArgumentException (sm.getString("standardContext.filterMap.either")); - if ((servletName != null) && (urlPattern != null)) + // FIXME: Older spec revisions may still check this + /* + if ((servletNames.length != 0) && (urlPatterns.length != 0)) throw new IllegalArgumentException (sm.getString("standardContext.filterMap.either")); + */ // Because filter-pattern is new in 2.3, no need to adjust // for 2.2 backwards compatibility - if ((urlPattern != null) && !validateURLPattern(urlPattern)) - throw new IllegalArgumentException - (sm.getString("standardContext.filterMap.pattern", - urlPattern)); + for (int i = 0; i < urlPatterns.length; i++) { + if (!validateURLPattern(urlPatterns[i])) { + throw new IllegalArgumentException + (sm.getString("standardContext.filterMap.pattern", + urlPatterns[i])); + } + } // Add this filter mapping to our registered set synchronized (filterMaps) { @@ -4446,7 +4480,7 @@ lifecycle.fireLifecycleEvent(DESTROY_EVENT, null); instanceListeners = new String[0]; - applicationListeners = new String[0]; + } private void resetContext() throws Exception, MBeanRegistrationException { @@ -4460,6 +4494,10 @@ // Bugzilla 32867 distributable = false; + applicationListeners = new String[0]; + applicationEventListenersObjects = new Object[0]; + applicationLifecycleListenersObjects = new Object[0]; + if(log.isDebugEnabled()) log.debug("resetContext " + oname + " " + mserver); } Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/deploy/FilterMap.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/deploy/FilterMap.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/deploy/FilterMap.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/deploy/FilterMap.java Tue Apr 4 15:34:09 2006 @@ -79,14 +79,17 @@ /** * The servlet name this mapping matches. */ - private String servletName = null; + private String[] servletNames = new String[0]; - public String getServletName() { - return (this.servletName); + public String[] getServletNames() { + return (this.servletNames); } - public void setServletName(String servletName) { - this.servletName = servletName; + public void addServletName(String servletName) { + String[] results = new String[servletNames.length + 1]; + System.arraycopy(servletNames, 0, results, 0, servletNames.length); + results[servletNames.length] = servletName; + servletNames = results; } @@ -103,17 +106,20 @@ /** * The URL pattern this mapping matches. */ - private String urlPattern = null; + private String[] urlPatterns = new String[0]; - public String getURLPattern() { - return (this.urlPattern); + public String[] getURLPatterns() { + return (this.urlPatterns); } - public void setURLPattern(String urlPattern) { + public void addURLPattern(String urlPattern) { if ("*".equals(urlPattern)) { this.allMatch = true; } else { - this.urlPattern = RequestUtil.URLDecode(urlPattern); + String[] results = new String[urlPatterns.length + 1]; + System.arraycopy(urlPatterns, 0, results, 0, urlPatterns.length); + results[urlPatterns.length] = RequestUtil.URLDecode(urlPattern); + urlPatterns = results; } } @@ -211,13 +217,13 @@ StringBuffer sb = new StringBuffer("FilterMap["); sb.append("filterName="); sb.append(this.filterName); - if (servletName != null) { + for (int i = 0; i < servletNames.length; i++) { sb.append(", servletName="); - sb.append(servletName); + sb.append(servletNames[i]); } - if (urlPattern != null) { + for (int i = 0; i < urlPatterns.length; i++) { sb.append(", urlPattern="); - sb.append(urlPattern); + sb.append(urlPatterns[i]); } sb.append("]"); return (sb.toString()); Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/startup/WebRuleSet.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/startup/WebRuleSet.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/startup/WebRuleSet.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/startup/WebRuleSet.java Tue Apr 4 15:34:09 2006 @@ -19,9 +19,14 @@ import java.lang.reflect.Method; +import java.util.ArrayList; + import org.apache.catalina.Context; import org.apache.catalina.Wrapper; import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.tomcat.util.IntrospectionUtils; +import org.apache.tomcat.util.digester.CallMethodRule; +import org.apache.tomcat.util.digester.CallParamRule; import org.apache.tomcat.util.digester.Digester; import org.apache.tomcat.util.digester.Rule; import org.apache.tomcat.util.digester.RuleSetBase; @@ -115,6 +120,8 @@ digester.addRule(prefix + "web-app", new SetPublicIdRule("setPublicId")); + digester.addRule(prefix + "web-app", + new IgnoreAnnotationsRule()); digester.addCallMethod(prefix + "web-app/context-param", "addParameter", 2); @@ -222,15 +229,15 @@ digester.addObjectCreate(prefix + "web-app/filter-mapping", "org.apache.catalina.deploy.FilterMap"); digester.addSetNext(prefix + "web-app/filter-mapping", - "addFilterMap", - "org.apache.catalina.deploy.FilterMap"); + "addFilterMap", + "org.apache.catalina.deploy.FilterMap"); digester.addCallMethod(prefix + "web-app/filter-mapping/filter-name", "setFilterName", 0); digester.addCallMethod(prefix + "web-app/filter-mapping/servlet-name", - "setServletName", 0); + "addServletName", 0); digester.addCallMethod(prefix + "web-app/filter-mapping/url-pattern", - "setURLPattern", 0); + "addURLPattern", 0); digester.addCallMethod(prefix + "web-app/filter-mapping/dispatcher", "setDispatcher", 0); @@ -392,10 +399,10 @@ digester.addCallMethod(prefix + "web-app/servlet/servlet-name", "setName", 0); - digester.addCallMethod(prefix + "web-app/servlet-mapping", - "addServletMapping", 2); + digester.addRule(prefix + "web-app/servlet-mapping", + new CallMethodMultiRule("addServletMapping", 2, 0)); digester.addCallParam(prefix + "web-app/servlet-mapping/servlet-name", 1); - digester.addCallParam(prefix + "web-app/servlet-mapping/url-pattern", 0); + digester.addRule(prefix + "web-app/servlet-mapping/url-pattern", new CallParamMultiRule(0)); digester.addRule(prefix + "web-app/session-config", sessionConfig); @@ -611,6 +618,142 @@ Wrapper wrapper = (Wrapper) digester.pop(); if (digester.getLogger().isDebugEnabled()) digester.getLogger().debug("pop " + wrapper.getClass().getName()); + } + +} + + +/** + * A Rule that can be used to call multiple times a method as many times as needed + * (used for addServletMapping). + */ +final class CallParamMultiRule extends CallParamRule { + + public CallParamMultiRule(int paramIndex) { + super(paramIndex); + } + + public void end(String namespace, String name) { + if (bodyTextStack != null && !bodyTextStack.empty()) { + // what we do now is push one parameter onto the top set of parameters + Object parameters[] = (Object[]) digester.peekParams(); + ArrayList params = (ArrayList) parameters[paramIndex]; + if (params == null) { + params = new ArrayList(); + parameters[paramIndex] = params; + } + params.add(bodyTextStack.pop()); + } + } + +} + + +/** + * A Rule that can be used to call multiple times a method as many times as needed + * (used for addServletMapping). + */ +final class CallMethodMultiRule extends CallMethodRule { + + protected int multiParamIndex = 0; + + public CallMethodMultiRule(String methodName, int paramCount, int multiParamIndex) { + super(methodName, paramCount); + this.multiParamIndex = multiParamIndex; + } + + public void end() throws Exception { + + // Retrieve or construct the parameter values array + Object parameters[] = null; + if (paramCount > 0) { + parameters = (Object[]) digester.popParams(); + } else { + super.end(); + } + + ArrayList multiParams = (ArrayList) parameters[multiParamIndex]; + + // Construct the parameter values array we will need + // We only do the conversion if the param value is a String and + // the specified paramType is not String. + Object paramValues[] = new Object[paramTypes.length]; + for (int i = 0; i < paramTypes.length; i++) { + if (i != multiParamIndex) { + // convert nulls and convert stringy parameters + // for non-stringy param types + if(parameters[i] == null || (parameters[i] instanceof String + && !String.class.isAssignableFrom(paramTypes[i]))) { + paramValues[i] = + IntrospectionUtils.convert((String) parameters[i], paramTypes[i]); + } else { + paramValues[i] = parameters[i]; + } + } + } + + // Determine the target object for the method call + Object target; + if (targetOffset >= 0) { + target = digester.peek(targetOffset); + } else { + target = digester.peek(digester.getCount() + targetOffset); + } + + if (target == null) { + StringBuffer sb = new StringBuffer(); + sb.append("[CallMethodRule]{"); + sb.append(""); + sb.append("} Call target is null ("); + sb.append("targetOffset="); + sb.append(targetOffset); + sb.append(",stackdepth="); + sb.append(digester.getCount()); + sb.append(")"); + throw new org.xml.sax.SAXException(sb.toString()); + } + + for (int j = 0; j < multiParams.size(); j++) { + Object param = multiParams.get(j); + if(param == null || (param instanceof String + && !String.class.isAssignableFrom(paramTypes[multiParamIndex]))) { + paramValues[multiParamIndex] = + IntrospectionUtils.convert((String) param, paramTypes[multiParamIndex]); + } else { + paramValues[multiParamIndex] = param; + } + Object result = IntrospectionUtils.callMethodN(target, methodName, + paramValues, paramTypes); + } + + } + +} + + + +/** + * A Rule that check if the annotations have to be loaded. + * + */ + +final class IgnoreAnnotationsRule extends Rule { + + public IgnoreAnnotationsRule() { + } + + public void begin(String namespace, String name, Attributes attributes) + throws Exception { + Context context = (Context) digester.peek(digester.getCount() - 1); + String value = attributes.getValue("metadata-complete"); + if ("true".equals(value)) { + context.setIgnoreAnnotations(true); + } + if (digester.getLogger().isDebugEnabled()) { + digester.getLogger().debug + (context.getClass().getName() + ".setIgnoreAnnotations( " + + context.getIgnoreAnnotations() + ")"); + } } } Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/digester/CallMethodRule.java URL: http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/digester/CallMethodRule.java?rev=391432&r1=391431&r2=391432&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/digester/CallMethodRule.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/digester/CallMethodRule.java Tue Apr 4 15:34:09 2006 @@ -355,7 +355,7 @@ * top of the digester object stack. The default value of zero * means the target object is the one on top of the stack. */ - private int targetOffset = 0; + protected int targetOffset = 0; /** * The method name to call on the parent object. @@ -380,7 +380,7 @@ * The names of the classes of the parameters to be collected. * This attribute allows creation of the classes to be postponed until the digester is set. */ - private String paramClassNames[] = null; + protected String paramClassNames[] = null; /** * Should <code>MethodUtils.invokeExactMethod</code> be used for reflection. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]