Author: mgrigorov
Date: Sun Mar 20 17:43:21 2011
New Revision: 1083519
URL: http://svn.apache.org/viewvc?rev=1083519&view=rev
Log:
WICKET-3544 Race condition in WicketFilter startup with following
StringIndexOutOfBoundsException
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java?rev=1083519&r1=1083518&r2=1083519&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
Sun Mar 20 17:43:21 2011
@@ -494,10 +494,13 @@ public class WicketFilter implements Fil
// We only need to determine it once. It'll not change.
if (filterPathLength == -1)
{
- filterPathLength = filterPath.length();
if (filterPath.endsWith("/"))
{
- filterPathLength -= 1;
+ filterPathLength = filterPath.length() - 1;
+ }
+ else
+ {
+ filterPathLength = filterPath.length();
}
}
Modified:
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java?rev=1083519&r1=1083518&r2=1083519&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java
(original)
+++
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java
Sun Mar 20 17:43:21 2011
@@ -28,6 +28,9 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -214,4 +217,88 @@ public class WicketFilterTest extends Te
filter.setFilterPath("");
assertNull("", filter.checkIfRedirectRequired("/", ""));
}
+
+ private static class CheckRedirectWorker implements Runnable
+ {
+ private final WicketFilter filter;
+ private final CountDownLatch startLatch;
+ private final CountDownLatch finishLatch;
+ private final AtomicInteger successCount;
+
+ public CheckRedirectWorker(WicketFilter filter, CountDownLatch
startLatch,
+ CountDownLatch finishLatch, AtomicInteger successCount)
+ {
+ this.filter = filter;
+ this.startLatch = startLatch;
+ this.finishLatch = finishLatch;
+ this.successCount = successCount;
+ }
+
+ public void run()
+ {
+ try
+ {
+ try
+ {
+ startLatch.await(2, TimeUnit.SECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ fail();
+ }
+ assertEquals("/filter/",
filter.checkIfRedirectRequired("/filter", ""));
+ successCount.incrementAndGet();
+ }
+ finally
+ {
+ finishLatch.countDown();
+ }
+ }
+ }
+
+ /**
+ * Starts {@code threadCount} threads which try to check whether a
redirect is required and
+ * initialize {@link WicketFilter#filterPathLength}
+ *
+ * @param threadCount
+ * the number of simultaneous threads
+ */
+ private void testParallelCheckRedirect(int threadCount)
+ {
+ WicketFilter filter = new WicketFilter();
+ filter.setFilterPath("filter/");
+ AtomicInteger successCount = new AtomicInteger(0);
+ CountDownLatch startLatch = new CountDownLatch(1);
+ CountDownLatch finishLatch = new CountDownLatch(threadCount);
+ for (int i = 0; i < threadCount; i++)
+ {
+ new Thread(new CheckRedirectWorker(filter, startLatch,
finishLatch, successCount)).start();
+ }
+ startLatch.countDown();
+ try
+ {
+ finishLatch.await(2, TimeUnit.SECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ fail();
+ }
+ assertEquals("all threads finished", 0, finishLatch.getCount());
+ assertEquals("all redirects correct", threadCount,
successCount.get());
+ }
+
+ /**
+ * <a
href="https://issues.apache.org/jira/browse/WICKET-3544">WICKET-3544</a>
+ * <p>
+ * Runs 1000 times 8 simultaneous threads which try to initialize
WicketFilter#filterPathLength
+ */
+ public void testRepeatedParallelCheckRedirect()
+ {
+ int threadCount = 8;
+ int repeatCount = 1000;
+ for (int i = 0; i < repeatCount; i++)
+ {
+ testParallelCheckRedirect(threadCount);
+ }
+ }
}