You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by ts...@apache.org on 2015/03/12 11:33:58 UTC

wicket git commit: WICKET-5827 - CssUrlReplacer supports base64 encoded images

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 <kl...@192.168.2.110>
Authored: Wed Feb 18 16:33:21 2015 +0100
Committer: klopfdreh <kl...@192.168.2.110>
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" + "}";