1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts2.sitemesh;
22
23 import java.io.IOException;
24 import java.util.Locale;
25
26 import javax.servlet.ServletContext;
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.struts2.views.freemarker.FreemarkerManager;
34
35 import com.opensymphony.module.sitemesh.Decorator;
36 import com.opensymphony.module.sitemesh.HTMLPage;
37 import com.opensymphony.module.sitemesh.Page;
38 import com.opensymphony.xwork2.ActionContext;
39 import com.opensymphony.xwork2.ActionInvocation;
40 import com.opensymphony.xwork2.LocaleProvider;
41 import com.opensymphony.xwork2.inject.Inject;
42 import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
43
44 import freemarker.template.Configuration;
45 import freemarker.template.SimpleHash;
46 import freemarker.template.Template;
47
48 /***
49 * Applies FreeMarker-based sitemesh decorators.
50 *
51 * <!-- START SNIPPET: javadoc -->
52 *
53 * The following variables are available to the decorating freemarker page :-
54 * <ul>
55 * <li>${title} - content of <title> tag in the decorated page</li>
56 * <li>${head} - content of <head> tag in the decorated page</li>
57 * <li>${body} - content of t<body> tag in the decorated page</li>
58 * <li>${page.properties} - content of the page properties</li>
59 * </ul>
60 * <p/>
61 * With the following decorated page :-
62 * <pre>
63 * <html>
64 * <meta name="author" content="tm_jee" />
65 * <head>
66 * <title>My Title</title>
67 * <link rel="stylesheet" type="text/css" href="mycss.css" />
68 * <style type="text/javascript" language="javascript" src="myjavascript.js"></script>
69 * </head>
70 * <body<
71 * <h1>Sample</h1>
72 * </body>
73 * </html>
74 * </pre>
75 * <p/>
76 * <table border="1">
77 * <tr>
78 * <td>Properties</td>
79 * <td>Content</td>
80 * </tr>
81 * <tr>
82 * <td>${title}</td>
83 * <td>My Title</td>
84 * </tr>
85 * <tr>
86 * <td>${head}</td>
87 * <td>
88 * <link rel="stylesheet" type="text/css" href="mycss.css" />
89 * <style type="text/javascript" language="javascript" src="myjavascript.js"></script>
90 * </td>
91 * </tr>
92 * <tr>
93 * <td>${body}</td>
94 * <td>
95 * <h1>Sample</h1>
96 * </td>
97 * </tr>
98 * <tr>
99 * <td>${page.properties.meta.author}</td>
100 * <td>tm_jee</td>
101 * </tr>
102 * </table>
103 *
104 * <!-- END SNIPPET: javadoc -->
105 *
106 * @version $Date: 2006-11-16 09:32:03 +0100 (Do, 16 Nov 2006) $ $Id: FreeMarkerPageFilter.java 475637 2006-11-16 08:32:03Z mrdon $
107 */
108 public class FreeMarkerPageFilter extends TemplatePageFilter {
109 private static final Log LOG = LogFactory.getLog(FreeMarkerPageFilter.class);
110
111 private static FreemarkerManager freemarkerManager;
112
113 @Inject(required=false)
114 public static void setFreemarkerManager(FreemarkerManager mgr) {
115 freemarkerManager = mgr;
116 }
117
118 /***
119 * Applies the decorator, using the relevent contexts
120 *
121 * @param page The page
122 * @param decorator The decorator
123 * @param req The servlet request
124 * @param res The servlet response
125 * @param servletContext The servlet context
126 * @param ctx The action context for this request, populated with the server state
127 */
128 protected void applyDecorator(Page page, Decorator decorator,
129 HttpServletRequest req, HttpServletResponse res,
130 ServletContext servletContext, ActionContext ctx)
131 throws ServletException, IOException {
132
133 String timerKey = "FreemarkerPageFilter_applyDecorator: ";
134 if (freemarkerManager == null) {
135 throw new ServletException("Missing freemarker dependency");
136 }
137
138 try {
139 UtilTimerStack.push(timerKey);
140
141
142 Configuration config = freemarkerManager.getConfiguration(servletContext);
143 Template template = config.getTemplate(decorator.getPage(), getLocale(ctx.getActionInvocation(), config));
144
145
146 SimpleHash model = freemarkerManager.buildTemplateModel(ctx.getValueStack(), null, servletContext, req, res, config.getObjectWrapper());
147
148
149 model.put("page", page);
150 if (page instanceof HTMLPage) {
151 HTMLPage htmlPage = ((HTMLPage) page);
152 model.put("head", htmlPage.getHead());
153 }
154 model.put("title",page.getTitle());
155 model.put("body",page.getBody());
156 model.put("page.properties", new SimpleHash(page.getProperties()));
157
158
159 template.process(model, res.getWriter());
160 } catch (Exception e) {
161 String msg = "Error applying decorator: " + e.getMessage();
162 LOG.error(msg, e);
163 throw new ServletException(msg, e);
164 }
165 finally {
166 UtilTimerStack.pop(timerKey);
167 }
168 }
169
170 /***
171 * Returns the locale used for the {@link Configuration#getTemplate(String, Locale)} call. The base implementation
172 * simply returns the locale setting of the action (assuming the action implements {@link LocaleProvider}) or, if
173 * the action does not the configuration's locale is returned. Override this method to provide different behaviour,
174 */
175 protected Locale getLocale(ActionInvocation invocation, Configuration configuration) {
176 if (invocation.getAction() instanceof LocaleProvider) {
177 return ((LocaleProvider) invocation.getAction()).getLocale();
178 } else {
179 return configuration.getLocale();
180 }
181 }
182
183 }