package spark.template.mvel; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.mvel2.templates.CompiledTemplate; import org.mvel2.templates.TemplateCompiler; import org.mvel2.templates.TemplateRuntime; import spark.ModelAndView; import spark.TemplateEngine; /** * Template Engine based on <a href="https://github.com/mvel/mvel">MVEL</a>. * * @author DevNG https://github.com/devng */ public class MvelTemplateEngine extends TemplateEngine { private static final String DEFAULT_PREFIX = "templates/"; // lets do some caching of expressions to see if we cant go a bit faster private final ConcurrentMap<String, CompiledTemplate> templateCache; private final String prefix; public MvelTemplateEngine() { this(DEFAULT_PREFIX); } public MvelTemplateEngine(final String prefix) { this.templateCache = new ConcurrentHashMap<>(); this.prefix = prefix; } @Override public String render(final ModelAndView modelAndView) { final CompiledTemplate compiledTemplate = loadTemplate(modelAndView.getViewName()); return (String) TemplateRuntime.execute(compiledTemplate, modelAndView.getModel()); } public CompiledTemplate loadTemplate(String resourceName) { final String fullPath = prefix + resourceName; CompiledTemplate compiledTemplate = templateCache.get(fullPath); if (compiledTemplate == null) { // use the Stupid scanner trick in order not to rely on external libs // https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks compiledTemplate = TemplateCompiler .compileTemplate(Thread.currentThread().getContextClassLoader().getResourceAsStream(fullPath)); templateCache.putIfAbsent(fullPath, compiledTemplate); } return compiledTemplate; } }