net.jmatrix.db.common.ConnectionInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jsql Show documentation
Show all versions of jsql Show documentation
SQL Utilities including simple command line, schema management.
The newest version!
package net.jmatrix.db.common;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.sql.DataSource;
import net.jmatrix.db.drivers.DriverMap;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* JSON serializable data containser for JDBC connection details.
*
* Password is obfuscated by base64 - but this is certainly not secure.
*
*/
public class ConnectionInfo
implements Comparable, DataSource {
String url;
String driverClass;
String username;
String passwordB64;
long lastConnectTime=-1;
// some property names
static final String SCHEMA="jsql.schema";
static final String CATALOG="jsql.catalog";
Map properties;
Connection connection=null;
Driver driver=null;
public enum Flavor {ORACLE, SQL_SERVER, MYSQL, HSQL, GENERIC};
Flavor flavor=Flavor.GENERIC;
BASE64Encoder b64encoder=new BASE64Encoder();
BASE64Decoder b64decoder=new BASE64Decoder();
public ConnectionInfo() {}
public ConnectionInfo(String d, String u, String un, String pw) {
driverClass=d;
url=u;
username=un;
setPassword(pw);
flavor();
}
static String cformat="user/[email protected]";
/*
* Connect string is:
*
* username/password@jdbcurl
*
* Driver is inferred from connectionURL.
*/
public ConnectionInfo(String s) throws SQLException {
int at=s.indexOf("@");
if (at == -1) {
throw new SQLException("Invalid Connect format. missing @. use: "+cformat);
}
String upw=s.substring(0, at);
url=s.substring(at+1);
driverClass=DriverMap.findDriver(url);
if (driverClass == null) {
throw new SQLException("Cannot find driver class for url '"+url+"'. Connect with explicit driver.");
}
String split[]=upw.split("\\/");
if (split.length != 2) {
throw new SQLException("Invalid Connect format. username password has no '/'. use: "+cformat);
}
username=split[0];
String pass=split[1];
setPassword(pass);
flavor();
}
public void close() {
if (connection != null) {
DBUtils.close(connection);
}
}
@JsonIgnore
public void setSchema(String schema) {
setProperty(SCHEMA, schema);
boolean error=false;
try {
connection.setSchema(schema); // only supported from Java 1.7
} catch (Error er) {
error=true;
} catch (SQLException ex) {
ex.printStackTrace();
}
}
@JsonIgnore
public String getSchema() {
String schema=null;
boolean error=false;
try {
schema=connection.getSchema();
} catch (Error er) {
error=true;
} catch (SQLException ex) {
ex.printStackTrace();
}
if (! error)
return schema;
schema = getProperty(SCHEMA);
if (schema != null)
return schema;
if (flavor == Flavor.ORACLE)
return username;
return null;
}
@JsonIgnore
public void setCatalog(String catalog) {
setProperty(CATALOG, catalog);
}
@JsonIgnore
public String getCatalog() {
return getProperty(CATALOG);
}
@Override
public int compareTo(ConnectionInfo o) {
ConnectionInfo ci=(ConnectionInfo)o;
return Long.compare(ci.lastConnectTime, lastConnectTime);
}
@Override
public int hashCode() {
return (driver+url+username).hashCode();
}
@Override
public boolean equals(Object o) {
if (o instanceof ConnectionInfo) {
ConnectionInfo ci=(ConnectionInfo)o;
//System.out.println ("Equals: "+ci+"\n"+
// " "+this);
return equals(ci.driverClass, driverClass) &&
equals(ci.url, url) &&
equals(ci.username, username);
}
return false;
}
@Override
public String toString() {
return username+" on "+url;
}
private static final boolean equals(String s1, String s2) {
if (s1 == null && s2 == null)
return true;
if (s1 != null && s2 != null)
return s1.equals(s2);
return false;
}
/** Guesses DB flavor based on connection URL heuristics. */
private void flavor() {
if (url != null) {
String lurl=url.toLowerCase();
if (lurl.contains("oracle"))
flavor=Flavor.ORACLE;
else if (lurl.contains("sqlserver"))
flavor=Flavor.SQL_SERVER;
else if (lurl.contains("mysql"))
flavor=Flavor.MYSQL;
}
}
@JsonIgnore
public boolean isConnected() {
return connection != null;
}
public Connection initDefaultConnection() throws SQLException {
Connection con=connect();
setDefaultConnection(con);
return con;
}
public Connection connect() throws SQLException {
try {
Class.forName(driverClass);
} catch (Exception ex) {
throw new SQLException("Cannot load driver '"+driverClass+"': "+ex);
}
try {
driver=DriverManager.getDriver(url);
} catch (Exception ex) {
throw new SQLException("Error getting driver for url '"+url+"' "+ex);
}
if (driver == null) {
throw new SQLException("No driver accepts url '"+url+"'");
} else {
//log(" Driver Version: "+driver.getMajorVersion()+"."+driver.getMinorVersion());
}
try {
Connection con=DriverManager.getConnection(url, username, getPassword());
//setConnection(con);
return con;
} catch (Exception ex) {
throw new SQLException("Cannot connect: "+ex);
}
}
public void setProperty(String key, String value) {
if (properties == null)
properties=new HashMap();
properties.put(key, value);
}
public String getProperty(String key) {
if (properties == null)
return null;
return properties.get(key);
}
///////////////////////////////////////////////////////////////////////////
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
flavor();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@JsonIgnore
public String getPassword() {
if (passwordB64 == null)
return null;
try {
return new String(b64decoder.decodeBuffer(passwordB64), "UTF-8");
} catch (Exception ex) {
throw new RuntimeException("Unable to decode password.");
}
}
@JsonIgnore
public void setPassword(String password) {
if (password == null)
passwordB64=null;
this.passwordB64=b64encoder.encode(password.getBytes());
}
public String getDriverClass() {
return driverClass;
}
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
@JsonIgnore
public Connection getDefaultConnection() {
return connection;
}
@JsonIgnore
public void setDefaultConnection(Connection connection) {
lastConnectTime=System.currentTimeMillis();
this.connection = connection;
}
@JsonIgnore
public Driver getDriver() {
return driver;
}
@JsonIgnore
public void setDriver(Driver driver) {
this.driver = driver;
}
@JsonIgnore
public Flavor getFlavor() {
return flavor;
}
@JsonIgnore
public void setFlavor(Flavor flavor) {
this.flavor = flavor;
}
public String getPasswordB64() {
return passwordB64;
}
public void setPasswordB64(String passwordB64) {
this.passwordB64 = passwordB64;
}
public long getLastConnectTime() {
return lastConnectTime;
}
public void setLastConnectTime(long lastConnectTime) {
this.lastConnectTime = lastConnectTime;
}
public Map getProperties() {
return properties;
}
public void setProperties(Map properties) {
this.properties = properties;
}
///////////////////////////////////////////////////////////////////////
// Implementing DataSource
@JsonIgnore
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@JsonIgnore
@Override
public void setLogWriter(PrintWriter out) throws SQLException { }
@JsonIgnore
@Override
public void setLoginTimeout(int seconds) throws SQLException { }
@JsonIgnore
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@JsonIgnore
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
@JsonIgnore
@Override
public T unwrap(Class iface) throws SQLException {
return null;
}
@JsonIgnore
@Override
public boolean isWrapperFor(Class> iface) throws SQLException {
return false;
}
@JsonIgnore
@Override
public Connection getConnection() throws SQLException {
return connect();
}
@JsonIgnore
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return connect();
}
}