java/sql-dk/src/info/globalcode/sql/dk/configuration/Loader.java
author František Kučera <franta-hg@frantovo.cz>
Tue, 26 Feb 2019 18:19:49 +0100
branchv_0
changeset 236 a3ec71fa8e17
parent 196 76da38d49e81
permissions -rw-r--r--
Avoid reusing/rewriting the DB connection properties.
There was weird random errors while testing connection to multiple DB in parallel when one of them was meta connection to same DB connection.
Two kinds of exception: 1) missing password 2) „Passing DB password as CLI parameter is insecure!“
franta-hg@16
     1
/**
franta-hg@16
     2
 * SQL-DK
franta-hg@189
     3
 * Copyright © 2015 František Kučera (frantovo.cz)
franta-hg@16
     4
 *
franta-hg@16
     5
 * This program is free software: you can redistribute it and/or modify
franta-hg@16
     6
 * it under the terms of the GNU General Public License as published by
franta-hg@16
     7
 * the Free Software Foundation, either version 3 of the License, or
franta-hg@16
     8
 * (at your option) any later version.
franta-hg@16
     9
 *
franta-hg@16
    10
 * This program is distributed in the hope that it will be useful,
franta-hg@16
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@16
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
franta-hg@16
    13
 * GNU General Public License for more details.
franta-hg@16
    14
 *
franta-hg@16
    15
 * You should have received a copy of the GNU General Public License
franta-hg@16
    16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
franta-hg@16
    17
 */
franta-hg@189
    18
package info.globalcode.sql.dk.configuration;
franta-hg@1
    19
franta-hg@189
    20
import info.globalcode.sql.dk.*;
franta-hg@192
    21
import static info.globalcode.sql.dk.DatabaseConnection.JDBC_PROPERTY_USER;
franta-hg@192
    22
import static info.globalcode.sql.dk.DatabaseConnection.JDBC_PROPERTY_PASSWORD;
franta-hg@192
    23
import java.sql.Connection;
franta-hg@194
    24
import java.sql.Driver;
franta-hg@192
    25
import java.sql.DriverManager;
franta-hg@192
    26
import java.sql.SQLException;
franta-hg@192
    27
import java.util.logging.Level;
franta-hg@192
    28
import java.util.logging.Logger;
franta-hg@33
    29
import javax.xml.bind.JAXBContext;
franta-hg@33
    30
import javax.xml.bind.Unmarshaller;
franta-hg@13
    31
franta-hg@1
    32
/**
franta-hg@189
    33
 * Configuration loader – deserializes Configuration from the XML file.
franta-hg@1
    34
 *
franta-hg@1
    35
 * @author Ing. František Kučera (frantovo.cz)
franta-hg@1
    36
 */
franta-hg@189
    37
public class Loader {
franta-hg@1
    38
franta-hg@192
    39
	private static final Logger log = Logger.getLogger(Loader.class.getName());
franta-hg@192
    40
franta-hg@189
    41
	public Configuration loadConfiguration() throws ConfigurationException {
franta-hg@33
    42
		try {
franta-hg@193
    43
			JAXBContext jaxb = JAXBContext.newInstance(Configuration.class.getPackage().getName(), Configuration.class.getClassLoader());
franta-hg@33
    44
			Unmarshaller u = jaxb.createUnmarshaller();
franta-hg@33
    45
			return (Configuration) u.unmarshal(Constants.CONFIG_FILE);
franta-hg@33
    46
		} catch (Exception e) {
franta-hg@33
    47
			throw new ConfigurationException("Unable to load configuration from " + Constants.CONFIG_FILE, e);
franta-hg@33
    48
		}
franta-hg@20
    49
	}
franta-hg@80
    50
franta-hg@192
    51
	/**
franta-hg@192
    52
	 * JDBC connection should not be used directly in SQL-DK.
franta-hg@192
    53
	 *
franta-hg@192
    54
	 * @see DatabaseDefinition#connect(info.globalcode.sql.dk.configuration.Properties)
franta-hg@192
    55
	 * @param properties
franta-hg@192
    56
	 * @param databaseDefinition
franta-hg@192
    57
	 * @return
franta-hg@192
    58
	 * @throws java.sql.SQLException
franta-hg@192
    59
	 */
franta-hg@192
    60
	public static Connection jdbcConnect(DatabaseDefinition databaseDefinition, Properties properties) throws SQLException {
franta-hg@236
    61
		synchronized (properties) {
franta-hg@236
    62
			/**
franta-hg@236
    63
			 * Avoid rewriting the properties. Usually, the connection is created only once, but
franta-hg@236
    64
			 * with --test-connection and with SQL-DK JDBC driver, it might be reused.
franta-hg@236
    65
			 */
franta-hg@236
    66
			properties = properties.clone();
franta-hg@236
    67
		}
franta-hg@192
    68
		if (properties.hasProperty(JDBC_PROPERTY_PASSWORD)) {
franta-hg@192
    69
			log.log(Level.WARNING, "Passing DB password as CLI parameter is insecure!");
franta-hg@192
    70
		}
franta-hg@192
    71
		Properties credentials = new Properties();
franta-hg@192
    72
		credentials.add(new Property(JDBC_PROPERTY_USER, databaseDefinition.getUserName()));
franta-hg@192
    73
		credentials.add(new Property(JDBC_PROPERTY_PASSWORD, databaseDefinition.getPassword()));
franta-hg@192
    74
		credentials.setDefaults(databaseDefinition.getProperties());
franta-hg@192
    75
		properties.setDefaults(credentials);
franta-hg@192
    76
		java.util.Properties javaProperties = properties.getJavaProperties();
franta-hg@194
    77
franta-hg@194
    78
		String driverClassName = databaseDefinition.getDriver();
franta-hg@194
    79
		final String url = databaseDefinition.getUrl();
franta-hg@194
    80
		if (driverClassName == null) {
franta-hg@194
    81
			log.log(Level.FINE, "Using DriverManager to create connection for „{0}“", url);
franta-hg@194
    82
			return DriverManager.getConnection(url, javaProperties);
franta-hg@194
    83
		} else {
franta-hg@194
    84
			log.log(Level.FINE, "Using custom Driver „{0}“ to create connection for „{1}“", new Object[]{driverClassName, url});
franta-hg@194
    85
			try {
franta-hg@194
    86
				Class<Driver> driverClass = (Class<Driver>) Class.forName(driverClassName);
franta-hg@194
    87
				Driver driver = driverClass.newInstance();
franta-hg@196
    88
				Connection connection = driver.connect(url, javaProperties);
franta-hg@196
    89
				if (connection == null) {
franta-hg@196
    90
					log.log(Level.SEVERE, "Driver „{0}“ returend null → it does not accept the URL: „{1}“", new Object[]{driverClassName, url});
franta-hg@196
    91
					throw new SQLException("Unable to connect: driver returned null.");
franta-hg@196
    92
				} else {
franta-hg@196
    93
					return connection;
franta-hg@196
    94
				}
franta-hg@194
    95
			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) {
franta-hg@194
    96
				throw new SQLException("Unable to connect usig specific driver: " + driverClassName, e);
franta-hg@194
    97
			}
franta-hg@194
    98
		}
franta-hg@192
    99
	}
franta-hg@192
   100
franta-hg@1
   101
}