Updated Branches: refs/heads/master 7934dbf93 -> 0aaea4354
WICKET-4334 Prevent Wicket from causing redundant download of stateless resources (.js, .css etc.,) on browser with cookies enabled Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/0aaea435 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/0aaea435 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/0aaea435 Branch: refs/heads/master Commit: 0aaea43541563ebe840636cd807420db09f7e26d Parents: d3a26f7 Author: martin-g <[email protected]> Authored: Mon Jan 16 13:57:42 2012 +0100 Committer: martin-g <[email protected]> Committed: Mon Jan 16 14:27:18 2012 +0100 ---------------------------------------------------------------------- .../main/java/org/apache/wicket/Application.java | 5 +- .../src/main/java/org/apache/wicket/Session.java | 9 +- .../wicket/ajax/res/js/wicket-ajax-jquery.js | 44 +-- .../wicket/markup/head/JavaScriptHeaderItem.java | 8 +- .../apache/wicket/request/cycle/RequestCycle.java | 41 ++- .../resource/ResourceReferenceRequestHandler.java | 4 +- .../handler/resource/ResourceRequestHandler.java | 7 +- .../request/mapper/BufferedResponseMapper.java | 18 +- .../wicket/request/resource/PackageResource.java | 19 +- .../markup/html/internal/HeaderResponseTest.java | 325 ++++++++------- .../request/cycle/RequestCycleUrlForTest.java | 200 +++++++++ 11 files changed, 448 insertions(+), 232 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/Application.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Application.java b/wicket-core/src/main/java/org/apache/wicket/Application.java index 31831e6..47a69ab 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Application.java +++ b/wicket-core/src/main/java/org/apache/wicket/Application.java @@ -1645,7 +1645,10 @@ public abstract class Application implements UnboundListener, IEventSink @Override public void onDetach(final RequestCycle requestCycle) { - Session.get().getPageManager().commitRequest(); + if (Session.exists()) + { + Session.get().getPageManager().commitRequest(); + } } @Override http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/Session.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Session.java b/wicket-core/src/main/java/org/apache/wicket/Session.java index 6e574ef..24258b1 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Session.java +++ b/wicket-core/src/main/java/org/apache/wicket/Session.java @@ -49,9 +49,6 @@ import org.slf4j.LoggerFactory; * Holds information about a user session, including some fixed number of most recent pages (and all * their nested component information). * <ul> - * <li><b>Access via RequestCycle </b>- The Session for a {@link RequestCycle} can be retrieved by - * calling {@link RequestCycle#getSession()}. - * * <li><b>Access via Component </b>- If a RequestCycle object is not available, the Session can be * retrieved for a Component by calling {@link Component#getSession()}. As currently implemented, * each Component does not itself have a reference to the session that contains it. However, the @@ -162,7 +159,7 @@ public abstract class Session implements IClusterable, IEventSink /** * Cached instance of agent info which is typically designated by calling - * {@link RequestCycle#newClientInfo()}. + * {@link Session#getClientInfo()}. */ protected ClientInfo clientInfo; @@ -841,9 +838,7 @@ public abstract class Session implements IClusterable, IEventSink /** * Returns the {@link IPageManager} instance. - * - * @see #newPageManager() - * + * * @return {@link IPageManager} instance. */ public final IPageManager getPageManager() http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js index 539b56b..feb5c0e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js +++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js @@ -1743,7 +1743,7 @@ // is an element in head that is of same type as myElement, and whose src // attribute is same as myElement.src. containsElement: function (element, mandatoryAttribute) { - var attr = Wicket.Head._stripJSessionId(element.getAttribute(mandatoryAttribute)); + var attr = element.getAttribute(mandatoryAttribute); if (isUndef(attr) || attr === "") { return false; } @@ -1764,9 +1764,8 @@ // this is necessary for filtering script references if (node.tagName.toLowerCase() === element.tagName.toLowerCase()) { - var loadedUrl = Wicket.Head._stripJSessionId(node.getAttribute(mandatoryAttribute)); - var loadedUrl_ = Wicket.Head._stripJSessionId( - node.getAttribute(mandatoryAttribute+"_")); + var loadedUrl = node.getAttribute(mandatoryAttribute); + var loadedUrl_ = node.getAttribute(mandatoryAttribute+"_"); if (loadedUrl === attr || loadedUrl_ === attr) { return true; } @@ -1775,43 +1774,6 @@ return false; }, - /** - * Removes the optional ';jsessionid=...' from the passed url - * - * @param {String} url the url to strip the jsessionid from - * @return {String} the url without the jsessionid and its value - */ - // WICKET-3596, WICKET-4312 - _stripJSessionId: function (url) { - if (url === null) - { - return null; - } - - // http://.../abc;jsessionid=...?param=... - var ixSemiColon = url.indexOf(";"); - if (ixSemiColon === -1) - { - return url; - } - - var ixQuestionMark = url.indexOf("?"); - if (ixQuestionMark === -1) - { - // no query paramaters; cut off at ";" - // http://.../abc;jsession=... - return url.substring(0, ixSemiColon); - } - - if (ixQuestionMark <= ixSemiColon) - { - // ? is before ; - no jsessionid in the url - return url; - } - - return url.substring(0, ixSemiColon) + url.substring(ixQuestionMark); - }, - // Adds a javascript element to page header. // The fakeSrc attribute is used to filter out duplicate javascript references. // External javascripts are loaded using xmlhttprequest. Then a javascript element is created and the http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/markup/head/JavaScriptHeaderItem.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/head/JavaScriptHeaderItem.java b/wicket-core/src/main/java/org/apache/wicket/markup/head/JavaScriptHeaderItem.java index d61efcd..aaa3d9c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/head/JavaScriptHeaderItem.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/head/JavaScriptHeaderItem.java @@ -19,6 +19,7 @@ package org.apache.wicket.markup.head; import org.apache.wicket.request.Response; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.string.JavaScriptUtils; import org.apache.wicket.util.string.Strings; @@ -203,11 +204,8 @@ public abstract class JavaScriptHeaderItem extends HeaderItem protected static void internalRenderJavaScriptReference(Response response, String url, String id, boolean defer, String charset) { - if (Strings.isEmpty(url)) - { - throw new IllegalArgumentException("url cannot be empty or null"); - } + Args.notEmpty(url, "url"); - JavaScriptUtils.writeJavaScriptUrl(response, url, id, defer, charset); + JavaScriptUtils.writeJavaScriptUrl(response, Strings.stripJSessionId(url), id, defer, charset); } } http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java b/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java index 94f295c..32103aa 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/cycle/RequestCycle.java @@ -40,8 +40,11 @@ import org.apache.wicket.request.handler.IPageProvider; import org.apache.wicket.request.handler.PageProvider; import org.apache.wicket.request.handler.RenderPageRequestHandler; import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; +import org.apache.wicket.request.handler.resource.ResourceRequestHandler; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.IResource; import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.request.resource.caching.IStaticCacheableResource; import org.apache.wicket.util.lang.Args; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -450,7 +453,8 @@ public class RequestCycle implements IRequestCycle, IEventSink */ public final CharSequence urlFor(ResourceReference reference, PageParameters params) { - return renderUrl(mapUrlFor(reference, params)); + ResourceReferenceRequestHandler handler = new ResourceReferenceRequestHandler(reference, params); + return renderUrl(mapUrlFor(handler), handler); } /** @@ -469,7 +473,9 @@ public class RequestCycle implements IRequestCycle, IEventSink public final <C extends Page> CharSequence urlFor(final Class<C> pageClass, final PageParameters parameters) { - return renderUrl(mapUrlFor(pageClass, parameters)); + IRequestHandler handler = new BookmarkablePageRequestHandler(new PageProvider(pageClass, + parameters)); + return renderUrl(mapUrlFor(handler), handler); } /** @@ -483,14 +489,39 @@ public class RequestCycle implements IRequestCycle, IEventSink */ public CharSequence urlFor(IRequestHandler handler) { - return renderUrl(mapUrlFor(handler)); + Url mappedUrl = mapUrlFor(handler); + CharSequence url = renderUrl(mappedUrl, handler); + return url; } - private String renderUrl(Url url) + private String renderUrl(Url url, IRequestHandler handler) { if (url != null) { - return getOriginalResponse().encodeURL(getUrlRenderer().renderUrl(url)); + String renderedUrl = getUrlRenderer().renderUrl(url); + if (handler instanceof ResourceReferenceRequestHandler) + { + ResourceReferenceRequestHandler rrrh = (ResourceReferenceRequestHandler) handler; + IResource resource = rrrh.getResource(); + if (resource instanceof IStaticCacheableResource == false) + { + renderedUrl = getOriginalResponse().encodeURL(renderedUrl); + } + } + else if (handler instanceof ResourceRequestHandler) + { + ResourceRequestHandler rrh = (ResourceRequestHandler) handler; + IResource resource = rrh.getResource(); + if (resource instanceof IStaticCacheableResource == false) + { + renderedUrl = getOriginalResponse().encodeURL(renderedUrl); + } + } + else + { + renderedUrl = getOriginalResponse().encodeURL(renderedUrl); + } + return renderedUrl; } else { http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceReferenceRequestHandler.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceReferenceRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceReferenceRequestHandler.java index 0f38e74..80dc89b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceReferenceRequestHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceReferenceRequestHandler.java @@ -82,7 +82,7 @@ public class ResourceReferenceRequestHandler implements IRequestHandler, ILoggab } /** - * @see org.apache.org.apache.wicket.request.IRequestHandler#detach(org.apache.wicket.request.cycle.RequestCycle) + * @see org.apache.wicket.request.IRequestHandler#detach(org.apache.wicket.request.IRequestCycle) */ @Override public void detach(IRequestCycle requestCycle) @@ -100,7 +100,7 @@ public class ResourceReferenceRequestHandler implements IRequestHandler, ILoggab /** - * @see org.apache.org.apache.wicket.request.IRequestHandler#respond(org.apache.wicket.request.cycle.RequestCycle) + * @see org.apache.wicket.request.IRequestHandler#respond(org.apache.wicket.request.IRequestCycle) */ @Override public void respond(IRequestCycle requestCycle) http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceRequestHandler.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceRequestHandler.java b/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceRequestHandler.java index 7f97bfc..09537e2 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceRequestHandler.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/handler/resource/ResourceRequestHandler.java @@ -36,9 +36,6 @@ public class ResourceRequestHandler implements IRequestHandler * Construct. * * @param resource - * @param locale - * @param style - * @param variation * @param pageParameters */ public ResourceRequestHandler(IResource resource, PageParameters pageParameters) @@ -68,7 +65,7 @@ public class ResourceRequestHandler implements IRequestHandler } /** - * @see org.apache.org.apache.wicket.request.IRequestHandler#respond(org.apache.wicket.request.cycle.RequestCycle) + * @see org.apache.wicket.request.IRequestHandler#respond(org.apache.wicket.request.IRequestCycle) */ @Override public void respond(final IRequestCycle requestCycle) @@ -79,7 +76,7 @@ public class ResourceRequestHandler implements IRequestHandler } /** - * @see org.apache.org.apache.wicket.request.IRequestHandler#detach(org.apache.wicket.request.cycle.RequestCycle) + * @see org.apache.wicket.request.IRequestHandler#detach(org.apache.wicket.request.IRequestCycle) */ @Override public void detach(IRequestCycle requestCycle) http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/request/mapper/BufferedResponseMapper.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/mapper/BufferedResponseMapper.java b/wicket-core/src/main/java/org/apache/wicket/request/mapper/BufferedResponseMapper.java index b376d1c..66bbfd7 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/mapper/BufferedResponseMapper.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/mapper/BufferedResponseMapper.java @@ -16,15 +16,18 @@ */ package org.apache.wicket.request.mapper; +import org.apache.wicket.Application; import org.apache.wicket.Session; import org.apache.wicket.protocol.http.BufferedWebResponse; import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.request.IRequestCycle; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.IRequestMapper; import org.apache.wicket.request.Request; import org.apache.wicket.request.Url; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.handler.BufferedResponseRequestHandler; +import org.apache.wicket.session.ISessionStore; import org.apache.wicket.util.string.Strings; /** @@ -47,7 +50,20 @@ public class BufferedResponseMapper implements IRequestMapper */ protected String getSessionId() { - return RequestCycle.get() != null ? Session.get().getId() : null; + String sessionId = null; + + if (Application.exists() && RequestCycle.get() != null) + { + ISessionStore sessionStore = Application.get().getSessionStore(); + IRequestCycle requestCycle = RequestCycle.get(); + Session session = sessionStore.lookup(requestCycle.getRequest()); + if (session != null) + { + sessionId = session.getId(); + } + } + + return sessionId; } protected boolean hasBufferedResponse(Url url) http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java index 3a78942..b55b405 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java @@ -138,9 +138,7 @@ public class PackageResource extends AbstractResource implements IStaticCacheabl // Convert resource path to absolute path relative to base package absolutePath = Packages.absolutePath(scope, name); - final String parentEscape = Application.get() - .getResourceSettings() - .getParentFolderPlaceholder(); + final String parentEscape = getParentFolderPlaceholder(); if (Strings.isEmpty(parentEscape) == false) { @@ -499,6 +497,21 @@ public class PackageResource extends AbstractResource implements IStaticCacheabl return true; } + String getParentFolderPlaceholder() + { + String parentFolderPlaceholder; + if (Application.exists()) + { + parentFolderPlaceholder = Application.get() + .getResourceSettings() + .getParentFolderPlaceholder(); + } else + { + parentFolderPlaceholder = ".."; + } + return parentFolderPlaceholder; + } + private static class CacheKey implements Serializable { private final String scopeName; http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/HeaderResponseTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/HeaderResponseTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/HeaderResponseTest.java index fc84c48..c4bcc43 100644 --- a/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/HeaderResponseTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/internal/HeaderResponseTest.java @@ -47,166 +47,167 @@ import org.junit.Test; */ public class HeaderResponseTest { - private static final String RESOURCE_NAME = "resource.name"; - - private IHeaderResponse headerResponse; - - private ResourceReference reference; - - /** - * Prepare - */ - @Before - public void before() - { - final Response realResponse = new StringResponse(); - - headerResponse = new HeaderResponse() - { - @Override - protected Response getRealResponse() - { - return realResponse; - } - }; - - reference = new ResourceReference("testReference") - { - private static final long serialVersionUID = 1L; - - @Override - public IResource getResource() - { - return null; - } - }; - - RequestCycle requestCycle = mock(RequestCycle.class); - when(requestCycle.urlFor(any(IRequestHandler.class))).thenReturn(RESOURCE_NAME); - - Request request = mock(Request.class); - when(request.getCharset()).thenReturn(Charset.defaultCharset()); - when(requestCycle.getRequest()).thenReturn(request); - - UrlRenderer urlRenderer = mock(UrlRenderer.class); - when(urlRenderer.renderContextRelativeUrl((any(String.class)))).thenReturn(RESOURCE_NAME); - when(requestCycle.getUrlRenderer()).thenReturn(urlRenderer); - - ThreadContext.setRequestCycle(requestCycle); - } - - /** - * Tear down - */ - @After - public void after() - { - ThreadContext.setRequestCycle(null); - } - - /** - * Tests the creation of a proper IE conditional comment - */ - @Test - public void conditionalRenderCSSReference() - { - headerResponse.render(CssHeaderItem.forReference(reference, null, "screen", "lt IE 8")); - String expected = "<!--[if lt IE 8]><link rel=\"stylesheet\" type=\"text/css\" href=\"" + - RESOURCE_NAME + "\" media=\"screen\" /><![endif]-->\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * Tests the creation of a proper IE conditional comment - */ - @Test - public void conditionalRenderCSSReferenceWithUrl() - { - headerResponse.render(CssHeaderItem.forUrl("resource.css", "screen", "lt IE 8")); - String expected = "<!--[if lt IE 8]><link rel=\"stylesheet\" type=\"text/css\" href=\"" + - RESOURCE_NAME + "\" media=\"screen\" /><![endif]-->\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * Tests setting of 'defer' attribute - * <p> - * WICKET-3661 - */ - @Test - public void deferJavaScriptReference() - { - boolean defer = true; - headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", defer)); - String expected = "<script type=\"text/javascript\" id=\"some-id\" defer=\"defer\" src=\"" + - RESOURCE_NAME + "\"></script>\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * Tests non-setting of 'defer' attribute - * <p> - * WICKET-3661 - */ - @Test - public void deferFalseJavaScriptReference() - { - boolean defer = false; - headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", defer)); - String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"" + RESOURCE_NAME + - "\"></script>\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * Tests setting of 'charset' attribute - * <p> - * WICKET-3909 - */ - @Test - public void charsetSetJavaScriptReference() - { - String charset = "foo"; - headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", false, - charset)); - String expected = "<script type=\"text/javascript\" id=\"some-id\" charset=\"" + charset + - "\" src=\"" + RESOURCE_NAME + "\"></script>\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * Tests non-setting of 'charset' attribute - * <p> - * WICKET-3909 - */ - @Test - public void charsetNotSetJavaScriptReference() - { - headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", false, null)); - String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"" + RESOURCE_NAME + - "\"></script>\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } - - /** - * https://issues.apache.org/jira/browse/WICKET-4312 - */ - @Test - public void preserveJSessionId() { - WicketTester tester = new WicketTester(); - try { - headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js;jsessionid=1h402r54r4xuep32znicouftm", "some-id", false, null)); - String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"js-resource.js;jsessionid=1h402r54r4xuep32znicouftm\"></script>\n"; - String actual = headerResponse.getResponse().toString(); - Assert.assertEquals(expected, actual); - } finally { - tester.destroy(); - } - } + private static final String RESOURCE_NAME = "resource.name"; + + private IHeaderResponse headerResponse; + + private ResourceReference reference; + + /** + * Prepare + */ + @Before + public void before() + { + final Response realResponse = new StringResponse(); + + headerResponse = new HeaderResponse() + { + @Override + protected Response getRealResponse() + { + return realResponse; + } + }; + + reference = new ResourceReference("testReference") + { + private static final long serialVersionUID = 1L; + + @Override + public IResource getResource() + { + return null; + } + }; + + RequestCycle requestCycle = mock(RequestCycle.class); + when(requestCycle.urlFor(any(IRequestHandler.class))).thenReturn(RESOURCE_NAME); + + Request request = mock(Request.class); + when(request.getCharset()).thenReturn(Charset.defaultCharset()); + when(requestCycle.getRequest()).thenReturn(request); + + UrlRenderer urlRenderer = mock(UrlRenderer.class); + when(urlRenderer.renderContextRelativeUrl((any(String.class)))).thenReturn(RESOURCE_NAME); + when(requestCycle.getUrlRenderer()).thenReturn(urlRenderer); + + ThreadContext.setRequestCycle(requestCycle); + } + + /** + * Tear down + */ + @After + public void after() + { + ThreadContext.setRequestCycle(null); + } + + /** + * Tests the creation of a proper IE conditional comment + */ + @Test + public void conditionalRenderCSSReference() + { + headerResponse.render(CssHeaderItem.forReference(reference, null, "screen", "lt IE 8")); + String expected = "<!--[if lt IE 8]><link rel=\"stylesheet\" type=\"text/css\" href=\"" + + RESOURCE_NAME + "\" media=\"screen\" /><![endif]-->\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * Tests the creation of a proper IE conditional comment + */ + @Test + public void conditionalRenderCSSReferenceWithUrl() + { + headerResponse.render(CssHeaderItem.forUrl("resource.css", "screen", "lt IE 8")); + String expected = "<!--[if lt IE 8]><link rel=\"stylesheet\" type=\"text/css\" href=\"" + + RESOURCE_NAME + "\" media=\"screen\" /><![endif]-->\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * Tests setting of 'defer' attribute + * <p> + * WICKET-3661 + */ + @Test + public void deferJavaScriptReference() + { + boolean defer = true; + headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", defer)); + String expected = "<script type=\"text/javascript\" id=\"some-id\" defer=\"defer\" src=\"" + + RESOURCE_NAME + "\"></script>\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * Tests non-setting of 'defer' attribute + * <p> + * WICKET-3661 + */ + @Test + public void deferFalseJavaScriptReference() + { + boolean defer = false; + headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", defer)); + String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"" + RESOURCE_NAME + + "\"></script>\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * Tests setting of 'charset' attribute + * <p> + * WICKET-3909 + */ + @Test + public void charsetSetJavaScriptReference() + { + String charset = "foo"; + headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", false, + charset)); + String expected = "<script type=\"text/javascript\" id=\"some-id\" charset=\"" + charset + + "\" src=\"" + RESOURCE_NAME + "\"></script>\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * Tests non-setting of 'charset' attribute + * <p> + * WICKET-3909 + */ + @Test + public void charsetNotSetJavaScriptReference() + { + headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js", "some-id", false, null)); + String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"" + RESOURCE_NAME + + "\"></script>\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } + + /** + * https://issues.apache.org/jira/browse/WICKET-4334 + * https://issues.apache.org/jira/browse/WICKET-4312 + */ + @Test + public void doNotPreserveJSessionId() { + WicketTester tester = new WicketTester(); + try { + headerResponse.render(JavaScriptHeaderItem.forUrl("js-resource.js;jsessionid=1h402r54r4xuep32znicouftm", "some-id", false, null)); + String expected = "<script type=\"text/javascript\" id=\"some-id\" src=\"js-resource.js\"></script>\n"; + String actual = headerResponse.getResponse().toString(); + Assert.assertEquals(expected, actual); + } finally { + tester.destroy(); + } + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/0aaea435/wicket-core/src/test/java/org/apache/wicket/request/cycle/RequestCycleUrlForTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/request/cycle/RequestCycleUrlForTest.java b/wicket-core/src/test/java/org/apache/wicket/request/cycle/RequestCycleUrlForTest.java new file mode 100644 index 0000000..b779521 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/request/cycle/RequestCycleUrlForTest.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.request.cycle; + +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.wicket.mock.MockHomePage; +import org.apache.wicket.request.IExceptionMapper; +import org.apache.wicket.request.IRequestMapper; +import org.apache.wicket.request.Request; +import org.apache.wicket.request.Response; +import org.apache.wicket.request.Url; +import org.apache.wicket.request.handler.BookmarkablePageRequestHandler; +import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; +import org.apache.wicket.request.handler.resource.ResourceRequestHandler; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.ByteArrayResource; +import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.request.resource.caching.IStaticCacheableResource; +import org.apache.wicket.response.StringResponse; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests that RequestCycle#urlFor() does not encode the jsessionid for static resources. + * + * https://issues.apache.org/jira/browse/WICKET-4334 + */ +public class RequestCycleUrlForTest extends Assert +{ + private static final String JSESSIONID = ";jsessionid=1234567890"; + private static final String BOOKMARKABLE_PAGE_URL = "/bookmarkablePage"; + private static final String RES_REF_URL = "/resRef"; + private static final String RESOURCE_URL = "/res"; + + RequestCycle requestCycle; + + @Before + public void before() + { + Request request = mock(Request.class); + Response response = new StringResponse() { + @Override + public String encodeURL(CharSequence url) + { + return url + JSESSIONID; + } + }; + IRequestMapper mapper = mock(IRequestMapper.class); + + Url bookmarkablePageUrl = Url.parse(BOOKMARKABLE_PAGE_URL); + when(mapper.mapHandler(argThat(new ExactClassMatcher<BookmarkablePageRequestHandler>(BookmarkablePageRequestHandler.class)))).thenReturn(bookmarkablePageUrl); + + Url resourceUrl = Url.parse(RESOURCE_URL); + when(mapper.mapHandler(argThat(new ExactClassMatcher<ResourceRequestHandler>(ResourceRequestHandler.class)))).thenReturn(resourceUrl); + + Url resourceReferenceUrl = Url.parse(RES_REF_URL); + when(mapper.mapHandler(argThat(new ExactClassMatcher<ResourceReferenceRequestHandler>(ResourceReferenceRequestHandler.class)))).thenReturn(resourceReferenceUrl); + + IExceptionMapper exceptionMapper = mock(IExceptionMapper.class); + RequestCycleContext context = new RequestCycleContext(request, response, mapper, exceptionMapper); + + requestCycle = new RequestCycle(context); + } + + /** + * Pages should have the jsessionid encoded in the url + * + * @throws Exception + */ + @Test + public void urlForClass() throws Exception + { + CharSequence url = requestCycle.urlFor(MockHomePage.class, new PageParameters()); + assertEquals("/bookmarkablePage"+JSESSIONID, url); + } + + /** + * ResourceReference with IStaticCacheableResource should not have the jsessionid encoded in the url + * + * @throws Exception + */ + @Test + public void urlForResourceReference() throws Exception + { + final IStaticCacheableResource resource = mock(IStaticCacheableResource.class); + ResourceReference reference = new ResourceReference("dummy") + { + @Override + public IResource getResource() + { + return resource; + } + }; + ResourceReferenceRequestHandler handler = new ResourceReferenceRequestHandler(reference); + CharSequence url = requestCycle.urlFor(handler); + assertEquals(RES_REF_URL, url); + } + + /** + * ResourceReference with non-IStaticCacheableResource should not have the jsessionid encoded in the url + * + * @throws Exception + */ + @Test + public void urlForResourceReferenceWithNonStaticResource() throws Exception + { + final IResource resource = mock(IResource.class); + ResourceReference reference = new ResourceReference("dummy") + { + @Override + public IResource getResource() + { + return resource; + } + }; + ResourceReferenceRequestHandler handler = new ResourceReferenceRequestHandler(reference); + CharSequence url = requestCycle.urlFor(handler); + assertEquals(RES_REF_URL+JSESSIONID, url); + } + + /** + * IStaticCacheableResource should not have the jsessionid encoded in the url + * + * @throws Exception + */ + @Test + public void urlForStaticResource() throws Exception + { + IStaticCacheableResource resource = mock(IStaticCacheableResource.class); + ResourceRequestHandler handler = new ResourceRequestHandler(resource, new PageParameters()); + CharSequence url = requestCycle.urlFor(handler); + assertEquals(RESOURCE_URL, url); + } + + /** + * Non-IStaticCacheableResource should have the jsessionid encoded in the url + * + * @throws Exception + */ + @Test + public void urlForDynamicResource() throws Exception + { + ByteArrayResource resource = new ByteArrayResource(null, new byte[] {1, 2}, "test.bin"); + ResourceRequestHandler handler = new ResourceRequestHandler(resource, new PageParameters()); + CharSequence url = requestCycle.urlFor(handler); + assertEquals(RESOURCE_URL + JSESSIONID, url); + } + + /** + * A matcher that matches only when the object class is exactly the same as the expected one. + * + * @param <T> + * the type of the expected class + */ + private static class ExactClassMatcher<T> extends BaseMatcher<T> + { + private final Class<T> targetClass; + + public ExactClassMatcher(Class<T> targetClass) + { + this.targetClass = targetClass; + } + + @SuppressWarnings("unchecked") + public boolean matches(Object obj) + { + if (obj != null) + { + return targetClass.equals(obj.getClass()); + } + return false; + } + + public void describeTo(Description desc) + { + desc.appendText("Matches a class or subclass"); + } + } +}
