All Downloads are FREE. Search and download functionalities are using the official Maven repository.

migratedb.v1.commandline.DriverSupport Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package migratedb.v1.commandline;

import migratedb.v1.core.api.configuration.Configuration;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.sql.Driver;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Implements driver-based database connection support in the command line application.
 */
public interface DriverSupport {
    /**
     * This is useful for databases that allow setting this in order to easily correlate individual application with
     * database connections.
     */
    String APPLICATION_NAME = "MigrateDB";

    // Don't grab semicolons and ampersands - they have special meaning in URLs
    Pattern defaultJdbcCredentialsPattern = Pattern.compile("password=([^;&]*).*", Pattern.CASE_INSENSITIVE);

    /**
     * @return The human-readable name.
     */
    String getName();

    /**
     * Check if this database type should handle the given JDBC url
     *
     * @param url The JDBC url.
     * @return {@code true} if this handles the JDBC url, {@code false} if not.
     */
    boolean handlesJdbcUrl(String url);

    /**
     * Detects whether a user is required from configuration. This may not be the case if the driver supports other
     * authentication mechanisms, or supports the user being encoded in the URL
     *
     * @param url The url to check
     * @return true if a username needs to be provided
     */
    default boolean detectUserRequiredByUrl(String url) {
        return true;
    }

    /**
     * Detects whether a password is required from configuration. This may not be the case if the driver supports other
     * authentication mechanisms, or supports the password being encoded in the URL
     *
     * @param url The url to check
     * @return true if a password needs to be provided
     */
    default boolean detectPasswordRequiredByUrl(String url) {
        return true;
    }

    /**
     * Detects whether external authentication is required.
     *
     * @return true if external authentication is required, else false.
     */
    default boolean externalAuthPropertiesRequired(String url, @Nullable String username, @Nullable String password) {
        return false;
    }

    /**
     * @param url      The JDBC url.
     * @param username The username for the connection.
     * @return Authentication properties from database specific locations (e.g. pgpass)
     */
    default Map getExternalAuthProperties( @Nullable String url,  @Nullable String username) {
        return Map.of();
    }

    /**
     * A regex that identifies credentials in the JDBC URL, where they conform to a pattern specific to this database.
     * The first captured group must represent the password text, so that it can be redacted if necessary.
     *
     * @return The URL regex.
     */
    default Pattern getJdbcCredentialsPattern() {
        return defaultJdbcCredentialsPattern;
    }

    /**
     * (Probably) replaces secrets in {@code url} with {@code "***"}.
     */
    default String redactJdbcUrl(String url) {
        Matcher matcher = getJdbcCredentialsPattern().matcher(url);
        if (matcher.find()) {
            String password = matcher.group(1);
            return url.replace(password, "***");
        }
        return url;
    }

    /**
     * Get the driver class used to handle this JDBC url. This will only be called if {@code matchesJDBCUrl} previously
     * returned {@code true}.
     *
     * @param url         The JDBC url.
     * @param classLoader The classLoader to check for driver classes.
     * @return The full driver class name to be instantiated to handle this url.
     */
    String getDriverClass(String url, ClassLoader classLoader);

    /**
     * Retrieves a second choice backup driver for a JDBC url, in case the one returned by {@code getDriverClass} is not
     * available.
     *
     * @param url         The JDBC url.
     * @param classLoader The classLoader to check for driver classes.
     * @return The JDBC driver. {@code null} if none.
     */
    default @Nullable String getBackupDriverClass(String url, ClassLoader classLoader) {
        return null;
    }

    /**
     * @return A hint on the requirements for creating database instances (libs on class path, etc.)
     */
    default String instantiateClassExtendedErrorMessage() {
        return "";
    }

    /**
     * Set the default connection properties. These can be overridden by {@code
     * setConfigConnectionProps} and {@code setOverridingConnectionProps}.
     *
     * @param url         The JDBC url.
     * @param props       The properties to write to.
     * @param classLoader The classLoader to use.
     */
    default void modifyDefaultConnectionProps(String url, Properties props, ClassLoader classLoader) {
    }

    /**
     * Set any necessary connection properties based on MigrateDB's configuration. These can be overridden by {@code
     * setOverridingConnectionProps}.
     *
     * @param config      The MigrateDB configuration to read properties from.
     * @param props       The properties to write to.
     * @param classLoader The classLoader to use.
     */
    default void modifyConfigConnectionProps(Configuration config, Properties props, ClassLoader classLoader) {
    }

    /**
     * These will override anything set by {@code setDefaultConnectionProps} and {@code setConfigConnectionProps} and
     * should only be used if neither of those can satisfy your requirement.
     *
     * @param props The properties to write to.
     */
    default void modifyOverridingConnectionProps(Map props) {
    }

    /**
     * Only applicable to embedded databases that require this.
     */
    default void shutdownDatabase(String url, Driver driver) {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy