/* * Copyright 2006-2012 Amazon Technologies, Inc. or its affiliates. * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks * of Amazon Technologies, Inc. or its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.amazon.carbonado.repo.jdbc; import java.sql.SQLException; import com.amazon.carbonado.ConstraintException; import com.amazon.carbonado.FetchDeadlockException; import com.amazon.carbonado.FetchException; import com.amazon.carbonado.FetchTimeoutException; import com.amazon.carbonado.PersistDeadlockException; import com.amazon.carbonado.PersistDeniedException; import com.amazon.carbonado.PersistException; import com.amazon.carbonado.PersistTimeoutException; import com.amazon.carbonado.UniqueConstraintException; import com.amazon.carbonado.spi.ExceptionTransformer; /** * Custom exception transform rules. * * @author Brian S O'Neill */ class JDBCExceptionTransformer extends ExceptionTransformer { // Getting actual SQLSTATE codes is quite difficult, unless you shell out // cash for the proper manuals. SQLSTATE codes are five characters long, // where the first two indicate error class. Although the following links // are for DB2 SQLSTATE codes, the codes are fairly standard across all // major database implementations. // // ftp://ftp.software.ibm.com/ps/products/db2/info/vr6/htm/db2m0/db2state.htm // http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/core/r0sttmsg.htm /** Two digit SQLSTATE class prefix for all constraint violations */ public static String SQLSTATE_CONSTRAINT_VIOLATION_CLASS_CODE = "23"; /** * Five digit SQLSTATE code for "A violation of the constraint imposed by a * unique index or a unique constraint occurred" */ public static String SQLSTATE_UNIQUE_CONSTRAINT_VIOLATION = "23505"; /** * Five digit SQLSTATE code for "Deadlock or timeout with automatic * rollback occurred" */ public static String SQLSTATE_DEADLOCK_WITH_ROLLBACK = "40001"; public static String SQLSTATE_PROCESSING_CANCELED = "57014"; /** * Examines the SQLSTATE code of the given SQL exception and determines if * it is a generic constaint violation. */ public boolean isConstraintError(SQLException e) { if (e != null) { String sqlstate = e.getSQLState(); if (sqlstate != null) { return sqlstate.startsWith(SQLSTATE_CONSTRAINT_VIOLATION_CLASS_CODE); } } return false; } /** * Examines the SQLSTATE code of the given SQL exception and determines if * it is a unique constaint violation. */ public boolean isUniqueConstraintError(SQLException e) { if (isConstraintError(e)) { String sqlstate = e.getSQLState(); return SQLSTATE_UNIQUE_CONSTRAINT_VIOLATION.equals(sqlstate); } return false; } /** * Examines the SQLSTATE code of the given SQL exception and determines if * it indicates insufficient privileges. */ public boolean isInsufficientPrivilegesError(SQLException e) { return false; } public boolean isDeadlockError(SQLException e) { if (e != null) { String sqlstate = e.getSQLState(); if (sqlstate != null) { return sqlstate.startsWith(SQLSTATE_DEADLOCK_WITH_ROLLBACK); } } return false; } public boolean isTimeoutError(SQLException e) { if (e != null) { String sqlstate = e.getSQLState(); if (sqlstate != null) { return SQLSTATE_PROCESSING_CANCELED.equals(sqlstate); } } return false; } JDBCExceptionTransformer() { } @Override protected FetchException transformIntoFetchException(Throwable e) { FetchException fe = super.transformIntoFetchException(e); if (fe != null) { return fe; } if (e instanceof SQLException) { SQLException se = (SQLException) e; if (isDeadlockError(se)) { return new FetchDeadlockException(e); } if (isTimeoutError(se)) { return new FetchTimeoutException(e); } } return null; } @Override protected PersistException transformIntoPersistException(Throwable e) { PersistException pe = super.transformIntoPersistException(e); if (pe != null) { return pe; } if (e instanceof SQLException) { SQLException se = (SQLException) e; if (isUniqueConstraintError(se)) { return new UniqueConstraintException(e); } if (isConstraintError(se)) { return new ConstraintException(e); } if (isInsufficientPrivilegesError(se)) { return new PersistDeniedException(e); } if (isDeadlockError(se)) { return new PersistDeadlockException(e); } if (isTimeoutError(se)) { return new PersistTimeoutException(e); } } return null; } }