com.adobe.granite.ui.clientlibs.script.Utils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*************************************************************************
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2011 Adobe
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe
* and its suppliers and are protected by all applicable intellectual
* property laws, including trade secret and copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe.
**************************************************************************/
package com.adobe.granite.ui.clientlibs.script;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.jcr.Binary;
import javax.jcr.Property;
import javax.jcr.Session;
import org.apache.jackrabbit.util.Base64;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The CssFileBuilder
provides all specific css builder functionality.
*/
public final class Utils {
/**
* default logger
*/
private static final Logger log = LoggerFactory.getLogger(Utils.class);
/**
* pattern that matches a scheme start, e.g. "http://"
*/
private static Pattern SCHEME_START = Pattern.compile("^[^:/]+:[^/]*/.*");
/**
* pattern that matches an css url reference. eg: "background: url(image.jpg);"
*/
private static Pattern URL_PATTERN= Pattern.compile("url\\(\\s*(['\"]?)([^'\")]*)(['\"]?\\s*)\\)");
/**
* static class
*/
private Utils() {
}
/**
* Resolves relative links within a css, such as an url to a background image, in respect to the
* library path.
*
* @param libPath the library path.
* @param filePath the path of the original css file
* @param css the css to transform
* @return the transformed css
*/
public static String rewriteUrlsInCss(String libPath, String filePath, String css) {
return rewriteUrlsInCss(Text.explode(libPath, '/'), Text.explode(filePath, '/'), css, null, 0);
}
/**
* Resolves relative links within a css, such as an url to a background image, in respect to the
* library path.
*
* @param libPath the library path.
* @param filePath the path of the original css file
* @param css the css to transform
* @param session use to auto-inline data uris.
* @param maxDataUriSize only inline data uris if smaller
* @return the transformed css
*/
public static String rewriteUrlsInCss(String libPath, String filePath, String css, Session session, long maxDataUriSize) {
return rewriteUrlsInCss(Text.explode(libPath, '/'), Text.explode(filePath, '/'), css, session, maxDataUriSize);
}
/**
* Resolves relative links within a css, such as an url to a background image, in respect to the
* library path.
*
* @param libPathSegs the library path segments.
* @param filePathSegs the path segments of the original css file
* @param css the css to transform
* @param session the session to use for embedding the data
* @param maxDataUriSize the max size for data uris
* @return the transformed css
*/
public static String rewriteUrlsInCss(String[] libPathSegs, String[] filePathSegs, String css, Session session, long maxDataUriSize) {
Matcher m = URL_PATTERN.matcher(css);
StringBuffer result = new StringBuffer();
while (m.find()) {
String url = m.group(2);
if (url.startsWith("absolute:")) {
url = url.substring(9);
} else if (url.endsWith(".htc") || url.startsWith("//")) {
// do nothing
} else {
url = resolveUrl(libPathSegs, filePathSegs, url);
if (maxDataUriSize > 0 && session != null && !SCHEME_START.matcher(url).matches()) {
// check if referenced data exists and is smaller than max size
Binary bin = null;
String path = new StringBuilder("/")
.append(Text.implode(libPathSegs, "/"))
.append("/../")
.append(url)
.append("/jcr:content/jcr:data")
.toString();
try {
if (session.propertyExists(path)) {
Property p = session.getProperty(path);
if (p.getLength() < maxDataUriSize) {
bin = p.getBinary();
StringWriter w = new StringWriter();
Base64.encode(bin.getStream(), w);
url = new StringBuilder("data:")
.append(p.getParent().getProperty(Property.JCR_MIMETYPE).getString())
.append(";base64,")
.append(w.toString())
.toString();
}
}
} catch (Exception e) {
log.warn("Error while encoding data uri of {}: {}", path, e.toString());
} finally {
if (bin != null) {
bin.dispose();
}
}
}
}
url = url.replace("$", "\\$");
m.appendReplacement(result, "url($1" + url + "$3)");
}
m.appendTail(result);
return result.toString();
}
/**
* Resolves a relative link from a css style, such as an url to a background image, in respect to the
* library path. If the given url is absolute, it is returned unchanged.
*
* Note that the libPath and filePath need to be canonical in order to work correctly.
*
* @param libPath the library path.
* @param filePath the path of the original css file
* @param url the url referenced in the css file
* @return the resolved url
*/
public static String resolveUrl(String libPath, String filePath, String url) {
return resolveUrl(Text.explode(libPath, '/'), Text.explode(filePath, '/'), url);
}
/**
* Resolves a relative link from a css style, such as an url to a background image, in respect to the
* library path. If the given url is absolute it is returned unchanged.
*
* Note that the libPath and filePath need to be canonical in order to work correctly.
*
* @param libPath the library path.
* @param filePath the path of the original css file
* @param url the url referenced in the css file
* @return the resolved url
*/
private static String resolveUrl(String[] libPath, String[] filePath, String url) {
// ignore empty, path absolute or absolute urls
if (url.length() == 0 || SCHEME_START.matcher(url).matches()) {
if (log.isDebugEnabled()) {
log.debug("resolving lib=/{}, file=/{}, url={} (ignored)", new Object[]{
Text.implode(libPath, "/"), Text.implode(filePath, "/"), url
});
}
return url;
}
// resolve url in respect to css file
LinkedList file = new LinkedList();
if (url.startsWith("/")) {
// if absolute, we start with an empty 'CSS' file
} else {
file.addAll(Arrays.asList(filePath));
// remove last segment as the urls are relative to the file's directory
file.removeLast();
}
boolean warned = false;
for (String seg: Text.explode(url, '/')) {
if ("..".equals(seg)) {
if (file.isEmpty()) {
if (!warned) {
log.warn("/{}: url('{}') invalid. too many '..'", Text.implode(filePath, "/"), url);
warned = true;
}
} else {
file.removeLast();
}
} else if (".".equals(seg)) {
// skip
} else {
file.add(seg);
}
}
// make relative path in respect to library path. first remove the segments that are equal
int i=0;
while (i < libPath.length -1 && libPath[i].matches(file.getFirst())) {
file.removeFirst();
i++;
}
// then add parent segments up to the root
while (i++ < libPath.length - 1) {
file.addFirst("..");
}
// build resulting path
StringBuilder ret = new StringBuilder();
String delim = "";
for (String seg: file) {
ret.append(delim).append(seg);
delim = "/";
}
if (log.isDebugEnabled()) {
log.debug("resolving lib=/{}, file=/{}, url={} -> {}", new Object[]{
Text.implode(libPath, "/"), Text.implode(filePath, "/"), url, ret
});
}
return ret.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy