From 5906228e60581e0be4a662fa921c9af514a4a95f Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Wed, 1 Dec 2021 13:38:42 +0200 Subject: [PATCH] Make AbstractTemplateEngine#init method final, use lazy instantiation (#591) --- .../ro/pippo/core/AbstractTemplateEngine.java | 63 +++++---- .../core/AbstractTemplateEngineTest.java | 5 - .../freemarker/FreemarkerTemplateEngine.java | 125 +++++++++--------- .../ro/pippo/groovy/GroovyTemplateEngine.java | 86 ++++++------ .../ro/pippo/jade/JadeTemplateEngine.java | 74 +++++------ .../ro/pippo/pebble/PebbleTemplateEngine.java | 105 +++++++-------- .../ro/pippo/trimou/TrimouTemplateEngine.java | 110 +++++++-------- 7 files changed, 264 insertions(+), 304 deletions(-) diff --git a/pippo-core/src/main/java/ro/pippo/core/AbstractTemplateEngine.java b/pippo-core/src/main/java/ro/pippo/core/AbstractTemplateEngine.java index c6d588a8..ddc15d04 100644 --- a/pippo-core/src/main/java/ro/pippo/core/AbstractTemplateEngine.java +++ b/pippo-core/src/main/java/ro/pippo/core/AbstractTemplateEngine.java @@ -21,12 +21,7 @@ import java.util.Locale; /** - * Convenience abstract implementation of {@link TemplateEngine} - * - * To use the convenience methods in this class, implementations must override {@link #init(Application)} - * and call this class' implementation before performing any of their initialization. - * - * @see TemplateEngine + * Convenience abstract implementation of {@link TemplateEngine}. * * @author Ranganath Kini */ @@ -37,28 +32,20 @@ public abstract class AbstractTemplateEngine implements TemplateEngine { private Router router; private PippoSettings pippoSettings; + private Application application; + private String fileExtension; private String templatePathPrefix; /** - * Performs common initialization for template engines. - * - * Implementations must override this method to do their own template engine specific initialization. - * To use the convenience of this class, implementations must invoke this class's implementation before - * performing their own initialization. + * This method is called by {@link Application#setTemplateEngine(TemplateEngine)}. * * @param application reference to the Pippo {@link Application} that can be used to retrieve settings * and other settings for the initialization */ @Override - public void init(Application application) { - languages = application.getLanguages(); - messages = application.getMessages(); - router = application.getRouter(); - pippoSettings = application.getPippoSettings(); - - fileExtension = pippoSettings.getString(PippoConstants.SETTING_TEMPLATE_EXTENSION, getDefaultFileExtension()); - templatePathPrefix = pippoSettings.getString(PippoConstants.SETTING_TEMPLATE_PATH_PREFIX, TemplateEngine.DEFAULT_PATH_PREFIX); + public final void init(Application application) { + this.application = application; } /** @@ -85,6 +72,10 @@ public final void setFileExtension(String extension) { * @return String the configured file extension for template resources */ protected final String getFileExtension() { + if (fileExtension == null) { + fileExtension = getPippoSettings().getString(PippoConstants.SETTING_TEMPLATE_EXTENSION, getDefaultFileExtension()); + } + return fileExtension; } @@ -92,6 +83,10 @@ protected final String getFileExtension() { * @see Application#getLanguages() */ protected final Languages getLanguages() { + if (languages == null) { + languages = getApplication().getLanguages(); + } + return languages; } @@ -99,13 +94,21 @@ protected final Languages getLanguages() { * @see Application#getMessages() */ protected final Messages getMessages() { - return this.messages; + if (messages == null) { + messages = getApplication().getMessages(); + } + + return messages; } /** * @see Application#getPippoSettings() */ protected final PippoSettings getPippoSettings() { + if (pippoSettings == null) { + pippoSettings = getApplication().getPippoSettings(); + } + return pippoSettings; } @@ -113,34 +116,38 @@ protected final PippoSettings getPippoSettings() { * @see Languages#getLocaleOrDefault(String) */ protected final Locale getLocaleOrDefault(String language) { - return languages.getLocaleOrDefault(language); + return getLanguages().getLocaleOrDefault(language); } /** * @see Languages#getLocaleOrDefault(RouteContext) */ protected final Locale getLocaleOrDefault(RouteContext routeContext) { - return languages.getLocaleOrDefault(routeContext); + return getLanguages().getLocaleOrDefault(routeContext); } /** * @see Languages#getLanguageOrDefault(String) */ protected final String getLanguageOrDefault(String language) { - return languages.getLanguageOrDefault(language); + return getLanguages().getLanguageOrDefault(language); } /** * @see Languages#getLanguageOrDefault(RouteContext) */ protected final String getLanguageOrDefault(RouteContext routeContext) { - return languages.getLanguageOrDefault(routeContext); + return getLanguages().getLanguageOrDefault(routeContext); } /** * @see Application#getRouter() */ protected final Router getRouter() { + if (router == null) { + router = getApplication().getRouter(); + } + return router; } @@ -150,7 +157,15 @@ protected final Router getRouter() { * @return String the template path prefix for loading template resources */ protected final String getTemplatePathPrefix() { + if (templatePathPrefix == null) { + templatePathPrefix = getPippoSettings().getString(PippoConstants.SETTING_TEMPLATE_PATH_PREFIX, TemplateEngine.DEFAULT_PATH_PREFIX); + } + return templatePathPrefix; } + protected final Application getApplication() { + return application; + } + } diff --git a/pippo-core/src/test/java/ro/pippo/core/AbstractTemplateEngineTest.java b/pippo-core/src/test/java/ro/pippo/core/AbstractTemplateEngineTest.java index bbdff237..36cb1040 100644 --- a/pippo-core/src/test/java/ro/pippo/core/AbstractTemplateEngineTest.java +++ b/pippo-core/src/test/java/ro/pippo/core/AbstractTemplateEngineTest.java @@ -237,11 +237,6 @@ public void shouldReturnTemplatePathPrefixConfiguredInSettings() { private static class TestTemplateEngine extends AbstractTemplateEngine { - @Override - public void init(Application application) { - super.init(application); - } - @Override public void renderString(String templateContent, Map model, Writer writer) { // do nothing diff --git a/pippo-template-parent/pippo-freemarker/src/main/java/ro/pippo/freemarker/FreemarkerTemplateEngine.java b/pippo-template-parent/pippo-freemarker/src/main/java/ro/pippo/freemarker/FreemarkerTemplateEngine.java index 568ca82c..87a25480 100644 --- a/pippo-template-parent/pippo-freemarker/src/main/java/ro/pippo/freemarker/FreemarkerTemplateEngine.java +++ b/pippo-template-parent/pippo-freemarker/src/main/java/ro/pippo/freemarker/FreemarkerTemplateEngine.java @@ -21,12 +21,9 @@ import freemarker.template.Template; import org.kohsuke.MetaInfServices; import ro.pippo.core.AbstractTemplateEngine; -import ro.pippo.core.Application; import ro.pippo.core.PippoConstants; import ro.pippo.core.PippoRuntimeException; -import ro.pippo.core.PippoSettings; import ro.pippo.core.TemplateEngine; -import ro.pippo.core.route.Router; import ro.pippo.core.util.StringUtils; import java.io.Writer; @@ -41,9 +38,10 @@ public class FreemarkerTemplateEngine extends AbstractTemplateEngine { public static final String FTL = "ftl"; + private Configuration configuration; + private WebjarsAtMethod webjarResourcesMethod; private PublicAtMethod publicResourcesMethod; - private Configuration configuration; static { try { @@ -54,26 +52,53 @@ public class FreemarkerTemplateEngine extends AbstractTemplateEngine { } @Override - public void init(Application application) { - super.init(application); + public void renderString(String templateContent, Map model, Writer writer) { + Map enhancedModel = enhancesTemplateModel(model); + + try { + Template template = new Template("StringTemplate", templateContent, getConfiguration()); + template.process(enhancedModel, writer); + } catch (Exception e) { + throw new PippoRuntimeException(e); + } + } - Router router = getRouter(); - PippoSettings pippoSettings = getPippoSettings(); + @Override + public void renderResource(String templateName, Map model, Writer writer) { + Map enhancedModel = enhancesTemplateModel(model); + Locale locale = (Locale) enhancedModel.get("locale"); - configuration = new Configuration(Configuration.VERSION_2_3_21); + try { + if (templateName.indexOf('.') == -1) { + templateName += "." + getFileExtension(); + } + Template template = getConfiguration().getTemplate(templateName, locale); + template.process(enhancedModel, writer); + } catch (Exception e) { + throw new PippoRuntimeException(e); + } + } + + @Override + protected String getDefaultFileExtension() { + return FTL; + } + + protected Configuration createConfiguration() { + Configuration configuration = new Configuration(Configuration.VERSION_2_3_21); configuration.setDefaultEncoding(PippoConstants.UTF8); configuration.setOutputEncoding(PippoConstants.UTF8); configuration.setLocalizedLookup(true); configuration.setClassForTemplateLoading(FreemarkerTemplateEngine.class, getTemplatePathPrefix()); - // We also do not want Freemarker to chose a platform dependent + // We also do not want Freemarker to choose a platform dependent // number formatting. Eg "1000" could be printed out by FTL as "1,000" // on some platforms. // See also: // http://freemarker.sourceforge.net/docs/app_faq.html#faq_number_grouping configuration.setNumberFormat("0.######"); // now it will print 1000000 - if (pippoSettings.isDev()) { + if (getPippoSettings().isDev()) { configuration.setTemplateUpdateDelayMilliseconds(0); // disable cache } else { // never update the templates in production or while testing... @@ -85,28 +110,19 @@ public void init(Application application) { } // set global template variables - configuration.setSharedVariable("contextPath", new SimpleScalar(router.getContextPath())); - configuration.setSharedVariable("appPath", new SimpleScalar(router.getApplicationPath())); + configuration.setSharedVariable("contextPath", new SimpleScalar(getRouter().getContextPath())); + configuration.setSharedVariable("appPath", new SimpleScalar(getRouter().getApplicationPath())); - webjarResourcesMethod = new WebjarsAtMethod(router); - publicResourcesMethod = new PublicAtMethod(router); - - // allow custom initialization - init(application, configuration); - } - - @Override - protected String getDefaultFileExtension() { - return FTL; + return configuration; } - @Override - public void renderString(String templateContent, Map model, Writer writer) { + protected Map enhancesTemplateModel(Map model) { // prepare the locale-aware i18n method String language = (String) model.get(PippoConstants.REQUEST_PARAMETER_LANG); if (StringUtils.isNullOrEmpty(language)) { language = getLanguageOrDefault(language); } + model.put("lang", language); model.put("i18n", new I18nMethod(getMessages(), language)); // prepare the locale-aware prettyTime method @@ -114,56 +130,37 @@ public void renderString(String templateContent, Map model, Writ if (locale == null) { locale = getLocaleOrDefault(language); } + model.put("locale", locale); model.put("prettyTime", new PrettyTimeMethod(locale)); model.put("formatTime", new FormatTimeMethod(locale)); - model.put("webjarsAt", webjarResourcesMethod); - model.put("publicAt", publicResourcesMethod); + model.put("webjarsAt", getWebjarResourcesMethod()); + model.put("publicAt", getPublicResourcesMethod()); - try { - Template template = new Template("StringTemplate", templateContent, configuration); - template.process(model, writer); - } catch (Exception e) { - throw new PippoRuntimeException(e); - } + return model; } - @Override - public void renderResource(String templateName, Map model, Writer writer) { - // prepare the locale-aware i18n method - String language = (String) model.get(PippoConstants.REQUEST_PARAMETER_LANG); - if (StringUtils.isNullOrEmpty(language)) { - language = getLanguageOrDefault(language); + protected final WebjarsAtMethod getWebjarResourcesMethod() { + if (webjarResourcesMethod == null) { + webjarResourcesMethod = new WebjarsAtMethod(getRouter()); } - model.put("i18n", new I18nMethod(getMessages(), language)); - // prepare the locale-aware prettyTime method - Locale locale = (Locale) model.get(PippoConstants.REQUEST_PARAMETER_LOCALE); - if (locale == null) { - locale = getLocaleOrDefault(language); - } - model.put("prettyTime", new PrettyTimeMethod(locale)); - model.put("formatTime", new FormatTimeMethod(locale)); - model.put("webjarsAt", webjarResourcesMethod); - model.put("publicAt", publicResourcesMethod); + return webjarResourcesMethod; + } - try { - if (templateName.indexOf('.') == -1) { - templateName += "." + getFileExtension(); - } - Template template = configuration.getTemplate(templateName, locale); - template.process(model, writer); - } catch (Exception e) { - throw new PippoRuntimeException(e); + protected final PublicAtMethod getPublicResourcesMethod() { + if (publicResourcesMethod == null) { + publicResourcesMethod = new PublicAtMethod(getRouter()); } + + return publicResourcesMethod; } - /** - * Override this method if you want to modify the template configuration. - * - * @param application - * @param configuration - */ - protected void init(Application application, Configuration configuration) { + private Configuration getConfiguration() { + if (configuration == null) { + configuration = createConfiguration(); + } + + return configuration; } } diff --git a/pippo-template-parent/pippo-groovy/src/main/java/ro/pippo/groovy/GroovyTemplateEngine.java b/pippo-template-parent/pippo-groovy/src/main/java/ro/pippo/groovy/GroovyTemplateEngine.java index 035caf24..b85be11b 100644 --- a/pippo-template-parent/pippo-groovy/src/main/java/ro/pippo/groovy/GroovyTemplateEngine.java +++ b/pippo-template-parent/pippo-groovy/src/main/java/ro/pippo/groovy/GroovyTemplateEngine.java @@ -22,9 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ro.pippo.core.AbstractTemplateEngine; -import ro.pippo.core.Application; import ro.pippo.core.PippoRuntimeException; -import ro.pippo.core.PippoSettings; import ro.pippo.core.TemplateEngine; import ro.pippo.core.util.StringUtils; @@ -46,48 +44,10 @@ public class GroovyTemplateEngine extends AbstractTemplateEngine { private MarkupTemplateEngine engine; - @Override - public void init(Application application) { - super.init(application); - - PippoSettings pippoSettings = getPippoSettings(); - - TemplateConfiguration configuration = new TemplateConfiguration(); - configuration.setBaseTemplateClass(PippoGroovyTemplate.class); - configuration.setAutoEscape(true); - - if (pippoSettings.isDev()) { - // Do not cache templates in dev mode - configuration.setCacheTemplates(false); - } else { - configuration.setAutoIndent(true); - configuration.setAutoNewLine(true); - configuration.setAutoIndentString(" "); - } - - String pathPrefix = getTemplatePathPrefix(); - pathPrefix = StringUtils.removeStart(pathPrefix, "/"); - pathPrefix = StringUtils.removeEnd(pathPrefix, "/"); - - GroovyTemplateResolver cachingResolver = new GroovyTemplateResolver(pathPrefix); - - ClassLoader classLoader = getClass().getClassLoader(); - - // allow custom initialization - init(application, configuration); - - engine = new MarkupTemplateEngine(classLoader, configuration, cachingResolver); - } - - @Override - protected String getDefaultFileExtension() { - return GROOVY; - } - @Override public void renderString(String templateContent, Map model, Writer writer) { try { - Template groovyTemplate = engine.createTemplate(templateContent); + Template groovyTemplate = getMarkupTemplateEngine().createTemplate(templateContent); PippoGroovyTemplate gt = (PippoGroovyTemplate) groovyTemplate.make(model); gt.setup(getLanguages(), getMessages(), getRouter()); gt.writeTo(writer); @@ -105,7 +65,7 @@ public void renderResource(String templateName, Map model, Write Template groovyTemplate; try { - groovyTemplate = engine.createTemplateByPath(templateName); + groovyTemplate = getMarkupTemplateEngine().createTemplateByPath(templateName); } catch (ClassNotFoundException | IOException | RuntimeException e) { log.error("Error reading Groovy template {} ", templateName, e); throw new PippoRuntimeException(e); @@ -121,13 +81,41 @@ public void renderResource(String templateName, Map model, Write } } - /** - * Override this method if you want to modify the template configuration. - * - * @param application - * @param configuration - */ - protected void init(Application application, TemplateConfiguration configuration) { + @Override + protected String getDefaultFileExtension() { + return GROOVY; } + protected TemplateConfiguration createTemplateConfiguration() { + TemplateConfiguration configuration = new TemplateConfiguration(); + configuration.setBaseTemplateClass(PippoGroovyTemplate.class); + configuration.setAutoEscape(true); + + if (getPippoSettings().isDev()) { + // Do not cache templates in dev mode + configuration.setCacheTemplates(false); + } else { + configuration.setAutoIndent(true); + configuration.setAutoNewLine(true); + configuration.setAutoIndentString(" "); + } + + return configuration; + } + + protected GroovyTemplateResolver createGroovyTemplateResolver() { + String pathPrefix = getTemplatePathPrefix(); + pathPrefix = StringUtils.removeStart(pathPrefix, "/"); + pathPrefix = StringUtils.removeEnd(pathPrefix, "/"); + + return new GroovyTemplateResolver(pathPrefix); + } + + private MarkupTemplateEngine getMarkupTemplateEngine() { + if (engine == null) { + engine = new MarkupTemplateEngine(getClass().getClassLoader(), createTemplateConfiguration(), createGroovyTemplateResolver()); + } + + return engine; + } } diff --git a/pippo-template-parent/pippo-jade/src/main/java/ro/pippo/jade/JadeTemplateEngine.java b/pippo-template-parent/pippo-jade/src/main/java/ro/pippo/jade/JadeTemplateEngine.java index 2972398a..11f35b6b 100644 --- a/pippo-template-parent/pippo-jade/src/main/java/ro/pippo/jade/JadeTemplateEngine.java +++ b/pippo-template-parent/pippo-jade/src/main/java/ro/pippo/jade/JadeTemplateEngine.java @@ -48,34 +48,6 @@ public class JadeTemplateEngine extends AbstractTemplateEngine { private JadeConfiguration configuration; - @Override - public void init(Application application) { - super.init(application); - - Router router = getRouter(); - PippoSettings pippoSettings = getPippoSettings(); - - configuration = new JadeConfiguration(); - configuration.setTemplateLoader(new ClassTemplateLoader(JadeTemplateEngine.class, getTemplatePathPrefix())); - configuration.setMode(Mode.HTML); - if (pippoSettings.isDev()) { - configuration.setPrettyPrint(true); - configuration.setCaching(false); // disable cache - } - - // set global template variables - configuration.getSharedVariables().put("contextPath", router.getContextPath()); - configuration.getSharedVariables().put("appPath", router.getApplicationPath()); - - // allow custom initialization - init(application, configuration); - } - - @Override - protected String getDefaultFileExtension() { - return JADE; - } - @Override public void renderString(String templateContent, Map model, Writer writer) { // prepare the locale-aware i18n method @@ -97,11 +69,11 @@ public void renderString(String templateContent, Map model, Writ JadeConfiguration stringTemplateConfiguration = new JadeConfiguration(); stringTemplateConfiguration.setCaching(false); stringTemplateConfiguration.setTemplateLoader(stringTemplateLoader); - stringTemplateConfiguration.setMode(configuration.getMode()); - stringTemplateConfiguration.setPrettyPrint(configuration.isPrettyPrint()); + stringTemplateConfiguration.setMode(getConfiguration().getMode()); + stringTemplateConfiguration.setPrettyPrint(getConfiguration().isPrettyPrint()); - JadeTemplate stringTemplate = configuration.getTemplate("StringTemplate"); - configuration.renderTemplate(stringTemplate, model, writer); + JadeTemplate stringTemplate = getConfiguration().getTemplate("StringTemplate"); + getConfiguration().renderTemplate(stringTemplate, model, writer); writer.flush(); } catch (Exception e) { throw new PippoRuntimeException(e); @@ -124,21 +96,41 @@ public void renderResource(String templateName, Map model, Write model.put("pippo", new PippoHelper(getMessages(), language, locale, getRouter())); try { - JadeTemplate template = configuration.getTemplate(templateName); - configuration.renderTemplate(template, model, writer); + JadeTemplate template = getConfiguration().getTemplate(templateName); + getConfiguration().renderTemplate(template, model, writer); writer.flush(); } catch (Exception e) { throw new PippoRuntimeException(e); } } - /** - * Override this method if you want to modify the template configuration. - * - * @param application - * @param configuration - */ - protected void init(Application application, JadeConfiguration configuration) { + @Override + protected String getDefaultFileExtension() { + return JADE; + } + + protected JadeConfiguration createJadeConfiguration() { + JadeConfiguration configuration = new JadeConfiguration(); + configuration.setTemplateLoader(new ClassTemplateLoader(JadeTemplateEngine.class, getTemplatePathPrefix())); + configuration.setMode(Mode.HTML); + if (getPippoSettings().isDev()) { + configuration.setPrettyPrint(true); + configuration.setCaching(false); // disable cache + } + + // set global template variables + configuration.getSharedVariables().put("contextPath", getRouter().getContextPath()); + configuration.getSharedVariables().put("appPath", getRouter().getApplicationPath()); + + return configuration; + } + + private JadeConfiguration getConfiguration() { + if (configuration == null) { + configuration = createJadeConfiguration(); + } + + return configuration; } private class ClassTemplateLoader implements TemplateLoader { diff --git a/pippo-template-parent/pippo-pebble/src/main/java/ro/pippo/pebble/PebbleTemplateEngine.java b/pippo-template-parent/pippo-pebble/src/main/java/ro/pippo/pebble/PebbleTemplateEngine.java index c3e168a6..12b7a3f1 100644 --- a/pippo-template-parent/pippo-pebble/src/main/java/ro/pippo/pebble/PebbleTemplateEngine.java +++ b/pippo-template-parent/pippo-pebble/src/main/java/ro/pippo/pebble/PebbleTemplateEngine.java @@ -27,12 +27,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ro.pippo.core.AbstractTemplateEngine; -import ro.pippo.core.Application; import ro.pippo.core.PippoConstants; import ro.pippo.core.PippoRuntimeException; -import ro.pippo.core.PippoSettings; import ro.pippo.core.TemplateEngine; -import ro.pippo.core.route.Router; import ro.pippo.core.util.StringUtils; import java.io.Writer; @@ -55,58 +52,6 @@ public class PebbleTemplateEngine extends AbstractTemplateEngine { private PebbleEngine engine; - @Override - public void init(Application application) { - super.init(application); - - Router router = getRouter(); - PippoSettings pippoSettings = getPippoSettings(); - - List> loaders = new ArrayList<>(); - PippoTemplateLoader templateLoader = new PippoTemplateLoader(); - - templateLoader.setCharset(PippoConstants.UTF8); - templateLoader.setPrefix(getTemplatePathPrefix()); - if (pippoSettings.getBoolean("pebble.suffix.enabled", true)) { - templateLoader.setSuffix("." + getFileExtension()); - } - loaders.add(templateLoader); - - PebbleEngine.Builder builder = new PebbleEngine.Builder() - .loader(new DelegatingLoader(loaders)) - .strictVariables(false) - .extension(new GlobalVariablesExtension() - .set("contextPath", router.getContextPath()) - .set("appPath", router.getApplicationPath())) - .extension(new I18nExtension(application.getMessages())) - .extension(new FormatTimeExtension()) - .extension(new PrettyTimeExtension()) - .extension(new AngularJSExtension()) - .extension(new WebjarsAtExtension(router)) - .extension(new PublicAtExtension(router)) - .extension(new RouteExtension(router)); - - if (pippoSettings.isDev()) { - // do not cache templates in dev mode - builder.cacheActive(false); - builder.extension(new DebugExtension()); - } - - // allow custom initialization - init(application, builder); - - engine = builder.build(); - } - - /** - * Override this method if you want to modify the template configuration. - * - * @param application - * @param configurationTarget - */ - protected void init(Application application, PebbleEngine.Builder configurationTarget) { - } - @Override public void renderString(String templateContent, Map model, Writer writer) { String language = getLanguage(model); @@ -115,7 +60,7 @@ public void renderString(String templateContent, Map model, Writ try { PebbleEngine stringEngine = new PebbleEngine.Builder() .loader(new StringLoader()) - .strictVariables(engine.isStrictVariables()) + .strictVariables(getPebbleEngine().isStrictVariables()) .templateCache(null) .build(); @@ -146,7 +91,7 @@ public void renderResource(String templateName, Map model, Write if (template == null) { // fallback to the template without any language or locale - template = engine.getTemplate(templateName); + template = getPebbleEngine().getTemplate(templateName); } template.evaluate(writer, model, locale); @@ -165,11 +110,11 @@ private PebbleTemplate getTemplate(String templateName, String localePart) throw PebbleTemplate template = null; try { if (StringUtils.isNullOrEmpty(localePart)) { - template = engine.getTemplate(templateName); + template = getPebbleEngine().getTemplate(templateName); } else { String localizedName = StringUtils.removeEnd(templateName, "." + getFileExtension()) + "_" + localePart; - template = engine.getTemplate(localizedName); + template = getPebbleEngine().getTemplate(localizedName); } } catch (LoaderException e) { log.debug(e.getMessage()); @@ -198,4 +143,46 @@ protected Locale getLocale(Map model, String language) { return locale; } + protected PebbleEngine.Builder createPebbleEngineBuilder() { + List> loaders = new ArrayList<>(); + PippoTemplateLoader templateLoader = new PippoTemplateLoader(); + + templateLoader.setCharset(PippoConstants.UTF8); + templateLoader.setPrefix(getTemplatePathPrefix()); + if (getPippoSettings().getBoolean("pebble.suffix.enabled", true)) { + templateLoader.setSuffix("." + getFileExtension()); + } + loaders.add(templateLoader); + + PebbleEngine.Builder builder = new PebbleEngine.Builder() + .loader(new DelegatingLoader(loaders)) + .strictVariables(false) + .extension(new GlobalVariablesExtension() + .set("contextPath", getRouter().getContextPath()) + .set("appPath", getRouter().getApplicationPath())) + .extension(new I18nExtension(getMessages())) + .extension(new FormatTimeExtension()) + .extension(new PrettyTimeExtension()) + .extension(new AngularJSExtension()) + .extension(new WebjarsAtExtension(getRouter())) + .extension(new PublicAtExtension(getRouter())) + .extension(new RouteExtension(getRouter())); + + if (getPippoSettings().isDev()) { + // do not cache templates in dev mode + builder.cacheActive(false); + builder.extension(new DebugExtension()); + } + + return builder; + } + + private PebbleEngine getPebbleEngine() { + if (engine == null) { + engine = createPebbleEngineBuilder().build(); + } + + return engine; + } + } diff --git a/pippo-template-parent/pippo-trimou/src/main/java/ro/pippo/trimou/TrimouTemplateEngine.java b/pippo-template-parent/pippo-trimou/src/main/java/ro/pippo/trimou/TrimouTemplateEngine.java index ed544925..a32cb520 100644 --- a/pippo-template-parent/pippo-trimou/src/main/java/ro/pippo/trimou/TrimouTemplateEngine.java +++ b/pippo-template-parent/pippo-trimou/src/main/java/ro/pippo/trimou/TrimouTemplateEngine.java @@ -28,12 +28,9 @@ import org.trimou.minify.Minify; import org.trimou.prettytime.PrettyTimeHelper; import ro.pippo.core.AbstractTemplateEngine; -import ro.pippo.core.Application; import ro.pippo.core.PippoConstants; import ro.pippo.core.PippoRuntimeException; -import ro.pippo.core.PippoSettings; import ro.pippo.core.TemplateEngine; -import ro.pippo.core.route.Router; import ro.pippo.core.util.StringUtils; import java.io.Writer; @@ -52,55 +49,9 @@ public class TrimouTemplateEngine extends AbstractTemplateEngine { public static final String MUSTACHE = "mustache"; - private ThreadLocalLocaleSupport localeSupport; - private MustacheEngine engine; - - @Override - public void init(Application application) { - super.init(application); - - this.localeSupport = new ThreadLocalLocaleSupport(); + private ThreadLocalLocaleSupport localeSupport = new ThreadLocalLocaleSupport(); - Router router = getRouter(); - PippoSettings pippoSettings = getPippoSettings(); - - MustacheEngineBuilder builder = MustacheEngineBuilder.newBuilder(); - builder.setLocaleSupport(localeSupport); - builder.setProperty(EngineConfigurationKey.DEFAULT_FILE_ENCODING, PippoConstants.UTF8); - builder.registerHelper("ng", new AngularJsHelper()); - builder.registerHelper("i18n", new I18nHelper(application.getMessages())); - builder.registerHelper("formatTime", new DateTimeFormatHelper()); - builder.registerHelper("prettyTime", new PrettyTimeHelper()); - builder.registerHelper("webjarsAt", new WebjarsAtHelper(router)); - builder.registerHelper("publicAt", new PublicAtHelper(router)); - builder.registerHelpers(HelpersBuilder.extra().build()); - - String pathPrefix = getTemplatePathPrefix(); - pathPrefix = StringUtils.removeStart(pathPrefix, "/"); - builder.addTemplateLocator(new ClassPathTemplateLocator(10, pathPrefix, MUSTACHE)); - - if (pippoSettings.isDev()) { - // enable debug mode - builder.setProperty(EngineConfigurationKey.DEBUG_MODE, true); - } else { - // automatically minify pages generated in production/test - builder.addMustacheListener(Minify.htmlListener()); - } - - // set global template variables - builder.addGlobalData("contextPath", router.getContextPath()); - builder.addGlobalData("appPath", router.getApplicationPath()); - - // allow custom initialization - init(application, builder); - - engine = builder.build(); - } - - @Override - protected String getDefaultFileExtension() { - return MUSTACHE; - } + private MustacheEngine engine; @Override public void renderString(String templateContent, Map model, Writer writer) { @@ -117,7 +68,7 @@ public void renderString(String templateContent, Map model, Writ try { localeSupport.setCurrentLocale(locale); - Mustache template = engine.compileMustache("StringTemplate", templateContent); + Mustache template = getMustacheEngine().compileMustache("StringTemplate", templateContent); template.render(writer, model); writer.flush(); } catch (Exception e) { @@ -152,16 +103,16 @@ public void renderResource(String templateName, Map model, Write if (locale != null) { // try the complete Locale - template = engine.getMustache(getLocalizedTemplateName(templateName, locale.toString())); + template = getMustacheEngine().getMustache(getLocalizedTemplateName(templateName, locale.toString())); if (template == null) { // try only the language - template = engine.getMustache(getLocalizedTemplateName(templateName, locale.getLanguage())); + template = getMustacheEngine().getMustache(getLocalizedTemplateName(templateName, locale.getLanguage())); } } if (template == null) { // fallback to the template without any language or locale - template = engine.getMustache(templateName); + template = getMustacheEngine().getMustache(templateName); } if (template == null) { @@ -180,17 +131,52 @@ public void renderResource(String templateName, Map model, Write } } - /** - * Override this method if you want to modify the template configuration. - * - * @param application - * @param builder - */ - protected void init(Application application, MustacheEngineBuilder builder) { + @Override + protected String getDefaultFileExtension() { + return MUSTACHE; + } + + protected MustacheEngineBuilder createMustacheEngineBuilder() { + MustacheEngineBuilder builder = MustacheEngineBuilder.newBuilder() + .setLocaleSupport(localeSupport) + .setProperty(EngineConfigurationKey.DEFAULT_FILE_ENCODING, PippoConstants.UTF8) + .registerHelper("ng", new AngularJsHelper()) + .registerHelper("i18n", new I18nHelper(getMessages())) + .registerHelper("formatTime", new DateTimeFormatHelper()) + .registerHelper("prettyTime", new PrettyTimeHelper()) + .registerHelper("webjarsAt", new WebjarsAtHelper(getRouter())) + .registerHelper("publicAt", new PublicAtHelper(getRouter())) + .registerHelpers(HelpersBuilder.extra().build()); + + String pathPrefix = getTemplatePathPrefix(); + pathPrefix = StringUtils.removeStart(pathPrefix, "/"); + builder.addTemplateLocator(new ClassPathTemplateLocator(10, pathPrefix, MUSTACHE)); + + if (getPippoSettings().isDev()) { + // enable debug mode + builder.setProperty(EngineConfigurationKey.DEBUG_MODE, true); + } else { + // automatically minify pages generated in production/test + builder.addMustacheListener(Minify.htmlListener()); + } + + // set global template variables + builder.addGlobalData("contextPath", getRouter().getContextPath()); + builder.addGlobalData("appPath", getRouter().getApplicationPath()); + + return builder; } private String getLocalizedTemplateName(String templateName, String localePart) { return StringUtils.removeEnd(templateName, "." + getFileExtension()) + "_" + localePart; } + private MustacheEngine getMustacheEngine() { + if (engine == null) { + engine = createMustacheEngineBuilder().build(); + } + + return engine; + } + }