Added the code that actually maps exceptions to error messages.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@45 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -0,0 +1,142 @@
|
|||||||
|
//
|
||||||
|
// $Id: ExceptionMap.java,v 1.1 2001/02/13 20:00:28 mdb Exp $
|
||||||
|
|
||||||
|
package com.samskivert.webmacro;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The exception map is used to load the exception to error message
|
||||||
|
* mapping information and to look up the appropriate response for a given
|
||||||
|
* exception instance.
|
||||||
|
*
|
||||||
|
* @see FriendlyServlet
|
||||||
|
*/
|
||||||
|
public class ExceptionMap
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Searches for the <code>exceptionmap.properties</code> file in the
|
||||||
|
* classpath and loads it. If the file could not be found, an error is
|
||||||
|
* reported and a default set of mappings is used.
|
||||||
|
*/
|
||||||
|
public static synchronized void init ()
|
||||||
|
{
|
||||||
|
// only initialize ourselves once
|
||||||
|
if (_keys != null) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_keys = new ArrayList();
|
||||||
|
_values = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// first try loading the properties file without a leading slash
|
||||||
|
InputStream config = getStream(PROPS_NAME);
|
||||||
|
if (config == null) {
|
||||||
|
// some JVMs require the leading slash, some don't
|
||||||
|
config = getStream("/" + PROPS_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// still no props, then we complain
|
||||||
|
if (config == null) {
|
||||||
|
Log.log.warning("Unable to load " + PROPS_NAME +
|
||||||
|
" from CLASSPATH.");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise process ye old config file.
|
||||||
|
try {
|
||||||
|
// we'll do some serious jiggery pokery to leverage the
|
||||||
|
// parsing implementation provided by
|
||||||
|
// java.util.Properties. god bless method overloading
|
||||||
|
Properties loader = new Properties() {
|
||||||
|
public Object put (Object key, Object value)
|
||||||
|
{
|
||||||
|
_keys.add(key);
|
||||||
|
_values.add(value);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loader.load(config);
|
||||||
|
|
||||||
|
// now cruise through and resolve the exceptions named as
|
||||||
|
// keys and throw out any that don't appear to exist
|
||||||
|
for (int i = 0; i < _keys.size(); i++) {
|
||||||
|
String exclass = (String)_keys.get(i);
|
||||||
|
try {
|
||||||
|
Class cl = Class.forName(exclass);
|
||||||
|
// replace the string with the class object
|
||||||
|
_keys.set(i, cl);
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.log.warning("Unable to resolve exception " +
|
||||||
|
"class. [class=" + exclass +
|
||||||
|
", error=" + t + "].");
|
||||||
|
_keys.remove(i);
|
||||||
|
_values.remove(i);
|
||||||
|
i--; // back on up a notch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.log.warning("Error reading exception mapping file: " +
|
||||||
|
ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up the supplied exception in the map and returns the most
|
||||||
|
* specific error message available for exceptions of that class.
|
||||||
|
*
|
||||||
|
* @param ex The exception to resolve into an error message.
|
||||||
|
*
|
||||||
|
* @return The error message to which this exception maps (properly
|
||||||
|
* populated with the message associated with this exception
|
||||||
|
* instance).
|
||||||
|
*/
|
||||||
|
public static String getMessage (Throwable ex)
|
||||||
|
{
|
||||||
|
String msg = DEFAULT_ERROR_MSG;
|
||||||
|
|
||||||
|
for (int i = 0; i < _keys.size(); i++) {
|
||||||
|
Class cl = (Class)_keys.get(i);
|
||||||
|
if (cl.isInstance(ex)) {
|
||||||
|
msg = (String)_values.get(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringUtil.replace(msg, MESSAGE_MARKER, ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static InputStream getStream (String path)
|
||||||
|
{
|
||||||
|
// first try using the classloader that loaded us
|
||||||
|
Class c = ExceptionMap.class;
|
||||||
|
InputStream in = c.getResourceAsStream(path);
|
||||||
|
if (null == in) {
|
||||||
|
// if that didn't work, try the system classloader
|
||||||
|
c = Class.class;
|
||||||
|
in = c.getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
ExceptionMap map = new ExceptionMap();
|
||||||
|
System.out.println(map.getMessage(new Exception("Test error")));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static List _keys;
|
||||||
|
protected static List _values;
|
||||||
|
|
||||||
|
// initialize ourselves
|
||||||
|
static { init(); }
|
||||||
|
|
||||||
|
protected static final String PROPS_NAME = "exceptionmap.properties";
|
||||||
|
protected static final String DEFAULT_ERROR_MSG = "Error: {m}.";
|
||||||
|
protected static final String MESSAGE_MARKER = "{m}";
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: FriendlyServlet.java,v 1.1 2001/02/13 18:49:41 mdb Exp $
|
// $Id: FriendlyServlet.java,v 1.2 2001/02/13 20:00:28 mdb Exp $
|
||||||
|
|
||||||
package com.samskivert.webmacro;
|
package com.samskivert.webmacro;
|
||||||
|
|
||||||
@@ -25,23 +25,41 @@ import org.webmacro.servlet.*;
|
|||||||
* webmacro procedure.
|
* webmacro procedure.
|
||||||
*
|
*
|
||||||
* <p> The process of mapping exceptions to friendly error messages is
|
* <p> The process of mapping exceptions to friendly error messages is
|
||||||
* done through a properties file loaded via the classpath. The properties
|
* done through a configuration file loaded via the classpath. The file
|
||||||
* file should be named 'exceptionmap.properties' and placed in a
|
* should be named <code>exceptionmap.properties</code> and placed in the
|
||||||
* directory contained in the classpath of the JVM in which the servlet is
|
* classpath of the JVM in which the servlet is executed. The file should
|
||||||
* executed. The file should contain mappings from exception classes to
|
* contain colon-separated mappings from exception classes to friendly
|
||||||
* friendly error messages. For example:
|
* error messages. For example:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* com.samskivert.webmacro.FriendlyException = An error occurred while \
|
* # Exception mappings (lines beginning with # are ignored)
|
||||||
|
* com.samskivert.webmacro.FriendlyException: An error occurred while \
|
||||||
* processing your request: {m}
|
* processing your request: {m}
|
||||||
* java.sql.SQLException = The database is currently unavailable. Please \
|
*
|
||||||
|
* # lines ending with \ are continued on the next line
|
||||||
|
* java.sql.SQLException: The database is currently unavailable. Please \
|
||||||
* try your request again later.
|
* try your request again later.
|
||||||
* java.lang.Exception = An unexpected error occurred while processing \
|
*
|
||||||
|
* java.lang.Exception: An unexpected error occurred while processing \
|
||||||
* your request. Please try again later.
|
* your request. Please try again later.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* The message associated with the exception will be substituted into the
|
* The message associated with the exception will be substituted into the
|
||||||
* error string in place of <code>{m}</code>.
|
* error string in place of <code>{m}</code>. The exceptions should be
|
||||||
|
* listed in order of most specific to least specific, for the first
|
||||||
|
* mapping for which the exception to report is an instance of the
|
||||||
|
* exception in the left hand side will be used.
|
||||||
|
*
|
||||||
|
* <em>Note:</em> These exception mappings are used for all servlets
|
||||||
|
* (perhaps some day only for servlets associated with a particular
|
||||||
|
* application identifier). Regardless, this error handling mechanism
|
||||||
|
* should not be used for servlet specific errors. For example, an SQL
|
||||||
|
* exception reporting a duplicate key should probably be caught and
|
||||||
|
* reported specifically by the servlet (it can still leverage the pattern
|
||||||
|
* of inserting the error message into the context as
|
||||||
|
* <code>"error"</code>) rather than relying on the default SQL exception
|
||||||
|
* error message which is not likely to be meaningful for such a
|
||||||
|
* situation.
|
||||||
*/
|
*/
|
||||||
public abstract class FriendlyServlet extends WMServlet
|
public abstract class FriendlyServlet extends WMServlet
|
||||||
{
|
{
|
||||||
@@ -59,6 +77,7 @@ public abstract class FriendlyServlet extends WMServlet
|
|||||||
try {
|
try {
|
||||||
populateContext(ctx, tmpl);
|
populateContext(ctx, tmpl);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ctx.put(ERROR_KEY, ExceptionMap.getMessage(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmpl;
|
return tmpl;
|
||||||
@@ -87,4 +106,7 @@ public abstract class FriendlyServlet extends WMServlet
|
|||||||
*/
|
*/
|
||||||
protected abstract void populateContext (WebContext ctx, Template tmpl)
|
protected abstract void populateContext (WebContext ctx, Template tmpl)
|
||||||
throws Exception;
|
throws Exception;
|
||||||
|
|
||||||
|
/** This is the key used in the context for error messages. */
|
||||||
|
protected static final String ERROR_KEY = "error";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// $Id: Log.java,v 1.1 2001/02/13 20:00:28 mdb Exp $
|
||||||
|
|
||||||
|
package com.samskivert.webmacro;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A placeholder class that contains a reference to the log object used by
|
||||||
|
* the webmacro package.
|
||||||
|
*/
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
public static com.samskivert.util.Log log =
|
||||||
|
new com.samskivert.util.Log("com.samskivert.webmacro");
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
#
|
#
|
||||||
# $Id: Makefile,v 1.1 2001/02/13 18:49:41 mdb Exp $
|
# $Id: Makefile,v 1.2 2001/02/13 20:00:28 mdb Exp $
|
||||||
|
|
||||||
ROOT = ../../..
|
ROOT = ../../..
|
||||||
|
|
||||||
SRCS = \
|
SRCS = \
|
||||||
|
ExceptionMap.java \
|
||||||
FriendlyException.java \
|
FriendlyException.java \
|
||||||
FriendlyServlet.java \
|
FriendlyServlet.java \
|
||||||
|
Log.java \
|
||||||
|
|
||||||
include $(ROOT)/build/Makefile.java
|
include $(ROOT)/build/Makefile.java
|
||||||
|
|||||||
Reference in New Issue
Block a user