FileDocCategorySizeDatePackage
PBControllerServlet.javaAPI DocExample12801Thu Jun 28 16:14:16 BST 2001com.ora.jsp.servlets

PBControllerServlet.java

package com.ora.jsp.servlets;

import java.io.*;
import java.net.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;
import com.ora.jsp.beans.emp.*;
import com.ora.jsp.beans.news.*;
import com.ora.jsp.sql.*;

/**
 * This class is an example of a servlet used as the Controller for
 * the Project Billboard application.
 * <p>
 * It initializes a number of servlet context attributes in its
 * init() method. The doGet()/doPost() methods perform authentication
 * and access control, and perform the action specified by the
 * action request parameter is the client is authorized.
 *
 * @author Hans Bergsten, Gefion software <hans@gefionsoftware.com>
 * @version 1.0
 */
public class PBControllerServlet extends HttpServlet {

    /**
     * Creates an EmployeeRegistryBean and a NewsBean, and saves them
     * as servlet context attributes.
     */
    public void init() throws ServletException {
        /* 
         * In a real application, it's better to let an application
         * initialization servlet create a DataSource and save it
         * as a context attribute, so all other servlets and JSP
         * pages can get to it.
         */
        DataSource ds = null;
        try {
            ds = new DataSourceWrapper("sun.jdbc.odbc.JdbcOdbcDriver", 
                "jdbc:odbc:example", null, null);
        }
        catch (Exception e) {} // Ignore all in this example
        EmployeeRegistryBean empReg = new EmployeeRegistryBean();
        empReg.setDataSource(ds);
        getServletContext().setAttribute("empReg", empReg);

        NewsBean news = new NewsBean();
        getServletContext().setAttribute("news", news);
    }
    
    /**
     * Removes the EmployeeRegistryBean and NewsBean
     * servlet context attributes.
     */
    public void destroy() {
        getServletContext().removeAttribute("empReg");
        getServletContext().removeAttribute("news");
    }
    
    /**
     * Processes a GET request by calling doPost().
     */
    public void doGet(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        doPost(request, response);
    }
    
    /**
     * Performs authentication, if needed, and access control.
     * If the user is authorized, performs the action specified by
     * the "action" request parameter.
     */
    public void doPost(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        
        String action = request.getParameter("action");
        
        // Check if the user is authenticated
        if (!isAuthenticated(request) && 
            !("authenticate".equals(action) || 
            "logout".equals(action))) {
            doForwardToLogin(request, response);
        }
        else {
            if ("authenticate".equals(action)) {
                doAuthenticate(request, response);
            }
            else if ("logout".equals(action)) {
                doLogout(request, response);
            }
            else if ("storeMsg".equals(action)) {
                doStoreMsg(request, response);
            }
            else if ("updateProfile".equals(action)) {
                doUpdateProfile(request, response);
            }
            else if ("showPage".equals(action)) {
                doShowPage(request, response);
            }
            else {
                response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
            }
        }
    }
    
    /**
     * Returns true if an authentication token object is found
     * in the session.
     */
    private boolean isAuthenticated(HttpServletRequest request) {
        boolean isAuthenticated = false;
        HttpSession session = request.getSession();
        if (session.getAttribute("validUser") != null) {
            isAuthenticated = true;
        }
        return isAuthenticated;
    }
    
    /**
     * Forwards the request to the login JSP page, with an
     * "errorMsg" parameter containing text to be displayed on
     * the login page.
     */
    private void doForwardToLogin(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        String origURL = HttpUtils.getRequestURL(request).toString();
        String queryString = request.getQueryString();
        if (queryString != null) {
            origURL += "?" + queryString;
        }
        String loginURL = "login.jsp" + "?origURL=" + 
            URLEncoder.encode(origURL) +
            "&errorMsg=" + URLEncoder.encode("Please log in first");
        forward(loginURL, request, response);
    }
    
    /**
     * Autheticates a user with help from the EmployeeRegistryBean,
     * using the "userName" and "password" request parameters.
     * If the user can be authenticated, the "validUser" session 
     * attribute is set to an instance of the EmployeeBean, to
     * serve as an authentication token in this application.
     * <p>
     * Cookies with the user name and password are set or reset
     * as specified by the "remember" request parameter.
     */
    private void doAuthenticate(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        String userName = request.getParameter("userName");
        if (userName == null) {
            throw new ServletException("Missing User Name");
        }
        String password = request.getParameter("password");
        if (password == null) {
            throw new ServletException("Missing Password");
        }

        try {
            EmployeeRegistryBean empReg = (EmployeeRegistryBean) 
                getServletContext().getAttribute("empReg");
            boolean isRegistered = empReg.authenticate(userName, password);
            if (isRegistered) {
                EmployeeBean emp = empReg.getEmployee(userName);
                HttpSession session = request.getSession();
                session.setAttribute("validUser", emp);
                
                // Set or "delete" cookies, as requested
                Cookie userNameCookie = new Cookie("userName", userName);
                Cookie passwordCookie = new Cookie("password", password);
                int maxAge = 2592000;
                if (request.getParameter("remember") == null) {
                    maxAge = 0;
                }
                userNameCookie.setMaxAge(maxAge);
                passwordCookie.setMaxAge(maxAge);
                response.addCookie(userNameCookie);
                response.addCookie(passwordCookie);
                
                // Redirect to the originally requested URL or main
                String next = request.getParameter("origURL");
                if (next == null || next.length() == 0) {
                    next = getShowPageURL(request) + "main.jsp";
                }
                response.sendRedirect(next);
            }
            else {
                String loginURL = "login.jsp" + 
                    "?errorMsg=" + 
                    URLEncoder.encode("Invalid User Name or Password");
                response.sendRedirect(loginURL);
            }
        }
        catch (SQLException e) {
            throw new ServletException("Database error", e);
        }
    }
    
    /**
     * Invalidates the session, thereby removing the authentication
     * token, and redirects to the login page.
     */
    private void doLogout(HttpServletRequest request, 
        HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        session.invalidate();
        response.sendRedirect("login.jsp");
    }
    
    /**
     * Creates a new NewsItemBean and sets its properties based
     * on the "category" and "msg" request parameters, plus
     * the firstName and lastName properties of the authenticated
     * user (an EmployeeBean accessible as the "validUser" session
     * attribute). The NewItemBean is then added to the NewsBean.
     * This action is only performed for POST request.
     * Before returning, the client is redirected to the main page, 
     * where the new message is displayed.
     */
    private void doStoreMsg(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        if (request.getMethod().equals("POST")) {
            String category = request.getParameter("category");
            String msg = request.getParameter("msg");
            if (category == null || msg == null) {
                throw new ServletException("Missing message info");
            }
            HttpSession session = request.getSession();
            EmployeeBean emp = 
                (EmployeeBean) session.getAttribute("validUser");
            NewsItemBean item = new NewsItemBean();
            item.setCategory(category);
            item.setMsg(msg);
            item.setPostedBy(emp.getFirstName() + " " +
                emp.getLastName());
            NewsBean news = (NewsBean)
                getServletContext().getAttribute("news");
            news.setNewsItem(item);
        }
        response.sendRedirect(getShowPageURL(request) + "main.jsp");
    }
    
    /**
     * Updates the projects property of an authenticated user,
     * represented by the "validUser" session attribute, using
     * the EmployeeRegistryBean. This action is only performed
     * for POST requests. Before returning, the client is
     * redirected to the main page, where the new set of projects
     * are displayed.
     */
    private void doUpdateProfile(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        if (request.getMethod().equals("POST")) {
            String[] projects = request.getParameterValues("projects");
            if (projects == null) {
                projects = new String[0];
            }
            HttpSession session = request.getSession();
            EmployeeBean emp = 
                (EmployeeBean) session.getAttribute("validUser");
            emp.setProjects(projects);
            EmployeeRegistryBean empReg = (EmployeeRegistryBean) 
                getServletContext().getAttribute("empReg");
            try {
                empReg.saveEmployee(emp);
            }
            catch (SQLException e) {
                throw new ServletException("Database error", e);
            }
        }
        response.sendRedirect(getShowPageURL(request) + "main.jsp");
    }

    /**
     * Forwards to the specified JSP page. The reason for using this
     * action instead of requesting a JSP page directly is to let
     * the PBDispatcher handle authentication and access control even 
     * for JSP pages. Note that nothing prevents a user from
     * requesting a JSP page directly, so this is not a secure way
     * to perform access control. What it does give is automatic
     * redirection to the login page for users that are not properly
     * logged in. 
     * 
     * In this application, as in most applications with  a servlet as 
     * a controller, accessing a JSP page directly doesn't reveal any 
     * restricted information however; the JSP page only displays 
     * information available in beans, created by the controller.
     */
    private void doShowPage(HttpServletRequest request, 
        HttpServletResponse response) 
        throws IOException, ServletException {
        String url = request.getParameter("page");
        if (url == null) {
            throw new ServletException("Missing page info");
        }
        forward(url, request, response);
    }

    /**
     * Returns an absolute URL, suitable for redirecting a request 
     * back to this servlet, with an "action" parameter set to
     * "showPage" and a "page" parameter set to the specified
     * (relative) page URL. 
     */
    private String getShowPageURL(HttpServletRequest request) {
        return request.getContextPath() + request.getServletPath() + 
            "?action=showPage&page=";
    }
    
    /**
     * Forwards the request to the specified relative URL.
     */
    private void forward(String url, HttpServletRequest request,
        HttpServletResponse response) 
        throws IOException, ServletException {
        RequestDispatcher rd = request.getRequestDispatcher(url);
        rd.forward(request, response);
    }
}