Repository: wicket Updated Branches: refs/heads/wicket-6.x 630fbc14e -> 8c9fd4efa
WICKET-5827 - CssUrlReplacer supports base64 encoded images Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/8c9fd4ef Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/8c9fd4ef Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/8c9fd4ef Branch: refs/heads/wicket-6.x Commit: 8c9fd4efa2abdd774fd0e396131b4237a3bc528f Parents: 630fbc1 Author: klopfdreh <[email protected]> Authored: Wed Feb 18 16:33:21 2015 +0100 Committer: klopfdreh <[email protected]> Committed: Thu Mar 12 11:33:20 2015 +0100 ---------------------------------------------------------------------- .../apache/wicket/resource/CssUrlReplacer.java | 76 ++++++++++++++++++-- .../wicket/resource/CssUrlReplacerTest.java | 14 ++++ 2 files changed, 85 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/8c9fd4ef/wicket-core/src/main/java/org/apache/wicket/resource/CssUrlReplacer.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/resource/CssUrlReplacer.java b/wicket-core/src/main/java/org/apache/wicket/resource/CssUrlReplacer.java index 7734e91..8071d9a 100644 --- a/wicket-core/src/main/java/org/apache/wicket/resource/CssUrlReplacer.java +++ b/wicket-core/src/main/java/org/apache/wicket/resource/CssUrlReplacer.java @@ -16,13 +16,20 @@ */ package org.apache.wicket.resource; +import java.io.IOException; +import java.io.InputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.css.ICssCompressor; import org.apache.wicket.request.Url; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.resource.PackageResourceReference; +import org.apache.wicket.util.crypt.Base64; +import org.apache.wicket.util.io.IOUtils; +import org.apache.wicket.util.resource.IResourceStream; +import org.apache.wicket.util.resource.ResourceStreamNotFoundException; /** * This compressor is used to replace url within css files with resources that belongs to their @@ -44,6 +51,12 @@ public class CssUrlReplacer implements IScopeAwareTextResourceProcessor, ICssCom private static final Pattern URL_PATTERN = Pattern.compile("url\\(['|\"]*(.*?)['|\"]*\\)"); /** + * Used to be append to CSS URLs (background-image: url('Beer.gif?embedBase64');). The + * CssUrlReplacer embeds the base64 content instead of using an URL. + */ + public static final String EMBED_BASE64 = "embedBase64"; + + /** * Replaces the URLs of CSS resources with Wicket representatives. */ @Override @@ -58,6 +71,8 @@ public class CssUrlReplacer implements IScopeAwareTextResourceProcessor, ICssCom { Url imageCandidateUrl = Url.parse(matcher.group(1)); CharSequence processedUrl; + boolean embedded = false; + if (imageCandidateUrl.isFull()) { processedUrl = imageCandidateUrl.toString(Url.StringMode.FULL); @@ -71,21 +86,72 @@ public class CssUrlReplacer implements IScopeAwareTextResourceProcessor, ICssCom // relativize against the url for the containing CSS file Url cssUrlCopy = new Url(cssUrl); cssUrlCopy.resolveRelative(imageCandidateUrl); - PackageResourceReference imageReference = new PackageResourceReference(scope, - cssUrlCopy.toString()); - processedUrl = cycle.urlFor(imageReference, null); + + // if the image should be processed as URL or base64 embedded + if (cssUrlCopy.getQueryString() != null && + cssUrlCopy.getQueryString().contains(EMBED_BASE64)) + { + embedded = true; + PackageResourceReference imageReference = new PackageResourceReference(scope, + cssUrlCopy.toString().replace("?" + EMBED_BASE64, "")); + try + { + processedUrl = createBase64EncodedImage(imageReference); + } + catch (Exception e) + { + throw new WicketRuntimeException( + "Error while embedding an image into the css: " + imageReference, e); + } + } + else + { + PackageResourceReference imageReference = new PackageResourceReference(scope, + cssUrlCopy.toString()); + processedUrl = cycle.urlFor(imageReference, null); + } } - matcher.appendReplacement(output, "url('" + processedUrl + "')"); + matcher.appendReplacement(output, embedded ? "url(" + processedUrl + ")" : "url('" + + processedUrl + "')"); } matcher.appendTail(output); return output.toString(); } + /** + * Creates a base64 encoded image string based on the given image reference + * + * @param imageReference + * the image reference to create the base64 encoded image string of + * @return the base64 encoded image string + * @throws ResourceStreamNotFoundException + * if the resource couldn't be found + * @throws IOException + * if the stream couldn't be read + */ + private CharSequence createBase64EncodedImage(PackageResourceReference imageReference) + throws ResourceStreamNotFoundException, IOException + { + IResourceStream resourceStream = imageReference.getResource().getResourceStream(); + InputStream inputStream = resourceStream.getInputStream(); + try + { + byte[] bytes = IOUtils.toByteArray(inputStream); + String base64EncodedImage = Base64.encodeBase64String(bytes); + return "data:" + resourceStream.getContentType() + ";base64," + + base64EncodedImage.replaceAll("\\s", ""); + } + finally + { + IOUtils.closeQuietly(inputStream); + } + } + @Override public String compress(String original) { throw new UnsupportedOperationException(CssUrlReplacer.class.getSimpleName() + ".process() should be used instead!"); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/wicket/blob/8c9fd4ef/wicket-core/src/test/java/org/apache/wicket/resource/CssUrlReplacerTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/CssUrlReplacerTest.java b/wicket-core/src/test/java/org/apache/wicket/resource/CssUrlReplacerTest.java index f83338a..85973f9 100644 --- a/wicket-core/src/test/java/org/apache/wicket/resource/CssUrlReplacerTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/resource/CssUrlReplacerTest.java @@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import org.apache.wicket.WicketTestCase; +import org.apache.wicket.markup.html.image.ImageTest; import org.apache.wicket.mock.MockApplication; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy; @@ -142,6 +143,19 @@ public class CssUrlReplacerTest extends WicketTestCase } @Test + public void base64EncodedImage() + { + String input = ".class {background-image: url('Beer.gif?embedBase64');}"; + Class<?> scope = ImageTest.class; + String cssRelativePath = "some.css"; + CssUrlReplacer replacer = new CssUrlReplacer(); + String processed = replacer.process(input, scope, cssRelativePath); + assertThat( + processed, + containsString(".class {background-image: url(data:image/gif;base64,R0lGODlh1wATAXAAACH5BAEAAP8ALAAAAADXA")); + } + + @Test public void severalUrls() { String input = ".class {\n" + "a: url('../images/a.img');\n" + "b: url('./b.img');\n" + "}";
