alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (TemplateServlet.java)

This example Groovy source code file (TemplateServlet.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

could, http, io, ioexception, nullpointerexception, request, response, servlet, servletbinding, servletexception, servletexception, string, string, template, template, templatecacheentry, templatecacheentry, templateengine, templateservlet, util

The Groovy TemplateServlet.java source code

/*
 * Copyright 2003-2007 the original author or authors.
 *
 * Licensed 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 groovy.servlet;

import groovy.text.SimpleTemplateEngine;
import groovy.text.Template;
import groovy.text.TemplateEngine;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.util.Map;
import java.util.WeakHashMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * A generic servlet for serving (mostly HTML) templates.
 * <p/>
 * <p/>
 * It delegates work to a <code>groovy.text.TemplateEngine implementation
 * processing HTTP requests.
 * <p/>
 * <h4>Usage
 * <p/>
 * <code>helloworld.html is a headless HTML-like template
 * <pre>
 *  <html>
 *    <body>
 *      <% 3.times { %>
 *        Hello World!
 *      <% } %>
 *      <br>
 *    </body>
 *  </html>
 * </code>
* <p/> * Minimal <code>web.xml example serving HTML-like templates * <pre> * <web-app> * <servlet> * <servlet-name>template</servlet-name> * <servlet-class>groovy.servlet.TemplateServlet</servlet-class> * </servlet> * <servlet-mapping> * <servlet-name>template</servlet-name> * <url-pattern>*.html</url-pattern> * </servlet-mapping> * </web-app> * </code> * <p/> * <h4>Template engine configuration * <p/> * <p/> * By default, the TemplateServer uses the {@link groovy.text.SimpleTemplateEngine} * which interprets JSP-like templates. The init parameter <code>template.engine * defines the fully qualified class name of the template to use: * <pre> * template.engine = [empty] - equals groovy.text.SimpleTemplateEngine * template.engine = groovy.text.SimpleTemplateEngine * template.engine = groovy.text.GStringTemplateEngine * template.engine = groovy.text.XmlTemplateEngine * </pre> * <p/> * <h3>Servlet Init Parameters * <p/> * <h4>Logging and extra-output options * <p/> * <p/> * This implementation provides a verbosity flag switching log statements. * The servlet init parameter name is: * <pre> * generated.by = true(default) | false * </pre> * <p/> * <h4>Groovy Source Encoding Parameter * <p/> * <p/> * The following servlet init parameter name can be used to specify the encoding TemplateServlet will use * to read the template groovy source files: * <pre> * groovy.source.encoding * </pre> * * @author Christian Stein * @author Guillaume Laforge * @version 2.0 * @see TemplateServlet#setVariables(ServletBinding) */ public class TemplateServlet extends AbstractHttpServlet { /** * Simple cache entry that validates against last modified and length * attributes of the specified file. * * @author Christian Stein */ private static class TemplateCacheEntry { Date date; long hit; long lastModified; long length; Template template; public TemplateCacheEntry(File file, Template template) { this(file, template, false); // don't get time millis for sake of speed } public TemplateCacheEntry(File file, Template template, boolean timestamp) { if (file == null) { throw new NullPointerException("file"); } if (template == null) { throw new NullPointerException("template"); } if (timestamp) { this.date = new Date(System.currentTimeMillis()); } else { this.date = null; } this.hit = 0; this.lastModified = file.lastModified(); this.length = file.length(); this.template = template; } /** * Checks the passed file attributes against those cached ones. * * @param file Other file handle to compare to the cached values. * @return <code>true if all measured values match, else false */ public boolean validate(File file) { if (file == null) { throw new NullPointerException("file"); } if (file.lastModified() != this.lastModified) { return false; } if (file.length() != this.length) { return false; } hit++; return true; } public String toString() { if (date == null) { return "Hit #" + hit; } return "Hit #" + hit + " since " + date; } } /** * Simple file name to template cache map. */ private final Map cache; /** * Underlying template engine used to evaluate template source files. */ private TemplateEngine engine; /** * Flag that controls the appending of the "Generated by ..." comment. */ private boolean generateBy; private String fileEncodingParamVal; private static final String GROOVY_SOURCE_ENCODING = "groovy.source.encoding"; /** * Create new TemplateServlet. */ public TemplateServlet() { this.cache = new WeakHashMap(); this.engine = null; // assigned later by init() this.generateBy = true; // may be changed by init() this.fileEncodingParamVal = null; // may be changed by init() } /** * Gets the template created by the underlying engine parsing the request. * <p/> * <p> * This method looks up a simple (weak) hash map for an existing template * object that matches the source file. If the source file didn't change in * length and its last modified stamp hasn't changed compared to a precompiled * template object, this template is used. Otherwise, there is no or an * invalid template object cache entry, a new one is created by the underlying * template engine. This new instance is put to the cache for consecutive * calls. * </p> * * @param file The HttpServletRequest. * @return The template that will produce the response text. * @throws ServletException If the request specified an invalid template source file */ protected Template getTemplate(File file) throws ServletException { String key = file.getAbsolutePath(); Template template = null; /* * Test cache for a valid template bound to the key. */ if (verbose) { log("Looking for cached template by key \"" + key + "\""); } TemplateCacheEntry entry = (TemplateCacheEntry) cache.get(key); if (entry != null) { if (entry.validate(file)) { if (verbose) { log("Cache hit! " + entry); } template = entry.template; } else { if (verbose) { log("Cached template needs recompilation!"); } } } else { if (verbose) { log("Cache miss."); } } // // Template not cached or the source file changed - compile new template! // if (template == null) { if (verbose) { log("Creating new template from file " + file + "..."); } String fileEncoding = (fileEncodingParamVal != null) ? fileEncodingParamVal : System.getProperty(GROOVY_SOURCE_ENCODING); Reader reader = null; try { reader = fileEncoding == null ? new FileReader(file) : new InputStreamReader(new FileInputStream(file), fileEncoding); template = engine.createTemplate(reader); } catch (Exception e) { throw new ServletException("Creation of template failed: " + e, e); } finally { if (reader != null) { try { reader.close(); } catch (IOException ignore) { // e.printStackTrace(); } } } cache.put(key, new TemplateCacheEntry(file, template, verbose)); if (verbose) { log("Created and added template to cache. [key=" + key + "]"); } } // // Last sanity check. // if (template == null) { throw new ServletException("Template is null? Should not happen here!"); } return template; } /** * Initializes the servlet from hints the container passes. * <p/> * Delegates to sub-init methods and parses the following parameters: * <ul> * <li> "generatedBy" : boolean, appends "Generated by ..." to the * HTML response text generated by this servlet. * </li> * </ul> * * @param config Passed by the servlet container. * @throws ServletException if this method encountered difficulties * @see TemplateServlet#initTemplateEngine(ServletConfig) */ public void init(ServletConfig config) throws ServletException { super.init(config); this.engine = initTemplateEngine(config); if (engine == null) { throw new ServletException("Template engine not instantiated."); } String value = config.getInitParameter("generated.by"); if (value != null) { this.generateBy = Boolean.valueOf(value); } value = config.getInitParameter(GROOVY_SOURCE_ENCODING); if (value != null) { this.fileEncodingParamVal = value; } log("Servlet " + getClass().getName() + " initialized on " + engine.getClass()); } /** * Creates the template engine. * <p/> * Called by {@link TemplateServlet#init(ServletConfig)} and returns just * <code>new groovy.text.SimpleTemplateEngine() if the init parameter * <code>template.engine is not set by the container configuration. * * @param config Current servlet configuration passed by the container. * @return The underlying template engine or <code>null on error. */ protected TemplateEngine initTemplateEngine(ServletConfig config) { String name = config.getInitParameter("template.engine"); if (name == null) { return new SimpleTemplateEngine(); } try { return (TemplateEngine) Class.forName(name).newInstance(); } catch (InstantiationException e) { log("Could not instantiate template engine: " + name, e); } catch (IllegalAccessException e) { log("Could not access template engine class: " + name, e); } catch (ClassNotFoundException e) { log("Could not find template engine class: " + name, e); } return null; } /** * Services the request with a response. * <p> * First the request is parsed for the source file uri. If the specified file * could not be found or can not be read an error message is sent as response. * <p/> * </p> * * @param request The http request. * @param response The http response. * @throws IOException if an input or output error occurs while the servlet is * handling the HTTP request * @throws ServletException if the HTTP request cannot be handled */ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (verbose) { log("Creating/getting cached template..."); } // // Get the template source file handle. // File file = super.getScriptUriAsFile(request); String name = file.getName(); if (!file.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; // throw new IOException(file.getAbsolutePath()); } if (!file.canRead()) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "Can not read \"" + name + "\"!"); return; // throw new IOException(file.getAbsolutePath()); } // // Get the requested template. // long getMillis = System.currentTimeMillis(); Template template = getTemplate(file); getMillis = System.currentTimeMillis() - getMillis; // // Create new binding for the current request. // ServletBinding binding = new ServletBinding(request, response, servletContext); setVariables(binding); // // Prepare the response buffer content type _before_ getting the writer. // and set status code to ok // response.setContentType(CONTENT_TYPE_TEXT_HTML + "; charset=" + encoding); response.setStatus(HttpServletResponse.SC_OK); // // Get the output stream writer from the binding. // Writer out = (Writer) binding.getVariable("out"); if (out == null) { out = response.getWriter(); } // // Evaluate the template. // if (verbose) { log("Making template \"" + name + "\"..."); } // String made = template.make(binding.getVariables()).toString(); // log(" = " + made); long makeMillis = System.currentTimeMillis(); template.make(binding.getVariables()).writeTo(out); makeMillis = System.currentTimeMillis() - makeMillis; if (generateBy) { StringBuffer sb = new StringBuffer(100); sb.append("\n<!-- Generated by Groovy TemplateServlet [create/get="); sb.append(Long.toString(getMillis)); sb.append(" ms, make="); sb.append(Long.toString(makeMillis)); sb.append(" ms] -->\n"); out.write(sb.toString()); } // // flush the response buffer. // response.flushBuffer(); if (verbose) { log("Template \"" + name + "\" request responded. [create/get=" + getMillis + " ms, make=" + makeMillis + " ms]"); } } }

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy TemplateServlet.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.