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]
