001 /*
002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.sql;
027
028 import java.util.Iterator;
029 import java.util.NoSuchElementException;
030 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
031
032 /**
033 * <P>An exception that provides information on a database access
034 * error or other errors.
035 *
036 * <P>Each <code>SQLException</code> provides several kinds of information:
037 * <UL>
038 * <LI> a string describing the error. This is used as the Java Exception
039 * message, available via the method <code>getMesasge</code>.
040 * <LI> a "SQLstate" string, which follows either the XOPEN SQLstate conventions
041 * or the SQL:2003 conventions.
042 * The values of the SQLState string are described in the appropriate spec.
043 * The <code>DatabaseMetaData</code> method <code>getSQLStateType</code>
044 * can be used to discover whether the driver returns the XOPEN type or
045 * the SQL:2003 type.
046 * <LI> an integer error code that is specific to each vendor. Normally this will
047 * be the actual error code returned by the underlying database.
048 * <LI> a chain to a next Exception. This can be used to provide additional
049 * error information.
050 * <LI> the causal relationship, if any for this <code>SQLException</code>.
051 * </UL>
052 */
053 public class SQLException extends java.lang.Exception implements
054 Iterable<Throwable> {
055
056 /**
057 * Constructs a <code>SQLException</code> object with a given
058 * <code>reason</code>, <code>SQLState</code> and
059 * <code>vendorCode</code>.
060 *
061 * The <code>cause</code> is not initialized, and may subsequently be
062 * initialized by a call to the
063 * {@link Throwable#initCause(java.lang.Throwable)} method.
064 * <p>
065 * @param reason a description of the exception
066 * @param SQLState an XOPEN or SQL:2003 code identifying the exception
067 * @param vendorCode a database vendor-specific exception code
068 */
069 public SQLException(String reason, String SQLState, int vendorCode) {
070 super (reason);
071 this .SQLState = SQLState;
072 this .vendorCode = vendorCode;
073 if (!(this instanceof SQLWarning)) {
074 if (DriverManager.getLogWriter() != null) {
075 DriverManager.println("SQLState(" + SQLState
076 + ") vendor code(" + vendorCode + ")");
077 printStackTrace(DriverManager.getLogWriter());
078 }
079 }
080 }
081
082 /**
083 * Constructs a <code>SQLException</code> object with a given
084 * <code>reason</code> and <code>SQLState</code>.
085 *
086 * The <code>cause</code> is not initialized, and may subsequently be
087 * initialized by a call to the
088 * {@link Throwable#initCause(java.lang.Throwable)} method. The vendor code
089 * is initialized to 0.
090 * <p>
091 * @param reason a description of the exception
092 * @param SQLState an XOPEN or SQL:2003 code identifying the exception
093 */
094 public SQLException(String reason, String SQLState) {
095 super (reason);
096 this .SQLState = SQLState;
097 this .vendorCode = 0;
098 if (!(this instanceof SQLWarning)) {
099 if (DriverManager.getLogWriter() != null) {
100 printStackTrace(DriverManager.getLogWriter());
101 DriverManager.println("SQLException: SQLState("
102 + SQLState + ")");
103 }
104 }
105 }
106
107 /**
108 * Constructs a <code>SQLException</code> object with a given
109 * <code>reason</code>. The <code>SQLState</code> is initialized to
110 * <code>null</code> and the vender code is initialized to 0.
111 *
112 * The <code>cause</code> is not initialized, and may subsequently be
113 * initialized by a call to the
114 * {@link Throwable#initCause(java.lang.Throwable)} method.
115 * <p>
116 * @param reason a description of the exception
117 */
118 public SQLException(String reason) {
119 super (reason);
120 this .SQLState = null;
121 this .vendorCode = 0;
122 if (!(this instanceof SQLWarning)) {
123 if (DriverManager.getLogWriter() != null) {
124 printStackTrace(DriverManager.getLogWriter());
125 }
126 }
127 }
128
129 /**
130 * Constructs a <code>SQLException</code> object.
131 * The <code>reason</code>, <code>SQLState</code> are initialized
132 * to <code>null</code> and the vendor code is initialized to 0.
133 *
134 * The <code>cause</code> is not initialized, and may subsequently be
135 * initialized by a call to the
136 * {@link Throwable#initCause(java.lang.Throwable)} method.
137 * <p>
138 */
139 public SQLException() {
140 super ();
141 this .SQLState = null;
142 this .vendorCode = 0;
143 if (!(this instanceof SQLWarning)) {
144 if (DriverManager.getLogWriter() != null) {
145 printStackTrace(DriverManager.getLogWriter());
146 }
147 }
148 }
149
150 /**
151 * Constructs a <code>SQLException</code> object with a given
152 * <code>cause</code>.
153 * The <code>SQLState</code> is initialized
154 * to <code>null</code> and the vendor code is initialized to 0.
155 * The <code>reason</code> is initialized to <code>null</code> if
156 * <code>cause==null</code> or to <code>cause.toString()</code> if
157 * <code>cause!=null</code>.
158 * <p>
159 * @param cause the underlying reason for this <code>SQLException</code>
160 * (which is saved for later retrieval by the <code>getCause()</code> method);
161 * may be null indicating the cause is non-existent or unknown.
162 * @since 1.6
163 */
164 public SQLException(Throwable cause) {
165 super (cause);
166
167 if (!(this instanceof SQLWarning)) {
168 if (DriverManager.getLogWriter() != null) {
169 printStackTrace(DriverManager.getLogWriter());
170 }
171 }
172 }
173
174 /**
175 * Constructs a <code>SQLException</code> object with a given
176 * <code>reason</code> and <code>cause</code>.
177 * The <code>SQLState</code> is initialized to <code>null</code>
178 * and the vendor code is initialized to 0.
179 * <p>
180 * @param reason a description of the exception.
181 * @param cause the underlying reason for this <code>SQLException</code>
182 * (which is saved for later retrieval by the <code>getCause()</code> method);
183 * may be null indicating the cause is non-existent or unknown.
184 * @since 1.6
185 */
186 public SQLException(String reason, Throwable cause) {
187 super (reason, cause);
188
189 if (!(this instanceof SQLWarning)) {
190 if (DriverManager.getLogWriter() != null) {
191 printStackTrace(DriverManager.getLogWriter());
192 }
193 }
194 }
195
196 /**
197 * Constructs a <code>SQLException</code> object with a given
198 * <code>reason</code>, <code>SQLState</code> and <code>cause</code>.
199 * The vendor code is initialized to 0.
200 * <p>
201 * @param reason a description of the exception.
202 * @param sqlState an XOPEN or SQL:2003 code identifying the exception
203 * @param cause the underlying reason for this <code>SQLException</code>
204 * (which is saved for later retrieval by the
205 * <code>getCause()</code> method); may be null indicating
206 * the cause is non-existent or unknown.
207 * @since 1.6
208 */
209 public SQLException(String reason, String sqlState, Throwable cause) {
210 super (reason, cause);
211
212 this .SQLState = sqlState;
213 this .vendorCode = 0;
214 if (!(this instanceof SQLWarning)) {
215 if (DriverManager.getLogWriter() != null) {
216 printStackTrace(DriverManager.getLogWriter());
217 DriverManager.println("SQLState(" + SQLState + ")");
218 }
219 }
220 }
221
222 /**
223 * Constructs a <code>SQLException</code> object with a given
224 * <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code>
225 * and <code>cause</code>.
226 * <p>
227 * @param reason a description of the exception
228 * @param sqlState an XOPEN or SQL:2003 code identifying the exception
229 * @param vendorCode a database vendor-specific exception code
230 * @param cause the underlying reason for this <code>SQLException</code>
231 * (which is saved for later retrieval by the <code>getCause()</code> method);
232 * may be null indicating the cause is non-existent or unknown.
233 * @since 1.6
234 */
235 public SQLException(String reason, String sqlState, int vendorCode,
236 Throwable cause) {
237 super (reason, cause);
238
239 this .SQLState = sqlState;
240 this .vendorCode = vendorCode;
241 if (!(this instanceof SQLWarning)) {
242 if (DriverManager.getLogWriter() != null) {
243 DriverManager.println("SQLState(" + SQLState
244 + ") vendor code(" + vendorCode + ")");
245 printStackTrace(DriverManager.getLogWriter());
246 }
247 }
248 }
249
250 /**
251 * Retrieves the SQLState for this <code>SQLException</code> object.
252 *
253 * @return the SQLState value
254 */
255 public String getSQLState() {
256 return (SQLState);
257 }
258
259 /**
260 * Retrieves the vendor-specific exception code
261 * for this <code>SQLException</code> object.
262 *
263 * @return the vendor's error code
264 */
265 public int getErrorCode() {
266 return (vendorCode);
267 }
268
269 /**
270 * Retrieves the exception chained to this
271 * <code>SQLException</code> object by setNextException(SQLException ex).
272 *
273 * @return the next <code>SQLException</code> object in the chain;
274 * <code>null</code> if there are none
275 * @see #setNextException
276 */
277 public SQLException getNextException() {
278 return (next);
279 }
280
281 /**
282 * Adds an <code>SQLException</code> object to the end of the chain.
283 *
284 * @param ex the new exception that will be added to the end of
285 * the <code>SQLException</code> chain
286 * @see #getNextException
287 */
288 public void setNextException(SQLException ex) {
289
290 SQLException current = this ;
291 for (;;) {
292 SQLException next = current.next;
293 if (next != null) {
294 current = next;
295 continue;
296 }
297
298 if (nextUpdater.compareAndSet(current, null, ex)) {
299 return;
300 }
301 current = current.next;
302 }
303 }
304
305 /**
306 * Returns an iterator over the chained SQLExceptions. The iterator will
307 * be used to iterate over each SQLException and its underlying cause
308 * (if any).
309 *
310 * @return an iterator over the chained SQLExceptions and causes in the proper
311 * order
312 *
313 * @since 1.6
314 */
315 public Iterator<Throwable> iterator() {
316
317 return new Iterator<Throwable>() {
318
319 SQLException firstException = SQLException.this ;
320 SQLException nextException = firstException
321 .getNextException();
322 Throwable cause = firstException.getCause();
323
324 public boolean hasNext() {
325 if (firstException != null || nextException != null
326 || cause != null)
327 return true;
328 return false;
329 }
330
331 public Throwable next() {
332 Throwable throwable = null;
333 if (firstException != null) {
334 throwable = firstException;
335 firstException = null;
336 } else if (cause != null) {
337 throwable = cause;
338 cause = cause.getCause();
339 } else if (nextException != null) {
340 throwable = nextException;
341 cause = nextException.getCause();
342 nextException = nextException.getNextException();
343 } else
344 throw new NoSuchElementException();
345 return throwable;
346 }
347
348 public void remove() {
349 throw new UnsupportedOperationException();
350 }
351
352 };
353
354 }
355
356 /**
357 * @serial
358 */
359 private String SQLState;
360
361 /**
362 * @serial
363 */
364 private int vendorCode;
365
366 /**
367 * @serial
368 */
369 private volatile SQLException next;
370
371 private static final AtomicReferenceFieldUpdater<SQLException, SQLException> nextUpdater = AtomicReferenceFieldUpdater
372 .newUpdater(SQLException.class, SQLException.class, "next");
373
374 private static final long serialVersionUID = 2135244094396331484L;
375 }
|