loginmodules/password/authenticators/jdbc/src/main/java/org/beiter/michael/authn/jaas/loginmodules/password/authenticators/jdbc/propsbuilder/JaasBasedConnPropsBuilder.java
public static ConnectionProperties build(final Map<String, ?> properties) {

        Validate.notNull(properties, "The validated object 'properties' is null");

        // tmpConfig now holds all the configuration values with the keys expected by the Util libs connection
        // properties builder. We will let that library do all the hard work of setting reasonable defaults and
        // dealing with null values.
        // For this, we first try to copy the entire map to a Map<String, String> map (because this is what the builder
        // we will be using requires), and then ALSO copy the values that are in the Map and that we care about to the
        // same map, potentially overwriting values that may already be there (e.g. if the user has configured them
        // under a key that coincidentally collides with a key that we care about).

        final Map<String, String> tmpConfig = new ConcurrentHashMap<>();

        // first try to copy all the values in the map. We know that they are all of the same type, but we do not know
        // what that type is. Let's reasonably assume that they are Strings (not sure if the JAAS configuration
        // mechanism allows anything else), and just cast them. If the cast fails, we will fail the entire operation:
        try {
            for (final Map.Entry<String, ?> entry : properties.entrySet()) {
                final String key = entry.getKey();
                final String value = (String) entry.getValue();

                if (value != null) {
                    tmpConfig.put(key, value);
                }
            }
        } catch (ClassCastException e) {
            final String error = "The values of the configured JAAS properties must be Strings. "
                    + "Sorry, but we do not support anything else here!";
            throw new IllegalArgumentException(error, e);
        }

        // second, we copy the values that we care about from the "JAAS config namespace" to the "Connection namespace":
        copyValue(properties, KEY_DRIVER, tmpConfig, MapBasedConnPropsBuilder.KEY_DRIVER);
        copyValue(properties, KEY_URL, tmpConfig, MapBasedConnPropsBuilder.KEY_URL);
        copyValue(properties, KEY_USERNAME, tmpConfig, MapBasedConnPropsBuilder.KEY_USERNAME);
        copyValue(properties, KEY_PASSWORD, tmpConfig, MapBasedConnPropsBuilder.KEY_PASSWORD);
        copyValue(properties, KEY_MAX_TOTAL, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_TOTAL);
        copyValue(properties, KEY_MAX_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_IDLE);
        copyValue(properties, KEY_MIN_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_MIN_IDLE);
        copyValue(properties, KEY_MAX_WAIT_MILLIS, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_WAIT_MILLIS);
        copyValue(properties, KEY_TEST_ON_CREATE, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_CREATE);
        copyValue(properties, KEY_TEST_ON_BORROW, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_BORROW);
        copyValue(properties, KEY_TEST_ON_RETURN, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_RETURN);
        copyValue(properties, KEY_TEST_WHILE_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_WHILE_IDLE);
        copyValue(properties, KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
        copyValue(properties, KEY_NUM_TESTS_PER_EVICITON_RUN,
                tmpConfig, MapBasedConnPropsBuilder.KEY_NUM_TESTS_PER_EVICITON_RUN);
        copyValue(properties, KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS);
        copyValue(properties, KEY_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
        copyValue(properties, KEY_LIFO, tmpConfig, MapBasedConnPropsBuilder.KEY_LIFO);
        copyValue(properties, KEY_AUTO_COMMIT, tmpConfig, MapBasedConnPropsBuilder.KEY_AUTO_COMMIT);
        copyValue(properties, KEY_READ_ONLY, tmpConfig, MapBasedConnPropsBuilder.KEY_READ_ONLY);
        copyValue(properties, KEY_TRANSACTION_ISOLATION, tmpConfig, MapBasedConnPropsBuilder.KEY_TRANSACTION_ISOLATION);
        copyValue(properties, KEY_CACHE_STATE, tmpConfig, MapBasedConnPropsBuilder.KEY_CACHE_STATE);
        copyValue(properties, KEY_VALIDATION_QUERY, tmpConfig, MapBasedConnPropsBuilder.KEY_VALIDATION_QUERY);
        copyValue(properties, KEY_MAX_CONN_LIFETIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_CONN_LIFETIME_MILLIS);


        return MapBasedConnPropsBuilder.build(tmpConfig);
    }
public static ConnectionProperties build(final Map<String, ?> properties) {

        Validate.notNull(properties, "The validated object 'properties' is null");

        // tmpConfig now holds all the configuration values with the keys expected by the Util libs connection
        // properties builder. We will let that library do all the hard work of setting reasonable defaults and
        // dealing with null values.
        // For this, we first try to copy the entire map to a Map<String, String> map (because this is what the builder
        // we will be using requires), and then ALSO copy the values that are in the Map and that we care about to the
        // same map, potentially overwriting values that may already be there (e.g. if the user has configured them
        // under a key that coincidentally collides with a key that we care about).

        final Map<String, String> tmpConfig = new ConcurrentHashMap<>();

        // first try to copy all the values in the map. We know that they are all of the same type, but we do not know
        // what that type is. Let's reasonably assume that they are Strings (not sure if the JAAS configuration
        // mechanism allows anything else), and just cast them. If the cast fails, we will fail the entire operation:
        try {
            for (final Map.Entry<String, ?> entry : properties.entrySet()) {
                final String key = entry.getKey();
                final String value = (String) entry.getValue();

                if (value != null) {
                    tmpConfig.put(key, value);
                }
            }
        } catch (ClassCastException e) {
            final String error = "The values of the configured JAAS properties must be Strings. "
                    + "Sorry, but we do not support anything else here!";
            throw new IllegalArgumentException(error, e);
        }

        // second, we copy the values that we care about from the "JAAS config namespace" to the "Connection namespace":
        copyValue(properties, KEY_DRIVER, tmpConfig, MapBasedConnPropsBuilder.KEY_DRIVER);
        copyValue(properties, KEY_URL, tmpConfig, MapBasedConnPropsBuilder.KEY_URL);
        copyValue(properties, KEY_USERNAME, tmpConfig, MapBasedConnPropsBuilder.KEY_USERNAME);
        copyValue(properties, KEY_PASSWORD, tmpConfig, MapBasedConnPropsBuilder.KEY_PASSWORD);
        copyValue(properties, KEY_MAX_TOTAL, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_TOTAL);
        copyValue(properties, KEY_MAX_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_IDLE);
        copyValue(properties, KEY_MIN_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_MIN_IDLE);
        copyValue(properties, KEY_MAX_WAIT_MILLIS, tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_WAIT_MILLIS);
        copyValue(properties, KEY_TEST_ON_CREATE, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_CREATE);
        copyValue(properties, KEY_TEST_ON_BORROW, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_BORROW);
        copyValue(properties, KEY_TEST_ON_RETURN, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_ON_RETURN);
        copyValue(properties, KEY_TEST_WHILE_IDLE, tmpConfig, MapBasedConnPropsBuilder.KEY_TEST_WHILE_IDLE);
        copyValue(properties, KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
        copyValue(properties, KEY_NUM_TESTS_PER_EVICITON_RUN,
                tmpConfig, MapBasedConnPropsBuilder.KEY_NUM_TESTS_PER_EVICITON_RUN);
        copyValue(properties, KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_MIN_EVICTABLE_IDLE_TIME_MILLIS);
        copyValue(properties, KEY_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
        copyValue(properties, KEY_LIFO, tmpConfig, MapBasedConnPropsBuilder.KEY_LIFO);
        copyValue(properties, KEY_AUTO_COMMIT, tmpConfig, MapBasedConnPropsBuilder.KEY_AUTO_COMMIT);
        copyValue(properties, KEY_READ_ONLY, tmpConfig, MapBasedConnPropsBuilder.KEY_READ_ONLY);
        copyValue(properties, KEY_TRANSACTION_ISOLATION, tmpConfig, MapBasedConnPropsBuilder.KEY_TRANSACTION_ISOLATION);
        copyValue(properties, KEY_CACHE_STATE, tmpConfig, MapBasedConnPropsBuilder.KEY_CACHE_STATE);
        copyValue(properties, KEY_VALIDATION_QUERY, tmpConfig, MapBasedConnPropsBuilder.KEY_VALIDATION_QUERY);
        copyValue(properties, KEY_MAX_CONN_LIFETIME_MILLIS,
                tmpConfig, MapBasedConnPropsBuilder.KEY_MAX_CONN_LIFETIME_MILLIS);


        return MapBasedConnPropsBuilder.build(tmpConfig);
    }
Initialize a set of connection properties based on key / values in a <code>HashMap</code>.

@param properties A <code>HashMap</code> with configuration properties as required by the init() method in JAAS,
using the keys as specified in this class
@return A <code>ConnectionProperties</code> object with default values, plus the provided parameters
@throws NullPointerException When {@code properties} is {@code null}