package com.oreilly.jent.people.servlet;

/**
 * In general, you may use the code in this book in your programs and 
 * documentation. You do not need to contact us for permission unless 
 * you're reproducing a significant portion of the code. For example, 
 * writing a program that uses several chunks of code from this book does 
 * not require permission. Selling or distributing a CD-ROM of examples 
 * from O'Reilly books does require permission. Answering a question by 
 * citing this book and quoting example code does not require permission. 
 * Incorporating a significant amount of example code from this book into 
 * your product's documentation does require permission.
 * 
 * We appreciate, but do not require, attribution. An attribution usually 
 * includes the title, author, publisher, and ISBN. For example: 
 * 
 *   "Java Enterprise in a Nutshell, Third Edition, 
 *    by Jim Farley and William Crawford 
 *    with Prakash Malani, John G. Norman, and Justin Gehtland. 
 *    Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
 *  
 *  If you feel your use of code examples falls outside fair use or the 
 *  permission given above, feel free to contact us at 
 *  permissions@oreilly.com.
 */

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginFilter implements Filter {
    // Some constants used for session variables and request parameters
    public static final String AUTHN_ID_VAR = "pf-authn-id";
    public static final String USER_VAR = "pf-user";
    public static final String PASSWORD_VAR = "pf-pw";
    
    private String[][] mAccounts =
        { {"john", "johnpw"},
          {"jane", "janepw"} };

    // URL location of the login entry screen
    private String mLoginURI = "login";
    
    /** Default constructor */
    public LoginFilter() {
        super();
    }

    /** Initialization callback */
    public void init(FilterConfig arg0) throws ServletException {
    }

    /** Execute the filter on an incoming request. */
    public void doFilter(ServletRequest sReq, ServletResponse sResp,
                         FilterChain chain)
        throws IOException, ServletException {
        boolean loggedIn = false;
        
        HttpServletRequest request = (HttpServletRequest)sReq;
        HttpServletResponse response = (HttpServletResponse)sResp;
        HttpSession session = request.getSession();
        
        // If the target is the login entry screen, let the
        // request pass through
        if (request.getRequestURI().endsWith(getLoginURI())) {
            chain.doFilter(request, response);
            return;
        }
        
        // Check the session for our authentication id
        if (session == null ||
            session.getAttribute(AUTHN_ID_VAR) == null) {
            // No session attribute set yet, so check for the login 
            // parameters
            String user = request.getParameter(USER_VAR);
            String pw = request.getParameter(PASSWORD_VAR);
            // Compare these to our set of accounts to see if there's a match
            String authnID = null;
            for (int i = 0; i < this.mAccounts.length; i++) {
                if (user != null && user.equals(this.mAccounts[i][0]) &&
                    pw != null && pw.equals(this.mAccounts[i][1])) {
                    authnID = user;
                    break;
                }
            }
            // If there's a match, set the session variable with the 
            // authenticated user's id, and pass through
            if (authnID != null) {
                session.setAttribute(AUTHN_ID_VAR, authnID);
                chain.doFilter(request, response);
            }
            // If we failed to login the user, redirect them to the login page
            else {
                response.sendRedirect(response.encodeRedirectURL(getLoginURI()));
                return;
            }
        }
        // If there is a session authn id, pass them through, because they're
        // already logged in
        else {
            chain.doFilter(request, response);
        }
    }

    /** Cleanup any initialized resources */
    public void destroy() {        
    }

    /**
     * @return Returns the mLoginURI.
     */
    public String getLoginURI() {
        return mLoginURI;
    }
    /**
     * @param loginURI The mLoginURI to set.
     */
    public void setLoginURI(String loginURI) {
        mLoginURI = loginURI;
    }
}
