/*
 *  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 groovy.servlet;

import groovy.util.ResourceConnector;
import groovy.util.ResourceException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A base class dealing with common HTTP servlet API housekeeping aspects.
 * <p>
 * <h4>Resource name mangling (pattern replacement)</h4>
 * <p>
 * Also implements Groovy's {@link groovy.util.ResourceConnector} in a dynamic
 * manner. It allows you to modify the resource name that is searched for with a
 * <i>replace all</i> operation. See {@link java.util.regex.Pattern} and
 * {@link java.util.regex.Matcher} for details.
 * The servlet init parameter names are:
 * <pre>
 * {@value #INIT_PARAM_RESOURCE_NAME_REGEX} = empty - defaults to null
 * resource.name.replacement = empty - defaults to null
 * resource.name.replace.all = true (default) | false means replaceFirst()
 * </pre>
 * Note: If you specify a regex, you have to specify a replacement string too!
 * Otherwise an exception gets raised.
 * <p>
 * <h4>Logging and bug-hunting options</h4>
 * <p>
 * This implementation provides a verbosity flag switching log statements.
 * The servlet init parameter name is:
 * <pre>
 * verbose = false(default) | true
 * </pre>
 * <p>
 * In order to support class-loading-troubles-debugging with Tomcat 4 or
 * higher, you can log the class loader responsible for loading some classes.
 * See <a href="https://issues.apache.org/jira/browse/GROOVY-861">GROOVY-861</a> for details.
 * The servlet init parameter name is:
 * <pre>
 * log.GROOVY861 = false(default) | true
 * </pre>
 * <p>
 * If you experience class-loading-troubles with Tomcat 4 (or higher) or any
 * other servlet container using custom class loader setups, you can fallback
 * to use (slower) reflection in Groovy's MetaClass implementation. Please
 * contact the dev team with your problem! Thanks.
 * The servlet init parameter name is:
 * <pre>
 * reflection = false(default) | true
 * </pre>
 */
public abstract class AbstractHttpServlet extends HttpServlet implements ResourceConnector {

    public static final String INIT_PARAM_RESOURCE_NAME_REGEX = "resource.name.regex";

    public static final String INIT_PARAM_RESOURCE_NAME_REGEX_FLAGS = "resource.name.regex.flags";

    /**
     * Content type of the HTTP response.
     */
    public static final String CONTENT_TYPE_TEXT_HTML = "text/html";

    /**
     * Servlet API include key name: path_info
     */
    public static final String INC_PATH_INFO = "javax.servlet.include.path_info";

    /* *** Not used, yet. See comments in getScriptUri(HttpServletRequest). ***
     * Servlet API include key name: request_uri
     */
    public static final String INC_REQUEST_URI = "javax.servlet.include.request_uri";

    /**
     * Servlet API include key name: servlet_path
     */
    public static final String INC_SERVLET_PATH = "javax.servlet.include.servlet_path";

    /**
     * Servlet (or the web application) context.
     */
    protected ServletContext servletContext;

    /**
     * Either <code>null</code> or a compiled pattern read from "{@value #INIT_PARAM_RESOURCE_NAME_REGEX}"
     * and used in {@link AbstractHttpServlet#getScriptUri(HttpServletRequest)}.
     */
    protected Pattern resourceNamePattern;

    /**
     * The replacement used by the resource name matcher.
     */
    protected String resourceNameReplacement;

    /**
     * The replace method to use on the matcher.
     * <pre>
     * true - replaceAll(resourceNameReplacement); (default)
     * false - replaceFirst(resourceNameReplacement);
     * </pre>
     */
    protected boolean resourceNameReplaceAll;

    /**
     * Controls almost all log output.
     */
    protected boolean verbose;

    /**
     * Encoding to use, becomes charset part of contentType.
     */
    protected String encoding = "UTF-8";

    /**
     * Mirrors the static value of the reflection flag in MetaClass.
     * See AbstractHttpServlet#logGROOVY861
     */
    protected boolean reflection;

    /**
     * Debug flag logging the class the class loader of the request.
     */
    private boolean logGROOVY861;

    /** a.fink: it was in {@link #removeNamePrefix}, but was extracted to var for optimization*/
    protected String namePrefix;

    /**
     * Initializes all fields with default values.
     */
    public AbstractHttpServlet () {
        this.servletContext = null;
        this.resourceNameReplacement = null;
        this.resourceNameReplaceAll = true;
        this.verbose = false;
        this.reflection = false;
        this.logGROOVY861 = false;
    }

    protected void generateNamePrefixOnce () {
        URI uri = null;

        String realPath = servletContext.getRealPath("/");
        if (realPath != null) { uri = new File(realPath).toURI();}//prevent NPE if in .war

        try {
            URL res = servletContext.getResource("/");
            if (res != null) { uri = res.toURI(); }
        } catch (MalformedURLException | URISyntaxException ignore) {
        }

        if (uri != null) {
            try {
                namePrefix = uri.toURL().toExternalForm();
                return;
            } catch (MalformedURLException e) {
                log("generateNamePrefixOnce [ERROR] Malformed URL for base path / == '"+ uri +'\'', e);
            }
        }

        namePrefix = "";
    }

    protected String removeNamePrefix(String name) throws ResourceException {
        if (namePrefix == null) {
            generateNamePrefixOnce();
        }
        if (name.startsWith(namePrefix)) {//usualy name has text
            return name.substring(namePrefix.length());
        }
        return name;
    }

    /**
     * Interface method for ResourceContainer. This is used by the GroovyScriptEngine.
     */
    public URLConnection getResourceConnection (String name) throws ResourceException {
        name = removeNamePrefix(name).replace('\\', '/');

        //remove the leading / as we are trying with a leading / now
        if (name.startsWith("WEB-INF/groovy/")) {
            name = name.substring(15);//just for uniformity
        } else if (name.startsWith("/")) {
            name = name.substring(1);
        }

        /*
        * Try to locate the resource and return an opened connection to it.
        */
        try {
            URL url = servletContext.getResource('/' + name);
            if (url == null) {
                url = servletContext.getResource("/WEB-INF/groovy/" + name);
            }
            if (url == null) {
                throw new ResourceException("Resource \"" + name + "\" not found!");
            }
            return url.openConnection();
        } catch (IOException e) {
            throw new ResourceException("Problems getting resource named \"" + name + "\"!", e);
        }
    }

    /**
     * Returns the include-aware uri of the script or template file.
     *
     * @param request the http request to analyze
     * @return the include-aware uri either parsed from request attributes or
     *         hints provided by the servlet container
     */
    protected String getScriptUri(HttpServletRequest request) {
        /*
         * Log some debug information for https://issues.apache.org/jira/browse/GROOVY-861
         */
        if (logGROOVY861) {
            log("Logging request class and its class loader:");
            log(" c = request.getClass() :\"" + request.getClass() + "\"");
            log(" l = c.getClassLoader() :\"" + request.getClass().getClassLoader() + "\"");
            log(" l.getClass()           :\"" + request.getClass().getClassLoader().getClass() + "\"");
            /*
             * Keep logging, if we're verbose. Else turn it off.
             */
            logGROOVY861 = verbose;
        }

        //
        // NOTE: This piece of code is heavily inspired by Apaches Jasper2!
        // 
        // http://cvs.apache.org/viewcvs.cgi/jakarta-tomcat-jasper/jasper2/ \
        //        src/share/org/apache/jasper/servlet/JspServlet.java?view=markup
        //
        // Why doesn't it use request.getRequestURI() or INC_REQUEST_URI?
        //

        String uri = null;
        String info = null;

        //
        // Check to see if the requested script/template source file has been the
        // target of a RequestDispatcher.include().
        //
        uri = (String) request.getAttribute(INC_SERVLET_PATH);
        if (uri != null) {
            //
            // Requested script/template file has been target of 
            // RequestDispatcher.include(). Its path is assembled from the relevant
            // javax.servlet.include.* request attributes and returned!
            //
            info = (String) request.getAttribute(INC_PATH_INFO);
            if (info != null) {
                uri += info;
            }
            return applyResourceNameMatcher(uri);
        }

        //
        // Requested script/template file has not been the target of a 
        // RequestDispatcher.include(). Reconstruct its path from the request's
        // getServletPath() and getPathInfo() results.
        //
        uri = request.getServletPath();
        info = request.getPathInfo();
        if (info != null) {
            uri += info;
        }

        /*
         * TODO : Enable auto ".groovy" extension replacing here!
         * http://cvs.groovy.codehaus.org/viewrep/groovy/groovy/groovy-core/src/main/groovy/servlet/GroovyServlet.java?r=1.10#l259
         */

        return applyResourceNameMatcher(uri);
    }

    protected String applyResourceNameMatcher (String uri) {
        if (resourceNamePattern != null) {// mangle resource name with the compiled pattern.
            Matcher matcher = resourceNamePattern.matcher(uri);

            String replaced;
            if (resourceNameReplaceAll) {
                replaced = matcher.replaceAll(resourceNameReplacement);
            } else {
                replaced = matcher.replaceFirst(resourceNameReplacement);
            }
            if (!uri.equals(replaced)) {
                if (verbose) {
                    log("Replaced resource name \"" + uri + "\" with \"" + replaced + "\".");
                }
                return replaced;
            }
        }
        return uri;
    }

    /**
     * Parses the http request for the real script or template source file.
     * 
     * @param request
     *            the http request to analyze
     * @return a file object using an absolute file path name, or <code>null</code> if the
     *         servlet container cannot translate the virtual path to a real
     *         path for any reason (such as when the content is being made
     *         available from a .war archive).
     */
    protected File getScriptUriAsFile(HttpServletRequest request) {
        String uri = getScriptUri(request);
        String real = servletContext.getRealPath(uri);
        if (real == null) {
            return null;
        }
        return new File(real).getAbsoluteFile();
    }

    /**
     * Overrides the generic init method to set some debug flags.
     *
     * @param config the servlet configuration provided by the container
     * @throws ServletException if init() method defined in super class
     *                          javax.servlet.GenericServlet throws it
     */
    public void init(ServletConfig config) throws ServletException {
        /*
         * Never forget super.init()!
         */
        super.init(config);

        /*
         * Grab the servlet context.
         */
        this.servletContext = config.getServletContext();

        // Get verbosity hint.
        String value = config.getInitParameter("verbose");
        if (value != null) {
            this.verbose = Boolean.valueOf(value);
        }

        // get encoding
        value = config.getInitParameter("encoding");
        if (value != null) {
            this.encoding = value;
        }

        // And now the real init work...
        if (verbose) {
            log("Parsing init parameters...");
        }

        String regex = config.getInitParameter(INIT_PARAM_RESOURCE_NAME_REGEX);
        if (regex != null) {
            String replacement = config.getInitParameter("resource.name.replacement");
            if (replacement == null) {
                Exception npex = new NullPointerException("resource.name.replacement");
                String message = "Init-param 'resource.name.replacement' not specified!";
                log(message, npex);
                throw new ServletException(message, npex);
            } else if ("EMPTY_STRING".equals(replacement)) {//<param-value></param-value> is prohibited
                replacement = "";
            }
            int flags = 0; // TODO : Parse pattern compile flags (literal names).
            String flagsStr = config.getInitParameter(INIT_PARAM_RESOURCE_NAME_REGEX_FLAGS);
            if (flagsStr != null && flagsStr.length() > 0) {
              flags = Integer.decode(flagsStr.trim());//throws NumberFormatException
            }
            resourceNamePattern = Pattern.compile(regex, flags);
            this.resourceNameReplacement = replacement;
            String all = config.getInitParameter("resource.name.replace.all");
            if (all != null) {
                this.resourceNameReplaceAll = Boolean.valueOf(all.trim());
            }
        }

        value = config.getInitParameter("logGROOVY861");
        if (value != null) {
            this.logGROOVY861 = Boolean.valueOf(value);
            // nothing else to do here
        }

        /*
         * If verbose, log the parameter values.
         */
        if (verbose) {
            log("(Abstract) init done. Listing some parameter name/value pairs:");
            log("verbose = " + verbose); // this *is* verbose! ;)
            log("reflection = " + reflection);
            log("logGROOVY861 = " + logGROOVY861);
            log(INIT_PARAM_RESOURCE_NAME_REGEX + " = " + resourceNamePattern);//toString == pattern
            log("resource.name.replacement = " + resourceNameReplacement);
        }
    }

    /**
     * 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>
     * 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>
     * And via implicit 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>
     * The binding also provides convenient methods:
     * <ul>
     * <li><tt>"forward(String path)"</tt> : request.getRequestDispatcher(path).forward(request, response);</li>
     * <li><tt>"include(String path)"</tt> : request.getRequestDispatcher(path).include(request, response);</li>
     * <li><tt>"redirect(String location)"</tt> : response.sendRedirect(location);</li>
     * </ul>
     * <p>
     * <p>Example binding all servlet context variables:
     * <pre><code>
     * class MyServlet 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>
     *
     * @param binding to be modified
     */
    protected void setVariables(ServletBinding binding) {
        // empty
    }
}
