org.h2.table.TableLinkConnection Maven / Gradle / Ivy
/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.table;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Objects;
import org.h2.message.DbException;
import org.h2.util.JdbcUtils;
/**
* A connection for a linked table. The same connection may be used for multiple
* tables, that means a connection may be shared.
*/
public class TableLinkConnection {
/**
* The map where the link is kept.
*/
private final HashMap map;
/**
* The connection information.
*/
private final String driver, url, user, password;
/**
* The database connection.
*/
private Connection conn;
/**
* How many times the connection is used.
*/
private int useCounter;
private TableLinkConnection(
HashMap map,
String driver, String url, String user, String password) {
this.map = map;
this.driver = driver;
this.url = url;
this.user = user;
this.password = password;
}
/**
* Open a new connection.
*
* @param map the map where the connection should be stored
* (if shared connections are enabled).
* @param driver the JDBC driver class name
* @param url the database URL
* @param user the user name
* @param password the password
* @param shareLinkedConnections if connections should be shared
* @return a connection
*/
public static TableLinkConnection open(
HashMap map,
String driver, String url, String user, String password,
boolean shareLinkedConnections) {
TableLinkConnection t = new TableLinkConnection(map, driver, url,
user, password);
if (!shareLinkedConnections) {
t.open();
return t;
}
synchronized (map) {
TableLinkConnection result = map.get(t);
if (result == null) {
t.open();
// put the connection in the map after is has been opened,
// when we know it works
map.put(t, t);
result = t;
}
result.useCounter++;
return result;
}
}
private void open() {
try {
conn = JdbcUtils.getConnection(driver, url, user, password);
} catch (SQLException e) {
throw DbException.convert(e);
}
}
@Override
public int hashCode() {
return Objects.hashCode(driver)
^ Objects.hashCode(url)
^ Objects.hashCode(user)
^ Objects.hashCode(password);
}
@Override
public boolean equals(Object o) {
if (o instanceof TableLinkConnection) {
TableLinkConnection other = (TableLinkConnection) o;
return Objects.equals(driver, other.driver)
&& Objects.equals(url, other.url)
&& Objects.equals(user, other.user)
&& Objects.equals(password, other.password);
}
return false;
}
/**
* Get the connection.
* This method and methods on the statement must be
* synchronized on this object.
*
* @return the connection
*/
Connection getConnection() {
return conn;
}
/**
* Closes the connection if this is the last link to it.
*
* @param force if the connection needs to be closed even if it is still
* used elsewhere (for example, because the connection is broken)
*/
void close(boolean force) {
boolean actuallyClose = false;
synchronized (map) {
if (--useCounter <= 0 || force) {
actuallyClose = true;
map.remove(this);
}
}
if (actuallyClose) {
JdbcUtils.closeSilently(conn);
}
}
}