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 2021/05/31 14:40:29 UTC

[commons-dbcp] 02/02: [DBCP-562] Avoid exposing password via JMX #38.

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

commit e89deb37d3bc681c2791b173592d16a3c7c3fdaa
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon May 31 10:40:23 2021 -0400

    [DBCP-562] Avoid exposing password via JMX #38.
    
    This commit is a cleanup version of the PR
    https://patch-diff.githubusercontent.com/raw/apache/commons-dbcp/pull/38.diff
    
    - Fix spelling in private method name: registrateJmxObjectName ->
    registerJmxObjectName.
    - Use @since 2.9.0 <- 2.9
    - Update some Javadocs with links.
    - Order methods in new interface.
---
 src/changes/changes.xml                            |   3 +
 .../org/apache/commons/dbcp2/BasicDataSource.java  |  42 ++-
 .../commons/dbcp2/BasicDataSourceMXBean.java       | 330 +--------------------
 ...DataSourceMXBean.java => DataSourceMXBean.java} | 284 +++++++++---------
 .../apache/commons/dbcp2/TestBasicDataSource.java  |  31 ++
 5 files changed, 207 insertions(+), 483 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 0a697af..5b9fd31 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -77,6 +77,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action dev="ggregory" type="update" due-to="Gary Gregory, DaGeRe">
         Performance Enhancement: Call toArray with Zero Array Size #20.
       </action>
+      <action issue="DBCP-562" dev="ggregory" type="update" due-to="Frank Gasdorf, Gary Gregory">
+        Avoid exposing password via JMX #38.
+      </action>
       <!-- UPDATES -->
       <action dev="ggregory" type="update" due-to="Dependabot">
         Bump mockito-core from 3.5.11 to 3.10.0 #66, #72, #77, #85, #91, #105.
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
index a595439..199078b 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
@@ -40,7 +40,9 @@ import java.util.logging.Logger;
 import javax.management.MBeanRegistration;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
 import javax.management.ObjectName;
+import javax.management.StandardMBean;
 import javax.sql.DataSource;
 
 import org.apache.commons.logging.Log;
@@ -53,10 +55,11 @@ import org.apache.commons.pool2.impl.GenericObjectPool;
 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 
 /**
+ * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties.
+ *
  * <p>
- * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties. This is not
- * the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a "one stop
- * shopping" solution for basic requirements.
+ * This is not the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a
+ * one-stop solution for basic requirements.
  * </p>
  *
  * @since 2.0
@@ -1489,9 +1492,11 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
         if (requestedName == null) {
             return;
         }
+        registeredJmxObjectName = registerJmxObjectName(requestedName, null);
         try {
-            ObjectNameWrapper.wrap(requestedName).registerMBean(this);
-        } catch (final MalformedObjectNameException e) {
+            final StandardMBean standardMBean = new StandardMBean(this, DataSourceMXBean.class);
+            registeredJmxObjectName.registerMBean(standardMBean);
+        } catch (final NotCompliantMBeanException e) {
             log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
         }
     }
@@ -1533,17 +1538,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
 
     @Override
     public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) {
-        final String requestedName = getJmxName();
-        if (requestedName != null) {
-            try {
-                registeredJmxObjectName = ObjectNameWrapper.wrap(requestedName);
-            } catch (final MalformedObjectNameException e) {
-                log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
-            }
-        }
-        if (registeredJmxObjectName == null) {
-            registeredJmxObjectName = ObjectNameWrapper.wrap(objectName);
-        }
+        registeredJmxObjectName = registerJmxObjectName(getJmxName(), objectName);
         return ObjectNameWrapper.unwrap(registeredJmxObjectName);
     }
 
@@ -2459,4 +2454,19 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
         config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX);
     }
 
+    private ObjectNameWrapper registerJmxObjectName(final String requestedName, final ObjectName objectName) {
+        ObjectNameWrapper objectNameWrapper = null;
+        if (requestedName != null) {
+            try {
+                objectNameWrapper = ObjectNameWrapper.wrap(requestedName);
+            } catch (final MalformedObjectNameException e) {
+                log.warn("The requested JMX name '" + requestedName + "' was not valid and will be ignored.");
+            }
+        }
+        if (objectNameWrapper == null) {
+            objectNameWrapper = ObjectNameWrapper.wrap(objectName);
+        }
+        return objectNameWrapper;
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java
index dee386b..8043269 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java
@@ -16,337 +16,23 @@
  */
 package org.apache.commons.dbcp2;
 
-import java.sql.SQLException;
-
 /**
- * Defines the methods that will be made available via JMX.
+ * Interface to keep API compatibility. Methods listed here are not made available to
+ * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html">JMX</a>.
+ * <p>
+ * As of 2.9.0, this interface extends {@link DataSourceMXBean}.
+ * </p>
  *
  * @since 2.0
  */
-public interface BasicDataSourceMXBean {
-
-    /**
-     * See {@link BasicDataSource#getAbandonedUsageTracking()}
-     *
-     * @return {@link BasicDataSource#getAbandonedUsageTracking()}
-     */
-    boolean getAbandonedUsageTracking();
-
-    /**
-     * See {@link BasicDataSource#getDefaultAutoCommit()}
-     *
-     * @return {@link BasicDataSource#getDefaultAutoCommit()}
-     */
-    Boolean getDefaultAutoCommit();
-
-    /**
-     * See {@link BasicDataSource#getDefaultReadOnly()}
-     *
-     * @return {@link BasicDataSource#getDefaultReadOnly()}
-     */
-    Boolean getDefaultReadOnly();
-
-    /**
-     * See {@link BasicDataSource#getDefaultTransactionIsolation()}
-     *
-     * @return {@link BasicDataSource#getDefaultTransactionIsolation()}
-     */
-    int getDefaultTransactionIsolation();
-
-    /**
-     * See {@link BasicDataSource#getDefaultCatalog()}
-     *
-     * @return {@link BasicDataSource#getDefaultCatalog()}
-     */
-    String getDefaultCatalog();
-
-    /**
-     * See {@link BasicDataSource#getDefaultSchema()}
-     *
-     * @return {@link BasicDataSource#getDefaultSchema()}
-     * @since 2.5.0
-     */
-    default String getDefaultSchema() {
-        return null;
-    }
-
-    /**
-     * See {@link BasicDataSource#getCacheState()}
-     *
-     * @return {@link BasicDataSource#getCacheState()}
-     */
-    boolean getCacheState();
-
-    /**
-     * See {@link BasicDataSource#getDriverClassName()}
-     *
-     * @return {@link BasicDataSource#getDriverClassName()}
-     */
-    String getDriverClassName();
-
-    /**
-     * See {@link BasicDataSource#getLifo()}
-     *
-     * @return {@link BasicDataSource#getLifo()}
-     */
-    boolean getLifo();
-
-    /**
-     * See {@link BasicDataSource#getMaxTotal()}
-     *
-     * @return {@link BasicDataSource#getMaxTotal()}
-     */
-    int getMaxTotal();
-
-    /**
-     * See {@link BasicDataSource#getMaxIdle()}
-     *
-     * @return {@link BasicDataSource#getMaxIdle()}
-     */
-    int getMaxIdle();
-
-    /**
-     * See {@link BasicDataSource#getMinIdle()}
-     *
-     * @return {@link BasicDataSource#getMinIdle()}
-     */
-    int getMinIdle();
-
-    /**
-     * See {@link BasicDataSource#getInitialSize()}
-     *
-     * @return {@link BasicDataSource#getInitialSize()}
-     */
-    int getInitialSize();
-
-    /**
-     * See {@link BasicDataSource#getMaxWaitMillis()}
-     *
-     * @return {@link BasicDataSource#getMaxWaitMillis()}
-     */
-    long getMaxWaitMillis();
-
-    /**
-     * See {@link BasicDataSource#isPoolPreparedStatements()}
-     *
-     * @return {@link BasicDataSource#isPoolPreparedStatements()}
-     */
-    boolean isPoolPreparedStatements();
-
-    /**
-     * See {@link BasicDataSource#isClearStatementPoolOnReturn()}
-     *
-     * @return {@link BasicDataSource#isClearStatementPoolOnReturn()}
-     * @since 2.8.0
-     */
-    default boolean isClearStatementPoolOnReturn() {
-        return false;
-    }
-
-    /**
-     * See {@link BasicDataSource#getMaxOpenPreparedStatements()}
-     *
-     * @return {@link BasicDataSource#getMaxOpenPreparedStatements()}
-     */
-    int getMaxOpenPreparedStatements();
-
-    /**
-     * See {@link BasicDataSource#getTestOnCreate()}
-     *
-     * @return {@link BasicDataSource#getTestOnCreate()}
-     */
-    boolean getTestOnCreate();
-
-    /**
-     * See {@link BasicDataSource#getTestOnBorrow()}
-     *
-     * @return {@link BasicDataSource#getTestOnBorrow()}
-     */
-    boolean getTestOnBorrow();
-
-    /**
-     * See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
-     *
-     * @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
-     */
-    long getTimeBetweenEvictionRunsMillis();
-
-    /**
-     * See {@link BasicDataSource#getNumTestsPerEvictionRun()}
-     *
-     * @return {@link BasicDataSource#getNumTestsPerEvictionRun()}
-     */
-    int getNumTestsPerEvictionRun();
-
-    /**
-     * See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
-     *
-     * @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
-     */
-    long getMinEvictableIdleTimeMillis();
-
-    /**
-     * See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
-     *
-     * @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
-     */
-    long getSoftMinEvictableIdleTimeMillis();
-
-    /**
-     * See {@link BasicDataSource#getTestWhileIdle()}
-     *
-     * @return {@link BasicDataSource#getTestWhileIdle()}
-     */
-    boolean getTestWhileIdle();
-
-    /**
-     * See {@link BasicDataSource#getNumActive()}
-     *
-     * @return {@link BasicDataSource#getNumActive()}
-     */
-    int getNumActive();
-
-    /**
-     * See {@link BasicDataSource#getNumIdle()}
-     *
-     * @return {@link BasicDataSource#getNumIdle()}
-     */
-    int getNumIdle();
+public interface BasicDataSourceMXBean extends DataSourceMXBean {
 
     /**
      * See {@link BasicDataSource#getPassword()}
      *
      * @return {@link BasicDataSource#getPassword()}
+     * @deprecated exposing password via JMX is an Information Exposure issue.
      */
+    @Deprecated
     String getPassword();
-
-    /**
-     * See {@link BasicDataSource#getUrl()}
-     *
-     * @return {@link BasicDataSource#getUrl()}
-     */
-    String getUrl();
-
-    /**
-     * See {@link BasicDataSource#getUsername()}
-     *
-     * @return {@link BasicDataSource#getUsername()}
-     */
-    String getUsername();
-
-    /**
-     * See {@link BasicDataSource#getValidationQuery()}
-     *
-     * @return {@link BasicDataSource#getValidationQuery()}
-     */
-    String getValidationQuery();
-
-    /**
-     * See {@link BasicDataSource#getValidationQueryTimeout()}
-     *
-     * @return {@link BasicDataSource#getValidationQueryTimeout()}
-     */
-    int getValidationQueryTimeout();
-
-    /**
-     * See {@link BasicDataSource#getConnectionInitSqlsAsArray()}
-     *
-     * @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}
-     */
-    String[] getConnectionInitSqlsAsArray();
-
-    /**
-     * See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
-     *
-     * @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
-     */
-    boolean isAccessToUnderlyingConnectionAllowed();
-
-    /**
-     * See {@link BasicDataSource#getMaxConnLifetimeMillis()}
-     *
-     * @return {@link BasicDataSource#getMaxConnLifetimeMillis()}
-     */
-    long getMaxConnLifetimeMillis();
-
-    /**
-     * See {@link BasicDataSource#getLogExpiredConnections()}
-     *
-     * @return {@link BasicDataSource#getLogExpiredConnections()}
-     * @since 2.1
-     */
-    boolean getLogExpiredConnections();
-
-    /**
-     * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
-     *
-     * @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
-     */
-    boolean getRemoveAbandonedOnBorrow();
-
-    /**
-     * See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
-     *
-     * @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
-     */
-    boolean getRemoveAbandonedOnMaintenance();
-
-    /**
-     * See {@link BasicDataSource#getRemoveAbandonedTimeout()}
-     *
-     * @return {@link BasicDataSource#getRemoveAbandonedTimeout()}
-     */
-    int getRemoveAbandonedTimeout();
-
-    /**
-     * See {@link BasicDataSource#getLogAbandoned()}
-     *
-     * @return {@link BasicDataSource#getLogAbandoned()}
-     */
-    boolean getLogAbandoned();
-
-    /**
-     * See {@link BasicDataSource#isClosed()}
-     *
-     * @return {@link BasicDataSource#isClosed()}
-     */
-    boolean isClosed();
-
-    /**
-     * See {@link BasicDataSource#getFastFailValidation()}
-     *
-     * @return {@link BasicDataSource#getFastFailValidation()}
-     * @since 2.1
-     */
-    boolean getFastFailValidation();
-
-    /**
-     * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
-     *
-     * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
-     * @since 2.1
-     */
-    String[] getDisconnectionSqlCodesAsArray();
-
-    /**
-     * See {@link BasicDataSource#start()}
-     *
-     * @throws SQLException if an error occurs initializing the datasource
-     *
-     * @since 2.8.0
-     */
-    default void start() throws SQLException {
-        // do nothing
-    }
-
-    /**
-     * See {@link BasicDataSource#restart()}
-     *
-     * @throws SQLException if an error occurs initializing the datasource
-     *
-     * @since 2.8.0
-     */
-    default void restart() throws SQLException {
-        // do nothing by default?
-    }
 }
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
similarity index 62%
copy from src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java
copy to src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
index dee386b..56fb5c8 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java
+++ b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
@@ -19,334 +19,328 @@ package org.apache.commons.dbcp2;
 import java.sql.SQLException;
 
 /**
- * Defines the methods that will be made available via JMX.
+ * Defines the methods that will be made available via
+ * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html">JMX</a>.
  *
- * @since 2.0
+ * @since 2.9.0
  */
-public interface BasicDataSourceMXBean {
+public interface DataSourceMXBean {
 
     /**
-     * See {@link BasicDataSource#getAbandonedUsageTracking()}
+     * See {@link BasicDataSource#getAbandonedUsageTracking()}.
      *
      * @return {@link BasicDataSource#getAbandonedUsageTracking()}
      */
     boolean getAbandonedUsageTracking();
 
     /**
-     * See {@link BasicDataSource#getDefaultAutoCommit()}
+     * See {@link BasicDataSource#getCacheState()}.
      *
-     * @return {@link BasicDataSource#getDefaultAutoCommit()}
+     * @return {@link BasicDataSource#getCacheState()}.
      */
-    Boolean getDefaultAutoCommit();
+    boolean getCacheState();
 
     /**
-     * See {@link BasicDataSource#getDefaultReadOnly()}
+     * See {@link BasicDataSource#getConnectionInitSqlsAsArray()}.
      *
-     * @return {@link BasicDataSource#getDefaultReadOnly()}
+     * @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}.
      */
-    Boolean getDefaultReadOnly();
+    String[] getConnectionInitSqlsAsArray();
 
     /**
-     * See {@link BasicDataSource#getDefaultTransactionIsolation()}
+     * See {@link BasicDataSource#getDefaultAutoCommit()}.
      *
-     * @return {@link BasicDataSource#getDefaultTransactionIsolation()}
+     * @return {@link BasicDataSource#getDefaultAutoCommit()}.
      */
-    int getDefaultTransactionIsolation();
+    Boolean getDefaultAutoCommit();
 
     /**
-     * See {@link BasicDataSource#getDefaultCatalog()}
+     * See {@link BasicDataSource#getDefaultCatalog()}.
      *
-     * @return {@link BasicDataSource#getDefaultCatalog()}
+     * @return {@link BasicDataSource#getDefaultCatalog()}.
      */
     String getDefaultCatalog();
 
     /**
-     * See {@link BasicDataSource#getDefaultSchema()}
-     *
-     * @return {@link BasicDataSource#getDefaultSchema()}
-     * @since 2.5.0
-     */
-    default String getDefaultSchema() {
-        return null;
-    }
-
-    /**
-     * See {@link BasicDataSource#getCacheState()}
+     * See {@link BasicDataSource#getDefaultReadOnly()}.
      *
-     * @return {@link BasicDataSource#getCacheState()}
+     * @return {@link BasicDataSource#getDefaultReadOnly()}.
      */
-    boolean getCacheState();
+    Boolean getDefaultReadOnly();
 
     /**
-     * See {@link BasicDataSource#getDriverClassName()}
+     * See {@link BasicDataSource#getDefaultSchema()}.
      *
-     * @return {@link BasicDataSource#getDriverClassName()}
+     * @return {@link BasicDataSource#getDefaultSchema()}.
+     * @since 2.5.0
      */
-    String getDriverClassName();
+    default String getDefaultSchema() {
+        return null;
+    }
 
     /**
-     * See {@link BasicDataSource#getLifo()}
+     * See {@link BasicDataSource#getDefaultTransactionIsolation()}.
      *
-     * @return {@link BasicDataSource#getLifo()}
+     * @return {@link BasicDataSource#getDefaultTransactionIsolation()}.
      */
-    boolean getLifo();
+    int getDefaultTransactionIsolation();
 
     /**
-     * See {@link BasicDataSource#getMaxTotal()}
+     * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}.
      *
-     * @return {@link BasicDataSource#getMaxTotal()}
+     * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}.
+     * @since 2.1
      */
-    int getMaxTotal();
+    String[] getDisconnectionSqlCodesAsArray();
 
     /**
-     * See {@link BasicDataSource#getMaxIdle()}
+     * See {@link BasicDataSource#getDriverClassName()}.
      *
-     * @return {@link BasicDataSource#getMaxIdle()}
+     * @return {@link BasicDataSource#getDriverClassName()}.
      */
-    int getMaxIdle();
+    String getDriverClassName();
 
     /**
-     * See {@link BasicDataSource#getMinIdle()}
+     * See {@link BasicDataSource#getFastFailValidation()}.
      *
-     * @return {@link BasicDataSource#getMinIdle()}
+     * @return {@link BasicDataSource#getFastFailValidation()}.
+     * @since 2.1
      */
-    int getMinIdle();
+    boolean getFastFailValidation();
 
     /**
-     * See {@link BasicDataSource#getInitialSize()}
+     * See {@link BasicDataSource#getInitialSize()}.
      *
-     * @return {@link BasicDataSource#getInitialSize()}
+     * @return {@link BasicDataSource#getInitialSize()}.
      */
     int getInitialSize();
 
     /**
-     * See {@link BasicDataSource#getMaxWaitMillis()}
+     * See {@link BasicDataSource#getLifo()}.
      *
-     * @return {@link BasicDataSource#getMaxWaitMillis()}
+     * @return {@link BasicDataSource#getLifo()}.
      */
-    long getMaxWaitMillis();
+    boolean getLifo();
 
     /**
-     * See {@link BasicDataSource#isPoolPreparedStatements()}
+     * See {@link BasicDataSource#getLogAbandoned()}.
      *
-     * @return {@link BasicDataSource#isPoolPreparedStatements()}
+     * @return {@link BasicDataSource#getLogAbandoned()}.
      */
-    boolean isPoolPreparedStatements();
+    boolean getLogAbandoned();
 
     /**
-     * See {@link BasicDataSource#isClearStatementPoolOnReturn()}
+     * See {@link BasicDataSource#getLogExpiredConnections()}.
      *
-     * @return {@link BasicDataSource#isClearStatementPoolOnReturn()}
-     * @since 2.8.0
+     * @return {@link BasicDataSource#getLogExpiredConnections()}.
+     * @since 2.1
      */
-    default boolean isClearStatementPoolOnReturn() {
-        return false;
-    }
+    boolean getLogExpiredConnections();
 
     /**
-     * See {@link BasicDataSource#getMaxOpenPreparedStatements()}
+     * See {@link BasicDataSource#getMaxConnLifetimeMillis()}.
      *
-     * @return {@link BasicDataSource#getMaxOpenPreparedStatements()}
+     * @return {@link BasicDataSource#getMaxConnLifetimeMillis()}.
      */
-    int getMaxOpenPreparedStatements();
+    long getMaxConnLifetimeMillis();
 
     /**
-     * See {@link BasicDataSource#getTestOnCreate()}
+     * See {@link BasicDataSource#getMaxIdle()}.
      *
-     * @return {@link BasicDataSource#getTestOnCreate()}
+     * @return {@link BasicDataSource#getMaxIdle()}.
      */
-    boolean getTestOnCreate();
+    int getMaxIdle();
 
     /**
-     * See {@link BasicDataSource#getTestOnBorrow()}
+     * See {@link BasicDataSource#getMaxOpenPreparedStatements()}.
      *
-     * @return {@link BasicDataSource#getTestOnBorrow()}
+     * @return {@link BasicDataSource#getMaxOpenPreparedStatements()}.
      */
-    boolean getTestOnBorrow();
+    int getMaxOpenPreparedStatements();
 
     /**
-     * See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
+     * See {@link BasicDataSource#getMaxTotal()}.
      *
-     * @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
+     * @return {@link BasicDataSource#getMaxTotal()}.
      */
-    long getTimeBetweenEvictionRunsMillis();
+    int getMaxTotal();
 
     /**
-     * See {@link BasicDataSource#getNumTestsPerEvictionRun()}
+     * See {@link BasicDataSource#getMaxWaitMillis()}.
      *
-     * @return {@link BasicDataSource#getNumTestsPerEvictionRun()}
+     * @return {@link BasicDataSource#getMaxWaitMillis()}.
      */
-    int getNumTestsPerEvictionRun();
+    long getMaxWaitMillis();
 
     /**
-     * See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
+     * See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}.
      *
-     * @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
+     * @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}.
      */
     long getMinEvictableIdleTimeMillis();
 
     /**
-     * See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
+     * See {@link BasicDataSource#getMinIdle()}.
      *
-     * @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
+     * @return {@link BasicDataSource#getMinIdle()}.
      */
-    long getSoftMinEvictableIdleTimeMillis();
+    int getMinIdle();
 
     /**
-     * See {@link BasicDataSource#getTestWhileIdle()}
+     * See {@link BasicDataSource#getNumActive()}.
      *
-     * @return {@link BasicDataSource#getTestWhileIdle()}
+     * @return {@link BasicDataSource#getNumActive()}.
      */
-    boolean getTestWhileIdle();
+    int getNumActive();
 
     /**
-     * See {@link BasicDataSource#getNumActive()}
+     * See {@link BasicDataSource#getNumIdle()}.
      *
-     * @return {@link BasicDataSource#getNumActive()}
+     * @return {@link BasicDataSource#getNumIdle()}.
      */
-    int getNumActive();
+    int getNumIdle();
 
     /**
-     * See {@link BasicDataSource#getNumIdle()}
+     * See {@link BasicDataSource#getNumTestsPerEvictionRun()}.
      *
-     * @return {@link BasicDataSource#getNumIdle()}
+     * @return {@link BasicDataSource#getNumTestsPerEvictionRun()}.
      */
-    int getNumIdle();
+    int getNumTestsPerEvictionRun();
 
     /**
-     * See {@link BasicDataSource#getPassword()}
+     * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}.
      *
-     * @return {@link BasicDataSource#getPassword()}
+     * @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}.
      */
-    String getPassword();
+    boolean getRemoveAbandonedOnBorrow();
 
     /**
-     * See {@link BasicDataSource#getUrl()}
+     * See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}.
      *
-     * @return {@link BasicDataSource#getUrl()}
+     * @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}.
      */
-    String getUrl();
+    boolean getRemoveAbandonedOnMaintenance();
 
     /**
-     * See {@link BasicDataSource#getUsername()}
+     * See {@link BasicDataSource#getRemoveAbandonedTimeout()}.
      *
-     * @return {@link BasicDataSource#getUsername()}
+     * @return {@link BasicDataSource#getRemoveAbandonedTimeout()}.
      */
-    String getUsername();
+    int getRemoveAbandonedTimeout();
 
     /**
-     * See {@link BasicDataSource#getValidationQuery()}
+     * See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}.
      *
-     * @return {@link BasicDataSource#getValidationQuery()}
+     * @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}.
      */
-    String getValidationQuery();
+    long getSoftMinEvictableIdleTimeMillis();
 
     /**
-     * See {@link BasicDataSource#getValidationQueryTimeout()}
+     * See {@link BasicDataSource#getTestOnBorrow()}.
      *
-     * @return {@link BasicDataSource#getValidationQueryTimeout()}
+     * @return {@link BasicDataSource#getTestOnBorrow()}.
      */
-    int getValidationQueryTimeout();
+    boolean getTestOnBorrow();
 
     /**
-     * See {@link BasicDataSource#getConnectionInitSqlsAsArray()}
+     * See {@link BasicDataSource#getTestOnCreate()}.
      *
-     * @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}
+     * @return {@link BasicDataSource#getTestOnCreate()}.
      */
-    String[] getConnectionInitSqlsAsArray();
+    boolean getTestOnCreate();
 
     /**
-     * See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
+     * See {@link BasicDataSource#getTestWhileIdle()}.
      *
-     * @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
+     * @return {@link BasicDataSource#getTestWhileIdle()}.
      */
-    boolean isAccessToUnderlyingConnectionAllowed();
+    boolean getTestWhileIdle();
 
     /**
-     * See {@link BasicDataSource#getMaxConnLifetimeMillis()}
+     * See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}.
      *
-     * @return {@link BasicDataSource#getMaxConnLifetimeMillis()}
+     * @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}.
      */
-    long getMaxConnLifetimeMillis();
+    long getTimeBetweenEvictionRunsMillis();
 
     /**
-     * See {@link BasicDataSource#getLogExpiredConnections()}
+     * See {@link BasicDataSource#getUrl()}.
      *
-     * @return {@link BasicDataSource#getLogExpiredConnections()}
-     * @since 2.1
+     * @return {@link BasicDataSource#getUrl()}.
      */
-    boolean getLogExpiredConnections();
+    String getUrl();
 
     /**
-     * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
+     * See {@link BasicDataSource#getUsername()}.
      *
-     * @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
+     * @return {@link BasicDataSource#getUsername()}.
      */
-    boolean getRemoveAbandonedOnBorrow();
+    String getUsername();
 
     /**
-     * See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
+     * See {@link BasicDataSource#getValidationQuery()}.
      *
-     * @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
+     * @return {@link BasicDataSource#getValidationQuery()}.
      */
-    boolean getRemoveAbandonedOnMaintenance();
+    String getValidationQuery();
 
     /**
-     * See {@link BasicDataSource#getRemoveAbandonedTimeout()}
+     * See {@link BasicDataSource#getValidationQueryTimeout()}.
      *
-     * @return {@link BasicDataSource#getRemoveAbandonedTimeout()}
+     * @return {@link BasicDataSource#getValidationQueryTimeout()}.
      */
-    int getRemoveAbandonedTimeout();
+    int getValidationQueryTimeout();
 
     /**
-     * See {@link BasicDataSource#getLogAbandoned()}
+     * See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}.
      *
-     * @return {@link BasicDataSource#getLogAbandoned()}
+     * @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}.
      */
-    boolean getLogAbandoned();
+    boolean isAccessToUnderlyingConnectionAllowed();
 
     /**
-     * See {@link BasicDataSource#isClosed()}
+     * See {@link BasicDataSource#isClearStatementPoolOnReturn()}.
      *
-     * @return {@link BasicDataSource#isClosed()}
+     * @return {@link BasicDataSource#isClearStatementPoolOnReturn()}.
+     * @since 2.8.0
      */
-    boolean isClosed();
+    default boolean isClearStatementPoolOnReturn() {
+        return false;
+    }
 
     /**
-     * See {@link BasicDataSource#getFastFailValidation()}
+     * See {@link BasicDataSource#isClosed()}.
      *
-     * @return {@link BasicDataSource#getFastFailValidation()}
-     * @since 2.1
+     * @return {@link BasicDataSource#isClosed()}.
      */
-    boolean getFastFailValidation();
+    boolean isClosed();
 
     /**
-     * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
+     * See {@link BasicDataSource#isPoolPreparedStatements()}.
      *
-     * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
-     * @since 2.1
+     * @return {@link BasicDataSource#isPoolPreparedStatements()}.
      */
-    String[] getDisconnectionSqlCodesAsArray();
+    boolean isPoolPreparedStatements();
 
     /**
-     * See {@link BasicDataSource#start()}
+     * See {@link BasicDataSource#restart()}
      *
-     * @throws SQLException if an error occurs initializing the datasource
+     * @throws SQLException if an error occurs initializing the data source.
      *
      * @since 2.8.0
      */
-    default void start() throws SQLException {
-        // do nothing
+    default void restart() throws SQLException {
+        // do nothing by default?
     }
 
     /**
-     * See {@link BasicDataSource#restart()}
+     * See {@link BasicDataSource#start()}
      *
-     * @throws SQLException if an error occurs initializing the datasource
+     * @throws SQLException if an error occurs initializing the data source.
      *
      * @since 2.8.0
      */
-    default void restart() throws SQLException {
-        // do nothing by default?
+    default void start() throws SQLException {
+        // do nothing
     }
 }
diff --git a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
index dbcb794..d8964c4 100644
--- a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
+++ b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -36,6 +37,8 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.management.AttributeNotFoundException;
+import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.sql.DataSource;
@@ -1017,6 +1020,34 @@ public class TestBasicDataSource extends TestConnectionPool {
         assertEquals(1, ds.getNumIdle());
         ds.close();
     }
+
+    /**
+     * Tests JIRA <a href="https://issues.apache.org/jira/browse/DBCP-562">DBCP-562</a>.
+     * <p>
+     * Make sure Password Attribute is not exported via JMXBean.
+     * </p>
+     */
+    @Test
+    public void testJmxDoesNotExposePassword() throws Exception {
+        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+        try (Connection c = ds.getConnection()) {
+            // nothing
+        }
+        final ObjectName objectName = new ObjectName(ds.getJmxName());
+
+        final MBeanAttributeInfo[] attributes = mbs.getMBeanInfo(objectName).getAttributes();
+
+        assertTrue(attributes != null && attributes.length > 0);
+
+        Arrays.asList(attributes).forEach(attrInfo -> {
+            assertFalse("password".equalsIgnoreCase(attrInfo.getName()));
+        });
+
+        assertThrows(AttributeNotFoundException.class, () -> {
+            mbs.getAttribute(objectName, "Password");
+        });
+    }
 }