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 511461d4 Refactor duplicate pattern using AbandonedTrace
511461d4 is described below
commit 511461d4d0bb2dab381a258e851199135ed8edae
Author: Gary Gregory <[email protected]>
AuthorDate: Sun Jul 10 14:57:47 2022 -0400
Refactor duplicate pattern using AbandonedTrace
---
.../org/apache/commons/dbcp2/AbandonedTrace.java | 428 +++++++++++----------
.../apache/commons/dbcp2/DelegatingConnection.java | 8 +-
.../commons/dbcp2/DelegatingPreparedStatement.java | 14 +-
.../apache/commons/dbcp2/DelegatingStatement.java | 16 +-
4 files changed, 237 insertions(+), 229 deletions(-)
diff --git a/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java
b/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java
index 75a7034b..2c7629f7 100644
--- a/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java
+++ b/src/main/java/org/apache/commons/dbcp2/AbandonedTrace.java
@@ -1,201 +1,227 @@
-/*
- * 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.lang.ref.WeakReference;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.pool2.TrackedUse;
-
-/**
- * Tracks connection usage for recovering and reporting abandoned connections.
- * <p>
- * The JDBC Connection, Statement, and ResultSet classes extend this class.
- * </p>
- *
- * @since 2.0
- */
-public class AbandonedTrace implements TrackedUse {
-
- /** A list of objects created by children of this object. */
- private final List<WeakReference<AbandonedTrace>> traceList = new
ArrayList<>();
-
- /** Last time this connection was used. */
- private volatile Instant lastUsedInstant = Instant.EPOCH;
-
- /**
- * Creates a new AbandonedTrace without config and without doing abandoned
tracing.
- */
- public AbandonedTrace() {
- init(null);
- }
-
- /**
- * Constructs a new AbandonedTrace with a parent object.
- *
- * @param parent
- * AbandonedTrace parent object.
- */
- public AbandonedTrace(final AbandonedTrace parent) {
- init(parent);
- }
-
- /**
- * Adds an object to the list of objects being traced.
- *
- * @param trace
- * AbandonedTrace object to add.
- */
- protected void addTrace(final AbandonedTrace trace) {
- synchronized (this.traceList) {
- this.traceList.add(new WeakReference<>(trace));
- }
- setLastUsed();
- }
-
- /**
- * Clears the list of objects being traced by this object.
- */
- protected void clearTrace() {
- synchronized (this.traceList) {
- this.traceList.clear();
- }
- }
-
- /**
- * Gets the last time this object was used in milliseconds.
- *
- * @return long time in milliseconds.
- */
- @Override
- @Deprecated
- public long getLastUsed() {
- return lastUsedInstant.toEpochMilli();
- }
-
- @Override
- public Instant getLastUsedInstant() {
- return lastUsedInstant;
- }
-
- /**
- * Gets a list of objects being traced by this object.
- *
- * @return List of objects.
- */
- protected List<AbandonedTrace> getTrace() {
- final int size = traceList.size();
- if (size == 0) {
- return Collections.emptyList();
- }
- final ArrayList<AbandonedTrace> result = new ArrayList<>(size);
- synchronized (this.traceList) {
- final Iterator<WeakReference<AbandonedTrace>> iter =
traceList.iterator();
- while (iter.hasNext()) {
- final AbandonedTrace trace = iter.next().get();
- if (trace == null) {
- // Clean-up since we are here anyway
- iter.remove();
- } else {
- result.add(trace);
- }
- }
- }
- return result;
- }
-
- /**
- * Initializes abandoned tracing for this object.
- *
- * @param parent
- * AbandonedTrace parent object.
- */
- private void init(final AbandonedTrace parent) {
- if (parent != null) {
- parent.addTrace(this);
- }
- }
-
- /**
- * Removes this object the source object is tracing.
- *
- * @param source The object tracing
- * @since 2.7.0
- */
- protected void removeThisTrace(final Object source) {
- if (source instanceof AbandonedTrace) {
- AbandonedTrace.class.cast(source).removeTrace(this);
- }
- }
-
- /**
- * Removes a child object this object is tracing.
- *
- * @param trace
- * AbandonedTrace object to remove.
- */
- protected void removeTrace(final AbandonedTrace trace) {
- synchronized (this.traceList) {
- final Iterator<WeakReference<AbandonedTrace>> iter =
traceList.iterator();
- while (iter.hasNext()) {
- final AbandonedTrace traceInList = iter.next().get();
- if (trace != null && trace.equals(traceInList)) {
- iter.remove();
- break;
- }
- if (traceInList == null) {
- // Clean-up since we are here anyway
- iter.remove();
- }
- }
- }
- }
-
- /**
- * Sets the time this object was last used to the current time in
milliseconds.
- */
- protected void setLastUsed() {
- lastUsedInstant = Instant.now();
- }
-
- /**
- * Sets the instant this object was last used.
- *
- * @param lastUsedInstant
- * instant.
- * @since 2.10.0
- */
- protected void setLastUsed(final Instant lastUsedInstant) {
- this.lastUsedInstant = lastUsedInstant;
- }
-
- /**
- * Sets the time in milliseconds this object was last used.
- *
- * @param lastUsedMillis
- * time in milliseconds.
- * @deprecated Use {@link #setLastUsed(Instant)}
- */
- @Deprecated
- protected void setLastUsed(final long lastUsedMillis) {
- this.lastUsedInstant = Instant.ofEpochMilli(lastUsedMillis);
- }
-}
+/*
+ * 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.lang.ref.WeakReference;
+import java.sql.SQLException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.apache.commons.pool2.TrackedUse;
+
+/**
+ * Tracks connection usage for recovering and reporting abandoned connections.
+ * <p>
+ * The JDBC Connection, Statement, and ResultSet classes extend this class.
+ * </p>
+ *
+ * @since 2.0
+ */
+public class AbandonedTrace implements TrackedUse {
+
+ /** A list of objects created by children of this object. */
+ private final List<WeakReference<AbandonedTrace>> traceList = new
ArrayList<>();
+
+ /** Last time this connection was used. */
+ private volatile Instant lastUsedInstant = Instant.EPOCH;
+
+ /**
+ * Creates a new AbandonedTrace without config and without doing abandoned
tracing.
+ */
+ public AbandonedTrace() {
+ init(null);
+ }
+
+ /**
+ * Constructs a new AbandonedTrace with a parent object.
+ *
+ * @param parent
+ * AbandonedTrace parent object.
+ */
+ public AbandonedTrace(final AbandonedTrace parent) {
+ init(parent);
+ }
+
+ /**
+ * Adds an object to the list of objects being traced.
+ *
+ * @param trace
+ * AbandonedTrace object to add.
+ */
+ protected void addTrace(final AbandonedTrace trace) {
+ synchronized (this.traceList) {
+ this.traceList.add(new WeakReference<>(trace));
+ }
+ setLastUsed();
+ }
+
+ /**
+ * Clears the list of objects being traced by this object.
+ */
+ protected void clearTrace() {
+ synchronized (this.traceList) {
+ this.traceList.clear();
+ }
+ }
+
+ /**
+ * Subclasses can implement this nop.
+ *
+ * @throws SQLException Ignored here, for subclasses.
+ * @since 2.10.0
+ */
+ protected void close() throws SQLException {
+ // nop
+ }
+
+ /**
+ * Calls {@link #close()} and if an exception is caught, then {@code
exceptionHandler}.
+ *
+ * @param exceptionHandler Consumes exception thrown closing this resource.
+ * @since 2.10.0
+ */
+ protected void close(final Consumer<Exception> exceptionHandler) {
+ try {
+ close();
+ } catch (final Exception e) {
+ exceptionHandler.accept(e);
+ }
+ }
+
+ /**
+ * Gets the last time this object was used in milliseconds.
+ *
+ * @return long time in milliseconds.
+ */
+ @Override
+ @Deprecated
+ public long getLastUsed() {
+ return lastUsedInstant.toEpochMilli();
+ }
+
+ @Override
+ public Instant getLastUsedInstant() {
+ return lastUsedInstant;
+ }
+
+ /**
+ * Gets a list of objects being traced by this object.
+ *
+ * @return List of objects.
+ */
+ protected List<AbandonedTrace> getTrace() {
+ final int size = traceList.size();
+ if (size == 0) {
+ return Collections.emptyList();
+ }
+ final ArrayList<AbandonedTrace> result = new ArrayList<>(size);
+ synchronized (this.traceList) {
+ final Iterator<WeakReference<AbandonedTrace>> iter =
traceList.iterator();
+ while (iter.hasNext()) {
+ final AbandonedTrace trace = iter.next().get();
+ if (trace == null) {
+ // Clean-up since we are here anyway
+ iter.remove();
+ } else {
+ result.add(trace);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Initializes abandoned tracing for this object.
+ *
+ * @param parent
+ * AbandonedTrace parent object.
+ */
+ private void init(final AbandonedTrace parent) {
+ if (parent != null) {
+ parent.addTrace(this);
+ }
+ }
+
+ /**
+ * Removes this object the source object is tracing.
+ *
+ * @param source The object tracing
+ * @since 2.7.0
+ */
+ protected void removeThisTrace(final Object source) {
+ if (source instanceof AbandonedTrace) {
+ AbandonedTrace.class.cast(source).removeTrace(this);
+ }
+ }
+
+ /**
+ * Removes a child object this object is tracing.
+ *
+ * @param trace
+ * AbandonedTrace object to remove.
+ */
+ protected void removeTrace(final AbandonedTrace trace) {
+ synchronized (this.traceList) {
+ final Iterator<WeakReference<AbandonedTrace>> iter =
traceList.iterator();
+ while (iter.hasNext()) {
+ final AbandonedTrace traceInList = iter.next().get();
+ if (trace != null && trace.equals(traceInList)) {
+ iter.remove();
+ break;
+ }
+ if (traceInList == null) {
+ // Clean-up since we are here anyway
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the time this object was last used to the current time in
milliseconds.
+ */
+ protected void setLastUsed() {
+ lastUsedInstant = Instant.now();
+ }
+
+ /**
+ * Sets the instant this object was last used.
+ *
+ * @param lastUsedInstant
+ * instant.
+ * @since 2.10.0
+ */
+ protected void setLastUsed(final Instant lastUsedInstant) {
+ this.lastUsedInstant = lastUsedInstant;
+ }
+
+ /**
+ * Sets the time in milliseconds this object was last used.
+ *
+ * @param lastUsedMillis
+ * time in milliseconds.
+ * @deprecated Use {@link #setLastUsed(Instant)}
+ */
+ @Deprecated
+ protected void setLastUsed(final long lastUsedMillis) {
+ this.lastUsedInstant = Instant.ofEpochMilli(lastUsedMillis);
+ }
+}
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
index 66c8481f..654eb78c 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
@@ -653,13 +653,7 @@ public class DelegatingConnection<C extends Connection>
extends AbandonedTrace i
final List<AbandonedTrace> traceList = getTrace();
if (traceList != null && !traceList.isEmpty()) {
final List<Exception> thrownList = new ArrayList<>();
-
traceList.stream().filter(AutoCloseable.class::isInstance).forEach(trace -> {
- try {
- ((AutoCloseable) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- });
+ traceList.forEach(trace -> trace.close(thrownList::add));
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 78e868b0..e1b06ca8 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingPreparedStatement.java
@@ -702,18 +702,10 @@ public class DelegatingPreparedStatement extends
DelegatingStatement implements
// ResultSet's when it is closed.
// FIXME The PreparedStatement we're wrapping should handle this for
us.
// See DBCP-10 for what could happen when ResultSets are closed twice.
- final List<AbandonedTrace> resultSetList = getTrace();
- if (resultSetList != null) {
+ final List<AbandonedTrace> traceList = getTrace();
+ if (traceList != null) {
final List<Exception> thrownList = new ArrayList<>();
- resultSetList.forEach(trace -> {
- if (trace instanceof AutoCloseable) {
- try {
- ((AutoCloseable) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- }
- });
+ traceList.forEach(trace -> trace.close(thrownList::add));
clearTrace();
if (!thrownList.isEmpty()) {
throw new SQLExceptionList(thrownList);
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
index cf05106a..7b751ec2 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingStatement.java
@@ -139,17 +139,13 @@ public class DelegatingStatement extends AbandonedTrace
implements Statement {
// 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);
+ traceList.forEach(trace -> trace.close(e -> {
+ if (connection != null) {
+ // Does not rethrow e.
+ connection.handleExceptionNoThrow(e);
}
- });
+ thrownList.add(e);
+ }));
clearTrace();
}
if (statement != null) {