You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/07/10 18:42:19 UTC
[commons-dbcp] branch master updated: Use forEach and make AbandonedTrace processing type-safe
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git
The following commit(s) were added to refs/heads/master by this push:
new e92a0374 Use forEach and make AbandonedTrace processing type-safe
e92a0374 is described below
commit e92a0374aff8f973cf29cb3f103224ddb87b127d
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Jul 10 14:42:12 2022 -0400
Use forEach and make AbandonedTrace processing type-safe
---
.../org/apache/commons/dbcp2/BasicDataSource.java | 25 +-
.../commons/dbcp2/BasicDataSourceFactory.java | 21 +-
.../apache/commons/dbcp2/DelegatingConnection.java | 27 +-
.../commons/dbcp2/DelegatingPreparedStatement.java | 13 +-
.../apache/commons/dbcp2/DelegatingStatement.java | 1651 ++++++++++----------
.../commons/dbcp2/PoolableConnectionFactory.java | 5 +-
.../dbcp2/cpdsadapter/PooledConnectionImpl.java | 5 +-
.../datasources/InstanceKeyDataSourceFactory.java | 10 +-
.../dbcp2/datasources/PerUserPoolDataSource.java | 9 +-
9 files changed, 870 insertions(+), 896 deletions(-)
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
index 0ac82e28..23dd2bb3 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
@@ -38,6 +38,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.logging.Logger;
+import java.util.stream.Stream;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
@@ -1822,20 +1823,18 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
Objects.requireNonNull(connectionProperties, "connectionProperties");
final String[] entries = connectionProperties.split(";");
final Properties properties = new Properties();
- for (final String entry : entries) {
- if (!entry.isEmpty()) {
- final int index = entry.indexOf('=');
- if (index > 0) {
- final String name = entry.substring(0, index);
- final String value = entry.substring(index + 1);
- properties.setProperty(name, value);
- } else {
- // no value is empty string which is how
- // java.util.Properties works
- properties.setProperty(entry, "");
- }
+ Stream.of(entries).filter(e -> !e.isEmpty()).forEach(entry -> {
+ final int index = entry.indexOf('=');
+ if (index > 0) {
+ final String name = entry.substring(0, index);
+ final String value = entry.substring(index + 1);
+ properties.setProperty(name, value);
+ } else {
+ // no value is empty string which is how
+ // java.util.Properties works
+ properties.setProperty(entry, "");
}
- }
+ });
this.connectionProperties = properties;
}
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
index 457bc9e0..f5a73c89 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
@@ -31,7 +31,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
@@ -139,7 +138,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
private static final String SILENT_PROP_SINGLETON = "singleton";
private static final String SILENT_PROP_AUTH = "auth";
- private static final String[] ALL_PROPERTIES = {PROP_DEFAULT_AUTO_COMMIT, PROP_DEFAULT_READ_ONLY,
+ private static final List<String> ALL_PROPERTY_NAMES = Arrays.asList(PROP_DEFAULT_AUTO_COMMIT, PROP_DEFAULT_READ_ONLY,
PROP_DEFAULT_TRANSACTION_ISOLATION, PROP_DEFAULT_CATALOG, PROP_DEFAULT_SCHEMA, PROP_CACHE_STATE,
PROP_DRIVER_CLASS_NAME, PROP_LIFO, PROP_MAX_TOTAL, PROP_MAX_IDLE, PROP_MIN_IDLE, PROP_INITIAL_SIZE,
PROP_MAX_WAIT_MILLIS, PROP_TEST_ON_CREATE, PROP_TEST_ON_BORROW, PROP_TEST_ON_RETURN,
@@ -152,7 +151,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS,
PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN,
PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME,
- PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME};
+ PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME);
/**
* Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee
@@ -397,12 +396,12 @@ public class BasicDataSourceFactory implements ObjectFactory {
infoMessages.forEach(log::info);
final Properties properties = new Properties();
- for (final String propertyName : ALL_PROPERTIES) {
+ ALL_PROPERTY_NAMES.forEach(propertyName -> {
final RefAddr ra = ref.get(propertyName);
if (ra != null) {
properties.setProperty(propertyName, Objects.toString(ra.getContent(), null));
}
- }
+ });
return createDataSource(properties);
}
@@ -422,20 +421,18 @@ public class BasicDataSourceFactory implements ObjectFactory {
*/
private void validatePropertyNames(final Reference ref, final Name name, final List<String> warnMessages,
final List<String> infoMessages) {
- final List<String> allPropsAsList = Arrays.asList(ALL_PROPERTIES);
final String nameString = name != null ? "Name = " + name.toString() + " " : "";
if (NUPROP_WARNTEXT != null && !NUPROP_WARNTEXT.isEmpty()) {
- for (final Entry<String, String> entry : NUPROP_WARNTEXT.entrySet()) {
- final String propertyName = entry.getKey();
+ NUPROP_WARNTEXT.forEach((propertyName, value) -> {
final RefAddr ra = ref.get(propertyName);
- if (ra != null && !allPropsAsList.contains(ra.getType())) {
+ if (ra != null && !ALL_PROPERTY_NAMES.contains(ra.getType())) {
final StringBuilder stringBuilder = new StringBuilder(nameString);
final String propertyValue = Objects.toString(ra.getContent(), null);
- stringBuilder.append(entry.getValue()).append(" You have set value of \"").append(propertyValue).append("\" for \"").append(propertyName)
+ stringBuilder.append(value).append(" You have set value of \"").append(propertyValue).append("\" for \"").append(propertyName)
.append("\" property, which is being ignored.");
warnMessages.add(stringBuilder.toString());
}
- }
+ });
}
final Enumeration<RefAddr> allRefAddrs = ref.getAll();
@@ -444,7 +441,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
final String propertyName = ra.getType();
// If property name is not in the properties list, we haven't warned on it
// and it is not in the "silent" list, tell user we are ignoring it.
- if (!(allPropsAsList.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName) || SILENT_PROPERTIES.contains(propertyName))) {
+ if (!(ALL_PROPERTY_NAMES.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName) || SILENT_PROPERTIES.contains(propertyName))) {
final String propertyValue = Objects.toString(ra.getContent(), null);
final StringBuilder stringBuilder = new StringBuilder(nameString);
stringBuilder.append("Ignoring unknown property: ").append("value of \"").append(propertyValue).append("\" for \"").append(propertyName)
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
index 62163a03..66c8481f 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
@@ -25,7 +25,6 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
@@ -651,26 +650,16 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
// The JDBC specification requires that a Connection close any open
// Statement's when it is closed.
// DBCP-288. Not all the traced objects will be statements
- final List<AbandonedTrace> traces = getTrace();
- if (traces != null && !traces.isEmpty()) {
+ final List<AbandonedTrace> traceList = getTrace();
+ if (traceList != null && !traceList.isEmpty()) {
final List<Exception> thrownList = new ArrayList<>();
- for (final Object trace : traces) {
- if (trace instanceof Statement) {
- try {
- ((Statement) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- } else if (trace instanceof ResultSet) {
- // DBCP-265: Need to close the result sets that are
- // generated via DatabaseMetaData
- try {
- ((ResultSet) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
+ traceList.stream().filter(AutoCloseable.class::isInstance).forEach(trace -> {
+ try {
+ ((AutoCloseable) trace).close();
+ } catch (final Exception e) {
+ thrownList.add(e);
}
- }
+ });
clearTrace();
if (!thrownList.isEmpty()) {
throw new SQLExceptionList(thrownList);
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java b/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java
index 4f343b39..78e868b0 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java
@@ -697,7 +697,7 @@ public class DelegatingPreparedStatement extends DelegatingStatement implements
protected void prepareToReturn() throws SQLException {
setClosedInternal(true);
removeThisTrace(getConnectionInternal());
-
+
// The JDBC spec requires that a statement close any open
// ResultSet's when it is closed.
// FIXME The PreparedStatement we're wrapping should handle this for us.
@@ -705,22 +705,21 @@ public class DelegatingPreparedStatement extends DelegatingStatement implements
final List<AbandonedTrace> resultSetList = getTrace();
if (resultSetList != null) {
final List<Exception> thrownList = new ArrayList<>();
- final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
- for (final ResultSet resultSet : resultSets) {
- if (resultSet != null) {
+ resultSetList.forEach(trace -> {
+ if (trace instanceof AutoCloseable) {
try {
- resultSet.close();
+ ((AutoCloseable) trace).close();
} catch (final Exception e) {
thrownList.add(e);
}
}
- }
+ });
clearTrace();
if (!thrownList.isEmpty()) {
throw new SQLExceptionList(thrownList);
}
}
-
+
super.passivate();
}
}
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
index 0fd57837..cf05106a 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
@@ -1,827 +1,824 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.commons.dbcp2;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A base delegating implementation of {@link Statement}.
- * <p>
- * All of the methods from the {@link Statement} interface simply check to see that the {@link Statement} is active, and
- * call the corresponding method on the "delegate" provided in my constructor.
- * <p>
- * Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the
- * Statement ensures that the Connection which created it can close any open Statement's on Connection close.
- *
- * @since 2.0
- */
-public class DelegatingStatement extends AbandonedTrace implements Statement {
-
- /** My delegate. */
- private Statement statement;
-
- /** The connection that created me. **/
- private DelegatingConnection<?> connection;
-
- private boolean closed;
-
- /**
- * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code
- * which created it.
- *
- * @param statement
- * the {@link Statement} to delegate all calls to.
- * @param connection
- * the {@link DelegatingConnection} that created this statement.
- */
- public DelegatingStatement(final DelegatingConnection<?> connection, final Statement statement) {
- super(connection);
- this.statement = statement;
- this.connection = connection;
- }
-
- /**
- *
- * @throws SQLException
- * thrown by the delegating statement.
- * @since 2.4.0 made public, was protected in 2.3.0.
- */
- public void activate() throws SQLException {
- if (statement instanceof DelegatingStatement) {
- ((DelegatingStatement) statement).activate();
- }
- }
-
- @Override
- public void addBatch(final String sql) throws SQLException {
- checkOpen();
- try {
- statement.addBatch(sql);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void cancel() throws SQLException {
- checkOpen();
- try {
- statement.cancel();
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- protected void checkOpen() throws SQLException {
- if (isClosed()) {
- throw new SQLException(this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed.");
- }
- }
-
- @Override
- public void clearBatch() throws SQLException {
- checkOpen();
- try {
- statement.clearBatch();
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void clearWarnings() throws SQLException {
- checkOpen();
- try {
- statement.clearWarnings();
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- /**
- * Close this DelegatingStatement, and close any ResultSets that were not explicitly closed.
- */
- @Override
- public void close() throws SQLException {
- if (isClosed()) {
- return;
- }
- final List<Exception> thrownList = new ArrayList<>();
- try {
- if (connection != null) {
- connection.removeTrace(this);
- connection = null;
- }
-
- // The JDBC spec requires that a statement close any open
- // ResultSet's when it is closed.
- // FIXME The PreparedStatement we're wrapping should handle this for us.
- // See bug 17301 for what could happen when ResultSets are closed twice.
- final List<AbandonedTrace> resultSetList = getTrace();
- if (resultSetList != null) {
- final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
- for (final ResultSet resultSet : resultSets) {
- if (resultSet != null) {
- try {
- resultSet.close();
- } catch (final Exception e) {
- if (connection != null) {
- // Does not rethrow e.
- connection.handleExceptionNoThrow(e);
- }
- thrownList.add(e);
- }
- }
- }
- clearTrace();
- }
- if (statement != null) {
- try {
- statement.close();
- } catch (final Exception e) {
- if (connection != null) {
- // Does not rethrow e.
- connection.handleExceptionNoThrow(e);
- }
- thrownList.add(e);
- }
- }
- } finally {
- closed = true;
- statement = null;
- if (!thrownList.isEmpty()) {
- throw new SQLExceptionList(thrownList);
- }
- }
- }
-
- @Override
- public void closeOnCompletion() throws SQLException {
- checkOpen();
- try {
- Jdbc41Bridge.closeOnCompletion(statement);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public boolean execute(final String sql) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.execute(sql);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.execute(sql, autoGeneratedKeys);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.execute(sql, columnIndexes);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean execute(final String sql, final String[] columnNames) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.execute(sql, columnNames);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public int[] executeBatch() throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeBatch();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long[] executeLargeBatch() throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeLargeBatch();
- } catch (final SQLException e) {
- handleException(e);
- return null;
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long executeLargeUpdate(final String sql) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeLargeUpdate(sql);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeLargeUpdate(sql, autoGeneratedKeys);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeLargeUpdate(sql, columnIndexes);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeLargeUpdate(sql, columnNames);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @SuppressWarnings("resource") // Caller is responsible for closing the resource.
- @Override
- public ResultSet executeQuery(final String sql) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
- }
-
- @Override
- public int executeUpdate(final String sql) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeUpdate(sql);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeUpdate(sql, autoGeneratedKeys);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeUpdate(sql, columnIndexes);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
- checkOpen();
- setLastUsedInParent();
- try {
- return statement.executeUpdate(sql, columnNames);
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- // This is required because of statement pooling. The poolable
- // statements will always be strongly held by the statement pool. If the
- // delegating statements that wrap the poolable statement are not
- // strongly held they will be garbage collected but at that point the
- // poolable statements need to be returned to the pool else there will
- // be a leak of statements from the pool. Closing this statement will
- // close all the wrapped statements and return any poolable statements
- // to the pool.
- close();
- super.finalize();
- }
-
- @Override
- public Connection getConnection() throws SQLException {
- checkOpen();
- return getConnectionInternal(); // return the delegating connection that created this
- }
-
- protected DelegatingConnection<?> getConnectionInternal() {
- return connection;
- }
-
- /**
- * Returns my underlying {@link Statement}.
- *
- * @return my underlying {@link Statement}.
- * @see #getInnermostDelegate
- */
- public Statement getDelegate() {
- return statement;
- }
-
- @Override
- public int getFetchDirection() throws SQLException {
- checkOpen();
- try {
- return statement.getFetchDirection();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getFetchSize() throws SQLException {
- checkOpen();
- try {
- return statement.getFetchSize();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @SuppressWarnings("resource") // Caller is responsible for closing the resource.
- @Override
- public ResultSet getGeneratedKeys() throws SQLException {
- checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys());
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
- }
-
- /**
- * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively
- * invokes this method on my delegate.
- * <p>
- * Hence this method will return the first delegate that is not a {@code DelegatingStatement} or {@code null} when
- * no non-{@code DelegatingStatement} delegate can be found by traversing this chain.
- * </p>
- * <p>
- * This method is useful when you may have nested {@code DelegatingStatement}s, and you want to make sure to obtain
- * a "genuine" {@link Statement}.
- * </p>
- *
- * @return The innermost delegate.
- *
- * @see #getDelegate
- */
- @SuppressWarnings("resource")
- public Statement getInnermostDelegate() {
- Statement s = statement;
- while (s instanceof DelegatingStatement) {
- s = ((DelegatingStatement) s).getDelegate();
- if (this == s) {
- return null;
- }
- }
- return s;
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long getLargeMaxRows() throws SQLException {
- checkOpen();
- try {
- return statement.getLargeMaxRows();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public long getLargeUpdateCount() throws SQLException {
- checkOpen();
- try {
- return statement.getLargeUpdateCount();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getMaxFieldSize() throws SQLException {
- checkOpen();
- try {
- return statement.getMaxFieldSize();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getMaxRows() throws SQLException {
- checkOpen();
- try {
- return statement.getMaxRows();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public boolean getMoreResults() throws SQLException {
- checkOpen();
- try {
- return statement.getMoreResults();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean getMoreResults(final int current) throws SQLException {
- checkOpen();
- try {
- return statement.getMoreResults(current);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public int getQueryTimeout() throws SQLException {
- checkOpen();
- try {
- return statement.getQueryTimeout();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @SuppressWarnings("resource") // Caller is responsible for closing the resource.
- @Override
- public ResultSet getResultSet() throws SQLException {
- checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(this, statement.getResultSet());
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
- }
-
- @Override
- public int getResultSetConcurrency() throws SQLException {
- checkOpen();
- try {
- return statement.getResultSetConcurrency();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getResultSetHoldability() throws SQLException {
- checkOpen();
- try {
- return statement.getResultSetHoldability();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getResultSetType() throws SQLException {
- checkOpen();
- try {
- return statement.getResultSetType();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public int getUpdateCount() throws SQLException {
- checkOpen();
- try {
- return statement.getUpdateCount();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
- }
-
- @Override
- public SQLWarning getWarnings() throws SQLException {
- checkOpen();
- try {
- return statement.getWarnings();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
- }
-
- protected void handleException(final SQLException e) throws SQLException {
- if (connection == null) {
- throw e;
- }
- connection.handleException(e);
- }
-
- /*
- * Note: This method was protected prior to JDBC 4.
- */
- @Override
- public boolean isClosed() throws SQLException {
- return closed;
- }
-
- protected boolean isClosedInternal() {
- return closed;
- }
-
- @Override
- public boolean isCloseOnCompletion() throws SQLException {
- checkOpen();
- try {
- return Jdbc41Bridge.isCloseOnCompletion(statement);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean isPoolable() throws SQLException {
- checkOpen();
- try {
- return statement.isPoolable();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
- }
-
- @Override
- public boolean isWrapperFor(final Class<?> iface) throws SQLException {
- if (iface.isAssignableFrom(getClass())) {
- return true;
- }
- if (iface.isAssignableFrom(statement.getClass())) {
- return true;
- }
- return statement.isWrapperFor(iface);
- }
-
- /**
- *
- * @throws SQLException
- * thrown by the delegating statement.
- * @since 2.4.0 made public, was protected in 2.3.0.
- */
- public void passivate() throws SQLException {
- if (statement instanceof DelegatingStatement) {
- ((DelegatingStatement) statement).passivate();
- }
- }
-
- protected void setClosedInternal(final boolean closed) {
- this.closed = closed;
- }
-
- @Override
- public void setCursorName(final String name) throws SQLException {
- checkOpen();
- try {
- statement.setCursorName(name);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- /**
- * Sets my delegate.
- *
- * @param statement
- * my delegate.
- */
- public void setDelegate(final Statement statement) {
- this.statement = statement;
- }
-
- @Override
- public void setEscapeProcessing(final boolean enable) throws SQLException {
- checkOpen();
- try {
- statement.setEscapeProcessing(enable);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void setFetchDirection(final int direction) throws SQLException {
- checkOpen();
- try {
- statement.setFetchDirection(direction);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void setFetchSize(final int rows) throws SQLException {
- checkOpen();
- try {
- statement.setFetchSize(rows);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- /**
- * @since 2.5.0
- */
- @Override
- public void setLargeMaxRows(final long max) throws SQLException {
- checkOpen();
- try {
- statement.setLargeMaxRows(max);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- private void setLastUsedInParent() {
- if (connection != null) {
- connection.setLastUsed();
- }
- }
-
- @Override
- public void setMaxFieldSize(final int max) throws SQLException {
- checkOpen();
- try {
- statement.setMaxFieldSize(max);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void setMaxRows(final int max) throws SQLException {
- checkOpen();
- try {
- statement.setMaxRows(max);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void setPoolable(final boolean poolable) throws SQLException {
- checkOpen();
- try {
- statement.setPoolable(poolable);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- @Override
- public void setQueryTimeout(final int seconds) throws SQLException {
- checkOpen();
- try {
- statement.setQueryTimeout(seconds);
- } catch (final SQLException e) {
- handleException(e);
- }
- }
-
- /**
- * Returns a String representation of this object.
- *
- * @return String
- */
- @Override
- public synchronized String toString() {
- return statement == null ? "NULL" : statement.toString();
- }
-
- @Override
- public <T> T unwrap(final Class<T> iface) throws SQLException {
- if (iface.isAssignableFrom(getClass())) {
- return iface.cast(this);
- }
- if (iface.isAssignableFrom(statement.getClass())) {
- return iface.cast(statement);
- }
- return statement.unwrap(iface);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.dbcp2;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A base delegating implementation of {@link Statement}.
+ * <p>
+ * All of the methods from the {@link Statement} interface simply check to see that the {@link Statement} is active, and
+ * call the corresponding method on the "delegate" provided in my constructor.
+ * <p>
+ * Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the
+ * Statement ensures that the Connection which created it can close any open Statement's on Connection close.
+ *
+ * @since 2.0
+ */
+public class DelegatingStatement extends AbandonedTrace implements Statement {
+
+ /** My delegate. */
+ private Statement statement;
+
+ /** The connection that created me. **/
+ private DelegatingConnection<?> connection;
+
+ private boolean closed;
+
+ /**
+ * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code
+ * which created it.
+ *
+ * @param statement
+ * the {@link Statement} to delegate all calls to.
+ * @param connection
+ * the {@link DelegatingConnection} that created this statement.
+ */
+ public DelegatingStatement(final DelegatingConnection<?> connection, final Statement statement) {
+ super(connection);
+ this.statement = statement;
+ this.connection = connection;
+ }
+
+ /**
+ *
+ * @throws SQLException
+ * thrown by the delegating statement.
+ * @since 2.4.0 made public, was protected in 2.3.0.
+ */
+ public void activate() throws SQLException {
+ if (statement instanceof DelegatingStatement) {
+ ((DelegatingStatement) statement).activate();
+ }
+ }
+
+ @Override
+ public void addBatch(final String sql) throws SQLException {
+ checkOpen();
+ try {
+ statement.addBatch(sql);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void cancel() throws SQLException {
+ checkOpen();
+ try {
+ statement.cancel();
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ protected void checkOpen() throws SQLException {
+ if (isClosed()) {
+ throw new SQLException(this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed.");
+ }
+ }
+
+ @Override
+ public void clearBatch() throws SQLException {
+ checkOpen();
+ try {
+ statement.clearBatch();
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ checkOpen();
+ try {
+ statement.clearWarnings();
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ /**
+ * Close this DelegatingStatement, and close any ResultSets that were not explicitly closed.
+ */
+ @Override
+ public void close() throws SQLException {
+ if (isClosed()) {
+ return;
+ }
+ final List<Exception> thrownList = new ArrayList<>();
+ try {
+ if (connection != null) {
+ connection.removeTrace(this);
+ connection = null;
+ }
+
+ // The JDBC spec requires that a statement close any open
+ // ResultSet's when it is closed.
+ // FIXME The PreparedStatement we're wrapping should handle this for us.
+ // See bug 17301 for what could happen when ResultSets are closed twice.
+ final List<AbandonedTrace> traceList = getTrace();
+ if (traceList != null) {
+ traceList.stream().filter(AutoCloseable.class::isInstance).forEach(trace -> {
+ try {
+ ((AutoCloseable) trace).close();
+ } catch (final Exception e) {
+ if (connection != null) {
+ // Does not rethrow e.
+ connection.handleExceptionNoThrow(e);
+ }
+ thrownList.add(e);
+ }
+ });
+ clearTrace();
+ }
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (final Exception e) {
+ if (connection != null) {
+ // Does not rethrow e.
+ connection.handleExceptionNoThrow(e);
+ }
+ thrownList.add(e);
+ }
+ }
+ } finally {
+ closed = true;
+ statement = null;
+ if (!thrownList.isEmpty()) {
+ throw new SQLExceptionList(thrownList);
+ }
+ }
+ }
+
+ @Override
+ public void closeOnCompletion() throws SQLException {
+ checkOpen();
+ try {
+ Jdbc41Bridge.closeOnCompletion(statement);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public boolean execute(final String sql) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.execute(sql);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.execute(sql, autoGeneratedKeys);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.execute(sql, columnIndexes);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean execute(final String sql, final String[] columnNames) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.execute(sql, columnNames);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public int[] executeBatch() throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeBatch();
+ } catch (final SQLException e) {
+ handleException(e);
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long[] executeLargeBatch() throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeLargeBatch();
+ } catch (final SQLException e) {
+ handleException(e);
+ return null;
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long executeLargeUpdate(final String sql) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeLargeUpdate(sql);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeLargeUpdate(sql, autoGeneratedKeys);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeLargeUpdate(sql, columnIndexes);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeLargeUpdate(sql, columnNames);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @SuppressWarnings("resource") // Caller is responsible for closing the resource.
+ @Override
+ public ResultSet executeQuery(final String sql) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql));
+ } catch (final SQLException e) {
+ handleException(e);
+ throw new AssertionError();
+ }
+ }
+
+ @Override
+ public int executeUpdate(final String sql) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeUpdate(sql);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeUpdate(sql, autoGeneratedKeys);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeUpdate(sql, columnIndexes);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
+ checkOpen();
+ setLastUsedInParent();
+ try {
+ return statement.executeUpdate(sql, columnNames);
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ // This is required because of statement pooling. The poolable
+ // statements will always be strongly held by the statement pool. If the
+ // delegating statements that wrap the poolable statement are not
+ // strongly held they will be garbage collected but at that point the
+ // poolable statements need to be returned to the pool else there will
+ // be a leak of statements from the pool. Closing this statement will
+ // close all the wrapped statements and return any poolable statements
+ // to the pool.
+ close();
+ super.finalize();
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ checkOpen();
+ return getConnectionInternal(); // return the delegating connection that created this
+ }
+
+ protected DelegatingConnection<?> getConnectionInternal() {
+ return connection;
+ }
+
+ /**
+ * Returns my underlying {@link Statement}.
+ *
+ * @return my underlying {@link Statement}.
+ * @see #getInnermostDelegate
+ */
+ public Statement getDelegate() {
+ return statement;
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getFetchDirection();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getFetchSize() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getFetchSize();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @SuppressWarnings("resource") // Caller is responsible for closing the resource.
+ @Override
+ public ResultSet getGeneratedKeys() throws SQLException {
+ checkOpen();
+ try {
+ return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys());
+ } catch (final SQLException e) {
+ handleException(e);
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively
+ * invokes this method on my delegate.
+ * <p>
+ * Hence this method will return the first delegate that is not a {@code DelegatingStatement} or {@code null} when
+ * no non-{@code DelegatingStatement} delegate can be found by traversing this chain.
+ * </p>
+ * <p>
+ * This method is useful when you may have nested {@code DelegatingStatement}s, and you want to make sure to obtain
+ * a "genuine" {@link Statement}.
+ * </p>
+ *
+ * @return The innermost delegate.
+ *
+ * @see #getDelegate
+ */
+ @SuppressWarnings("resource")
+ public Statement getInnermostDelegate() {
+ Statement s = statement;
+ while (s instanceof DelegatingStatement) {
+ s = ((DelegatingStatement) s).getDelegate();
+ if (this == s) {
+ return null;
+ }
+ }
+ return s;
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long getLargeMaxRows() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getLargeMaxRows();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public long getLargeUpdateCount() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getLargeUpdateCount();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getMaxFieldSize() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getMaxFieldSize();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getMaxRows() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getMaxRows();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public boolean getMoreResults() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getMoreResults();
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean getMoreResults(final int current) throws SQLException {
+ checkOpen();
+ try {
+ return statement.getMoreResults(current);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public int getQueryTimeout() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getQueryTimeout();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @SuppressWarnings("resource") // Caller is responsible for closing the resource.
+ @Override
+ public ResultSet getResultSet() throws SQLException {
+ checkOpen();
+ try {
+ return DelegatingResultSet.wrapResultSet(this, statement.getResultSet());
+ } catch (final SQLException e) {
+ handleException(e);
+ throw new AssertionError();
+ }
+ }
+
+ @Override
+ public int getResultSetConcurrency() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getResultSetConcurrency();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getResultSetHoldability() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getResultSetHoldability();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getResultSetType() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getResultSetType();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public int getUpdateCount() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getUpdateCount();
+ } catch (final SQLException e) {
+ handleException(e);
+ return 0;
+ }
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ checkOpen();
+ try {
+ return statement.getWarnings();
+ } catch (final SQLException e) {
+ handleException(e);
+ throw new AssertionError();
+ }
+ }
+
+ protected void handleException(final SQLException e) throws SQLException {
+ if (connection == null) {
+ throw e;
+ }
+ connection.handleException(e);
+ }
+
+ /*
+ * Note: This method was protected prior to JDBC 4.
+ */
+ @Override
+ public boolean isClosed() throws SQLException {
+ return closed;
+ }
+
+ protected boolean isClosedInternal() {
+ return closed;
+ }
+
+ @Override
+ public boolean isCloseOnCompletion() throws SQLException {
+ checkOpen();
+ try {
+ return Jdbc41Bridge.isCloseOnCompletion(statement);
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isPoolable() throws SQLException {
+ checkOpen();
+ try {
+ return statement.isPoolable();
+ } catch (final SQLException e) {
+ handleException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isWrapperFor(final Class<?> iface) throws SQLException {
+ if (iface.isAssignableFrom(getClass())) {
+ return true;
+ }
+ if (iface.isAssignableFrom(statement.getClass())) {
+ return true;
+ }
+ return statement.isWrapperFor(iface);
+ }
+
+ /**
+ *
+ * @throws SQLException
+ * thrown by the delegating statement.
+ * @since 2.4.0 made public, was protected in 2.3.0.
+ */
+ public void passivate() throws SQLException {
+ if (statement instanceof DelegatingStatement) {
+ ((DelegatingStatement) statement).passivate();
+ }
+ }
+
+ protected void setClosedInternal(final boolean closed) {
+ this.closed = closed;
+ }
+
+ @Override
+ public void setCursorName(final String name) throws SQLException {
+ checkOpen();
+ try {
+ statement.setCursorName(name);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ /**
+ * Sets my delegate.
+ *
+ * @param statement
+ * my delegate.
+ */
+ public void setDelegate(final Statement statement) {
+ this.statement = statement;
+ }
+
+ @Override
+ public void setEscapeProcessing(final boolean enable) throws SQLException {
+ checkOpen();
+ try {
+ statement.setEscapeProcessing(enable);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void setFetchDirection(final int direction) throws SQLException {
+ checkOpen();
+ try {
+ statement.setFetchDirection(direction);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void setFetchSize(final int rows) throws SQLException {
+ checkOpen();
+ try {
+ statement.setFetchSize(rows);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ /**
+ * @since 2.5.0
+ */
+ @Override
+ public void setLargeMaxRows(final long max) throws SQLException {
+ checkOpen();
+ try {
+ statement.setLargeMaxRows(max);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ private void setLastUsedInParent() {
+ if (connection != null) {
+ connection.setLastUsed();
+ }
+ }
+
+ @Override
+ public void setMaxFieldSize(final int max) throws SQLException {
+ checkOpen();
+ try {
+ statement.setMaxFieldSize(max);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void setMaxRows(final int max) throws SQLException {
+ checkOpen();
+ try {
+ statement.setMaxRows(max);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void setPoolable(final boolean poolable) throws SQLException {
+ checkOpen();
+ try {
+ statement.setPoolable(poolable);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ @Override
+ public void setQueryTimeout(final int seconds) throws SQLException {
+ checkOpen();
+ try {
+ statement.setQueryTimeout(seconds);
+ } catch (final SQLException e) {
+ handleException(e);
+ }
+ }
+
+ /**
+ * Returns a String representation of this object.
+ *
+ * @return String
+ */
+ @Override
+ public synchronized String toString() {
+ return statement == null ? "NULL" : statement.toString();
+ }
+
+ @Override
+ public <T> T unwrap(final Class<T> iface) throws SQLException {
+ if (iface.isAssignableFrom(getClass())) {
+ return iface.cast(this);
+ }
+ if (iface.isAssignableFrom(statement.getClass())) {
+ return iface.cast(statement);
+ }
+ return statement.unwrap(iface);
+ }
+}
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
index a79a9019..fbca26ea 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
@@ -364,10 +364,9 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
throw new SQLException("initializeConnection: connection closed");
}
if (null != sqls) {
- try (Statement stmt = conn.createStatement()) {
+ try (Statement statement = conn.createStatement()) {
for (final String sql : sqls) {
- Objects.requireNonNull(sql, "null connectionInitSqls element");
- stmt.execute(sql);
+ statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element"));
}
}
}
diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
index c82910be..1e412bc9 100644
--- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
+++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
@@ -433,10 +433,7 @@ final class PooledConnectionImpl
*/
void notifyListeners() {
final ConnectionEvent event = new ConnectionEvent(this);
- final Object[] listeners = eventListeners.toArray();
- for (final Object listener : listeners) {
- ((ConnectionEventListener) listener).connectionClosed(event);
- }
+ new ArrayList<>(eventListeners).forEach(listener -> listener.connectionClosed(event));
}
/**
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
index f7d9f58a..adf29c33 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@@ -58,10 +57,11 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
public static void closeAll() throws ListException {
// Get iterator to loop over all instances of this data source.
final List<Throwable> exceptionList = new ArrayList<>(INSTANCE_MAP.size());
- for (final Entry<String, InstanceKeyDataSource> next : INSTANCE_MAP.entrySet()) {
+ INSTANCE_MAP.entrySet().forEach(entry -> {
// Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close().
- if (next != null) {
- @SuppressWarnings("resource") final InstanceKeyDataSource value = next.getValue();
+ if (entry != null) {
+ @SuppressWarnings("resource")
+ final InstanceKeyDataSource value = entry.getValue();
if (value != null) {
try {
value.close();
@@ -70,7 +70,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
}
}
}
- }
+ });
INSTANCE_MAP.clear();
if (!exceptionList.isEmpty()) {
throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList);
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
index 486aec16..f419bbce 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
@@ -102,13 +102,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
* @since 2.3.0
*/
public void clear() {
- for (final PooledConnectionManager manager : managers.values()) {
+ managers.values().forEach(manager -> {
try {
getCPDSConnectionFactoryPool(manager).clear();
} catch (final Exception ignored) {
// ignore and try to close others.
}
- }
+ });
InstanceKeyDataSourceFactory.removeInstance(getInstanceKey());
}
@@ -117,12 +117,9 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*
* @see org.apache.commons.pool2.ObjectPool#close()
*/
- @SuppressWarnings("resource")
@Override
public void close() {
- for (final PooledConnectionManager manager : managers.values()) {
- Utils.closeQuietly(getCPDSConnectionFactoryPool(manager));
- }
+ managers.values().forEach(manager -> Utils.closeQuietly(getCPDSConnectionFactoryPool(manager)));
InstanceKeyDataSourceFactory.removeInstance(getInstanceKey());
}