ExceptionCommonpublic abstract class ExceptionCommon extends Object implements com.vladium.util.IJREVersionTODO: javadoc
Based on code published
by me in JavaPro, 2002.
This non-instantiable class provides static support functions common to
{@link AbstractException} and {@link AbstractRuntimeException}. |
Fields Summary |
---|
private static final boolean | EMBED_ERROR_CODE | private static final String | ROOT_RESOURCE_BUNDLE_NAME | private static final ResourceBundle | ROOT_RESOURCE_BUNDLE | private static final Map | s_exceptionCodeMap | private static final String | NESTED_THROWABLE_HEADER | private static final Class | THROWABLE | private static final Class | ABSTRACT_EXCEPTION | private static final Class | ABSTACT_RUNTIME_EXCEPTION | static final Enumeration | EMPTY_ENUMERATION | private static final ResourceBundle | EMPTY_RESOURCE_BUNDLE | private static final String | EOL |
Constructors Summary |
---|
private ExceptionCommon()
|
Methods Summary |
---|
public static java.util.ResourceBundle | addExceptionResource(java.lang.Class namespace, java.lang.String messageResourceBundleName)This method can be called by static initializers of {@link AbstractException}
and {@link AbstractRuntimeException} subclasses in order to add another
resource bundle to the set that is used to look up error codes. This makes
it possible to extend the set of exception error codes across independently
maintained and built projects.
Note that this introduces a possibility of error code name clashes. This
is resolved in the following way:
- when
getMessage(namespace, code) is called, 'code'
is attempted to be looked up in the resource bundle previously keyed
under 'namespace';
- if no such bundle it found or if it does not contain a value for
key 'code', the same step is repeated for the superclass of 'namespace';
- finally, if all of the above steps fail, the root resource bundle
specified by {@link #ROOT_RESOURCE_BUNDLE_NAME} is searched.
This strategy ensures that error codes follow inheritance and hiding rules
similar to Java static methods.
IMPORTANT: this method must be called from static class initializers
only.
There is no visible state change if the indicated resource is not found
or if it has been added already under the same key.
if ((namespace != null) && (messageResourceBundleName != null)
&& (messageResourceBundleName.length () > 0))
{
// bail out if the some other exception hierarchy attempts
// to use this functionality:
if (! ABSTRACT_EXCEPTION.isAssignableFrom (namespace)
&& ! ABSTACT_RUNTIME_EXCEPTION.isAssignableFrom (namespace))
{
throw new Error ("addExceptionResource(): class [" + namespace +
"] is not a subclass of " + ABSTRACT_EXCEPTION.getName () +
" or " + ABSTACT_RUNTIME_EXCEPTION.getName ());
}
// try to load resource bundle
ResourceBundle temprb = null;
String nameInNamespace = null;
try
{
nameInNamespace = getNameInNamespace (namespace, messageResourceBundleName);
//temprb = ResourceBundle.getBundle (nameInNamespace);
ClassLoader loader = namespace.getClassLoader ();
if (loader == null) loader = ClassLoader.getSystemClassLoader ();
temprb = ResourceBundle.getBundle (nameInNamespace, Locale.getDefault (), loader);
}
catch (Throwable ignore)
{
// ignored intentionally: if the exception codes rb is absent,
// we are still in a supported configuration
temprb = null;
}
if (temprb != null)
{
synchronized (s_exceptionCodeMap)
{
final ResourceBundle currentrb =
(ResourceBundle) s_exceptionCodeMap.get (namespace);
if (currentrb != null)
return currentrb;
else
{
s_exceptionCodeMap.put (namespace, temprb);
return temprb;
}
}
}
}
return null;
| static java.lang.String | getMessage(java.lang.Class namespace, java.lang.String code)Provides support for lookup of exception error codes from {@link AbstractException}
and {@link AbstractRuntimeException} and their subclasses.
if (code == null) return null;
try
{
if (code.length () > 0)
{
// look the code up in the resource bundle:
final String msg = lookup (namespace, code);
if (msg == null)
{
// if code lookup failed, return 'code' as is:
return code;
}
else
{
return EMBED_ERROR_CODE ? "[" + code + "] " + msg : msg;
}
}
else
{
return "";
}
}
catch (Throwable t)
{
// this method must never fail: default to returning the input
// verbatim on all unexpected problems
return code;
}
| static java.lang.String | getMessage(java.lang.Class namespace, java.lang.String code, java.lang.Object[] arguments)Provides support for lookup of exception error codes from {@link AbstractException}
and {@link AbstractRuntimeException} and their subclasses.
if (code == null) return null;
final String pattern = getMessage (namespace, code);
// assertion: pattern != null
if ((arguments == null) || (arguments.length == 0))
{
return pattern;
}
else
{
try
{
return MessageFormat.format (pattern, arguments);
}
catch (Throwable t)
{
// this method cannot fail: default to returning the input
// verbatim on all unexpected problems:
final StringBuffer msg = new StringBuffer (code + EOL);
for (int a = 0; a < arguments.length; a ++)
{
msg.append ("\t{" + a + "} = [");
final Object arg = arguments [a];
try
{
msg.append (arg.toString ());
}
catch (Throwable e) // guard against bad toString() overrides
{
if (arg != null)
msg.append (arg.getClass ().getName ());
else
msg.append ("null");
}
msg.append ("]");
msg.append (EOL);
}
return msg.toString ();
}
}
| private static java.lang.String | getNameInNamespace(java.lang.Class namespace, java.lang.String name)
if (namespace == null) return name;
final String namespaceName = namespace.getName ();
final int lastDot = namespaceName.lastIndexOf ('.");
if (lastDot <= 0)
return name;
else
return namespaceName.substring (0, lastDot + 1) + name;
| private static java.lang.String | lookup(java.lang.Class namespace, java.lang.String propertyName)Internal property lookup method. It implements the lookup scheme described
in {@link #addExceptionResource}.
if (propertyName == null) return null;
// note: the following does not guard against exceptions that do not subclass
// our base classes [done elsewhere], however it will not crash either
// check extension bundles:
if (namespace != null)
{
ResourceBundle rb;
while (namespace != ABSTRACT_EXCEPTION && namespace != ABSTACT_RUNTIME_EXCEPTION
&& namespace != THROWABLE && namespace != null)
{
synchronized (s_exceptionCodeMap)
{
rb = (ResourceBundle) s_exceptionCodeMap.get (namespace);
if (rb == null)
{
// check if there is a default bundle to be loaded for this namespace:
if ((rb = addExceptionResource (namespace, "exceptions")) == null)
{
// add an immutable empty bundle to avoid this check in the future:
s_exceptionCodeMap.put (namespace, EMPTY_RESOURCE_BUNDLE);
}
}
}
if (rb != null)
{
String propertyValue = null;
try
{
propertyValue = rb.getString (propertyName);
}
catch (Throwable ignore) {}
if (propertyValue != null) return propertyValue;
}
// walk the inheritance chain for 'namespace':
namespace = namespace.getSuperclass ();
}
}
// if everything fails, check the root bundle:
if (ROOT_RESOURCE_BUNDLE != null)
{
String propertyValue = null;
try
{
propertyValue = ROOT_RESOURCE_BUNDLE.getString (propertyName);
}
catch (Throwable ignore) {}
if (propertyValue != null) return propertyValue;
}
return null;
| static void | printStackTrace(java.lang.Throwable t, java.io.PrintWriter out)
if (JRE_1_4_PLUS)
{
if (t instanceof IThrowableWrapper)
{
final IThrowableWrapper tw = (IThrowableWrapper) t;
tw.__printStackTrace (out);
}
else
{
t.printStackTrace (out);
}
}
else
{
for (boolean first = true; t != null; )
{
if (first)
first = false;
else
{
out.println ();
out.println (NESTED_THROWABLE_HEADER);
}
if (t instanceof IThrowableWrapper)
{
final IThrowableWrapper tw = (IThrowableWrapper) t;
tw.__printStackTrace (out);
t = tw.getCause ();
}
else
{
t.printStackTrace (out);
break;
}
}
}
| static void | printStackTrace(java.lang.Throwable t, java.io.PrintStream out)
if (JRE_1_4_PLUS)
{
if (t instanceof IThrowableWrapper)
{
final IThrowableWrapper tw = (IThrowableWrapper) t;
tw.__printStackTrace (out);
}
else
{
t.printStackTrace (out);
}
}
else
{
for (boolean first = true; t != null; )
{
if (first)
first = false;
else
{
out.println ();
out.println (NESTED_THROWABLE_HEADER);
}
if (t instanceof IThrowableWrapper)
{
final IThrowableWrapper tw = (IThrowableWrapper) t;
tw.__printStackTrace (out);
t = tw.getCause ();
}
else
{
t.printStackTrace (out);
break;
}
}
}
|
|