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

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

There is a newer version: 1.2.0
Show newest version
/*
 * Copyright (C) Red Gate Software Ltd 2010-2021
 * Copyright 2022 The MigrateDB contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package migratedb.v1.commandline;

import migratedb.v1.core.api.ConnectionProvider;
import migratedb.v1.core.api.ErrorCode;
import migratedb.v1.core.api.MigrateDbException;
import migratedb.v1.core.internal.util.ClassUtils;
import migratedb.v1.core.internal.util.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

/**
 * Uses {@link DriverSupport} to infer the {@link Driver} implementation unless the driver class name is given.
 */
public class DriverSupportDataSource implements ConnectionProvider {
    private Driver driver;
    private final String url;
    private final String user;
    private final String password;
    private final Properties properties;
    private final DriverSupport driverSupport;

    /**
     * Creates a new DriverDataSource.
     *
     * @param classLoader The ClassLoader to use.
     * @param driverClass The name of the JDBC Driver class to use. {@code null} for url-based autodetection.
     * @param url         The JDBC URL to use for connecting through the Driver. (required)
     * @param user        The JDBC user to use for connecting through the Driver.
     * @param password    The JDBC password to use for connecting through the Driver.
     * @param properties  Properties to pass to the JDBC driver when opening connections.
     * @throws MigrateDbException if the datasource could not be created.
     */
    public DriverSupportDataSource(ClassLoader classLoader,
                                   @Nullable String driverClass,
                                   String url,
                                   @Nullable String user,
                                   @Nullable String password,
                                   Map properties,
                                   DriverSupport driverSupport) throws MigrateDbException {
        this.url = Objects.requireNonNull(url);
        this.driverSupport = Objects.requireNonNull(driverSupport);

        if (!StringUtils.hasLength(driverClass)) {
            driverClass = driverSupport.getDriverClass(url, classLoader);
        }

        this.properties = new Properties();
        properties.forEach(this.properties::setProperty);

        try {
            this.driver = ClassUtils.instantiate(driverClass, classLoader);
        } catch (MigrateDbException e) {
            String backupDriverClass = driverSupport.getBackupDriverClass(url, classLoader);
            if (backupDriverClass == null) {
                String extendedError = driverSupport.instantiateClassExtendedErrorMessage();
                if (StringUtils.hasText(extendedError)) {
                    extendedError = "\n" + extendedError;
                }
                throw new MigrateDbException("Unable to instantiate JDBC driver: " + driverClass
                        + " => Check whether the jar file is present"
                        + extendedError, e,
                        ErrorCode.JDBC_DRIVER);
            }
            try {
                this.driver = ClassUtils.instantiate(backupDriverClass, classLoader);
            } catch (RuntimeException e1) {
                // Only report original exception about primary driver
                throw new MigrateDbException(
                        "Unable to instantiate JDBC driver: " + driverClass + " or backup driver: " + backupDriverClass +
                                " => Check whether the jar file is present", e,
                        ErrorCode.JDBC_DRIVER);
            }
        }

        this.user = user;
        this.password = password;

        if (driverSupport.externalAuthPropertiesRequired(url, user, password)) {
            properties.putAll(driverSupport.getExternalAuthProperties(url, user));
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        return getConnectionFromDriver(user, password);
    }

    /**
     * Build properties for the Driver, including the given user and password (if any), and obtain a corresponding
     * Connection.
     *
     * @param username the name of the user
     * @param password the password to use
     * @return the obtained Connection
     * @throws SQLException in case of failure
     * @see java.sql.Driver#connect(String, java.util.Properties)
     */
    private Connection getConnectionFromDriver(@Nullable String username, @Nullable String password) throws SQLException {
        Properties properties = new Properties(this.properties);

        if (username != null) {
            properties.setProperty("user", username);
        }
        if (password != null) {
            properties.setProperty("password", password);
        }

        Connection connection = driver.connect(url, properties);
        if (connection == null) {
            throw new MigrateDbException("Unable to connect to " + driverSupport.redactJdbcUrl(url));
        }
        connection.setAutoCommit(true);
        return connection;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy