From: <mgu...@us...> - 2013-02-14 14:15:53
|
Revision: 8108 http://sourceforge.net/p/htmlunit/code/8108 Author: mguillem Date: 2013-02-14 14:15:49 +0000 (Thu, 14 Feb 2013) Log Message: ----------- CookieManager: changed getCookies to return a copy of the current set of cookies to avoid ConcurrentModificationException. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/CookieManager.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManager2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2013-02-12 17:50:28 UTC (rev 8107) +++ trunk/htmlunit/src/changes/changes.xml 2013-02-14 14:15:49 UTC (rev 8108) @@ -9,6 +9,9 @@ <body> <release version="2.12" date="???" description="Bugfixes, CSS3 Selectors"> <action type="fix" dev="mguillem"> + CookieManager: changed getCookies to return a copy of the current set of cookies to avoid ConcurrentModificationException. + </action> + <action type="fix" dev="mguillem"> JavaScript: add empty implementations of CanvasRenderingContext2D methods createImageData, createPattern, createRadialGradient, fillText, getImageData, getLineData, isPointInPath, measureText, putImageData, rect, rotate, setTransform, strokeText, and transform (FF). Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/CookieManager.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/CookieManager.java 2013-02-12 17:50:28 UTC (rev 8107) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/CookieManager.java 2013-02-14 14:15:49 UTC (rev 8108) @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -89,7 +90,8 @@ * @return the currently configured cookies, in an unmodifiable set */ public synchronized Set<Cookie> getCookies() { - return Collections.unmodifiableSet(cookies_); + final Set<Cookie> copy = new HashSet<Cookie>(cookies_); + return Collections.unmodifiableSet(copy); } /** Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManager2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManager2Test.java 2013-02-12 17:50:28 UTC (rev 8107) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManager2Test.java 2013-02-14 14:15:49 UTC (rev 8108) @@ -16,6 +16,7 @@ import java.net.URL; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -121,4 +122,31 @@ final Set<Cookie> cookies = webClient.getCookieManager().getCookies(htmlPage.getUrl()); assertTrue(cookies.toString(), cookies.isEmpty()); } + + /** + * This was causing a ConcurrentModificationException. + * In "real life" the problem was arising due to changes to the cookies made from + * the JS processing thread. + * @throws Exception if the test fails + */ + @Test + public void getCookiesShouldReturnACopyOfCurentState() throws Exception { + final String html = "<html><body>" + + "<button id='it' onclick=\"document.cookie = 'foo=bla'\">click me</button>\n" + + "<script>\n" + + "document.cookie = 'cookie1=value1';\n" + + "</script></body></html>"; + + final WebClient webClient = getWebClient(); + + final HtmlPage page = loadPage(html); + final Set<Cookie> initialCookies = webClient.getCookieManager().getCookies(); + assertEquals(1, initialCookies.size()); + final Iterator<Cookie> iterator = initialCookies.iterator(); + + page.getHtmlElementById("it").click(); + iterator.next(); // ConcurrentModificationException was here + assertEquals(1, initialCookies.size()); + assertEquals(2, webClient.getCookieManager().getCookies().size()); + } } |