package org.jibeframework.core.app.template;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.management.RuntimeErrorException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jibeframework.core.Context;
import org.jibeframework.core.JibeRuntimeException;
import org.jibeframework.core.app.Application;
import org.jibeframework.core.service.CoreServices;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MruCacheStorage;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModelException;
public class FreeMarkerTemplateEngine implements TemplateEngine {
public static final String BEAN_ID = "jibe.FreemarkerTemplateEngine";
private Configuration config;
private List<FileTemplateLoader> loaders = new ArrayList<FileTemplateLoader>();
private static Log logger = LogFactory.getLog(FreeMarkerTemplateEngine.class);
private List<String> templatesPath = new ArrayList<String>();
public String processTemplate(String template, Map<String, Object> map) throws TemplateNotFoundException {
String json = getFromFreemarkerTemplate(map, template);
json = StringUtils.remove(json, "\r\n");
json = StringUtils.remove(json, "\t");
if (logger.isDebugEnabled()) {
logger.debug(String.format("Template %1$s", template));
}
return json;
}
private String getFromFreemarkerTemplate(Map<String, Object> model, String templateId)
throws TemplateNotFoundException {
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
Object servicesStatic = null;
try {
servicesStatic = staticModels.get(CoreServices.class.getName());
} catch (TemplateModelException e) {
throw new JibeRuntimeException("Services class can not be inserted into template model", e);
}
model.put("CoreServices", servicesStatic);
Context currentContext = Context.getCurrentContext();
if (currentContext != null) {
model.put("CurrentContext", currentContext);
}
Template t = null;
try {
t = getConfig().getTemplate(
new StringBuilder("/").append(templateId.replace('.', '/')).append(".ftl").toString());
} catch (IOException e) {
throw new TemplateNotFoundException();
}
Writer out = new StringWriter(1024);
try {
t.process(model, out);
} catch (Exception e) {
throw new JibeRuntimeException("There was an error processing template:" + templateId, e);
}
return out.toString();
}
public void registerTemplatesPath(String path) {
templatesPath.add(path);
}
/**
* Get the FreeMarker configuration for this instance
*
* @return FreeMarker configuration
*/
private Configuration getConfig() {
if (config == null) {
for (String templatePath : templatesPath) {
try {
File file = ResourceUtils.getFile(Application.getClasspathPrefix() + templatePath);
if (file.exists()) {
loaders.add(new FileTemplateLoader(file));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
config = new Configuration();
config.setCacheStorage(new MruCacheStorage(32, 32));
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
config.setTemplateLoader(loader);
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
}
return config;
}
}