1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.freemarker;
35
36 import freemarker.cache.TemplateLoader;
37 import freemarker.ext.jsp.TaglibFactory;
38 import freemarker.ext.servlet.FreemarkerServlet;
39 import freemarker.ext.servlet.HttpRequestHashModel;
40 import freemarker.ext.servlet.ServletContextHashModel;
41 import freemarker.template.Configuration;
42 import freemarker.template.ObjectWrapper;
43 import freemarker.template.Template;
44 import freemarker.template.TemplateException;
45 import freemarker.template.TemplateExceptionHandler;
46 import freemarker.template.TemplateModel;
47 import freemarker.template.TemplateModelException;
48 import info.magnolia.cms.beans.config.ServerConfiguration;
49 import info.magnolia.context.MgnlContext;
50 import info.magnolia.context.WebContext;
51 import info.magnolia.objectfactory.Components;
52
53 import javax.servlet.GenericServlet;
54 import javax.servlet.ServletContext;
55 import javax.servlet.ServletException;
56 import java.io.IOException;
57 import java.io.Reader;
58 import java.io.Writer;
59 import java.util.Locale;
60 import java.util.Map;
61 import java.util.Set;
62
63
64
65
66
67
68
69
70
71
72 public class FreemarkerHelper {
73 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FreemarkerHelper.class);
74
75 public static FreemarkerHelper getInstance() {
76 return Components.getSingleton(FreemarkerHelper.class);
77 }
78
79 private final Configuration cfg;
80
81
82 private TaglibFactory taglibFactory;
83 private ServletContextHashModel servletContextHashModel;
84
85 public FreemarkerHelper() {
86 this(Components.getSingleton(FreemarkerConfig.class));
87 }
88
89 public FreemarkerHelper(final FreemarkerConfig freemarkerConfig) {
90
91 this.cfg = new Configuration() {
92 @Override
93 public Set getSharedVariableNames() {
94 final Set names = super.getSharedVariableNames();
95 names.addAll(freemarkerConfig.getSharedVariables().keySet());
96 return names;
97 }
98
99 @Override
100 public TemplateModel getSharedVariable(String name) {
101 final TemplateModel value = super.getSharedVariable(name);
102 if (value==null) {
103 return freemarkerConfig.getSharedVariables().get(name);
104 }
105 return value;
106 }
107 };
108 cfg.setTemplateExceptionHandler(freemarkerConfig.getTemplateExceptionHandler());
109
110
111
112
113 cfg.setTemplateLoader(new ConfigDelegatingTemplateLoader(freemarkerConfig));
114 cfg.setObjectWrapper(new ConfigDelegatingObjectWrapper(freemarkerConfig));
115
116 cfg.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
117 cfg.setDefaultEncoding("UTF8");
118
119 }
120
121
122
123
124 public void resetObjectWrapper() {
125
126 }
127
128
129
130
131 public void render(String templatePath, Object root, Writer out) throws TemplateException, IOException {
132 render(templatePath, null, null, root, out);
133 }
134
135
136
137
138
139
140
141
142
143
144
145 public void render(String templatePath, Locale locale, String i18nBasename, Object root, Writer out) throws TemplateException, IOException {
146 final Locale localeToUse = checkLocale(locale);
147 prepareRendering(localeToUse, i18nBasename, root);
148
149 final Template template = cfg.getTemplate(templatePath, localeToUse);
150 template.process(root, out);
151 }
152
153
154
155
156
157
158
159 public void render(Reader template, Object root, Writer out) throws TemplateException, IOException {
160 render(template, null, null, root, out);
161 }
162
163 protected void render(Reader template, Locale locale, String i18nBasename, Object root, Writer out) throws TemplateException, IOException {
164 final Locale localeToUse = checkLocale(locale);
165 prepareRendering(localeToUse, i18nBasename, root);
166
167 final Template t = new Template("inlinetemplate", template, cfg);
168 t.setLocale(localeToUse);
169 t.process(root, out);
170 }
171
172
173
174
175 protected Locale checkLocale(Locale locale) {
176 if (locale != null) {
177 return locale;
178 } else if (MgnlContext.hasInstance()) {
179 return MgnlContext.getLocale();
180 } else {
181 return Locale.getDefault();
182 }
183 }
184
185
186
187
188 protected void prepareRendering(Locale checkedLocale, String i18nBasename, Object root) {
189 if (root instanceof Map) {
190 final Map<String, Object> data = (Map<String, Object>) root;
191 addDefaultData(data, checkedLocale, i18nBasename);
192 }
193 }
194
195 protected void addDefaultData(Map<String, Object> data, Locale locale, String i18nBasename) {
196 if (MgnlContext.hasInstance()) {
197 data.put("ctx", MgnlContext.getInstance());
198 }
199 if (MgnlContext.isWebContext()) {
200 final WebContext webCtx = MgnlContext.getWebContext();
201
202 data.put("contextPath", webCtx.getContextPath());
203 data.put("aggregationState", webCtx.getAggregationState());
204
205 addTaglibSupportData(data, webCtx);
206 }
207
208 data.put("defaultBaseUrl", ServerConfiguration.getInstance().getDefaultBaseUrl());
209
210 if (i18nBasename != null) {
211 data.put("i18n", new MessagesWrapper(i18nBasename, locale));
212 }
213
214
215
216
217
218
219
220 }
221
222 protected void addTaglibSupportData(Map<String, Object> data, WebContext webCtx) {
223 final ServletContext servletContext = webCtx.getServletContext();
224 try {
225 data.put(FreemarkerServlet.KEY_JSP_TAGLIBS, checkTaglibFactory(servletContext));
226 data.put(FreemarkerServlet.KEY_APPLICATION_PRIVATE, checkServletContextModel(servletContext));
227 data.put(FreemarkerServlet.KEY_REQUEST_PRIVATE, new HttpRequestHashModel(webCtx.getRequest(), cfg.getObjectWrapper()));
228 } catch (ServletException e) {
229
230 throw new RuntimeException("Can't initialize taglib support for FreeMarker: ", e);
231 }
232 }
233
234 protected TaglibFactory checkTaglibFactory(ServletContext servletContext) {
235 if (taglibFactory == null) {
236 taglibFactory = new TaglibFactory(servletContext);
237 }
238 return taglibFactory;
239 }
240
241 protected ServletContextHashModel checkServletContextModel(ServletContext servletContext) throws ServletException {
242 if (servletContextHashModel == null) {
243
244 final GenericServlet fs = new DoNothingServlet(servletContext);
245 servletContextHashModel = new ServletContextHashModel(fs, cfg.getObjectWrapper());
246 }
247 return servletContextHashModel;
248 }
249
250 protected Configuration getConfiguration() {
251 return cfg;
252 }
253
254 private class ConfigDelegatingTemplateLoader implements TemplateLoader {
255 private final FreemarkerConfig freemarkerConfig;
256
257 public ConfigDelegatingTemplateLoader(FreemarkerConfig freemarkerConfig) {
258 this.freemarkerConfig = freemarkerConfig;
259 }
260
261 public Object findTemplateSource(String name) throws IOException {
262 return freemarkerConfig.getTemplateLoader().findTemplateSource(name);
263 }
264
265 public long getLastModified(Object templateSource) {
266 return freemarkerConfig.getTemplateLoader().getLastModified(templateSource);
267 }
268
269 public Reader getReader(Object templateSource, String encoding) throws IOException {
270 return freemarkerConfig.getTemplateLoader().getReader(templateSource, encoding);
271 }
272
273 public void closeTemplateSource(Object templateSource) throws IOException {
274 freemarkerConfig.getTemplateLoader().closeTemplateSource(templateSource);
275 }
276 }
277
278 private class ConfigDelegatingObjectWrapper implements ObjectWrapper {
279 private final FreemarkerConfig freemarkerConfig;
280
281 public ConfigDelegatingObjectWrapper(FreemarkerConfig freemarkerConfig) {
282 this.freemarkerConfig = freemarkerConfig;
283 }
284
285 public TemplateModel wrap(Object obj) throws TemplateModelException {
286 return freemarkerConfig.getObjectWrapper().wrap(obj);
287 }
288 }
289 }