View Javadoc

    1   /*
    2    * $Id: FreeMarkerPageFilter.java 475637 2006-11-16 08:32:03Z mrdon $
    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  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 &lt;title&gt; tag in the decorated page</li>
    56   *      <li>${head}            - content of &lt;head&gt; tag in the decorated page</li>
    57   *      <li>${body}            - content of t&lt;body&gt; 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   *  &lt;html&gt;
    64   *      &lt;meta name="author" content="tm_jee" /&gt;
    65   *      &lt;head&gt;
    66   *          &lt;title&gt;My Title&lt;/title&gt;
    67   *          &lt;link rel="stylesheet" type="text/css" href="mycss.css" /&gt;
    68   *          &lt;style type="text/javascript" language="javascript" src="myjavascript.js"&gt;&lt;/script&gt;
    69   *      &lt;/head&gt;
    70   *      &lt;body&lt;
    71   *          &lt;h1&gt;Sample&lt;/h1&gt;
    72   *      &lt;/body&gt;
    73   *  &lt;/html&gt;
    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   *              &lt;link rel="stylesheet" type="text/css" href="mycss.css" /&gt;
    89   *              &lt;style type="text/javascript" language="javascript" src="myjavascript.js"&gt;&lt;/script&gt;
    90   *          </td>
    91   *      </tr>
    92   *      <tr>
    93   *          <td>${body}</td>
    94   *          <td>
    95   *              &lt;h1&gt;Sample&lt;/h1&gt;
    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 03:32:03 -0500 (Thu, 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             // get the configuration and template
    142             Configuration config = freemarkerManager.getConfiguration(servletContext);
    143             Template template = config.getTemplate(decorator.getPage(), getLocale(ctx.getActionInvocation(), config)); // WW-1181
    144
    145             // get the main hash
    146             SimpleHash model = freemarkerManager.buildTemplateModel(ctx.getValueStack(), null, servletContext, req, res, config.getObjectWrapper());
    147
    148             // populate the hash with the page
    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             // finally, render it
    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 }