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" + "}";

Reply via email to