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