001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2005 Emic Networks
004: * Contact: sequoia@continuent.org
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: * Initial developer(s): Marc Herbert
019: * Contributor(s): ______________________.
020: */package org.continuent.sequoia.common.exceptions.driver;
021:
022: import java.io.PrintStream;
023: import java.io.PrintWriter;
024: import java.sql.SQLException;
025:
026: import org.continuent.sequoia.common.exceptions.driver.protocol.SerializableException;
027:
028: /**
029: * This class customizes SQLException. Since JDBC allows only SQLExceptions, it
030: * is used to systematically wrap underlying exceptions (typically coming from
031: * the controller). The main feature added to SQLException is to override
032: * printStackTrace() methods so they also print the non-standard, serializable
033: * stack traces of SerializableException coming from the controller. Another
034: * feature is to provide constructors with a "cause" (chaining), avoiding the
035: * use of initCause()
036: */
037: /**
038: * FIXME: this class relies on "multiple dispatch", which does not exist in Java
039: * (doh!). The current workaround it to cast properly at each call site. The
040: * definitive fix is to use instanceof.
041: */
042: public class DriverSQLException extends SQLException {
043: private static final long serialVersionUID = 5414032528107747411L;
044:
045: /**
046: * @see SQLException#SQLException()
047: */
048: public DriverSQLException() {
049: super ();
050: }
051:
052: /**
053: * @see SQLException#SQLException(java.lang.String)
054: */
055: public DriverSQLException(String reason) {
056: super (reason);
057: }
058:
059: /**
060: * @see SQLException#SQLException(java.lang.String, java.lang.String)
061: */
062: public DriverSQLException(String reason, String sQLState) {
063: super (reason, sQLState);
064: }
065:
066: /**
067: * @see SQLException#SQLException(java.lang.String, java.lang.String, int)
068: */
069: public DriverSQLException(String reason, String sQLState,
070: int vendorCode) {
071: super (reason, sQLState, vendorCode);
072: }
073:
074: /**
075: * Creates a new <code>DriverSQLException</code> around a
076: * SerializableException received from controller, itself converted from an
077: * SQLException in most cases. So we set SQLState and vendorCode.
078: *
079: * @param message message
080: * @param cause exception from controller to wrap
081: */
082: public DriverSQLException(String message,
083: SerializableException cause) {
084: super (message, cause.getSQLState(), cause.getErrorCode());
085: initCause(cause);
086: }
087:
088: /**
089: * Missing message constructor: let's borrow message from cause.
090: *
091: * @param cause exception to wrap
092: */
093: public DriverSQLException(SerializableException cause) {
094: this ("Message of cause: " + cause.getLocalizedMessage(), cause);
095: }
096:
097: /**
098: * Missing message constructor: let's borrow message from cause.
099: *
100: * @param cause exception to wrap
101: */
102: public DriverSQLException(Exception cause) {
103: /**
104: * @see #DriverSQLException(String, SerializableException)
105: * @see #DriverSQLException(String, Exception)
106: */
107: this ("Message of cause: " + cause.getLocalizedMessage(), cause);
108: }
109:
110: /**
111: * Creates a new <code>DriverSQLException</code> around an exception of a
112: * type not specifically handled elsewhere. Typically used for exceptions
113: * internal to the driver.
114: *
115: * @param message message
116: * @param cause generic exception to wrap
117: */
118: public DriverSQLException(String message, Exception cause) {
119: super (message);
120: initCause(cause);
121: }
122:
123: /**
124: * @see #DriverSQLException(String, SQLException)
125: * @deprecated
126: */
127: public DriverSQLException(SQLException cause) {
128: this ("", cause);
129: }
130:
131: /**
132: * An SQLException should not be wrapped inside a DriverSQLException: this is
133: * a symptom of mixing different layers.
134: *
135: * @param message message
136: * @param cause cause
137: * @deprecated
138: * @throws IllegalArgumentException always
139: */
140: public DriverSQLException(String message, SQLException cause)
141: throws IllegalArgumentException {
142: // ok let's be tolerant for the moment
143: super (message);
144: initCause(cause);
145:
146: // TODO: ... but this is the future:
147: // A (Driver-)SQLException should be created here and nowhere below
148:
149: // IllegalArgumentException iae = new IllegalArgumentException(
150: // "Bug: cause of a DriverSQLException should not itself be an SQLException
151: // "
152: // + message);
153: // iae.initCause(cause);
154: // throw iae;
155: }
156:
157: /**
158: * Overrides super method so we print the serializable stack trace of next
159: * exceptions in the chain (if they use our serializable stack trace)
160: *
161: * @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
162: */
163: public void printStackTrace(PrintStream s) {
164: /*
165: * super does unfortunately not call printStackTrace() recursively on the
166: * chain: instead it breaks object encapsulation by calling instead printing
167: * methods and private fields on nexts. And since our chain uses its own
168: * private stack trace implementation (because of JDK 1.4 woes) this does
169: * print nothing in the end.
170: */
171: super .printStackTrace(s);
172:
173: // So we have to call printStackStrace() ourselves.
174: Throwable cause = getCause();
175: if (null != cause && cause instanceof SerializableException) {
176: s.println("SerializableStackTrace of each cause:");
177: ((SerializableException) cause).printStackTrace(s);
178: }
179: }
180:
181: /**
182: * Overrides super method so we print the serializable stack trace of next
183: * exceptions in the chain (if they use our serializable stack trace)
184: *
185: * @see java.lang.Throwable#printStackTrace()
186: */
187: public void printStackTrace() {
188: /**
189: * This comes back to
190: *
191: * @see DriverSQLException#printStackTrace(PrintStream)
192: */
193: super .printStackTrace();
194:
195: }
196:
197: /**
198: * Overrides super method so we print the serializable stack trace of next
199: * exceptions in the chain (if they use our serializable stack trace)
200: *
201: * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter)
202: */
203: public void printStackTrace(PrintWriter s) {
204: /** @see #printStackTrace(PrintStream) */
205: super .printStackTrace(s);
206:
207: Throwable cause = getCause();
208: if (null != cause && cause instanceof SerializableException) {
209: s.println("SerializableStackTrace of each cause:");
210: ((SerializableException) cause).printStackTrace(s);
211: }
212: }
213:
214: }
|