Skip to content

Commit bb17026

Browse files
committed
refactor the logic in OracleServerConfiguration
to make the flow here a bit clearer
1 parent daa44c8 commit bb17026

File tree

1 file changed

+104
-108
lines changed

1 file changed

+104
-108
lines changed

hibernate-core/src/main/java/org/hibernate/dialect/OracleServerConfiguration.java

Lines changed: 104 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44
*/
55
package org.hibernate.dialect;
66

7-
import java.lang.reflect.Field;
87
import java.lang.reflect.Method;
98
import java.sql.Connection;
109
import java.sql.DatabaseMetaData;
10+
import java.sql.Driver;
11+
import java.sql.DriverManager;
1112
import java.sql.ResultSet;
1213
import java.sql.SQLException;
1314
import java.sql.Statement;
14-
import java.util.List;
15+
import java.util.Map;
1516

1617
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
17-
import org.hibernate.internal.util.config.ConfigurationHelper;
1818

1919
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_APPLICATION_CONTINUITY;
2020
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_AUTONOMOUS_DATABASE;
2121
import static org.hibernate.cfg.DialectSpecificSettings.ORACLE_EXTENDED_STRING_SIZE;
22+
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
2223

2324
/**
2425
* Utility class that extract some initial configuration from the database for {@link OracleDialect}.
@@ -62,7 +63,7 @@ public OracleServerConfiguration(
6263
boolean extended,
6364
int driverMajorVersion,
6465
int driverMinorVersion) {
65-
this(autonomous, extended, false, driverMajorVersion, driverMinorVersion);
66+
this( autonomous, extended, false, driverMajorVersion, driverMinorVersion );
6667
}
6768

6869
public OracleServerConfiguration(
@@ -79,129 +80,124 @@ public OracleServerConfiguration(
7980
}
8081

8182
public static OracleServerConfiguration fromDialectResolutionInfo(DialectResolutionInfo info) {
82-
Boolean extended = null;
83-
Boolean autonomous = null;
84-
Boolean applicationContinuity = null;
85-
Integer majorVersion = null;
86-
Integer minorVersion = null;
87-
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
88-
if ( databaseMetaData != null ) {
89-
majorVersion = databaseMetaData.getDriverMajorVersion();
90-
minorVersion = databaseMetaData.getDriverMinorVersion();
9183

92-
93-
try {
94-
final Connection c = databaseMetaData.getConnection();
95-
96-
try (final Statement statement = c.createStatement()) {
97-
98-
// Use Oracle JDBC replay statistics information to determine if this
99-
// connection is protected by Application Continuity
100-
try {
101-
final Class statisticReportTypeEnum = Class.forName("oracle.jdbc.replay.ReplayableConnection$StatisticsReportType",false, Thread.currentThread().getContextClassLoader());
102-
final Field forCurrentConnection = statisticReportTypeEnum.getField("FOR_CURRENT_CONNECTION");
103-
104-
final Method getReplayStatistics = c.getClass().getMethod("getReplayStatistics", statisticReportTypeEnum);
105-
106-
Object stats = getReplayStatistics.invoke(c,forCurrentConnection.get(null));
107-
108-
final Method getTotalRequests = stats.getClass().getMethod("getTotalRequests");
109-
final Method getTotalProtectedCalls = stats.getClass().getMethod("getTotalProtectedCalls");
110-
111-
final Long totalRequestsBefore = (Long)getTotalRequests.invoke(stats);
112-
final Long protectedCallsBefore = (Long)getTotalProtectedCalls.invoke(stats);
113-
114-
try (ResultSet r = statement.executeQuery("select 1")) {
115-
r.next();
116-
}
117-
118-
stats = getReplayStatistics.invoke(c,forCurrentConnection.get(null));
119-
120-
final Long totalRequestsAfter = (Long)getTotalRequests.invoke(stats);
121-
final Long protectedCallsAfter = (Long)getTotalProtectedCalls.invoke(stats);
122-
123-
// Application continuity is enabled on this database service if the number of
124-
// total requests and the number of protected calls for this connection have
125-
// both increased.
126-
applicationContinuity = totalRequestsAfter > totalRequestsBefore && protectedCallsAfter > protectedCallsBefore;
127-
}
128-
catch(Exception e) {
129-
// A ClassCastException or a NullPointerException are expected here in the case
130-
// the Connection Factory is not the right one (not Replayable: ClassCastException)
131-
// or if the database service has not been configured (server side) to enable
132-
// application continuity (NullPointerException).
133-
applicationContinuity = false;
134-
}
135-
136-
// continue the checks...
137-
final ResultSet rs = statement.executeQuery(
138-
"select cast('string' as varchar2(32000)), " +
139-
"sys_context('USERENV','CLOUD_SERVICE') from dual"
140-
);
141-
if (rs.next()) {
142-
// succeeded, so MAX_STRING_SIZE == EXTENDED
143-
extended = true;
144-
autonomous = isAutonomous(rs.getString(2));
145-
}
146-
}
147-
}
148-
catch (SQLException ex) {
149-
// failed, so MAX_STRING_SIZE == STANDARD, still need to check autonomous
150-
extended = false;
151-
autonomous = isAutonomous( databaseMetaData );
152-
}
153-
}
15484
// default to the dialect-specific configuration settings
155-
if ( extended == null ) {
156-
extended = ConfigurationHelper.getBoolean(
157-
ORACLE_EXTENDED_STRING_SIZE,
158-
info.getConfigurationValues(),
159-
false
160-
);
161-
}
162-
if ( autonomous == null ) {
163-
autonomous = ConfigurationHelper.getBoolean(
164-
ORACLE_AUTONOMOUS_DATABASE,
165-
info.getConfigurationValues(),
166-
false
167-
);
168-
}
169-
if ( applicationContinuity == null ) {
170-
applicationContinuity = ConfigurationHelper.getBoolean(
171-
ORACLE_APPLICATION_CONTINUITY,
172-
info.getConfigurationValues(),
173-
false
174-
);
175-
}
176-
if ( majorVersion == null ) {
85+
final Map<String, Object> configuration = info.getConfigurationValues();
86+
final boolean defaultExtended = getBoolean( ORACLE_EXTENDED_STRING_SIZE, configuration, false );
87+
final boolean defaultAutonomous = getBoolean( ORACLE_AUTONOMOUS_DATABASE, configuration, false );
88+
final boolean defaultContinuity = getBoolean( ORACLE_APPLICATION_CONTINUITY, configuration, false );
89+
90+
boolean extended;
91+
boolean autonomous;
92+
boolean applicationContinuity;
93+
int majorVersion;
94+
int minorVersion;
95+
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
96+
if ( databaseMetaData == null ) {
97+
extended = defaultExtended;
98+
autonomous = defaultAutonomous;
99+
applicationContinuity = defaultContinuity;
177100
try {
178-
java.sql.Driver driver = java.sql.DriverManager.getDriver( "jdbc:oracle:thin:" );
101+
final Driver driver = DriverManager.getDriver( "jdbc:oracle:thin:" );
179102
majorVersion = driver.getMajorVersion();
180103
minorVersion = driver.getMinorVersion();
181104
}
182105
catch (SQLException ex) {
183106
majorVersion = 19;
184107
minorVersion = 0;
185108
}
186-
187109
}
110+
else {
111+
majorVersion = databaseMetaData.getDriverMajorVersion();
112+
minorVersion = databaseMetaData.getDriverMinorVersion();
113+
try {
114+
final Connection connection = databaseMetaData.getConnection(); // we should not close this
115+
try ( final Statement statement = connection.createStatement() ) {
116+
applicationContinuity = determineApplicationContinuity( connection, statement );
117+
autonomous = isAutonomous( statement );
118+
extended = isExtended( statement );
119+
}
120+
}
121+
catch (SQLException sqle) {
122+
extended = defaultExtended;
123+
autonomous = defaultAutonomous;
124+
applicationContinuity = defaultContinuity;
125+
}
126+
}
127+
188128
return new OracleServerConfiguration( autonomous, extended, applicationContinuity, majorVersion, minorVersion );
189129
}
190130

191-
private static boolean isAutonomous(String cloudServiceParam) {
192-
return cloudServiceParam != null && List.of( "OLTP", "DWCS", "JDCS" ).contains( cloudServiceParam );
131+
private static boolean isExtended(Statement statement) {
132+
try ( final ResultSet resultSet =
133+
statement.executeQuery( "select cast('string' as varchar2(32000)) from dual" ) ) {
134+
resultSet.next();
135+
// succeeded, so MAX_STRING_SIZE == EXTENDED
136+
return true;
137+
}
138+
catch (SQLException ex) {
139+
// failed, so MAX_STRING_SIZE == STANDARD, still need to check autonomous
140+
return false;
141+
}
193142
}
194143

195-
private static boolean isAutonomous(DatabaseMetaData databaseMetaData) {
196-
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
197-
return statement.executeQuery(
198-
"select 1 from dual where sys_context('USERENV','CLOUD_SERVICE') in ('OLTP','DWCS','JDCS')" )
199-
.next();
144+
private static Boolean determineApplicationContinuity(Connection connection, Statement statement) {
145+
// Use Oracle JDBC replay statistics information to determine if this
146+
// connection is protected by Application Continuity
147+
try {
148+
final Class<?> statisticReportTypeEnum =
149+
Class.forName( "oracle.jdbc.replay.ReplayableConnection$StatisticsReportType",
150+
false, Thread.currentThread().getContextClassLoader() );
151+
final Object forCurrentConnection =
152+
statisticReportTypeEnum.getField( "FOR_CURRENT_CONNECTION" ).get( null );
153+
final Method getReplayStatistics =
154+
connection.getClass().getMethod( "getReplayStatistics", statisticReportTypeEnum );
155+
final Class<?> replayStatistics = getReplayStatistics.getReturnType();
156+
final Method getTotalRequests = replayStatistics.getMethod("getTotalRequests");
157+
final Method getTotalProtectedCalls = replayStatistics.getMethod("getTotalProtectedCalls");
158+
159+
final Object before = getReplayStatistics.invoke( connection, forCurrentConnection );
160+
final Long totalRequestsBefore = (Long) getTotalRequests.invoke( before );
161+
final Long protectedCallsBefore = (Long) getTotalProtectedCalls.invoke( before );
162+
163+
try ( final ResultSet resultSet = statement.executeQuery("select 1") ) {
164+
resultSet.next();
165+
}
166+
167+
final Object after = getReplayStatistics.invoke( connection, forCurrentConnection );
168+
final Long totalRequestsAfter = (Long) getTotalRequests.invoke( after );
169+
final Long protectedCallsAfter = (Long) getTotalProtectedCalls.invoke( after );
170+
171+
// Application continuity is enabled on this database service if the number of
172+
// total requests and the number of protected calls for this connection have
173+
// both increased.
174+
return totalRequestsAfter > totalRequestsBefore
175+
&& protectedCallsAfter > protectedCallsBefore;
176+
}
177+
catch (Exception e) {
178+
// A ClassCastException or a NullPointerException are expected here in the case
179+
// the Connection Factory is not the right one (not Replayable: ClassCastException)
180+
// or if the database service has not been configured (server side) to enable
181+
// application continuity (NullPointerException).
182+
return false;
183+
}
184+
}
185+
186+
private static boolean isAutonomous(Statement statement) {
187+
try ( final ResultSet resultSet =
188+
statement.executeQuery( "select sys_context('USERENV','CLOUD_SERVICE') from dual" ) ) {
189+
return resultSet.next()
190+
&& isAutonomous( resultSet.getString(1) );
200191
}
201192
catch (SQLException ex) {
202-
// Ignore
193+
return false;
203194
}
204-
return false;
205195
}
206196

197+
private static boolean isAutonomous(String type) {
198+
return type != null && switch ( type ) {
199+
case "OLTP", "DWCS", "JDCS" -> true;
200+
default -> false;
201+
};
202+
}
207203
}

0 commit comments

Comments
 (0)