001: /*
002:
003: Derby - Class org.apache.derby.impl.jdbc.SQLExceptionFactory40
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.jdbc;
023:
024: import java.sql.SQLDataException;
025: import java.sql.SQLException;
026: import java.sql.SQLIntegrityConstraintViolationException;
027: import java.sql.SQLInvalidAuthorizationSpecException;
028: import java.sql.SQLSyntaxErrorException;
029: import java.sql.SQLTransactionRollbackException;
030: import java.sql.SQLTransientConnectionException;
031: import java.sql.SQLFeatureNotSupportedException;
032: import org.apache.derby.iapi.error.StandardException;
033: import org.apache.derby.shared.common.reference.SQLState;
034:
035: /**
036: * SQLExceptionFactory40 overwrites getSQLException method
037: * to return SQLException or one of its sub class
038: */
039:
040: public class SQLExceptionFactory40 extends SQLExceptionFactory {
041:
042: /**
043: * overwrites super class method to create JDBC4 exceptions
044: * SQLSTATE CLASS (prefix) Exception
045: * 0A java.sql.SQLFeatureNotSupportedException
046: * 08 java.sql.SQLTransientConnectionException
047: * 22 java.sql.SQLDataException
048: * 28 java.sql.SQLInvalidAuthorizationSpecException
049: * 40 java.sql.SQLTransactionRollbackException
050: * 42 java.sql.SQLSyntaxErrorException
051: *
052: * Note the following divergence from JDBC3 behavior: When running
053: * a JDBC3 client, we return EmbedSQLException. That exception class
054: * overrides Throwable.toString() and strips off the Throwable's class name.
055: * In contrast, the following JDBC4 implementation returns
056: * subclasses of java.sql.Exception. These subclasses inherit the behavior
057: * of Throwable.toString(). That is, their toString() output includes
058: * their class name. This will break code which relies on the
059: * stripping behavior of EmbedSQLSxception.toString().
060: */
061:
062: public SQLException getSQLException(String message,
063: String messageId, SQLException next, int severity,
064: Throwable t, Object[] args) {
065: String sqlState = StandardException
066: .getSQLStateFromIdentifier(messageId);
067:
068: //
069: // Create dummy exception which ferries arguments needed to serialize
070: // SQLExceptions across the DRDA network layer.
071: //
072: t = wrapArgsForTransportAcrossDRDA(message, messageId, next,
073: severity, t, args);
074:
075: final SQLException ex;
076: if (sqlState.startsWith(SQLState.CONNECTIVITY_PREFIX)) {
077: //none of the sqlstate supported by derby belongs to
078: //NonTransientConnectionException
079: ex = new SQLTransientConnectionException(message, sqlState,
080: severity, t);
081: } else if (sqlState.startsWith(SQLState.SQL_DATA_PREFIX)) {
082: ex = new SQLDataException(message, sqlState, severity, t);
083: } else if (sqlState
084: .startsWith(SQLState.INTEGRITY_VIOLATION_PREFIX)) {
085: ex = new SQLIntegrityConstraintViolationException(message,
086: sqlState, severity, t);
087: } else if (sqlState.startsWith(SQLState.AUTHORIZATION_PREFIX)) {
088: ex = new SQLInvalidAuthorizationSpecException(message,
089: sqlState, severity, t);
090: } else if (sqlState.startsWith(SQLState.TRANSACTION_PREFIX)) {
091: ex = new SQLTransactionRollbackException(message, sqlState,
092: severity, t);
093: } else if (sqlState.startsWith(SQLState.LSE_COMPILATION_PREFIX)) {
094: ex = new SQLSyntaxErrorException(message, sqlState,
095: severity, t);
096: } else if (sqlState.startsWith(SQLState.UNSUPPORTED_PREFIX)) {
097: ex = new SQLFeatureNotSupportedException(message, sqlState,
098: severity, t);
099: } else {
100: ex = new SQLException(message, sqlState, severity, t);
101: }
102:
103: if (next != null) {
104: ex.setNextException(next);
105: }
106: return ex;
107: }
108:
109: /**
110: * Unpack the exception, looking for an EmbedSQLException which carries
111: * the Derby messageID and args which we will serialize across DRDA so
112: * that the client can reconstitute a SQLException with appropriate text.
113: * If we are running JDBC4, then the
114: * passed-in exception will hopefully wrap an informative EmbedSQLException.
115: * See wrapArgsForTransportAcrossDRDA() below.
116: */
117: public SQLException getArgumentFerry(SQLException se) {
118: Throwable cause = se.getCause();
119:
120: if ((cause == null) || !(cause instanceof EmbedSQLException)) {
121: return se;
122: } else {
123: return (SQLException) cause;
124: }
125: }
126:
127: /**
128: * <p>
129: * The following method helps handle DERBY-1178. The problem is that we may
130: * need to serialize our final SQLException across the DRDA network layer.
131: * That serialization involves some clever encoding of the Derby messageID and
132: * arguments. Unfortunately, once we create one of the
133: * JDBC4-specific subclasses of SQLException, we lose the messageID and
134: * args. This method creates a dummy EmbedSQLException which preserves that
135: * information. We return the dummy exception.
136: * </p>
137: */
138: private SQLException wrapArgsForTransportAcrossDRDA(String message,
139: String messageId, SQLException next, int severity,
140: Throwable t, Object[] args) {
141: return super.getSQLException(message, messageId, next,
142: severity, t, args);
143: }
144:
145: }
|