From 4396cff3a612d2ee9e0f28f6cca5305e25bc70c1 Mon Sep 17 00:00:00 2001 From: kkolinko Date: Wed, 28 Apr 2010 08:21:32 +0000 Subject: [PATCH] Use a helper class to manage the filter mappings. Fix ArrayIndexOutOfBoundsException in addFilterMapBefore as reported in re: r937975 thread. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@938814 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/catalina/core/StandardContext.java | 181 +++++++++++++-------- 1 file changed, 115 insertions(+), 66 deletions(-) diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java index 3a7da44c7..865877794 100644 --- a/java/org/apache/catalina/core/StandardContext.java +++ b/java/org/apache/catalina/core/StandardContext.java @@ -383,21 +383,7 @@ public class StandardContext * added via the {@link ServletContext} possibly both before and after those * defined in the deployment descriptor. */ - private FilterMap filterMaps[] = new FilterMap[0]; - - private final Object filterMapsLock = new Object(); - - - /** - * Filter mappings added via {@link ServletContext} may have to be inserted - * before the mappings in the deployment descriptor but must be inserted in - * the order the {@link ServletContext} methods are called. This isn't an - * issue for the mappings added after the deployment descriptor - they are - * just added to the end - but correctly the adding mappings before the - * deployment descriptor mappings requires knowing where the last 'before' - * mapping was added. - */ - private int filterMapInsertPoint = 0; + private final ContextFilterMaps filterMaps = new ContextFilterMaps(); /** * Ignore annotations. @@ -2590,15 +2576,9 @@ public class StandardContext * is malformed */ public void addFilterMap(FilterMap filterMap) { - validateFilterMap(filterMap); // Add this filter mapping to our registered set - synchronized (filterMapsLock) { - FilterMap results[] = Arrays.copyOf(filterMaps, - filterMaps.length + 1); - results[filterMaps.length] = filterMap; - filterMaps = results; - } + filterMaps.add(filterMap); fireContainerEvent("addFilterMap", filterMap); } @@ -2614,22 +2594,9 @@ public class StandardContext * is malformed */ public void addFilterMapBefore(FilterMap filterMap) { - validateFilterMap(filterMap); - // Add this filter mapping to our registered set - synchronized (filterMapsLock) { - FilterMap results[] = new FilterMap[filterMaps.length + 1]; - System.arraycopy(filterMaps, 0, results, 0, filterMapInsertPoint); - results[filterMapInsertPoint] = filterMap; - System.arraycopy(filterMaps, filterMapInsertPoint, results, - filterMaps.length - (filterMapInsertPoint + 1), - filterMaps.length - filterMapInsertPoint); - - filterMapInsertPoint++; - - filterMaps = results; - } + filterMaps.addBefore(filterMap); fireContainerEvent("addFilterMap", filterMap); } @@ -3139,9 +3106,7 @@ public class StandardContext * Return the set of filter mappings for this Context. */ public FilterMap[] findFilterMaps() { - - return (filterMaps); - + return filterMaps.asArray(); } @@ -3711,35 +3676,9 @@ public class StandardContext * @param filterMap The filter mapping to be removed */ public void removeFilterMap(FilterMap filterMap) { - - synchronized (filterMapsLock) { - - // Make sure this filter mapping is currently present - int n = -1; - for (int i = 0; i < filterMaps.length; i++) { - if (filterMaps[i] == filterMap) { - n = i; - break; - } - } - if (n < 0) - return; - - // Remove the specified filter mapping - FilterMap results[] = new FilterMap[filterMaps.length - 1]; - System.arraycopy(filterMaps, 0, results, 0, n); - System.arraycopy(filterMaps, n + 1, results, n, - (filterMaps.length - 1) - n); - if (n < filterMapInsertPoint) { - filterMapInsertPoint--; - } - filterMaps = results; - - } - + filterMaps.remove(filterMap); // Inform interested listeners fireContainerEvent("removeFilterMap", filterMap); - } @@ -4104,6 +4043,116 @@ public class StandardContext return null; } + + /** + * A helper class to manage the filter mappings in a Context. + */ + private static final class ContextFilterMaps { + private final Object lock = new Object(); + + /** + * The set of filter mappings for this application, in the order they + * were defined in the deployment descriptor with additional mappings + * added via the {@link ServletContext} possibly both before and after + * those defined in the deployment descriptor. + */ + private FilterMap[] array = new FilterMap[0]; + + /** + * Filter mappings added via {@link ServletContext} may have to be + * inserted before the mappings in the deployment descriptor but must be + * inserted in the order the {@link ServletContext} methods are called. + * This isn't an issue for the mappings added after the deployment + * descriptor - they are just added to the end - but correctly the + * adding mappings before the deployment descriptor mappings requires + * knowing where the last 'before' mapping was added. + */ + private int insertPoint = 0; + + /** + * Reset the set to the initial state. + */ + public void clear() { + synchronized (lock) { + array = new FilterMap[0]; + insertPoint = 0; + } + } + + /** + * Return the set of filter mappings. + */ + public FilterMap[] asArray() { + synchronized (lock) { + return array; + } + } + + /** + * Add a filter mapping at the end of the current set of filter + * mappings. + * + * @param filterMap + * The filter mapping to be added + */ + public void add(FilterMap filterMap) { + synchronized (lock) { + FilterMap results[] = Arrays.copyOf(array, array.length + 1); + results[array.length] = filterMap; + array = results; + } + } + + /** + * Add a filter mapping before the mappings defined in the deployment + * descriptor but after any other mappings added via this method. + * + * @param filterMap + * The filter mapping to be added + */ + public void addBefore(FilterMap filterMap) { + synchronized (lock) { + FilterMap results[] = new FilterMap[array.length + 1]; + System.arraycopy(array, 0, results, 0, insertPoint); + System.arraycopy(array, insertPoint, results, insertPoint + 1, + array.length - insertPoint); + results[insertPoint] = filterMap; + array = results; + insertPoint++; + } + } + + /** + * Remove a filter mapping. + * + * @param filterMap The filter mapping to be removed + */ + public void remove(FilterMap filterMap) { + synchronized (lock) { + // Make sure this filter mapping is currently present + int n = -1; + for (int i = 0; i < array.length; i++) { + if (array[i] == filterMap) { + n = i; + break; + } + } + if (n < 0) + return; + + // Remove the specified filter mapping + FilterMap results[] = new FilterMap[array.length - 1]; + System.arraycopy(array, 0, results, 0, n); + System.arraycopy(array, n + 1, results, n, (array.length - 1) + - n); + array = results; + if (n < insertPoint) { + insertPoint--; + } + } + } + } + // --------------------------------------------------------- Public Methods -- 2.11.0