KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > util > exception > AbstractException


1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: AbstractException.java,v 1.1.1.1 2004/05/09 16:57:57 vlad_r Exp $
8  */

9 package com.vladium.util.exception;
10
11 import java.io.IOException JavaDoc;
12 import java.io.ObjectOutputStream JavaDoc;
13 import java.io.PrintStream JavaDoc;
14 import java.io.PrintWriter JavaDoc;
15
16 // ----------------------------------------------------------------------------
17
/**
18  * Based on code published by me in <a HREF="http://www.fawcette.com/javapro/2002_12/online/exception_vroubtsov_12_16_02/default_pf.asp">JavaPro, 2002</a>.<P>
19  *
20  * This checked exception class is designed as a base/expansion point for the
21  * entire hierarchy of checked exceptions in a project.<P>
22  *
23  * It provides the following features:
24  * <UL>
25  * <LI> ability to take in compact error codes that map to full text messages
26  * in a resource bundle loaded at this class' instantiation time. This avoids
27  * hardcoding the error messages in product code and allows for easy
28  * localization of such text if required. Additionally, these messages
29  * can be parametrized in the java.text.MessageFormat style;
30  * <LI> exception chaining in J2SE versions prior to 1.4
31  * </UL>
32  *
33  * See {@link AbstractRuntimeException} for an unchecked version of the same class.<P>
34  *
35  * TODO: javadoc
36  *
37  * Each constructor that accepts a String 'message' parameter accepts an error
38  * code as well. You are then responsible for ensuring that either the root
39  * <CODE>com.vladium.exception.exceptions</CODE> resource bundle
40  * or your project/exception class-specific resource bundle [see
41  * <A HREF="#details">below</A> for details] contains a mapping for this error
42  * code. When this lookup fails the passed String value itself will be used as
43  * the error message.<P>
44  *
45  * All constructors taking an 'arguments' parameter supply parameters to the error
46  * message used as a java.text.MessageFormat pattern.<P>
47  *
48  * Example:
49  * <PRE><CODE>
50  * File file = ...
51  * try
52  * ...
53  * catch (Exception e)
54  * {
55  * throw new AbstractException ("FILE_NOT_FOUND", new Object[] {file, e}, e);
56  * }
57  * </CODE></PRE>
58  * where <CODE>com.vladium.util.exception.exceptions</CODE> contains:
59  * <PRE><CODE>
60  * FILE_NOT_FOUND: file {0} could not be opened: {1}
61  * </CODE></PRE>
62  *
63  * To log exception data use {@link #getMessage} or <CODE>printStackTrace</CODE>
64  * family of methods. You should never have to use toString().<P>
65  *
66  * <A NAME="details"> It is also possible to use project- or exception
67  * subhierarchy-specific message resource bundles without maintaining all error
68  * codes in <CODE>com.vladium.exception.exceptions</CODE>. To do so, create a
69  * custom resource bundle and add the following static initializer code to your
70  * base exception class:
71  * <PRE><CODE>
72  * static
73  * {
74  * addExceptionResource (MyException.class, "my_custom_resource_bundle");
75  * }
76  * </CODE></PRE>
77  * The bundle name is relative to MyException package. This step can omitted if
78  * the bundle name is "exceptions".
79  *
80  * Note that the implementation correctly resolves error code name collisions
81  * across independently developed exception families, as long as resource bundles
82  * use unique names. Specifically, error codes follow inheritance and hiding rules
83  * similar to Java class static methods. See {@link ExceptionCommon#addExceptionResource}
84  * for further details.
85  *
86  * @author Vlad Roubtsov, (C) 2002
87  */

88 public
89 abstract class AbstractException extends Exception JavaDoc implements ICodedException, IThrowableWrapper
90 {
91     // public: ................................................................
92

93     /**
94      * Constructs an exception with null message and null cause.
95      */

96     public AbstractException ()
97     {
98         m_cause = null;
99         m_arguments = null;
100     }
101     
102     /**
103      * Constructs an exception with given error message/code and null cause.
104      *
105      * @param message the detail message [can be null]
106      */

107     public AbstractException (final String JavaDoc message)
108     {
109         super (message);
110         m_cause = null;
111         m_arguments = null;
112     }
113     
114     /**
115      * Constructs an exception with given error message/code and null cause.
116      *
117      * @param message the detail message [can be null]
118      * @param arguments message format parameters [can be null or empty]
119      *
120      * @see java.text.MessageFormat
121      */

122     public AbstractException (final String JavaDoc message, final Object JavaDoc [] arguments)
123     {
124         super (message);
125         m_cause = null;
126         m_arguments = arguments == null ? null : (Object JavaDoc []) arguments.clone ();
127     }
128     
129     /**
130      * Constructs an exception with null error message/code and given cause.
131      *
132      * @param cause the cause [nested exception] [can be null]
133      */

134     public AbstractException (final Throwable JavaDoc cause)
135     {
136         super ();
137         m_cause = cause;
138         m_arguments = null;
139     }
140     
141     /**
142      * Constructs an exception with given error message/code and given cause.
143      *
144      * @param message the detail message [can be null]
145      * @param cause the cause [nested exception] [can be null]
146      */

147     public AbstractException (final String JavaDoc message, final Throwable JavaDoc cause)
148     {
149         super (message);
150         m_cause = cause;
151         m_arguments = null;
152     }
153     
154     /**
155      * Constructs an exception with given error message/code and given cause.
156      *
157      * @param message the detail message [can be null]
158      * @param arguments message format parameters [can be null or empty]
159      * @param cause the cause [nested exception] [can be null]
160      *
161      * @see java.text.MessageFormat
162      */

163     public AbstractException (final String JavaDoc message, final Object JavaDoc [] arguments, final Throwable JavaDoc cause)
164     {
165         super (message);
166         m_cause = cause;
167         m_arguments = arguments == null ? null : (Object JavaDoc []) arguments.clone ();
168     }
169     
170
171     /**
172      * Overrides base method to support error code lookup and avoid returning nulls.
173      * Note that this does not recurse into any 'cause' for message lookup, it only
174      * uses the data passed into the constructor. Subclasses cannot override.<P>
175      *
176      * Equivalent to {@link #getLocalizedMessage}.
177      *
178      * @return String error message provided at construction time or the result
179      * of toString() if no/null message was provided [never null].
180      */

181     public final String JavaDoc getMessage ()
182     {
183         if (m_message == null) // not synchronized by design
184
{
185             String JavaDoc msg;
186             final String JavaDoc supermsg = super.getMessage ();
187             final Class JavaDoc _class = getClass ();
188             
189             if (m_arguments == null)
190             {
191                 msg = ExceptionCommon.getMessage (_class, supermsg);
192             }
193             else
194             {
195                 msg = ExceptionCommon.getMessage (_class, supermsg, m_arguments);
196             }
197             
198             if (msg == null)
199             {
200                 // this is the same as what's done in Throwable.toString() [copied here to be independent of future JDK changes]
201
final String JavaDoc className = _class.getName ();
202                 
203                 msg = (supermsg != null) ? (className + ": " + supermsg) : className;
204             }
205             
206             m_message = msg;
207         }
208         
209         return m_message;
210     }
211     
212     /**
213      * Overrides base method for the sole purpose of making it final.<P>
214      *
215      * Equivalent to {@link #getMessage}.
216      */

217     public final String JavaDoc getLocalizedMessage ()
218     {
219         // this is the same as what's done in Throwable
220
// [copied here to be independent of future JDK changes]
221
return getMessage ();
222     }
223
224     /**
225      * Overrides Exception.printStackTrace() to (a) force the output to go
226      * to System.out and (b) handle nested exceptions in JDKs prior to 1.4.<P>
227      *
228      * Subclasses cannot override.
229      */

230     public final void printStackTrace ()
231     {
232         // NOTE: unlike the JDK implementation, force the output to go to System.out:
233
ExceptionCommon.printStackTrace (this, System.out);
234     }
235     
236     /**
237      * Overrides Exception.printStackTrace() to handle nested exceptions in JDKs prior to 1.4.<P>
238      *
239      * Subclasses cannot override.
240      */

241     public final void printStackTrace (final PrintStream JavaDoc s)
242     {
243         ExceptionCommon.printStackTrace (this, s);
244     }
245     
246     /**
247      * Overrides Exception.printStackTrace() to handle nested exceptions in JDKs prior to 1.4.<P>
248      *
249      * Subclasses cannot override.
250      */

251     public final void printStackTrace (final PrintWriter JavaDoc s)
252     {
253         ExceptionCommon.printStackTrace (this, s);
254     }
255
256     // ICodedException:
257

258     /**
259      * Returns the String that was passed as 'message' constructor argument.
260      * Can be null.
261      *
262      * @return message code string [can be null]
263      */

264     public final String JavaDoc getErrorCode ()
265     {
266         return super.getMessage ();
267     }
268
269     // IThrowableWrapper:
270

271     /**
272      * This implements {@link IThrowableWrapper}
273      * and also overrides the base method in JDK 1.4+.
274      */

275     public final Throwable JavaDoc getCause ()
276     {
277         return m_cause;
278     }
279
280     public void __printStackTrace (final PrintStream JavaDoc ps)
281     {
282         super.printStackTrace (ps);
283     }
284     
285     public void __printStackTrace (final PrintWriter JavaDoc pw)
286     {
287         super.printStackTrace (pw);
288     }
289
290     /**
291      * Equivalent to {@link ExceptionCommon#addExceptionResource}, repeated here for
292      * convenience. Subclasses should invoke from static initializers <I>only</I>.
293      * 'namespace' should be YourException.class.
294      */

295     public static void addExceptionResource (final Class JavaDoc namespace,
296                                              final String JavaDoc messageResourceBundleName)
297     {
298         // note: 'namespace' will be the most derived class; it is possible to
299
// auto-detect that in a static method but that requires some security
300
// permissions
301
ExceptionCommon.addExceptionResource (namespace, messageResourceBundleName);
302     }
303     
304     // protected: .............................................................
305

306     // package: ...............................................................
307

308     // private: ...............................................................
309

310
311     /*
312      * Ensures that this instance can be serialized even if some message parameters
313      * are not serializable objects.
314      */

315     private void writeObject (final ObjectOutputStream JavaDoc out)
316         throws IOException JavaDoc
317     {
318         getMessage (); // transform this instance to serializable form
319
out.defaultWriteObject ();
320     }
321
322     
323     private String JavaDoc m_message; // marshalled/cached result of getMessage()
324
private transient final Object JavaDoc [] m_arguments;
325     // note: this field duplicates functionality available in stock Throwable in JRE 1.4+
326
private final Throwable JavaDoc m_cause;
327     
328 } // end of class
329
// ----------------------------------------------------------------------------
330
Popular Tags