From a2925e8ab6102c0308100d8296984ea5d883e133 Mon Sep 17 00:00:00 2001 From: mdb Date: Thu, 10 Nov 2005 17:43:04 +0000 Subject: [PATCH] Give applications a chance to perform global access control and to issue specific HTTP errors. git-svn-id: https://samskivert.googlecode.com/svn/trunk@1732 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../servlet/HttpErrorException.java | 64 +++++++++++++++++++ .../com/samskivert/velocity/Application.java | 13 ++++ .../velocity/DispatcherServlet.java | 13 ++++ 3 files changed, 90 insertions(+) create mode 100644 projects/samskivert/src/java/com/samskivert/servlet/HttpErrorException.java diff --git a/projects/samskivert/src/java/com/samskivert/servlet/HttpErrorException.java b/projects/samskivert/src/java/com/samskivert/servlet/HttpErrorException.java new file mode 100644 index 00000000..1cf11425 --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/servlet/HttpErrorException.java @@ -0,0 +1,64 @@ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2004 Michael Bayne +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.servlet; + +import javax.servlet.http.HttpServletResponse; + +/** + * An http error exception is thrown by servlet services when they wish to fail + * the request in some particular way (ie. {@link + * HttpServletResponse#SC_FORBIDDEN}, etc.). It is expected that error handling + * can be implemented in a single place such that servlets can simply allow + * this exception to propagate up to the proper handler which will then issue + * the appropriate failure header. + */ +public class HttpErrorException extends Exception +{ + public HttpErrorException (int errorCode) + { + super(String.valueOf(errorCode)); + _errorCode = errorCode; + } + + public HttpErrorException (int errorCode, String errorMessage) + { + super(errorMessage); + _errorCode = errorCode; + } + + /** + * Returns the HTTP error code supplied with this exception. + */ + public int getErrorCode () + { + return _errorCode; + } + + /** + * Returns the textual error message supplied with this exception or null + * if only an error code was supplied. + */ + public String getErrorMessage () + { + String msg = getMessage(); + return String.valueOf(_errorCode).equals(msg) ? null : msg; + } + + protected int _errorCode; +} diff --git a/projects/samskivert/src/java/com/samskivert/velocity/Application.java b/projects/samskivert/src/java/com/samskivert/velocity/Application.java index 5c90eff2..efbbdada 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/Application.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/Application.java @@ -28,8 +28,10 @@ import javax.servlet.ServletContext; import org.apache.velocity.app.Velocity; import com.samskivert.Log; +import com.samskivert.servlet.HttpErrorException; import com.samskivert.servlet.IndiscriminateSiteIdentifier; import com.samskivert.servlet.MessageManager; +import com.samskivert.servlet.RedirectException; import com.samskivert.servlet.SiteIdentifier; import com.samskivert.servlet.SiteResourceLoader; import com.samskivert.util.StringUtil; @@ -174,6 +176,17 @@ public class Application { } + /** + * Allows derived application classes to check access in a single location + * prior to resolving and dispatching a logic class, if they desire access + * control at this level. Alternatively, access control can be performed by + * the logic instance. + */ + protected void checkAccess (InvocationContext ctx) + throws RedirectException, HttpErrorException + { + } + /** * This should be overridden by the application implementation to * perform any necessary cleanup. diff --git a/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java b/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java index 782ccf33..08d77d57 100644 --- a/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java +++ b/projects/samskivert/src/java/com/samskivert/velocity/DispatcherServlet.java @@ -41,6 +41,7 @@ import org.apache.velocity.app.event.MethodExceptionEventHandler; import com.samskivert.Log; +import com.samskivert.servlet.HttpErrorException; import com.samskivert.servlet.MessageManager; import com.samskivert.servlet.RedirectException; import com.samskivert.servlet.SiteIdentifier; @@ -337,6 +338,9 @@ public class DispatcherServlet extends VelocityServlet // allow the application to prepare the context _app.prepareContext(ictx); + // allow the application to do global access control + _app.checkAccess(ictx); + // resolve the appropriate logic class for this URI and // execute it if it exists String path = req.getServletPath(); @@ -349,6 +353,15 @@ public class DispatcherServlet extends VelocityServlet ictx.getResponse().sendRedirect(re.getRedirectURL()); return null; + } catch (HttpErrorException hee) { + String msg = hee.getErrorMessage(); + if (msg != null) { + ictx.getResponse().sendError(hee.getErrorCode(), msg); + } else { + ictx.getResponse().sendError(hee.getErrorCode()); + } + return null; + } catch (FriendlyException fe) { // grab the error message, we'll deal with it shortly errmsg = fe.getMessage();