VariablesResolver.java
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.esigate.vars;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.cookie.Cookie;
import org.esigate.ConfigurationException;
import org.esigate.Driver;
import org.esigate.DriverFactory;
import org.esigate.http.IncomingRequest;
import org.esigate.impl.DriverRequest;
import org.esigate.util.HttpRequestHelper;
import org.esigate.util.UriUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manage variables replacement.
*
* @author Alexis Thaveau
* @author Nicolas Richeton
*/
public final class VariablesResolver {
private static final Logger LOG = LoggerFactory.getLogger(VariablesResolver.class);
private static Pattern userAgentVersion = Pattern.compile("^[A-Za-z]+/([0-9]+\\.[0-9]+)");
static {
// Load default settings
configure();
}
/**
* Properties file
*/
private static Properties properties;
private VariablesResolver() {
}
/**
* Loads variables from properties.
*
* @param props
* properties
*/
public static void configure(Properties props) {
properties = props;
}
/**
* Loads variables according to default configuration file org/esigate/vars.properties.
*/
public static void configure() {
InputStream inputStream = null;
try {
LOG.debug("Loading esigate-vars.properties file");
inputStream = Driver.class.getResourceAsStream("/esigate-vars.properties");
if (inputStream == null) {
inputStream = Driver.class.getResourceAsStream("vars.properties");
}
if (inputStream != null) {
properties = new Properties();
properties.load(inputStream);
}
} catch (IOException e) {
throw new ConfigurationException(e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// nothing to do
}
}
}
}
/**
* @return The URL of the variables file.
*/
public static URL getVariablessUrl() {
URL varsUrl = Driver.class.getResource("/esigate-vars.properties");
if (varsUrl == null) {
varsUrl = Driver.class.getResource("vars.properties");
}
return varsUrl;
}
/**
* Regexp to find variables
*/
private static final Pattern VAR_PATTERN = Pattern.compile("\\$\\((.*?)\\)");
/**
*
* @param strVars
* a String that may contain variables.
* @return true if contains variables
*/
static boolean containsVariable(String strVars) {
return strVars.contains("$(") && strVars.contains(")");
}
/**
* Replace all ESI variables found in strVars by their matching value in vars.properties.
*
* @param strVars
* a String containing variables.
* @return The resulting String
*/
public static String replaceAllVariables(String strVars) {
return replaceAllVariables(strVars, null);
}
/**
* Replace all ESI variables found in strVars by their matching value in vars.properties.
*
* @param strVars
* a String containing variables.
* @param request
* @return The resulting String
*/
public static String replaceAllVariables(String strVars, DriverRequest request) {
String result = strVars;
if (VariablesResolver.containsVariable(strVars)) {
Matcher matcher = VAR_PATTERN.matcher(strVars);
while (matcher.find()) {
String group = matcher.group();
String var = group.substring(2, group.length() - 1);
String arg = null;
// try to find argument
int argIndex = var.indexOf('{');
if (argIndex != -1) {
arg = VarUtils.removeSimpleQuotes(var.substring(argIndex + 1, var.indexOf('}')));
}
// try to find default value
// ESI 1.0 spec :
// 4.2 Variable Default Values
// Variables whose values are empty, nonexistent variables and
// undefined substructures of variables will evaluate to an
// empty string when they are accessed.
String defaultValue = StringUtils.EMPTY;
int defaultValueIndex = var.indexOf('|');
if (defaultValueIndex != -1) {
defaultValue = VarUtils.removeSimpleQuotes(var.substring(defaultValueIndex + 1));
}
String value = getProperty(var, arg, request);
if (value == null) {
value = defaultValue;
}
result = result.replace(group, value);
}
}
return result;
}
private static String getProperty(String var, String arg, DriverRequest request) {
String result = processVar(var, arg, request);
if (properties != null) {
result = properties.getProperty(var, result);
}
LOG.debug("Resolve property $({})={}", var, result);
return result;
}
private static String processVar(String var, String arg, DriverRequest request) {
IncomingRequest incomingRequest = null;
if (request != null) {
incomingRequest = request.getOriginalRequest();
}
String res = null;
if (var.contains("QUERY_STRING")) {
if (arg == null) {
res = UriUtils.getRawQuery(incomingRequest.getRequestLine().getUri());
} else {
res = HttpRequestHelper.getParameter(request, arg);
}
} else if (var.contains("HTTP_ACCEPT_LANGUAGE")) {
String langs = HttpRequestHelper.getFirstHeader("Accept-Language", incomingRequest);
if (arg == null) {
res = langs;
} else {
res = String.valueOf(!(langs == null || !langs.contains(arg)));
}
} else if (var.contains("HTTP_HEADER")) {
res = HttpRequestHelper.getFirstHeader(arg, incomingRequest);
} else if (var.contains("HTTP_HOST")) {
res = HttpRequestHelper.getFirstHeader("Host", incomingRequest);
} else if (var.contains("HTTP_REFERER")) {
res = HttpRequestHelper.getFirstHeader("Referer", incomingRequest);
} else if (var.contains("HTTP_COOKIE")) {
if (arg == null) {
// Add cookies
// In request header
String cookieHeaderValue = StringUtils.EMPTY;
for (Cookie c : request.getOriginalRequest().getCookies()) {
if (StringUtils.isNotBlank(cookieHeaderValue)) {
cookieHeaderValue = cookieHeaderValue + "; ";
}
cookieHeaderValue = cookieHeaderValue + c.getName() + "=" + c.getValue();
}
if (StringUtils.isNotBlank(cookieHeaderValue)) {
res = cookieHeaderValue;
}
} else {
Cookie[] cookies = request.getOriginalRequest().getCookies();
for (Cookie c : cookies) {
if (c.getName().equals(arg)) {
res = c.getValue();
break;
}
}
}
} else if (var.contains("HTTP_USER_AGENT")) {
if (arg == null) {
res = HttpRequestHelper.getFirstHeader("User-agent", incomingRequest);
} else {
String userAgent =
StringUtils.defaultString(HttpRequestHelper.getFirstHeader("User-Agent", incomingRequest))
.toLowerCase();
if (arg.equals("os")) {
if (userAgent.contains("unix")) {
res = "UNIX";
} else if (userAgent.contains("mac")) {
res = "MAC";
} else if (userAgent.contains("windows")) {
res = "WIN";
} else {
res = "OTHER";
}
} else if (arg.equals("browser")) {
if (userAgent.contains("msie")) {
res = "MSIE";
} else {
res = "MOZILLA";
}
} else if (arg.equals("version")) {
Matcher m = userAgentVersion.matcher(userAgent);
if (m.find()) {
res = m.group(1);
}
}
}
} else if (var.contains("PROVIDER")) {
String providerUrl = StringUtils.EMPTY;
try {
Driver driver = DriverFactory.getInstance(arg);
providerUrl =
driver.getConfiguration().getBaseUrlRetrieveStrategy().getBaseURL(request.getOriginalRequest());
} catch (Exception e) {
// No driver available for this id.
}
return providerUrl;
}
return res;
}
}