Repository: tapestry-5 Updated Branches: refs/heads/master 23f491d55 -> 2e11d5dd3
TAP5-2185 Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/2e11d5dd Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/2e11d5dd Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/2e11d5dd Branch: refs/heads/master Commit: 2e11d5dd3d9fdb48d47ed3ba8559b506e32c4486 Parents: 23f491d Author: Thiago H. de Paula Figueiredo <[email protected]> Authored: Wed Jul 2 12:42:38 2014 -0300 Committer: Thiago H. de Paula Figueiredo <[email protected]> Committed: Wed Jul 2 12:42:38 2014 -0300 ---------------------------------------------------------------------- .../internal/services/ResourceStreamerImpl.java | 79 +++++++++++++++++++- .../tapestry5/integration/app1/AssetTests.java | 12 +++ .../app1/pages/nested/AssetDemo.java | 19 +++++ .../integration/app1/pages/nested/AssetDemo.tml | 6 +- .../app1/pages/nested/AssetWithWrongChecksum.js | 1 + 5 files changed, 113 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2e11d5dd/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java index d5e6024..ce3d1ae 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java @@ -12,13 +12,16 @@ package org.apache.tapestry5.internal.services; +import org.apache.tapestry5.Asset; import org.apache.tapestry5.SymbolConstants; import org.apache.tapestry5.internal.InternalConstants; import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker; import org.apache.tapestry5.ioc.IOOperation; import org.apache.tapestry5.ioc.OperationTracker; import org.apache.tapestry5.ioc.Resource; +import org.apache.tapestry5.ioc.annotations.InjectService; import org.apache.tapestry5.ioc.annotations.Symbol; +import org.apache.tapestry5.services.AssetFactory; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.services.Response; import org.apache.tapestry5.services.assets.*; @@ -47,6 +50,10 @@ public class ResourceStreamerImpl implements ResourceStreamer private final ResourceChangeTracker resourceChangeTracker; private final String omitExpirationCacheControlHeader; + + private final AssetFactory classpathAssetFactory; + + private final AssetFactory contextAssetFactory; public ResourceStreamerImpl(Request request, @@ -62,7 +69,13 @@ public class ResourceStreamerImpl implements ResourceStreamer ResourceChangeTracker resourceChangeTracker, @Symbol(SymbolConstants.OMIT_EXPIRATION_CACHE_CONTROL_HEADER) - String omitExpirationCacheControlHeader) + String omitExpirationCacheControlHeader, + + @InjectService("ClasspathAssetFactory") + AssetFactory classpathAssetFactory, + + @InjectService("ContextAssetFactory") + AssetFactory contextAssetFactory) { this.request = request; this.response = response; @@ -72,6 +85,9 @@ public class ResourceStreamerImpl implements ResourceStreamer this.productionMode = productionMode; this.resourceChangeTracker = resourceChangeTracker; this.omitExpirationCacheControlHeader = omitExpirationCacheControlHeader; + + this.classpathAssetFactory = classpathAssetFactory; + this.contextAssetFactory = contextAssetFactory; } public boolean streamResource(final Resource resource, final String providedChecksum, final Set<Options> options) throws IOException @@ -87,7 +103,7 @@ public class ResourceStreamerImpl implements ResourceStreamer final boolean compress = providedChecksum.startsWith("z"); - return tracker.perform(String.format("Streaming %s%s", resource, compress ? " (compressed)" : ""), new IOOperation<Boolean>() + return tracker.perform("Streaming " + resource + (compress ? " (compressed)" : ""), new IOOperation<Boolean>() { public Boolean perform() throws IOException { @@ -97,13 +113,18 @@ public class ResourceStreamerImpl implements ResourceStreamer StreamableResource streamable = streamableResourceSource.getStreamableResource(resource, processing, resourceChangeTracker); - return streamResource(streamable, compress ? providedChecksum.substring(1) : providedChecksum, options); + return streamResource(resource, streamable, compress ? providedChecksum.substring(1) : providedChecksum, options); } }); } public boolean streamResource(StreamableResource streamable, String providedChecksum, Set<Options> options) throws IOException { + return streamResource(null, streamable, providedChecksum, options); + } + + public boolean streamResource(Resource resource, StreamableResource streamable, String providedChecksum, Set<Options> options) throws IOException + { assert streamable != null; assert providedChecksum != null; assert options != null; @@ -112,6 +133,19 @@ public class ResourceStreamerImpl implements ResourceStreamer if (providedChecksum.length() > 0 && !providedChecksum.equals(actualChecksum)) { + + // TAP5-2185: Trying to find the wrongly-checksummed resource in the classpath and context, + // so we can create an Asset with the correct checksum and redirect to it. + Asset asset = null; + if (resource != null) + { + asset = findAssetInsideWebapp(resource); + } + if (asset != null) + { + response.sendRedirect(asset.toClientURL()); + return true; + } return false; } @@ -198,4 +232,43 @@ public class ResourceStreamerImpl implements ResourceStreamer return true; } + private Asset findAssetInsideWebapp(Resource resource) + { + Asset asset; + asset = findAssetFromClasspath(resource); + if (asset == null) + { + asset = findAssetFromContext(resource); + } + return asset; + } + + private Asset findAssetFromContext(Resource resource) + { + Asset asset = null; + try + { + asset = contextAssetFactory.createAsset(resource); + } + catch (RuntimeException e) + { + // not an existing context asset. go ahead. + } + return asset; + } + + private Asset findAssetFromClasspath(Resource resource) + { + Asset asset = null; + try + { + asset = classpathAssetFactory.createAsset(resource); + } + catch (RuntimeException e) + { + // not an existing classpath asset. go ahead. + } + return asset; + } + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2e11d5dd/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java index 6e69fad..40f148c 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java @@ -68,6 +68,18 @@ public class AssetTests extends App1TestCase // check whether externaly @Import'ed d3 works assertTrue(isElementPresent("css=svg")); } + + // TAP5-2185 + @Test + public void redirection_of_requests_to_assets_with_wrong_checksums() + { + openLinks("AssetDemo"); + // paragraph is rendered with display="none" and the javascript asset changes it to display="block" + // without the fix, selenium timesout because the javascript code that sets the condition + // used by tapestry testing code to know when the page is finished loading is never invoked. + assertTrue(isVisible("assetWithWrongChecksum")); + } + private void compareDownloadedAsset(String assetURL, String localPath) throws Exception { http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2e11d5dd/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.java index ca77f76..8a0a669 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.java @@ -15,11 +15,13 @@ package org.apache.tapestry5.integration.app1.pages.nested; import org.apache.tapestry5.Asset; +import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.annotations.Environmental; import org.apache.tapestry5.annotations.Import; import org.apache.tapestry5.annotations.Path; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.services.AssetSource; import org.apache.tapestry5.services.javascript.JavaScriptSupport; import org.apache.tapestry5.services.javascript.StylesheetLink; import org.apache.tapestry5.services.javascript.StylesheetOptions; @@ -77,10 +79,27 @@ public class AssetDemo @Inject @Path("tapestry.png") private Asset logo; + + @Inject + private ComponentResources resources; + + @Inject + private AssetSource assetSource; @Import(stylesheet = "context:css/via-import.css") void afterRender() { javascriptSupport.importStylesheet(new StylesheetLink(ieOnly, new StylesheetOptions(null, "IE"))); + javascriptSupport.importJavaScriptLibrary(getAssetWithWrongChecksumUrl()); + } + + public String getAssetWithWrongChecksumUrl() { + final Asset asset = getAssetWithCorrectChecksum(); + return asset.toClientURL().replaceAll("[0-9a-f]{8}", "00000000"); + } + + public Asset getAssetWithCorrectChecksum() + { + return assetSource.getComponentAsset(resources, "AssetWithWrongChecksum.js", ""); } } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2e11d5dd/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.tml index 68bc425..695a825 100644 --- a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.tml +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.tml @@ -83,6 +83,10 @@ Using d3, loaded directly from a CDN using external asset support (example from http://christopheviau.com/d3_tutorial/): </p> -<div id="viz"/> +<div id="viz"></div> + +<p>Asset with good checksum: ${assetWithCorrectChecksum}</p> +<p>Asset with bad checksum: ${assetWithWrongChecksumUrl}</p> +<p id="assetWithWrongChecksum" style="display: none">Asset with wrong checksum handled correctly.</p> </html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/2e11d5dd/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetWithWrongChecksum.js ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetWithWrongChecksum.js b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetWithWrongChecksum.js new file mode 100644 index 0000000..652950f --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetWithWrongChecksum.js @@ -0,0 +1 @@ +document.getElementById('assetWithWrongChecksum').style.display = 'block'; \ No newline at end of file
