View Javadoc
1   package com.atlassian.activeobjects.internal;
2   
3   import net.java.ao.ActiveObjectsException;
4   import net.java.ao.EntityManager;
5   import org.slf4j.Logger;
6   import org.slf4j.LoggerFactory;
7   
8   import java.sql.Connection;
9   import java.sql.DatabaseMetaData;
10  import java.sql.SQLException;
11  import java.sql.SQLNonTransientConnectionException;
12  import java.sql.SQLTransientConnectionException;
13  
14  public final class ActiveObjectsSqlException extends ActiveObjectsException {
15      private final Logger logger = LoggerFactory.getLogger(this.getClass());
16  
17      private Database database;
18      private Driver driver;
19  
20      public ActiveObjectsSqlException(EntityManager entityManager, SQLException cause) {
21          super(cause);
22  
23          // If the cause is a connection-related exception, skip attempting to load metadata about the
24          // database to avoid potentially exacerbating situations where the database pool is exhausted
25          if (!isConnectionException(cause)) {
26              getInformation(entityManager);
27          }
28      }
29  
30      public SQLException getSqlException() {
31          return (SQLException) getCause();
32      }
33  
34      @Override
35      public String getMessage() {
36          return "There was a SQL exception thrown by the Active Objects library:\n" + database + "\n" + driver + "\n\n" +
37                  super.getMessage();
38      }
39  
40      private void getInformation(EntityManager entityManager) {
41          try (Connection connection = entityManager.getProvider().getConnection()) {
42              if (connection != null && !connection.isClosed()) {
43                  final DatabaseMetaData metaData = connection.getMetaData();
44                  database = getDatabase(metaData);
45                  driver = getDriver(metaData);
46              }
47          } catch (SQLException e) {
48              logger.debug("Could not load database connection meta data", e);
49              addSuppressed(e);
50          }
51      }
52  
53      private static Database getDatabase(DatabaseMetaData metaData) throws SQLException {
54          return new Database(
55                  metaData.getDatabaseProductName(),
56                  metaData.getDatabaseProductVersion(),
57                  String.valueOf(metaData.getDatabaseMinorVersion()),
58                  String.valueOf(metaData.getDatabaseMajorVersion()));
59      }
60  
61      private static Driver getDriver(DatabaseMetaData metaData) throws SQLException {
62          return new Driver(
63                  metaData.getDriverName(),
64                  metaData.getDriverVersion());
65      }
66  
67      private static boolean isConnectionException(SQLException e) {
68          return e instanceof SQLNonTransientConnectionException || e instanceof SQLTransientConnectionException;
69      }
70  
71      private static final class Database {
72          private final String name;
73          private final String version;
74          private final String minorVersion;
75          private final String majorVersion;
76  
77          Database(String name, String version, String minorVersion, String majorVersion) {
78              this.name = name;
79              this.version = version;
80              this.minorVersion = minorVersion;
81              this.majorVersion = majorVersion;
82          }
83  
84          @Override
85          public String toString() {
86              return "Database:\n"
87                      + "\t- name:" + name + "\n"
88                      + "\t- version:" + version + "\n"
89                      + "\t- minor version:" + minorVersion + "\n"
90                      + "\t- major version:" + majorVersion;
91          }
92      }
93  
94      private static final class Driver {
95          private final String name;
96          private final String version;
97  
98          Driver(String name, String version) {
99              this.name = name;
100             this.version = version;
101         }
102 
103         @Override
104         public String toString() {
105             return "Driver:\n"
106                     + "\t- name:" + name + "\n"
107                     + "\t- version:" + version;
108         }
109     }
110 }