/*
* DefaultRequestProcessor.java
*
* This work is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This work is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* Copyright (c) 2004-2005 Per Cederberg. All rights reserved.
*/
package org.liquidsite.app.servlet;
import org.liquidsite.app.admin.AdminRequestProcessor;
import org.liquidsite.app.legacy.ForumRequestProcessor;
import org.liquidsite.core.content.ContentException;
import org.liquidsite.core.content.ContentSite;
import org.liquidsite.core.content.User;
import org.liquidsite.core.web.Request;
import org.liquidsite.util.log.Log;
/**
* The default request processor for normal requests.
*
* @author Per Cederberg, <per at percederberg dot net>
* @version 1.0
*/
public class DefaultRequestProcessor extends RequestProcessor {
/**
* The class logger.
*/
private static final Log LOG = new Log(DefaultRequestProcessor.class);
/**
* The delay in milliseconds on a failed login attempt.
*/
private static final int FAILED_LOGIN_DELAY = 5000;
/**
* The admin request processor.
*/
private AdminRequestProcessor admin;
/**
* The forum request processor.
*/
private ForumRequestProcessor forum;
/**
* Creates a new default request processor.
*
* @param app the application context
*/
public DefaultRequestProcessor(Application app) {
super(app.getContentManager(), app.getBaseDir());
admin = new AdminRequestProcessor(app);
forum = new ForumRequestProcessor(app);
}
/**
* Destroys this request processor. This method frees all
* internal resources used by this processor.
*/
public void destroy() {
admin.destroy();
forum.destroy();
}
/**
* Processes a request.
*
* @param request the request object to process
*
* @throws RequestException if the request couldn't be processed
*/
public void process(Request request) throws RequestException {
String path = request.getPath();
User user;
ContentSite site;
// Find domain & site
try {
site = getContentManager().findSite(request.getProtocol(),
request.getHost(),
request.getPort(),
request.getPath());
if (site == null) {
LOG.warning("failed to locate site for request: " + request +
" (protocol: " + request.getProtocol() +
", host: " + request.getHost() +
", port: " + request.getPort() +
", path: " + request.getPath() + ")");
return;
}
request.getEnvironment().setDomain(site.getDomain());
request.getEnvironment().setSite(site);
} catch (ContentException e) {
LOG.error(e.getMessage());
throw RequestException.INTERNAL_ERROR;
}
// Process request action
if (request.getParameter("liquidsite.action") != null) {
processAction(request);
if (request.hasResponse()) {
return;
}
}
// Find page and create response
path = path.substring(site.getDirectory().length());
try {
if (path.startsWith("liquidsite/")) {
processLiquidSite(request, path.substring(11));
} else if (site.isAdmin()) {
user = request.getUser();
if (user != null && site.hasReadAccess(user)) {
admin.processAuthorized(request, path);
} else {
admin.processUnauthorized(request, path);
}
} else {
processNormal(request, site, path, false);
}
} catch (ContentException e) {
LOG.error(e.getMessage());
throw RequestException.INTERNAL_ERROR;
}
}
/**
* Processes a request action. The processing of the action may
* produce a response to the request object, which must be checked
* before contining processing after calling this method.
*
* @param request the request object
*
* @throws RequestException if the action couldn't be processed
*/
private void processAction(Request request)
throws RequestException {
String action = request.getParameter("liquidsite.action");
if (action.equals("login")) {
processLogin(request);
} else if (action.equals("logout")) {
processLogout(request);
} else if (action.startsWith("forum.")) {
forum.process(request);
} else {
if (action.indexOf("@") >= 0) {
if (action.length() > 20) {
action = action.substring(0, 20) + "...";
}
LOG.warning(request + ": request action '" + action +
"' is undefined and contains email address, " +
"sent from " + request.getRemoteAddr());
} else {
LOG.warning(request + ": request action '" + action +
"' is undefined");
}
throw RequestException.INTERNAL_ERROR;
}
}
/**
* Processes a login request. This will set the request user if
* successful, and send a redirect to the requested page. If
* unsuccessful, a request error attribute is set. Note that the
* request must be further processed in the case of an
* unsuccessful login, as the login page must be displayed again.
*
* @param request the request object
*
* @throws RequestException if the request couldn't be processed
*/
private void processLogin(Request request)
throws RequestException {
ContentSite site = request.getEnvironment().getSite();
String name;
String password;
String redirect;
User user;
name = request.getParameter("liquidsite.login", "");
password = request.getParameter("liquidsite.password", "");
redirect = request.getParameter("liquidsite.redirect", "");
try {
user = getContentManager().getUser(site.getDomain(), name);
LOG.info("correct login by user " + name + " in domain " +
site.getDomain().getName() + " from " +
request.getRemoteAddr());
} catch (ContentException e) {
LOG.error(e.getMessage());
throw RequestException.INTERNAL_ERROR;
}
if (user != null && user.verifyPassword(password)) {
request.setUser(user);
if (redirect.length() > 0) {
request.sendRedirect(redirect);
} else {
request.sendRedirect(request.getPath());
}
} else {
try {
Thread.sleep(FAILED_LOGIN_DELAY);
} catch (InterruptedException ignore) {
// Do nothing
}
request.setUser(null);
request.setAttribute("error", "Invalid user name or password");
}
}
/**
* Processes a logout request. This will set the request user to
* null, which invalidates the user session. The request will be
* redirected to the requested page.
*
* @param request the request object
*/
private void processLogout(Request request) {
request.setUser(null);
request.sendRedirect(request.getPath());
}
}