blob: 528270b5c1c0393c95ed86fda40a90d592b0f61f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package example;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import javax.servlet.*;
import javax.servlet.http.*;
import freemarker.template.*;
import freemarker.ext.beans.BeansWrapper;
/**
* <p>This is very very primitive MVC Controller servlet base class, based
* on example 1. The application specific controller servlet should extend
* this class.
*/
public class ControllerServlet extends HttpServlet {
// Volatile so that it's properly published according to JSR 133 (JMM).
// Although, the servlet container most certainly makes this unnecessarry.
private volatile Configuration cfg;
public void init() {
// Initialize the FreeMarker configuration;
// - Create a configuration instance, with the not-100%-backward-compatible
// fixes up until FreeMarker 2.3.21 applied (as far as it starts
// with 2.3, these are only minor changes that doesn't affect most apps):
Configuration cfg = new Configuration(Configuration.VERSION_2_3_21);
// - Templates are stoted in the WEB-INF/templates directory of the Web app.
cfg.setServletContextForTemplateLoading(
getServletContext(), "WEB-INF/templates");
// - At most how often should FreeMarker check if a template was updated:
cfg.setTemplateUpdateDelay(isInDevelopmentMode() ? 0 : 60);
// - When developing, set an error handler that prints errors so they are
// readable with a Web browser, otherwise we just let the HTTP 500
// handler deal with it.
cfg.setTemplateExceptionHandler(
isInDevelopmentMode()
? TemplateExceptionHandler.HTML_DEBUG_HANDLER
: TemplateExceptionHandler.RETHROW_HANDLER);
// - Set the default charset of the template files
cfg.setDefaultEncoding("ISO-8859-1");
// - Set the charset of the output. This is actually just a hint, that
// templates may require for URL encoding and for generating META
// element that uses http-equiv="Content-type".
cfg.setOutputEncoding("UTF-8");
// - Set the default locale
cfg.setLocale(Locale.US);
// Finished modifying cfg, so let's publish it to other threads:
this.cfg = cfg;
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Choose action method
String action = req.getServletPath();
if (action == null) action = "index";
if (action.startsWith("/")) action = action.substring(1);
if (action.lastIndexOf(".") != -1) {
action = action.substring(0, action.lastIndexOf("."));
}
Method actionMethod;
try {
actionMethod =
getClass().getMethod(action + "Action",
new Class[]{HttpServletRequest.class, Page.class});
} catch (NoSuchMethodException e) {
throw new ServletException("Unknown action: " + action);
}
// Set the request charset to the same as the output charset,
// because HTML forms normally send parameters encoded with that.
req.setCharacterEncoding(cfg.getOutputEncoding());
// Call the action method
Page page = new Page();
try {
actionMethod.invoke(this, new Object[]{req, page});
} catch (IllegalAccessException e) {
throw new ServletException(e);
} catch (InvocationTargetException e) {
throw new ServletException(e.getTargetException());
}
if (page.getTemplate() != null) { // show a page with a template
// Get the template object
Template t = cfg.getTemplate(page.getTemplate());
// Prepare the HTTP response:
// - Set the MIME-type and the charset of the output.
// Note that the charset should be in sync with the output_encoding setting.
resp.setContentType("text/html; charset=" + cfg.getOutputEncoding());
// - Prevent browser or proxy caching the page.
// Note that you should use it only for development and for interactive
// pages, as it significantly slows down the Web site.
resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, "
+ "post-check=0, pre-check=0");
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Expires", "Thu, 01 Dec 1994 00:00:00 GMT");
Writer out = resp.getWriter();
// Merge the data-model and the template
try {
t.process(page.getRoot(), out);
} catch (TemplateException e) {
throw new ServletException(
"Error while processing FreeMarker template", e);
}
} else if (page.getForward() != null) { // forward request
RequestDispatcher rd = req.getRequestDispatcher(page.getForward());
rd.forward(req, resp);
} else {
throw new ServletException("The action didn't specified a command.");
}
}
private boolean isInDevelopmentMode() {
// FIXME: Should detect this with a system property for example.
return true;
}
}