/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.taobao.tddl.common.jdbc.sorter;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
/**
* OracleExceptionSorter.java Created: Fri Mar 14 21:54:23 2003
*
* @author <a href="mailto:an_test@mail.ru">Andrey Demchenko</a>
* @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
* @author <a href="mailto:weston.price@jboss.com>Weston Price</a>
* @version 1.0
*/
public class OracleExceptionSorter implements ExceptionSorter, Serializable {
private static final long serialVersionUID = 573723525408205079L;
public OracleExceptionSorter(){
}
public boolean isExceptionFatal(SQLException e) {
int loopCount = 20; // 防止人为失误,当两个Throwable互为对方的initCause()时,造成死循环
Throwable cause = e;
while (cause != null) {
if (cause instanceof SQLException) {
SQLException sqlException = (SQLException) cause;
if (isExceptionFatal0(sqlException)) {
return true;
}
}
cause = cause.getCause();
if (--loopCount < 0) {
break;
}
}
return false;
}
public boolean isExceptionFatal0(final SQLException e) {
final int error_code = Math.abs(e.getErrorCode()); // I can't remember
// if the errors are
// negative or
// positive.
if ((error_code == 28) // session has been killed
|| (error_code == 600) // Internal oracle error
|| (error_code == 1012) // not logged on
|| (error_code == 1014) // Oracle shutdown in progress
|| (error_code == 1033) // Oracle initialization or shutdown in
// progress
|| (error_code == 1034) // Oracle not available
|| (error_code == 1035) // ORACLE only available to users with
// RESTRICTED SESSION privilege
|| (error_code == 1089) // immediate shutdown in progress - no
// operations are permitted
|| (error_code == 1090) // shutdown in progress - connection is not
// permitted
|| (error_code == 1092) // ORACLE instance terminated. Disconnection
// forced
|| (error_code == 1094) // ALTER DATABASE CLOSE in progress.
// Connections not permitted
|| (error_code == 2396) // exceeded maximum idle time, please
// connect again
|| (error_code == 3106) // fatal two-task communication protocol
// error
|| (error_code == 3111) // break received on communication channel
|| (error_code == 3113) // end-of-file on communication channel
|| (error_code == 3114) // not connected to ORACLE
|| (error_code >= 12100 && error_code <= 12299) // TNS issues
|| (error_code == 17002) // connection reset
|| (error_code == 17008)) // connection closed
{
return true;
}
if (e.getMessage() == null) {
return false;
}
final String error_text = (e.getMessage()).toUpperCase();
// Exclude oracle user defined error codes (20000 through 20999) from
// consideration when looking for
// certain strings.
if ((error_code < 20000 || error_code >= 21000)
&& ("NO DATASOURCE!".equals(error_text)
|| "NO ALIVE DATASOURCE".equals(error_text) // 兼容rjdbc抛出的错误
|| (error_text.indexOf("SOCKET") > -1) // for control socket
// error
|| (error_text.indexOf("CONNECTION HAS ALREADY BEEN CLOSED") > -1)
|| (error_text.indexOf("BROKEN PIPE") > -1) || (error_text.indexOf("TNS") > -1 && error_text.indexOf("ORA-") > -1))) {
return true;
}
if (externalExceptionSorters != null) {
for (ExceptionSorter externalSorter : externalExceptionSorters) {
if (externalSorter.isExceptionFatal(e)) {
return true;
}
}
}
return false;
}
private static List<ExceptionSorter> externalExceptionSorters;
/**
* @param sorter 外部的ExceptionSorter只需判断SQLException本身即可,不需要判断其cause链
*/
public static void addExceptionSorter(ExceptionSorter sorter) {
if (externalExceptionSorters == null) {
externalExceptionSorters = new LinkedList<ExceptionSorter>();
}
externalExceptionSorters.add(sorter);
}
}