edu.uvm.ccts.common.db.DataSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ccts-common Show documentation
Show all versions of ccts-common Show documentation
A library of useful generic objects and tools consolidated here to simplify all UVM CCTS projects
/*
* Copyright 2015 The University of Vermont and State
* Agricultural College. All rights reserved.
*
* Written by Matthew B. Storer
*
* This file is part of CCTS Common.
*
* CCTS Common is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CCTS Common is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CCTS Common. If not, see .
*/
package edu.uvm.ccts.common.db;
import edu.uvm.ccts.common.exceptions.BadCredentialsException;
import edu.uvm.ccts.common.exceptions.ConfigurationException;
import edu.uvm.ccts.common.model.AbstractCredentialedObject;
import edu.uvm.ccts.common.model.Credentials;
import edu.uvm.ccts.common.util.PropertiesUtil;
import electric.xml.Element;
import electric.xml.Elements;
import electric.xml.XPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.awt.*;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* Created by mstorer on 7/23/13.
*/
public class DataSource extends AbstractCredentialedObject implements Serializable {
private static final Log log = LogFactory.getLog(DataSource.class);
private static final String USER = "user";
private static final String PASSWORD = "password";
private static final String DOMAIN = "domain";
public static DataSource buildFromXml(Element xmlDataSource) throws ConfigurationException {
return buildFromXml(null, xmlDataSource);
}
public static DataSource buildFromXml(String name, Element xmlDataSource) throws ConfigurationException {
return buildFromXml(name, xmlDataSource, null);
}
public static DataSource buildFromXml(Element xmlDataSource, Frame frame) throws ConfigurationException {
return buildFromXml(null, xmlDataSource, frame);
}
public static DataSource buildFromXml(String name, Element xmlDataSource, Frame frame) throws ConfigurationException {
Properties info = new Properties();
Elements xmlProperties = xmlDataSource.getElements(new XPath("properties/property"));
while (xmlProperties.hasMoreElements()) {
Element xmlProperty = xmlProperties.next();
info.setProperty(xmlProperty.getAttribute("name"), xmlProperty.getAttribute("value"));
}
if (name == null) name = xmlDataSource.getAttribute("name");
return new DataSource(name,
xmlDataSource.getAttribute("driver"),
xmlDataSource.getAttribute("url"),
xmlDataSource.getAttribute("note"),
info,
frame);
}
//////////////////////////////////////////////////////////////////////////////////////////////
// instance methods and vars
//
private String name;
private String driver;
private String url;
private Properties info;
private transient Connection conn = null;
public DataSource(String name, String driver, String url, Properties info) throws ConfigurationException {
this(name, driver, url, null, info);
}
public DataSource(String name, String driver, String url, String note, Properties info) throws ConfigurationException {
this(name, driver, url, note, info, null);
}
public DataSource(String name, String driver, String url, String note, Properties info, Frame frame)
throws ConfigurationException {
this.name = name;
this.driver = driver;
int qmPos = url.indexOf('?');
if (qmPos >= 0) {
this.url = url.substring(0, qmPos);
this.info = info;
// add URL properties to info unless the URL property is already specified
for (String s : url.substring(qmPos + 1).split("&")) {
if (s.indexOf('=') < 0) continue;
String[] kvPair = s.split("=");
if ( ! this.info.containsKey(kvPair[0]) ) {
if (kvPair.length == 1) this.info.setProperty(kvPair[0], "");
else this.info.setProperty(kvPair[0], kvPair[1]);
}
}
} else {
this.url = url;
this.info = info;
}
loadDriver(driver);
ensureCredentials(note, frame);
addShutdownHook();
}
public String getName() {
return name;
}
public String getDriver() {
return driver;
}
public String getUrl() {
return url;
}
public Properties getInfo() {
return info;
}
public Connection getConnection() throws SQLException {
if (conn == null || conn.isClosed()) {
log.info("getConnection : establishing connection to '" + name + "'");
conn = DriverManager.getConnection(url, info);
}
return conn;
}
public void close() {
try {
if (conn != null && ! conn.isClosed()) {
log.info("close : closing connection '" + name + "'");
conn.close();
}
} catch (SQLException e) {
log.error("caught " + e.getClass().getName() + " attempting to close connection for '" + name + "' - " +
e.getMessage(), e);
} finally {
conn = null;
}
}
// used in [mlm-engine] ManagementImpl to ensure the driver is loaded prior to use
public void loadDriver() throws ConfigurationException {
loadDriver(driver);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// private methods
//
@Override
protected void ensureCredentials(String note, Frame frame) throws ConfigurationException {
boolean fallback = true;
String domain = getDomain();
if (domain != null) {
DomainCredentialRegistry dcr = DomainCredentialRegistry.getInstance();
if (dcr.isRegistered(domain)) {
Credentials cred = dcr.getCredentials(domain);
String user = getUser();
if (user == null || user.equalsIgnoreCase(cred.getUser())) {
Properties testProps = PropertiesUtil.copy(info);
testProps.setProperty(USER, cred.getUser());
testProps.setProperty(PASSWORD, cred.getPassword());
try {
testCredentials(testProps);
fallback = false;
setUser(cred.getUser());
setPassword(cred.getPassword());
} catch (BadCredentialsException e) {
// handle silently
}
}
}
}
if (fallback) {
super.ensureCredentials(note, frame);
if (domain != null) {
DomainCredentialRegistry.getInstance().register(domain, new Credentials(getUser(), getPassword()));
}
}
}
@Override
protected void testCredentials() throws BadCredentialsException, ConfigurationException {
testCredentials(info);
}
private void testCredentials(Properties props) throws BadCredentialsException, ConfigurationException {
Connection c = null;
try {
c = DriverManager.getConnection(url, props);
} catch (SQLException e) {
throw new BadCredentialsException(e.getMessage(), e);
} catch (Exception e) {
throw new ConfigurationException(e.getMessage(), e);
} finally {
try { if (c != null) c.close(); } catch (Exception e) {}
}
}
private void loadDriver(String driver) throws ConfigurationException {
try {
Class.forName(driver).newInstance();
} catch (Exception e) {
throw new ConfigurationException("invalid driver: " + driver, e);
}
}
@Override
protected String getCredentialType() {
return "data source";
}
@Override
protected String getCredentialTarget() {
return name;
}
@Override
protected String getUser() {
return info.getProperty(USER);
}
@Override
protected String getPassword() {
return info.getProperty(PASSWORD);
}
private String getDomain() {
return info.getProperty(DOMAIN);
}
@Override
protected void setUser(String user) {
if (user == null) info.remove(USER);
else info.setProperty(USER, user);
}
@Override
protected void setPassword(String password) {
if (password == null) info.remove(PASSWORD);
else info.setProperty(PASSWORD, password);
}
private void addShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
close();
}
});
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy