/**
* Copyright wro4j@2011
*/
package ro.isdc.wro.model.resource.processor.impl;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.model.resource.Resource;
import ro.isdc.wro.model.resource.processor.ResourcePostProcessor;
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
import ro.isdc.wro.util.ObjectFactory;
import ro.isdc.wro.util.WroUtil;
/**
* A processor which parse a resource and search for placeholders of this type: <code>${}</code> and replace them with
* the values found in a map provided the by client.
*
* @author Alex Objelean
* @since 1.3.8
* @created 15 Jun 2011
*/
public class PlaceholderProcessor
implements ResourcePreProcessor, ResourcePostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(PlaceholderProcessor.class);
private static final Pattern PATTERN_PLACEHOLDER = Pattern.compile(WroUtil.loadRegexpWithKey("placeholder"));
private static final Properties EMPTY_PROPERTIES = new Properties();
/**
* Factory used to build Properties object containing values of the variables to substitute.
*/
private ObjectFactory<Properties> propertiesFactory;
/**
* If false, when a variable is not defined, a runtime exception will be thrown. Default value is true - meaning that
* missing variables will be replaced with empty value.
*/
private boolean ignoreMissingVariables = true;
/**
* {@inheritDoc}
*/
public void process(final Reader reader, final Writer writer)
throws IOException {
process(null, reader, writer);
}
/**
* {@inheritDoc}
*/
public void process(final Resource resource, final Reader reader, final Writer writer)
throws IOException {
final String content = IOUtils.toString(reader);
final Matcher matcher = PATTERN_PLACEHOLDER.matcher(content);
final StringBuffer sb = new StringBuffer();
Properties properties = null;
if (propertiesFactory != null) {
properties = propertiesFactory.create();
}
//be sure that properties will never be null;
if (properties == null) {
properties = EMPTY_PROPERTIES;
}
while (matcher.find()) {
final String variableName = matcher.group(1);
LOG.debug("found placeholder: {}", variableName);
matcher.appendReplacement(sb, replaceVariable(properties, variableName));
}
matcher.appendTail(sb);
writer.write(sb.toString());
}
/**
* @param variableName
* @return
*/
private String replaceVariable(final Properties properties, final String variableName) {
final String variableValue = properties.getProperty(variableName);
if (!ignoreMissingVariables && variableValue == null) {
throw new WroRuntimeException("No value defind for variable called: [" + variableName + "]");
}
final String result = variableValue == null ? StringUtils.EMPTY : variableValue;
LOG.debug("replacing: [{}] with [{}]", variableName, result);
return result;
}
/**
* @param ignoreMissingVariables the ignoreMissingVariables to set
*/
public PlaceholderProcessor setIgnoreMissingVariables(final boolean ignoreMissingVariables) {
this.ignoreMissingVariables = ignoreMissingVariables;
return this;
}
/**
* @param propertiesFactory the propertiesFactory to set
*/
public PlaceholderProcessor setPropertiesFactory(final ObjectFactory<Properties> propertiesFactory) {
this.propertiesFactory = propertiesFactory;
return this;
}
}