/* |
|
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package java.sql; |
|
import java.util.Iterator; |
|
import java.util.NoSuchElementException; |
|
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; |
|
/** |
|
* <P>An exception that provides information on a database access |
|
* error or other errors. |
|
* |
|
* <P>Each {@code SQLException} provides several kinds of information: |
|
* <UL> |
|
* <LI> a string describing the error. This is used as the Java Exception |
|
* message, available via the method {@code getMessage}. |
|
* <LI> a "SQLstate" string, which follows either the XOPEN SQLstate conventions |
|
* or the SQL:2003 conventions. |
|
* The values of the SQLState string are described in the appropriate spec. |
|
* The {@code DatabaseMetaData} method {@code getSQLStateType} |
|
* can be used to discover whether the driver returns the XOPEN type or |
|
* the SQL:2003 type. |
|
* <LI> an integer error code that is specific to each vendor. Normally this will |
|
* be the actual error code returned by the underlying database. |
|
* <LI> a chain to a next Exception. This can be used to provide additional |
|
* error information. |
|
* <LI> the causal relationship, if any for this {@code SQLException}. |
|
* </UL> |
|
* |
|
* @since 1.1 |
|
*/ |
|
public class SQLException extends java.lang.Exception |
|
implements Iterable<Throwable> { |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason}, {@code SQLState} and |
|
* {@code vendorCode}. |
|
* |
|
* The {@code cause} is not initialized, and may subsequently be |
|
* initialized by a call to the |
|
* {@link Throwable#initCause(java.lang.Throwable)} method. |
|
* |
|
* @param reason a description of the exception |
|
* @param SQLState an XOPEN or SQL:2003 code identifying the exception |
|
* @param vendorCode a database vendor-specific exception code |
|
*/ |
|
public SQLException(String reason, String SQLState, int vendorCode) { |
|
super(reason); |
|
this.SQLState = SQLState; |
|
this.vendorCode = vendorCode; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
DriverManager.println("SQLState(" + SQLState + |
|
") vendor code(" + vendorCode + ")"); |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason} and {@code SQLState}. |
|
* |
|
* The {@code cause} is not initialized, and may subsequently be |
|
* initialized by a call to the |
|
* {@link Throwable#initCause(java.lang.Throwable)} method. The vendor code |
|
* is initialized to 0. |
|
* |
|
* @param reason a description of the exception |
|
* @param SQLState an XOPEN or SQL:2003 code identifying the exception |
|
*/ |
|
public SQLException(String reason, String SQLState) { |
|
super(reason); |
|
this.SQLState = SQLState; |
|
this.vendorCode = 0; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
DriverManager.println("SQLException: SQLState(" + SQLState + ")"); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason}. The {@code SQLState} is initialized to |
|
* {@code null} and the vendor code is initialized to 0. |
|
* |
|
* The {@code cause} is not initialized, and may subsequently be |
|
* initialized by a call to the |
|
* {@link Throwable#initCause(java.lang.Throwable)} method. |
|
* |
|
* @param reason a description of the exception |
|
*/ |
|
public SQLException(String reason) { |
|
super(reason); |
|
this.SQLState = null; |
|
this.vendorCode = 0; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object. |
|
* The {@code reason}, {@code SQLState} are initialized |
|
* to {@code null} and the vendor code is initialized to 0. |
|
* |
|
* The {@code cause} is not initialized, and may subsequently be |
|
* initialized by a call to the |
|
* {@link Throwable#initCause(java.lang.Throwable)} method. |
|
* |
|
*/ |
|
public SQLException() { |
|
super(); |
|
this.SQLState = null; |
|
this.vendorCode = 0; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code cause}. |
|
* The {@code SQLState} is initialized |
|
* to {@code null} and the vendor code is initialized to 0. |
|
* The {@code reason} is initialized to {@code null} if |
|
* {@code cause==null} or to {@code cause.toString()} if |
|
* {@code cause!=null}. |
|
* |
|
* @param cause the underlying reason for this {@code SQLException} |
|
* (which is saved for later retrieval by the {@code getCause()} method); |
|
* may be null indicating the cause is non-existent or unknown. |
|
* @since 1.6 |
|
*/ |
|
public SQLException(Throwable cause) { |
|
super(cause); |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason} and {@code cause}. |
|
* The {@code SQLState} is initialized to {@code null} |
|
* and the vendor code is initialized to 0. |
|
* |
|
* @param reason a description of the exception. |
|
* @param cause the underlying reason for this {@code SQLException} |
|
* (which is saved for later retrieval by the {@code getCause()} method); |
|
* may be null indicating the cause is non-existent or unknown. |
|
* @since 1.6 |
|
*/ |
|
public SQLException(String reason, Throwable cause) { |
|
super(reason,cause); |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason}, {@code SQLState} and {@code cause}. |
|
* The vendor code is initialized to 0. |
|
* |
|
* @param reason a description of the exception. |
|
* @param sqlState an XOPEN or SQL:2003 code identifying the exception |
|
* @param cause the underlying reason for this {@code SQLException} |
|
* (which is saved for later retrieval by the |
|
* {@code getCause()} method); may be null indicating |
|
* the cause is non-existent or unknown. |
|
* @since 1.6 |
|
*/ |
|
public SQLException(String reason, String sqlState, Throwable cause) { |
|
super(reason,cause); |
|
this.SQLState = sqlState; |
|
this.vendorCode = 0; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
printStackTrace(DriverManager.getLogWriter()); |
|
DriverManager.println("SQLState(" + SQLState + ")"); |
|
} |
|
} |
|
} |
|
/** |
|
* Constructs a {@code SQLException} object with a given |
|
* {@code reason}, {@code SQLState}, {@code vendorCode} |
|
* and {@code cause}. |
|
* |
|
* @param reason a description of the exception |
|
* @param sqlState an XOPEN or SQL:2003 code identifying the exception |
|
* @param vendorCode a database vendor-specific exception code |
|
* @param cause the underlying reason for this {@code SQLException} |
|
* (which is saved for later retrieval by the {@code getCause()} method); |
|
* may be null indicating the cause is non-existent or unknown. |
|
* @since 1.6 |
|
*/ |
|
public SQLException(String reason, String sqlState, int vendorCode, Throwable cause) { |
|
super(reason,cause); |
|
this.SQLState = sqlState; |
|
this.vendorCode = vendorCode; |
|
if (!(this instanceof SQLWarning)) { |
|
if (DriverManager.getLogWriter() != null) { |
|
DriverManager.println("SQLState(" + SQLState + |
|
") vendor code(" + vendorCode + ")"); |
|
printStackTrace(DriverManager.getLogWriter()); |
|
} |
|
} |
|
} |
|
/** |
|
* Retrieves the SQLState for this {@code SQLException} object. |
|
* |
|
* @return the SQLState value |
|
*/ |
|
public String getSQLState() { |
|
return (SQLState); |
|
} |
|
/** |
|
* Retrieves the vendor-specific exception code |
|
* for this {@code SQLException} object. |
|
* |
|
* @return the vendor's error code |
|
*/ |
|
public int getErrorCode() { |
|
return (vendorCode); |
|
} |
|
/** |
|
* Retrieves the exception chained to this |
|
* {@code SQLException} object by setNextException(SQLException ex). |
|
* |
|
* @return the next {@code SQLException} object in the chain; |
|
* {@code null} if there are none |
|
* @see #setNextException |
|
*/ |
|
public SQLException getNextException() { |
|
return (next); |
|
} |
|
/** |
|
* Adds an {@code SQLException} object to the end of the chain. |
|
* |
|
* @param ex the new exception that will be added to the end of |
|
* the {@code SQLException} chain |
|
* @see #getNextException |
|
*/ |
|
public void setNextException(SQLException ex) { |
|
SQLException current = this; |
|
for(;;) { |
|
SQLException next=current.next; |
|
if (next != null) { |
|
current = next; |
|
continue; |
|
} |
|
if (nextUpdater.compareAndSet(current,null,ex)) { |
|
return; |
|
} |
|
current=current.next; |
|
} |
|
} |
|
/** |
|
* Returns an iterator over the chained SQLExceptions. The iterator will |
|
* be used to iterate over each SQLException and its underlying cause |
|
* (if any). |
|
* |
|
* @return an iterator over the chained SQLExceptions and causes in the proper |
|
* order |
|
* |
|
* @since 1.6 |
|
*/ |
|
public Iterator<Throwable> iterator() { |
|
return new Iterator<Throwable>() { |
|
SQLException firstException = SQLException.this; |
|
SQLException nextException = firstException.getNextException(); |
|
Throwable cause = firstException.getCause(); |
|
public boolean hasNext() { |
|
if(firstException != null || nextException != null || cause != null) |
|
return true; |
|
return false; |
|
} |
|
public Throwable next() { |
|
Throwable throwable = null; |
|
if(firstException != null){ |
|
throwable = firstException; |
|
firstException = null; |
|
} |
|
else if(cause != null){ |
|
throwable = cause; |
|
cause = cause.getCause(); |
|
} |
|
else if(nextException != null){ |
|
throwable = nextException; |
|
cause = nextException.getCause(); |
|
nextException = nextException.getNextException(); |
|
} |
|
else |
|
throw new NoSuchElementException(); |
|
return throwable; |
|
} |
|
public void remove() { |
|
throw new UnsupportedOperationException(); |
|
} |
|
}; |
|
} |
|
/** |
|
* @serial |
|
*/ |
|
private String SQLState; |
|
/** |
|
* @serial |
|
*/ |
|
private int vendorCode; |
|
/** |
|
* @serial |
|
*/ |
|
private volatile SQLException next; |
|
private static final AtomicReferenceFieldUpdater<SQLException,SQLException> nextUpdater = |
|
AtomicReferenceFieldUpdater.newUpdater(SQLException.class,SQLException.class,"next"); |
|
private static final long serialVersionUID = 2135244094396331484L; |
|
} |