/*
 * 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.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>
 * It delegates work to a <code>groovy.text.TemplateEngine</code> implementation 
 * processing HTTP requests.
 *
 * <h4>Usage</h4>
 * 
 * <code>helloworld.html</code> is a headless HTML-like template
 * <pre><code>
 *  &lt;html&gt;
 *    &lt;body&gt;
 *      &lt;% 3.times { %&gt;
 *        Hello World!
 *      &lt;% } %&gt;
 *      &lt;br&gt;
 *    &lt;/body&gt;
 *  &lt;/html&gt; 
 * </code></pre>
 * 
 * Minimal <code>web.xml</code> example serving HTML-like templates
 * <pre><code>
 * &lt;web-app&gt;
 *   &lt;servlet&gt;
 *     &lt;servlet-name&gt;template&lt;/servlet-name&gt;
 *     &lt;servlet-class&gt;groovy.servlet.TemplateServlet&lt;/servlet-class&gt;
 *   &lt;/servlet&gt;
 *   &lt;servlet-mapping&gt;
 *     &lt;servlet-name&gt;template&lt;/servlet-name&gt;
 *     &lt;url-pattern&gt;*.html&lt;/url-pattern&gt;
 *   &lt;/servlet-mapping&gt;
 * &lt;/web-app&gt;
 * </code></pre>
 * 
 * <h4>Template engine configuration</h4>
 * 
 * <p>
 * By default, the TemplateServer uses the {@link groovy.text.SimpleTemplateEngine}
 * which interprets JSP-like templates. The init parameter <code>template.engine</code>
 * 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>
 * 
 * <h4>Logging and extra-output options</h4>
 *
 * <p>
 * This implementation provides a verbosity flag switching log statements.
 * The servlet init parameter name is:
 * <pre>
 *   generate.by = true(default) | false
 * </pre>
 * 
 * @see TemplateServlet#setVariables(ServletBinding)
 * 
 * @author Christian Stein
 * @author Guillaume Laforge
 * @version 2.0
 */
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</code> if all measured values match, else <code>false</code>
         */
        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;

    /**
     * Create new TemplateSerlvet.
     */
    public TemplateServlet() {
        this.cache = new WeakHashMap();
        this.engine = null; // assigned later by init()
        this.generateBy = true; // may be changed by init()
    }

    /**
     * Gets the template created by the underlying engine parsing the request.
     * 
     * <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>
     * 
     * @return The template that will produce the response text.
     * @param file
     *            The HttpServletRequest.
     * @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 recompiliation!");
                }
            }
        } 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 + "...");
            }
            FileReader reader = null;
            try {
                reader = new FileReader(file);
                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> <tt>"generatedBy"</tt> : 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).booleanValue();
        }
        log("Servlet " + getClass().getName() + " initialized on " + engine.getClass());
    }

    /**
     * Creates the template engine.
     * 
     * Called by {@link TemplateServlet#init(ServletConfig)} and returns just 
     * <code>new groovy.text.SimpleTemplateEngine()</code> if the init parameter
     * <code>template.engine</code> is not set by the container configuration.
     * 
     * @param config 
     *  Current serlvet configuration passed by the container.
     * 
     * @return The underlying template engine or <code>null</code> 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>
     * @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);
        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]");
        }

    }

    /**
     * Override this method to set your variables to the Groovy binding.
     * <p>
     * All variables bound the binding are passed to the template source text, 
     * e.g. the HTML file, when the template is merged.
     * </p>
     * <p>
     * The binding provided by TemplateServlet does already include some default
     * variables. As of this writing, they are (copied from 
     * {@link groovy.servlet.ServletBinding}):
     * <ul>
     * <li><tt>"request"</tt> : HttpServletRequest </li>
     * <li><tt>"response"</tt> : HttpServletResponse </li>
     * <li><tt>"context"</tt> : ServletContext </li>
     * <li><tt>"application"</tt> : ServletContext </li>
     * <li><tt>"session"</tt> : request.getSession(<b>false</b>) </li>
     * </ul>
     * </p>
     * <p>
     * And via implicite hard-coded keywords:
     * <ul>
     * <li><tt>"out"</tt> : response.getWriter() </li>
     * <li><tt>"sout"</tt> : response.getOutputStream() </li>
     * <li><tt>"html"</tt> : new MarkupBuilder(response.getWriter()) </li>
     * </ul>
     * </p>
     *
     * <p>Example binding all servlet context variables:
     * <pre><code>
     * class Mytlet extends TemplateServlet {
     * 
     *   protected void setVariables(ServletBinding binding) {
     *     // Bind a simple variable
     *     binding.setVariable("answer", new Long(42));
     *   
     *     // Bind all servlet context attributes...
     *     ServletContext context = (ServletContext) binding.getVariable("context");
     *     Enumeration enumeration = context.getAttributeNames();
     *     while (enumeration.hasMoreElements()) {
     *       String name = (String) enumeration.nextElement();
     *       binding.setVariable(name, context.getAttribute(name));
     *     }
     *   }
     * 
     * }
     * <code></pre>
     * </p>
     * 
     * @param binding
     *  to be modified
     */
    protected void setVariables(ServletBinding binding) {
        // empty
    }

}
