/*
 * 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 org.jsecurity.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsecurity.util.JavaEnvironment;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

/**
 * <p>View that redirects to an absolute, context relative, or current request
 * relative URL, exposing all model attributes as HTTP query parameters.
 *
 * <p>A URL for this view is supposed to be a HTTP redirect URL, i.e.
 * suitable for HttpServletResponse's <code>sendRedirect</code> method, which
 * is what actually does the redirect if the HTTP 1.0 flag is on, or via sending
 * back an HTTP 303 code - if the HTTP 1.0 compatibility flag is off.
 *
 * <p>Note that while the default value for the "contextRelative" flag is off,
 * you will probably want to almost always set it to true. With the flag off,
 * URLs starting with "/" are considered relative to the web server root, while
 * with the flag on, they are considered relative to the web application root.
 * Since most web apps will never know or care what their context path actually
 * is, they are much better off setting this flag to true, and submitting paths
 * which are to be considered relative to the web application root.
 *
 * <p>Note that in a Servlet 2.2 environment, i.e. a servlet container which
 * is only compliant to the limits of this spec, this class will probably fail
 * when feeding in URLs which are not fully absolute, or relative to the current
 * request (no leading "/"), as these are the only two types of URL that
 * <code>sendRedirect</code> supports in a Servlet 2.2 environment.
 *
 * <p><em>This class was borrowed from a nearly identical version found in
 * the <a href="http://www.springframework.org/">Spring Framework</a>, with minor modifications to
 * avoid a dependency on Spring itself for a very small amount of code - we couldn't have done it better, and
 * don't want to repeat all of their great effort ;).
 * The original author names and copyright (Apache 2.0) has been left in place.  A special
 * thanks to Rod Johnson, Juergen Hoeller, and Colin Sampaleanu for making this available.</em>
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Colin Sampaleanu
 * @see #setContextRelative
 * @see #setHttp10Compatible
 * @see javax.servlet.http.HttpServletResponse#sendRedirect
 * @since 0.2
 */
@SuppressWarnings({"deprecation"})
public class RedirectView {

    /**
     * The default encoding scheme: UTF-8
     */
    public static final String DEFAULT_ENCODING_SCHEME = "UTF-8";

    private static final Log log = LogFactory.getLog(RedirectView.class);

    private String url;

    private boolean contextRelative = false;

    private boolean http10Compatible = true;

    private String encodingScheme = DEFAULT_ENCODING_SCHEME;

    /**
     * Constructor for use as a bean.
     */
    public RedirectView() {
    }

    /**
     * Create a new RedirectView with the given URL.
     * <p>The given URL will be considered as relative to the web server,
     * not as relative to the current ServletContext.
     *
     * @param url the URL to redirect to
     * @see #RedirectView(String, boolean)
     */
    public RedirectView(String url) {
        setUrl(url);
    }

    /**
     * Create a new RedirectView with the given URL.
     *
     * @param url             the URL to redirect to
     * @param contextRelative whether to interpret the given URL as
     *                        relative to the current ServletContext
     */
    public RedirectView(String url, boolean contextRelative) {
        this(url);
        this.contextRelative = contextRelative;
    }

    /**
     * Create a new RedirectView with the given URL.
     *
     * @param url              the URL to redirect to
     * @param contextRelative  whether to interpret the given URL as
     *                         relative to the current ServletContext
     * @param http10Compatible whether to stay compatible with HTTP 1.0 clients
     */
    public RedirectView(String url, boolean contextRelative, boolean http10Compatible) {
        this(url);
        this.contextRelative = contextRelative;
        this.http10Compatible = http10Compatible;
    }


    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    /**
     * Set whether to interpret a given URL that starts with a slash ("/")
     * as relative to the current ServletContext, i.e. as relative to the
     * web application root.
     * <p>Default is "false": A URL that starts with a slash will be interpreted
     * as absolute, i.e. taken as-is. If true, the context path will be
     * prepended to the URL in such a case.
     *
     * @see javax.servlet.http.HttpServletRequest#getContextPath
     */
    public void setContextRelative(boolean contextRelative) {
        this.contextRelative = contextRelative;
    }

    /**
     * Set whether to stay compatible with HTTP 1.0 clients.
     * <p>In the default implementation, this will enforce HTTP status code 302
     * in any case, i.e. delegate to <code>HttpServletResponse.sendRedirect</code>.
     * Turning this off will send HTTP status code 303, which is the correct
     * code for HTTP 1.1 clients, but not understood by HTTP 1.0 clients.
     * <p>Many HTTP 1.1 clients treat 302 just like 303, not making any
     * difference. However, some clients depend on 303 when redirecting
     * after a POST request; turn this flag off in such a scenario.
     *
     * @see javax.servlet.http.HttpServletResponse#sendRedirect
     */
    public void setHttp10Compatible(boolean http10Compatible) {
        this.http10Compatible = http10Compatible;
    }

    /**
     * Set the encoding scheme for this view. Default is UTF-8.
     */
    public void setEncodingScheme(String encodingScheme) {
        this.encodingScheme = encodingScheme;
    }


    /**
     * Convert model to request parameters and redirect to the given URL.
     *
     * @see #appendQueryProperties
     * @see #sendRedirect
     */
    public final void renderMergedOutputModel(
            Map model, HttpServletRequest request, HttpServletResponse response) throws IOException {

        // Prepare name URL.
        StringBuffer targetUrl = new StringBuffer();
        if (this.contextRelative && getUrl().startsWith("/")) {
            // Do not apply context path to relative URLs.
            targetUrl.append(request.getContextPath());
        }
        targetUrl.append(getUrl());
        appendQueryProperties(targetUrl, model, this.encodingScheme);

        sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
    }

    /**
     * Append query properties to the redirect URL.
     * Stringifies, URL-encodes and formats model attributes as query properties.
     *
     * @param targetUrl      the StringBuffer to append the properties to
     * @param model          Map that contains model attributes
     * @param encodingScheme the encoding scheme to use
     * @throws java.io.UnsupportedEncodingException
     *          if string encoding failed
     * @see #queryProperties
     */
    protected void appendQueryProperties(StringBuffer targetUrl, Map model, String encodingScheme)
            throws UnsupportedEncodingException {

        // Extract anchor fragment, if any.
        // The following code does not use JDK 1.4's StringBuffer.indexOf(String)
        // method to retain JDK 1.3 compatibility.
        String fragment = null;
        int anchorIndex = targetUrl.toString().indexOf('#');
        if (anchorIndex > -1) {
            fragment = targetUrl.substring(anchorIndex);
            targetUrl.delete(anchorIndex, targetUrl.length());
        }

        // If there aren't already some parameters, we need a "?".
        boolean first = (getUrl().indexOf('?') < 0);
        Map queryProps = queryProperties(model);

        if (queryProps != null) {
            for (Object o : queryProps.entrySet()) {
                if (first) {
                    targetUrl.append('?');
                    first = false;
                } else {
                    targetUrl.append('&');
                }
                Map.Entry entry = (Map.Entry) o;
                String encodedKey = urlEncode(entry.getKey().toString(), encodingScheme);
                String encodedValue =
                        (entry.getValue() != null ? urlEncode(entry.getValue().toString(), encodingScheme) : "");
                targetUrl.append(encodedKey).append('=').append(encodedValue);
            }
        }

        // Append anchor fragment, if any, to end of URL.
        if (fragment != null) {
            targetUrl.append(fragment);
        }
    }

    /**
     * URL-encode the given input String with the given encoding scheme.
     * <p>Default implementation uses <code>URLEncoder.encode(input, enc)</code>
     * on JDK 1.4+, falling back to <code>URLEncoder.encode(input)</code>
     * (which uses the platform default encoding) on JDK 1.3.
     *
     * @param input          the unencoded input String
     * @param encodingScheme the encoding scheme
     * @return the encoded output String
     * @throws UnsupportedEncodingException if thrown by the JDK URLEncoder
     * @see java.net.URLEncoder#encode(String, String)
     * @see java.net.URLEncoder#encode(String)
     */
    protected String urlEncode(String input, String encodingScheme) throws UnsupportedEncodingException {
        if (!JavaEnvironment.isAtLeastVersion14()) {
            if (log.isDebugEnabled()) {
                log.debug("Only JDK 1.3 URLEncoder available: using platform default encoding " +
                        "instead of the requested scheme '" + encodingScheme + "'");
            }
            return URLEncoder.encode(input);
        }
        return URLEncoder.encode(input, encodingScheme);
    }

    /**
     * Determine name-value pairs for query strings, which will be stringified,
     * URL-encoded and formatted by appendQueryProperties.
     * <p>This implementation returns all model elements as-is.
     *
     * @see #appendQueryProperties
     */
    protected Map queryProperties(Map model) {
        return model;
    }

    /**
     * Send a redirect back to the HTTP client
     *
     * @param request          current HTTP request (allows for reacting to request method)
     * @param response         current HTTP response (for sending response headers)
     * @param targetUrl        the name URL to redirect to
     * @param http10Compatible whether to stay compatible with HTTP 1.0 clients
     * @throws IOException if thrown by response methods
     */
    protected void sendRedirect(
            HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible)
            throws IOException {

        if (http10Compatible) {
            // Always send status code 302.
            response.sendRedirect(response.encodeRedirectURL(targetUrl));
        } else {
            // Correct HTTP status code is 303, in particular for POST requests.
            response.setStatus(303);
            response.setHeader("Location", response.encodeRedirectURL(targetUrl));
        }
    }

}
