This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 82cca0857661e7de7180c98debbc8bab786fb66c
Author: opencode <[email protected]>
AuthorDate: Tue Nov 3 09:19:05 2026 +0100

    Put PoolUtilities' copy semantics fully in its javadoc
    
    The two methods documented neither their null-argument behavior nor the
    edges of their copy: what happens to a non-String value held only in the
    source's defaults table (it appears nowhere in the copy, because neither
    source nor copy resolves it), and that the copy is per-key best effort
    against a concurrently modified source - removed entries may still be
    copied, added ones only if present when the source was sampled - which
    is why a caller needing a consistent snapshot must serialize it, as the
    connect path now does. The clone @return also promised more than the copy
    delivers: it carries every String the source resolves and its other
    direct entries, not all entries.
    
    No behavioral change: javadoc and @throws only, with the in-code comment
    of the materialization pass trimmed to defer the precedence rule to the
    javadoc rather than restate it.
---
 .../org/apache/tomcat/jdbc/pool/PoolUtilities.java | 60 ++++++++++++++--------
 1 file changed, 38 insertions(+), 22 deletions(-)

diff --git 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
index fbc8117377..b797ac16f3 100644
--- 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
+++ 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
@@ -19,7 +19,9 @@ package org.apache.tomcat.jdbc.pool;
 import java.util.Properties;
 
 /**
- * Utility methods for managing JDBC pool properties.
+ * Utility methods for managing JDBC pool properties: the copy the connect
+ * path hands to the JDBC driver, and the password-masked copies the JMX and
+ * bean property getters expose, are all built here.
  */
 public class PoolUtilities {
 
@@ -43,33 +45,41 @@ public class PoolUtilities {
      * Creates a shallow copy of the given properties. Entries that the source
      * resolves to a String through a defaults table are materialized into the
      * copy as plain values, so the copy resolves every String the source
-     * resolves and needs no defaults table of its own. A String directly
-     * present in the source under the same key shadows the defaults there and
-     * takes precedence in the copy. A non-String directly present value
-     * shadows nothing, because {@link Properties#getProperty(String)} falls
-     * through to the defaults whenever the direct value is not a String, so
-     * where the source resolves a String under such a key the resolved String
-     * takes its place in the copy; entries the source resolves to no String
-     * are copied as they are. The defaults table itself is not carried over.
+     * resolves and needs no defaults table of its own; the defaults table
+     * itself is not carried over. A String directly present in the source
+     * under the same key shadows the defaults there and takes precedence in
+     * the copy. A non-String directly present value shadows nothing, because
+     * {@link Properties#getProperty(String)} falls through to the defaults
+     * whenever the direct value is not a String, so where the source resolves
+     * a String under such a key the resolved String takes its place in the
+     * copy; entries the source resolves to no String are copied as they are,
+     * and a non-String held only in a defaults table - which neither the
+     * source nor the copy resolves - does not appear in the copy at all.
+     * <p>
+     * The copy is per-key best effort against a source modified concurrently:
+     * an entry the modification removes may still be copied, and an entry it
+     * adds is copied only if it was already there when the copy sampled the
+     * source. A caller that needs the copy to show one state the source was
+     * actually in must serialize it against the modifications itself.
      *
-     * @param p the properties to clone
+     * @param p the properties to clone, not {@code null}
      *
-     * @return a new Properties instance containing all entries from the source
+     * @return a new Properties instance, without a defaults table, resolving
+     *         every String the source resolves and carrying over its other
+     *         direct entries
+     *
+     * @throws NullPointerException if the source is {@code null}
      */
     public static Properties clone(Properties p) {
         Properties c = new Properties();
         c.putAll(p);
         // putAll(...) copies only the entries directly present in the source,
         // so materialize the String values the source resolves through
-        // defaults. Re-read each value from the source: stringPropertyNames()
-        // is only a snapshot and the source may be modified concurrently, so
-        // a snapshotted key may resolve to nothing by the time it is read.
-        // Skip only a directly copied String, which is what the source
-        // resolves too; a non-String directly copied value resolves to
-        // nothing on its own - getProperty(...) only falls through to the
-        // defaults when the direct value is not a String - so the value the
-        // source resolves replaces it, keeping the copy able to resolve every
-        // String the source resolves
+        // defaults; the precedence rule deciding which of them are skipped is
+        // the javadoc's. Re-read each value from the source:
+        // stringPropertyNames() is only a snapshot and the source may be
+        // modified concurrently, so a snapshotted key may resolve to nothing
+        // by the time it is read
         for (String key : p.stringPropertyNames()) {
             String value = p.getProperty(key);
             if (value != null && !(c.get(key) instanceof String)) {
@@ -80,11 +90,17 @@ public class PoolUtilities {
     }
 
     /**
-     * Creates a copy of the given properties with the password entry removed.
+     * Creates a copy of the given properties as {@link #clone(Properties)}
+     * does, with the password entry removed. The copy carries no defaults
+     * table, so the removal also reaches a password the source only resolved
+     * through its defaults - a reference copy would let the remove walk past
+     * the defaults table and leave the password resolvable.
      *
-     * @param p the properties to clone
+     * @param p the properties to clone, not {@code null}
      *
      * @return a new Properties instance with all entries except the password
+     *
+     * @throws NullPointerException if the source is {@code null}
      */
     public static Properties cloneWithoutPassword(Properties p) {
         Properties result = clone(p);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to