001: package simpleorm.core;
002:
003: import java.io.PrintWriter;
004: import java.io.PrintStream;
005:
006: /** Poor man's exception chaining. Used to both convert exceptions to
007: RuntimeExceptions and to throw real exceptions. The print routines
008: are careful to only print the inner (ie most complete) stack trace.<p>
009:
010: SimpleORM takes care to trap most error conditions and throw
011: meaningful exception messages. Unlike most other Java code, they
012: always include information about which objects were being processed at
013: the time, eg. the primary key of the current record. We strongly
014: encourage this practice as it greatly facilitates maintenance and
015: debugging.<p>
016:
017: Subclasses are actually thrown, namely
018: <code>SException.Error</code> to indicate probable bugs in the user's
019: program, <code>SException.InternalError</code> to indicate bugs in
020: SimpleOrm, <code>SException.JDBC</code> for chained JDBC errors,
021: <code>SException.Data</code> for errors that probably the result of
022: run-time data problems. <code>SException.Test</code> is used to
023: indicate failed test cases.<p>
024:
025: Other well defined exceptions that a user may want to trap are given
026: explicit subclasses
027: (eg. <code>SRecordInstance.BrokenOptimisticLockException</code>).<p>
028:
029: SimpleORM only throws SExceptions which extend RuntimeException and so
030: avoid the need to clutter the code with unnecessary try/catch blocks.
031: The only reason to use try/catch when using SimpleORM is because you
032: <i>really</i> want to catch an error.<p>
033:
034: (The author stongly disagrees with the way that Java forces one to
035: declare and catch exceptions because it encourages mediocre
036: programmers to hide exceptions which is a very nasty practice. (Even Sun
037: programmers do this quite regularly in the Java libraries,
038: eg. <code>System.out.println()</code>!) It also clutters
039: the code for no good reason. IMHO Java's "checked" exceptions
040: add no value whatsoever in practice.)<P> */
041:
042: public abstract class SException extends RuntimeException {
043: private Throwable nestedException = null;
044:
045: /** A nested exception. Stack trace will include both
046: <code>message</code> and as well as any message in
047: <code>nestedException</code>.*/
048: public SException(String message, Throwable nestedException) {
049: super ("???" + message);
050: this .nestedException = nestedException;
051: }
052:
053: public SException(String message) {
054: super ("???" + message);
055: this .nestedException = null;
056: }
057:
058: public SException(Throwable nestedException) {
059: super ("??? Nested ");
060: this .nestedException = nestedException;
061: }
062:
063: /** Avoid using this one, include message.*/
064: public SException() {
065: super ("???");
066: }
067:
068: /** Prints all the exception messages and then just prints the inner
069: stack trace which is usually the relevant one. These are
070: normmaly only called by the System for uncaught errors.*/
071: public void printStackTrace(PrintWriter printer) {
072: printer.println("SException " + toString());
073: if (nestedException == null)
074: super .printStackTrace(printer);
075: else
076: nestedException.printStackTrace(printer);
077: }
078:
079: public void printStackTrace(PrintStream printer) {
080: if (printer == System.err)
081: printer = System.out; // Stops intermingling of output.
082: printer.println("SException " + toString());
083: if (nestedException == null)
084: super .printStackTrace(printer);
085: else
086: nestedException.printStackTrace(printer);
087: }
088:
089: public void printStackTrace() {
090: printStackTrace(System.err);
091: }
092:
093: /** Contains both the message and the nestedException message. */
094: public String toString() {
095: return super .toString()
096: + (nestedException != null ? ": " + nestedException
097: : "");
098: }
099:
100: /** Probable bug in user's program.*/
101: public static class Error extends SException {
102: public Error(String message, Throwable nestedException) {
103: super (message, nestedException);
104: }
105:
106: public Error(String message) {
107: super (message);
108: }
109:
110: public Error(Throwable nestedException) {
111: super (nestedException);
112: }
113:
114: public Error() {
115: super ();
116: }
117: }
118:
119: /** Probable bug in SimpleORM.*/
120: public static class InternalError extends SException {
121: public InternalError(String message, Throwable nestedException) {
122: super (message, nestedException);
123: }
124:
125: public InternalError(String message) {
126: super (message);
127: }
128:
129: public InternalError(Throwable nestedException) {
130: super (nestedException);
131: }
132:
133: public InternalError() {
134: super ();
135: }
136: }
137:
138: /** Chained JDBC Exception, could be anything as JDBC does not
139: separate exceptions out and provides minimal information about
140: their underlying causes.*/
141: public static class JDBC extends SException {
142: public JDBC(String message, Throwable nestedException) {
143: super (message, nestedException);
144: }
145:
146: public JDBC(String message) {
147: super (message);
148: }
149:
150: public JDBC(Throwable nestedException) {
151: super (nestedException);
152: }
153:
154: public JDBC() {
155: super ();
156: }
157: }
158:
159: /** Errors in data or environment at runtime, not necessarily a
160: programming bug. */
161: public static class Data extends SException {
162: public Data(String message, Throwable nestedException) {
163: super (message, nestedException);
164: }
165:
166: public Data(String message) {
167: super (message);
168: }
169:
170: public Data(Throwable nestedException) {
171: super (nestedException);
172: }
173:
174: public Data() {
175: super ();
176: }
177: }
178:
179: /** Exception thrown due to failed unit test cases.*/
180: public static class Test extends SException {
181: public Test(String message, Throwable nestedException) {
182: super (message, nestedException);
183: }
184:
185: public Test(String message) {
186: super (message);
187: }
188:
189: public Test(Throwable nestedException) {
190: super (nestedException);
191: }
192:
193: public Test() {
194: super();
195: }
196: }
197: }
|