content: // Copyright (C) 2018 Red Hat, Inc. and individual contributors as indicated by the @author tags.
  // You may not use this file except in compliance with the Apache License, Version 2.0.
  
  package io.agroal.api.exceptionsorter;
  
  import io.agroal.api.configuration.AgroalConnectionPoolConfiguration.ExceptionSorter;
  
  import java.sql.SQLException;
  import java.util.Locale;
  
  /**
   * Exception sorter for Oracle databases.
   *
   * @author <a href="jesper.pedersen@redhat.com">Jesper Pedersen</a>
   */
  public class OracleExceptionSorter implements ExceptionSorter {
  
      @Override
      @SuppressWarnings( {"CallToSuspiciousStringMethod", "MagicNumber"} )
      public boolean isFatal(SQLException e) {
          int errorCode = Math.abs( e.getErrorCode() );
  
          if ( errorCode == 28             //session has been killed
                  || errorCode == 600      //Internal oracle error
                  || errorCode == 1012     //not logged on
                  || errorCode == 1014     //Oracle shutdown in progress
                  || errorCode == 1033     //Oracle initialization or shutdown in progress
                  || errorCode == 1034     //Oracle not available
                  || errorCode == 1035     //ORACLE only available to users with RESTRICTED SESSION privilege
                  || errorCode == 1089     //immediate shutdown in progress - no operations are permitted
                  || errorCode == 1090     //shutdown in progress - connection is not permitted
                  || errorCode == 1092     //ORACLE instance terminated. Disconnection forced
                  || errorCode == 1094     //ALTER DATABASE CLOSE in progress. Connections not permitted
                  || errorCode == 2396     //exceeded maximum idle time, please connect again
                  || errorCode == 3106     //fatal two-task communication protocol error
                  || errorCode == 3111     //break received on communication channel
                  || errorCode == 3113     //end-of-file on communication channel
                  || errorCode == 3114     //not connected to ORACLE
                  || errorCode >= 12100 && errorCode <= 12299    // TNS issues
                  || errorCode == 17002    //connection reset
                  || errorCode == 17008    //connection closed
                  || errorCode == 17410    //No more data to read from socket
                  || errorCode == 17447    //OALL8 is in an inconsistent state
          ) {
              return true;
          }
  
          // Exclude oracle user defined error codes (20000 through 20999) from consideration when looking for certain strings.
          String errorText = ( e.getMessage() ).toUpperCase( Locale.US );
          if ( ( errorCode < 20000 || errorCode >= 21000 ) && ( errorText.contains( "SOCKET" ) || errorText.contains( "CONNECTION HAS ALREADY BEEN CLOSED" ) || errorText.contains( "BROKEN PIPE" ) ) ) {
              return true;
          }
  
          return "08000".equals( e.getSQLState() );
      }
  }
  