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);
}
}
|