\r
\r
/**\r
+ * Return the boolean on the annotations parsing.\r
+ */\r
+ public boolean getIgnoreAnnotations();\r
+ \r
+ \r
+ /**\r
+ * Set the boolean on the annotations parsing for this web \r
+ * application.\r
+ * \r
+ * @param ignoreAnnotations The boolean on the annotations parsing\r
+ */\r
+ public void setIgnoreAnnotations(boolean ignoreAnnotations);\r
+ \r
+ \r
+ /**\r
* Return the login configuration descriptor for this web application.\r
*/\r
public LoginConfig getLoginConfig();\r
return (false);\r
\r
// Match on context relative request path\r
- String testPath = filterMap.getURLPattern();\r
+ String[] testPaths = filterMap.getURLPatterns();\r
+ \r
+ for (int i = 0; i < testPaths.length; i++) {\r
+ if (matchFiltersURL(testPaths[i], requestPath)) {\r
+ return (true);\r
+ }\r
+ }\r
+ \r
+ // No match\r
+ return (false);\r
+ \r
+ }\r
+ \r
+\r
+ /**\r
+ * Return <code>true</code> if the context-relative request path\r
+ * matches the requirements of the specified filter mapping;\r
+ * otherwise, return <code>false</code>.\r
+ *\r
+ * @param testPath URL mapping being checked\r
+ * @param requestPath Context-relative request path of this request\r
+ */\r
+ private boolean matchFiltersURL(String testPath, String requestPath) {\r
+ \r
if (testPath == null)\r
return (false);\r
\r
if (servletName == null) {\r
return (false);\r
} else {\r
- if (servletName.equals(filterMap.getServletName())) {\r
- return (true);\r
- } else {\r
- return false;\r
+ String[] servletNames = filterMap.getServletNames();\r
+ for (int i = 0; i < servletNames.length; i++) {\r
+ if (servletName.equals(servletNames[i])) {\r
+ return (true);\r
+ }\r
}\r
+ return false;\r
}\r
\r
}\r
private boolean delegate = false;\r
\r
\r
- /**\r
+ /**\r
* The display name of this web application.\r
*/\r
private String displayName = null;\r
\r
\r
/**\r
+ * Ignore annotations.\r
+ */\r
+ private boolean ignoreAnnotations = false;\r
+\r
+\r
+ /**\r
* The set of classnames of InstanceListeners that will be added\r
* to each newly created Wrapper by <code>createWrapper()</code>.\r
*/\r
\r
\r
/**\r
+ * Return the boolean on the annotations parsing.\r
+ */\r
+ public boolean getIgnoreAnnotations() {\r
+ return this.ignoreAnnotations;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Set the boolean on the annotations parsing for this web \r
+ * application.\r
+ * \r
+ * @param ignoreAnnotations The boolean on the annotations parsing\r
+ */\r
+ public void setIgnoreAnnotations(boolean ignoreAnnotations) {\r
+ boolean oldIgnoreAnnotations = this.ignoreAnnotations;\r
+ this.ignoreAnnotations = ignoreAnnotations;\r
+ support.firePropertyChange("ignoreAnnotations", Boolean.valueOf(oldIgnoreAnnotations),\r
+ Boolean.valueOf(this.ignoreAnnotations));\r
+ }\r
+ \r
+ \r
+ /**\r
* Return the login configuration descriptor for this web application.\r
*/\r
public LoginConfig getLoginConfig() {\r
\r
// Validate the proposed filter mapping\r
String filterName = filterMap.getFilterName();\r
- String servletName = filterMap.getServletName();\r
- String urlPattern = filterMap.getURLPattern();\r
+ String[] servletNames = filterMap.getServletNames();\r
+ String[] urlPatterns = filterMap.getURLPatterns();\r
if (findFilterDef(filterName) == null)\r
throw new IllegalArgumentException\r
(sm.getString("standardContext.filterMap.name", filterName));\r
- if ((servletName == null) && (urlPattern == null))\r
+ if ((servletNames.length == 0) && (urlPatterns.length == 0))\r
throw new IllegalArgumentException\r
(sm.getString("standardContext.filterMap.either"));\r
- if ((servletName != null) && (urlPattern != null))\r
+ // FIXME: Older spec revisions may still check this\r
+ /*\r
+ if ((servletNames.length != 0) && (urlPatterns.length != 0))\r
throw new IllegalArgumentException\r
(sm.getString("standardContext.filterMap.either"));\r
+ */\r
// Because filter-pattern is new in 2.3, no need to adjust\r
// for 2.2 backwards compatibility\r
- if ((urlPattern != null) && !validateURLPattern(urlPattern))\r
- throw new IllegalArgumentException\r
- (sm.getString("standardContext.filterMap.pattern",\r
- urlPattern));\r
+ for (int i = 0; i < urlPatterns.length; i++) {\r
+ if (!validateURLPattern(urlPatterns[i])) {\r
+ throw new IllegalArgumentException\r
+ (sm.getString("standardContext.filterMap.pattern",\r
+ urlPatterns[i]));\r
+ }\r
+ }\r
\r
// Add this filter mapping to our registered set\r
synchronized (filterMaps) {\r
lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);\r
\r
instanceListeners = new String[0];\r
- applicationListeners = new String[0];\r
+\r
}\r
\r
private void resetContext() throws Exception, MBeanRegistrationException {\r
// Bugzilla 32867\r
distributable = false;\r
\r
+ applicationListeners = new String[0];\r
+ applicationEventListenersObjects = new Object[0];\r
+ applicationLifecycleListenersObjects = new Object[0];\r
+ \r
if(log.isDebugEnabled())\r
log.debug("resetContext " + oname + " " + mserver);\r
}\r
/**\r
* The servlet name this mapping matches.\r
*/\r
- private String servletName = null;\r
+ private String[] servletNames = new String[0];\r
\r
- public String getServletName() {\r
- return (this.servletName);\r
+ public String[] getServletNames() {\r
+ return (this.servletNames);\r
}\r
\r
- public void setServletName(String servletName) {\r
- this.servletName = servletName;\r
+ public void addServletName(String servletName) {\r
+ String[] results = new String[servletNames.length + 1];\r
+ System.arraycopy(servletNames, 0, results, 0, servletNames.length);\r
+ results[servletNames.length] = servletName;\r
+ servletNames = results;\r
}\r
\r
\r
/**\r
* The URL pattern this mapping matches.\r
*/\r
- private String urlPattern = null;\r
+ private String[] urlPatterns = new String[0];\r
\r
- public String getURLPattern() {\r
- return (this.urlPattern);\r
+ public String[] getURLPatterns() {\r
+ return (this.urlPatterns);\r
}\r
\r
- public void setURLPattern(String urlPattern) {\r
+ public void addURLPattern(String urlPattern) {\r
if ("*".equals(urlPattern)) {\r
this.allMatch = true;\r
} else {\r
- this.urlPattern = RequestUtil.URLDecode(urlPattern);\r
+ String[] results = new String[urlPatterns.length + 1];\r
+ System.arraycopy(urlPatterns, 0, results, 0, urlPatterns.length);\r
+ results[urlPatterns.length] = RequestUtil.URLDecode(urlPattern);\r
+ urlPatterns = results;\r
}\r
}\r
\r
StringBuffer sb = new StringBuffer("FilterMap[");\r
sb.append("filterName=");\r
sb.append(this.filterName);\r
- if (servletName != null) {\r
+ for (int i = 0; i < servletNames.length; i++) {\r
sb.append(", servletName=");\r
- sb.append(servletName);\r
+ sb.append(servletNames[i]);\r
}\r
- if (urlPattern != null) {\r
+ for (int i = 0; i < urlPatterns.length; i++) {\r
sb.append(", urlPattern=");\r
- sb.append(urlPattern);\r
+ sb.append(urlPatterns[i]);\r
}\r
sb.append("]");\r
return (sb.toString());\r
\r
\r
import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+\r
import org.apache.catalina.Context;\r
import org.apache.catalina.Wrapper;\r
import org.apache.catalina.deploy.SecurityConstraint;\r
+import org.apache.tomcat.util.IntrospectionUtils;\r
+import org.apache.tomcat.util.digester.CallMethodRule;\r
+import org.apache.tomcat.util.digester.CallParamRule;\r
import org.apache.tomcat.util.digester.Digester;\r
import org.apache.tomcat.util.digester.Rule;\r
import org.apache.tomcat.util.digester.RuleSetBase;\r
\r
digester.addRule(prefix + "web-app",\r
new SetPublicIdRule("setPublicId"));\r
+ digester.addRule(prefix + "web-app",\r
+ new IgnoreAnnotationsRule());\r
\r
digester.addCallMethod(prefix + "web-app/context-param",\r
"addParameter", 2);\r
digester.addObjectCreate(prefix + "web-app/filter-mapping",\r
"org.apache.catalina.deploy.FilterMap");\r
digester.addSetNext(prefix + "web-app/filter-mapping",\r
- "addFilterMap",\r
- "org.apache.catalina.deploy.FilterMap");\r
+ "addFilterMap",\r
+ "org.apache.catalina.deploy.FilterMap");\r
\r
digester.addCallMethod(prefix + "web-app/filter-mapping/filter-name",\r
"setFilterName", 0);\r
digester.addCallMethod(prefix + "web-app/filter-mapping/servlet-name",\r
- "setServletName", 0);\r
+ "addServletName", 0);\r
digester.addCallMethod(prefix + "web-app/filter-mapping/url-pattern",\r
- "setURLPattern", 0);\r
+ "addURLPattern", 0);\r
\r
digester.addCallMethod(prefix + "web-app/filter-mapping/dispatcher",\r
"setDispatcher", 0);\r
digester.addCallMethod(prefix + "web-app/servlet/servlet-name",\r
"setName", 0);\r
\r
- digester.addCallMethod(prefix + "web-app/servlet-mapping",\r
- "addServletMapping", 2);\r
+ digester.addRule(prefix + "web-app/servlet-mapping",\r
+ new CallMethodMultiRule("addServletMapping", 2, 0));\r
digester.addCallParam(prefix + "web-app/servlet-mapping/servlet-name", 1);\r
- digester.addCallParam(prefix + "web-app/servlet-mapping/url-pattern", 0);\r
+ digester.addRule(prefix + "web-app/servlet-mapping/url-pattern", new CallParamMultiRule(0));\r
\r
digester.addRule(prefix + "web-app/session-config",\r
sessionConfig);\r
}\r
\r
}\r
+\r
+\r
+/**\r
+ * A Rule that can be used to call multiple times a method as many times as needed\r
+ * (used for addServletMapping).\r
+ */\r
+final class CallParamMultiRule extends CallParamRule {\r
+\r
+ public CallParamMultiRule(int paramIndex) {\r
+ super(paramIndex);\r
+ }\r
+\r
+ public void end(String namespace, String name) {\r
+ if (bodyTextStack != null && !bodyTextStack.empty()) {\r
+ // what we do now is push one parameter onto the top set of parameters\r
+ Object parameters[] = (Object[]) digester.peekParams();\r
+ ArrayList params = (ArrayList) parameters[paramIndex];\r
+ if (params == null) {\r
+ params = new ArrayList();\r
+ parameters[paramIndex] = params;\r
+ }\r
+ params.add(bodyTextStack.pop());\r
+ }\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ * A Rule that can be used to call multiple times a method as many times as needed\r
+ * (used for addServletMapping).\r
+ */\r
+final class CallMethodMultiRule extends CallMethodRule {\r
+\r
+ protected int multiParamIndex = 0;\r
+ \r
+ public CallMethodMultiRule(String methodName, int paramCount, int multiParamIndex) {\r
+ super(methodName, paramCount);\r
+ this.multiParamIndex = multiParamIndex;\r
+ }\r
+\r
+ public void end() throws Exception {\r
+\r
+ // Retrieve or construct the parameter values array\r
+ Object parameters[] = null;\r
+ if (paramCount > 0) {\r
+ parameters = (Object[]) digester.popParams();\r
+ } else {\r
+ super.end();\r
+ }\r
+ \r
+ ArrayList multiParams = (ArrayList) parameters[multiParamIndex];\r
+ \r
+ // Construct the parameter values array we will need\r
+ // We only do the conversion if the param value is a String and\r
+ // the specified paramType is not String. \r
+ Object paramValues[] = new Object[paramTypes.length];\r
+ for (int i = 0; i < paramTypes.length; i++) {\r
+ if (i != multiParamIndex) {\r
+ // convert nulls and convert stringy parameters \r
+ // for non-stringy param types\r
+ if(parameters[i] == null || (parameters[i] instanceof String \r
+ && !String.class.isAssignableFrom(paramTypes[i]))) {\r
+ paramValues[i] =\r
+ IntrospectionUtils.convert((String) parameters[i], paramTypes[i]);\r
+ } else {\r
+ paramValues[i] = parameters[i];\r
+ }\r
+ }\r
+ }\r
+\r
+ // Determine the target object for the method call\r
+ Object target;\r
+ if (targetOffset >= 0) {\r
+ target = digester.peek(targetOffset);\r
+ } else {\r
+ target = digester.peek(digester.getCount() + targetOffset);\r
+ }\r
+\r
+ if (target == null) {\r
+ StringBuffer sb = new StringBuffer();\r
+ sb.append("[CallMethodRule]{");\r
+ sb.append("");\r
+ sb.append("} Call target is null (");\r
+ sb.append("targetOffset=");\r
+ sb.append(targetOffset);\r
+ sb.append(",stackdepth=");\r
+ sb.append(digester.getCount());\r
+ sb.append(")");\r
+ throw new org.xml.sax.SAXException(sb.toString());\r
+ }\r
+ \r
+ for (int j = 0; j < multiParams.size(); j++) {\r
+ Object param = multiParams.get(j);\r
+ if(param == null || (param instanceof String \r
+ && !String.class.isAssignableFrom(paramTypes[multiParamIndex]))) {\r
+ paramValues[multiParamIndex] =\r
+ IntrospectionUtils.convert((String) param, paramTypes[multiParamIndex]);\r
+ } else {\r
+ paramValues[multiParamIndex] = param;\r
+ }\r
+ Object result = IntrospectionUtils.callMethodN(target, methodName,\r
+ paramValues, paramTypes); \r
+ }\r
+ \r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+/**\r
+ * A Rule that check if the annotations have to be loaded.\r
+ * \r
+ */\r
+\r
+final class IgnoreAnnotationsRule extends Rule {\r
+\r
+ public IgnoreAnnotationsRule() {\r
+ }\r
+\r
+ public void begin(String namespace, String name, Attributes attributes)\r
+ throws Exception {\r
+ Context context = (Context) digester.peek(digester.getCount() - 1);\r
+ String value = attributes.getValue("metadata-complete");\r
+ if ("true".equals(value)) {\r
+ context.setIgnoreAnnotations(true);\r
+ }\r
+ if (digester.getLogger().isDebugEnabled()) {\r
+ digester.getLogger().debug\r
+ (context.getClass().getName() + ".setIgnoreAnnotations( " +\r
+ context.getIgnoreAnnotations() + ")");\r
+ }\r
+ }\r
+\r
+}\r
* top of the digester object stack. The default value of zero\r
* means the target object is the one on top of the stack.\r
*/\r
- private int targetOffset = 0;\r
+ protected int targetOffset = 0;\r
\r
/**\r
* The method name to call on the parent object.\r
* The names of the classes of the parameters to be collected.\r
* This attribute allows creation of the classes to be postponed until the digester is set.\r
*/\r
- private String paramClassNames[] = null;\r
+ protected String paramClassNames[] = null;\r
\r
/**\r
* Should <code>MethodUtils.invokeExactMethod</code> be used for reflection.\r