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) {

Reply via email to