View Javadoc

1   /*
2    * $Id: FreeMarkerPageFilter.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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 &lt;title&gt; tag in the decorated page</li>
57   *      <li>${head}            - content of &lt;head&gt; tag in the decorated page</li>
58   *      <li>${body}            - content of t&lt;body&gt; 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   *  &lt;html&gt;
65   *      &lt;meta name="author" content="tm_jee" /&gt;
66   *      &lt;head&gt;
67   *          &lt;title&gt;My Title&lt;/title&gt;
68   *          &lt;link rel="stylesheet" type="text/css" href="mycss.css" /&gt;
69   *          &lt;style type="text/javascript" language="javascript" src="myjavascript.js"&gt;&lt;/script&gt;
70   *      &lt;/head&gt;
71   *      &lt;body&lt;
72   *          &lt;h1&gt;Sample&lt;/h1&gt;
73   *      &lt;/body&gt;
74   *  &lt;/html&gt;
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   *              &lt;link rel="stylesheet" type="text/css" href="mycss.css" /&gt;
90   *              &lt;style type="text/javascript" language="javascript" src="myjavascript.js"&gt;&lt;/script&gt;
91   *          </td>
92   *      </tr>
93   *      <tr>
94   *          <td>${body}</td>
95   *          <td>
96   *              &lt;h1&gt;Sample&lt;/h1&gt;
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 09:41:38 -0400 (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             // get the configuration and template
143             Configuration config = freemarkerManager.getConfiguration(servletContext);
144             Template template = config.getTemplate(decorator.getPage(), getLocale(ctx.getActionInvocation(), config)); // WW-1181
145 
146             // get the main hash
147             SimpleHash model = freemarkerManager.buildTemplateModel(ctx.getValueStack(), null, servletContext, req, res, config.getObjectWrapper());
148 
149             // populate the hash with the page
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             // finally, render it
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 }