JDBCDriverManager written. Check for non-MySQL server required.

git-svn-id: https://svn.code.sf.net/p/jailer/code/trunk@156 3dd849cd-670e-4645-a7cd-dd197c8d0e81
This commit is contained in:
dair-targ
2008-02-10 08:07:44 +00:00
parent f4d081f4f9
commit 2d2c207cbe
7 changed files with 380 additions and 102 deletions
+1
View File
@@ -1 +1,2 @@
# Name; Upsert; Primary key; ; Author
sample; N; A INTEGER; ; Data Model Editor; ;
1 # Name # Name; Upsert; Primary key; ; Author Upsert Primary key Author
2 sample; N; A INTEGER; ; Data Model Editor; ;
@@ -1,8 +1,4 @@
# subject; condition; limit; restrictions
EMPLOYEE; NAME='SCOTT'; ; .embedded
null; ; ; .embedded
# from A (or association name); to B; restriction-condition
X; ; dsdsdsd
DEPARTMENT; EMPLOYEE; ignore
SUBORDINATE; ; neu
SALARYGRADE; EMPLOYEE; ignore
1 # subject; condition; limit; restrictions
2 EMPLOYEE; NAME='SCOTT'; ; .embedded null; ; ; .embedded
3 # from A (or association name); to B; restriction-condition
4
DEPARTMENT; EMPLOYEE; ignore
SUBORDINATE; ; neu
SALARYGRADE; EMPLOYEE; ignore
@@ -23,21 +23,12 @@ import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Properties;
import java.sql.*;
import java.util.*;
import java.text.MessageFormat;
import org.apache.log4j.Logger;
import net.sf.jailer.drivermanager.JDBCDriverManager;
/**
* Executes SQL-Statements.
@@ -90,14 +81,14 @@ public class StatementExecutor {
/**
* The logger.
*/
private static final Logger _log = Logger.getLogger("sql");
private static final Logger myLog = Logger.getLogger("sql");
/**
* Connection factory.
*/
private interface ConnectionFactory {
Connection getConnection() throws SQLException;
};
}
/**
* Connection factory.
@@ -132,7 +123,7 @@ public class StatementExecutor {
/**
* Classloader to load Jdbc-Driver with.
*/
public static ClassLoader classLoaderForJdbcDriver = null;
//public static ClassLoader myJDBCDriverLoader = null;
/**
* Wraps a Jdbc-Driver.
@@ -163,23 +154,23 @@ public class StatementExecutor {
}
/**
* Constructor.
* Constructs {@code StatementExecutor} for executing statements at
* specified DB-server with specified DB-driver and authorizes using
* specified DB-username and DB-password.
*
* @param driverClassName name of JDBC-driver class
* @param dbUrl the database URL
* @param user the DB-user
* @param password the DB-password
* @param driverClassName Name of JDBC-driver class
* @param host The database host URL
* @param user The DB-user
* @param password The DB-password
*/
public StatementExecutor(String driverClassName, final String dbUrl, final String user, final String password) throws Exception {
_log.info("connect to user " + user + " at "+ dbUrl);
if (classLoaderForJdbcDriver != null) {
Driver d = (Driver)Class.forName(driverClassName, true, classLoaderForJdbcDriver).newInstance();
DriverManager.registerDriver(new DriverShim(d));
} else {
Class.forName(driverClassName);
}
public StatementExecutor(String driverClassName, final String host, final String user, final String password)
throws Exception {
// todo: replace with locale string
myLog.info("connecting to db-server at " + host + " with user " + user + ";");
// Loading and registering a driver.
DriverManager.registerDriver(JDBCDriverManager.getDriver(driverClassName));
this.schemaName = user;
this.dbUrl = dbUrl;
this.dbUrl = host;
this.dbUser = user;
this.dbPassword = password;
connectionFactory = new ConnectionFactory() {
@@ -187,12 +178,12 @@ public class StatementExecutor {
Connection con = connection.get();
if (con == null) {
con = DriverManager.getConnection(dbUrl, user, password);
con = DriverManager.getConnection(host, user, password);
con.setAutoCommit(true);
try {
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
} catch (SQLException e) {
_log.info("can't set isolation level to UR. Reason: " + e.getMessage());
myLog.info("can't set isolation level to UR. Reason: " + e.getMessage());
}
connection.set(con);
connections.add(con);
@@ -220,7 +211,7 @@ public class StatementExecutor {
* @param reader the reader for the result
*/
public void executeQuery(String sqlQuery, ResultSetReader reader) throws SQLException {
_log.debug(sqlQuery);
myLog.debug(sqlQuery);
Statement statement = connectionFactory.getConnection().createStatement();
ResultSet resultSet = statement.executeQuery(sqlQuery);
while (resultSet.next()) {
@@ -264,11 +255,11 @@ public class StatementExecutor {
* Executes a SQL-Update (INSERT, DELETE or UPDATE).
*
* @param sqlUpdate the update in SQL
*
* @return update-count
* @throws SQLException
*/
public int executeUpdate(String sqlUpdate) throws SQLException {
_log.debug(sqlUpdate);
myLog.debug(sqlUpdate);
int rowCount = 0;
int failures = 0;
boolean ok = false;
@@ -285,14 +276,15 @@ public class StatementExecutor {
rowCount = statement.executeUpdate(sqlUpdate);
}
ok = true;
_log.debug("" + rowCount + " row(s)");
myLog.debug(MessageFormat.format("{0} row(s) affected", rowCount));
} catch (SQLException e) {
if (++failures > 10 || e.getErrorCode() != -911) {
// todo: replace '-911' sql-error with an appropriate constant.
if (++failures > myMaxFailures || e.getErrorCode() != -911) {
throw e;
}
// deadlock
serializeAccess = true;
_log.info("Deadlock! Try again.");
myLog.info("Deadlock! Try again.");
} finally {
if (statement != null) {
statement.close();
@@ -307,7 +299,7 @@ public class StatementExecutor {
*/
public void insertClob(String table, String column, String where, File lobFile) throws SQLException, FileNotFoundException {
String sqlUpdate = "Update " + table + " set " + column + "=? where " + where;
_log.debug(sqlUpdate);
myLog.debug(sqlUpdate);
PreparedStatement statement = null;
statement = connectionFactory.getConnection().prepareStatement(sqlUpdate);
statement.setCharacterStream(1, new InputStreamReader(new FileInputStream(lobFile)), (int) lobFile.length());
@@ -320,7 +312,7 @@ public class StatementExecutor {
*/
public void insertBlob(String table, String column, String where, File lobFile) throws SQLException, FileNotFoundException {
String sqlUpdate = "Update " + table + " set " + column + "=? where " + where;
_log.debug(sqlUpdate);
myLog.debug(sqlUpdate);
PreparedStatement statement = null;
statement = connectionFactory.getConnection().prepareStatement(sqlUpdate);
statement.setBinaryStream(1, new FileInputStream(lobFile), (int) lobFile.length());
@@ -334,7 +326,7 @@ public class StatementExecutor {
* @param sql the SQL-Statement
*/
public void execute(String sql) throws SQLException {
_log.debug(sql);
myLog.debug(sql);
Statement statement = connectionFactory.getConnection().createStatement();
statement.execute(sql);
statement.close();
@@ -350,16 +342,6 @@ public class StatementExecutor {
return connection.getMetaData();
}
/**
* Sets Classloader to load Jdbc-Driver with.
*
* @param classLoader Classloader to load Jdbc-Driver with
*/
public static void setClassLoaderForJdbcDriver(ClassLoader classLoader) {
classLoaderForJdbcDriver = classLoader;
}
/**
* Closes all connections.
*/
@@ -386,5 +368,48 @@ public class StatementExecutor {
public void setIntrospectionSchema(String introspectionSchema) {
this.introspectionSchema = introspectionSchema;
}
//////////////////////////
// Max Filures settings //
//////////////////////////
/**
* A maximum number of failures that could occurs during exeution of one
* query before an exception will be thrown out.
*
* The default value is 10.
*
* @see #getMaxFailures()
* @see #setMaxFailures(int)
*/
protected int myMaxFailures = 10;
/**
* Returns a maximum number of failures during query execution.
*
* @return A maximum number of failures during query execution.
*
* @see #setMaxFailures(int)
*/
public int getMaxFailures() {
return myMaxFailures;
}
/**
* Sets a maximum number of failures during query execution.
*
* @param maxFailures A new maximum number of failures during query
* execution.
* @throws IllegalArgumentException If a received value is negative.
*
* @see #setMaxFailures(int)
*/
public void setMaxFailures(int maxFailures)
throws IllegalArgumentException {
if (maxFailures < 0) {
throw new IllegalArgumentException("The maximum number of failures should be positive value");
}
myMaxFailures = maxFailures;
}
}
@@ -26,9 +26,7 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.DataModel;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.datamodel.*;
import net.sf.jailer.util.CsvFile;
import net.sf.jailer.util.PrintUtil;
import net.sf.jailer.util.CsvFile.Line;
@@ -0,0 +1,26 @@
package net.sf.jailer.drivermanager;
/**
* @author Vladimir "Dair T'arg" Berkutov
* @date: 09.02.2008
* @time: 22:19:38
*/
public class DriverNotFoundException extends Exception {
protected String myRequestedServer;
public DriverNotFoundException(String requestedServer) {
super("Driver for " + requestedServer + " has not found");
myRequestedServer = requestedServer;
}
/**
* Returns a server type for which driver has been requested.
*
* @return a server type for which driver has been requested.
*/
public String getRequestedServer() {
return myRequestedServer;
}
}
@@ -0,0 +1,272 @@
package net.sf.jailer.drivermanager;
import java.io.File;
import java.io.IOException;
import java.io.FileReader;
import java.io.FileWriter;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DriverPropertyInfo;
import java.util.Properties;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.InvocationTargetException;
/**
* This object manages the list of databases drivers. It performs loading of
* appropriate drivers during connection to a database server.
*
* Also, this object registers and unregisters a drivers.
*
* @author Vladimir "Dair T'arg" Berkutov
* @date: 08.02.2008
* @time: 14:49:29
*/
public final class JDBCDriverManager {
/**
* A default configuration file path.
*/
public final static String DEFAULT_DRIVERS_LIST_FILE = "drivers/drivers.list";
/**
* A default drivers directory.
*/
public final static String DEFAULT_DRIVERS_DIRECTORY = "drivers/";
/**
* Initializes the {@code JDBCDriverManager} engine.
*
* @param configurationFile A configuration xml file with a list of
* installed drivers.
* @param driversDirectory A directory with drivers.
*
* @throws RuntimeException If configuration file could not be loaded.
*/
public static void initialize(String configurationFile, String driversDirectory)
throws RuntimeException {
myConfigurationFile = configurationFile;
myDriversDirectory = driversDirectory;
initialized = true;
try {
loadDriverList(configurationFile);
} catch (IOException exception) {
throw new RuntimeException("Driver list could not be loaded", exception);
}
}
/////////////////////////
// Initialization flag //
/////////////////////////
/**
* The flag of the {@code JDBCDriverManager} initialization. If the
* {@code JDBCDriverManager} is initialized then this flag is true, otherways
* this flag is false.
*
* @see #isInitialized()
*/
private static boolean initialized = false;
/**
* Checks whether {@code JDBCDriverManager} engine is initialized or not.
*
* @return {@code true} if {@code JDBCDriverManager} is initialized and
* {@code false} if {@code JDBCDriverManager} is not initialized.
*/
public static boolean isInitialized() {
return initialized;
}
////////////////////////
// Configuration File //
////////////////////////
private static String myConfigurationFile;
/**
* Returns a path to the configuration file with a drivers list.
*
* @return A path to the configuration file with a drivers list.
*/
public static String getConfigurationFile() {
return myConfigurationFile;
}
///////////////////////
// Drivers Directory //
///////////////////////
/**
* A path to a directory with drivers libraries.
*
* @see #getDriversDirectory()
*/
private static String myDriversDirectory = null;
/**
* Returns a path to a directory with drivers libraries.
*
* @return A path to a directory with drivers libraries.
*/
public static String getDriversDirectory() {
if (!initialized) {
return "";
}
if (myDriversDirectory == null) {
return "";
}
return myDriversDirectory;
}
//////////////////
// Drivers List //
//////////////////
private final static Properties myDriversList = new Properties();
private static void loadDriverList(String configurationFile)
throws IOException {
myDriversList.load(new FileReader(configurationFile));
}
/////////
// API //
/////////
/**
* Returns a {@link java.sql.Driver} instance for requested server type.
*
* @param serverName A database server type.
* @return A {@link java.sql.Driver} instance for requested server type.
*
* @throws RuntimeException If the {@code JDBCDriverManager} engine has not been
* initialized or if a driver instance could not be created.
* @throws DriverNotFoundException If no {@link java.sql.Driver}s has been
* found for the specified serverName.
* @throws IOException If a driver library could not be loaded.
*/
public static Driver getDriver(String serverName)
throws RuntimeException, DriverNotFoundException, IOException {
if (!initialized) {
initialize(DEFAULT_DRIVERS_LIST_FILE, DEFAULT_DRIVERS_DIRECTORY);
}
if (!myDriversList.containsKey(serverName)) {
throw new DriverNotFoundException(serverName);
}
String fullName = myDriversList.getProperty(serverName);
String libraryName = myDriversDirectory + getLibraryName(fullName);
String className = getClassName(fullName);
try {
return createDriverInstance(libraryName, className);
} catch (Exception exception) {
System.err.println(exception);
throw new RuntimeException("Could not load database server driver", exception);
}
}
private static String getLibraryName(String fullName) {
return fullName.substring(0, fullName.indexOf('#'));
}
private static String getClassName(String fullName) {
return fullName.substring(fullName.indexOf("#") + 1);
}
private static Driver createDriverInstance(String libraryFileName, String className)
throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException, NoSuchMethodException, InvocationTargetException {
URL libraryURL = new File(libraryFileName).toURI().toURL();
// Adding libraryFileName to a system ClassLoader.
ClassLoader loader = new URLClassLoader(new URL[] {libraryURL},
ClassLoader.getSystemClassLoader());
try {
return new DriverProxy((Driver)loader.loadClass(className).newInstance());
} catch (Exception exception) {
System.err.println(exception);
throw new ClassNotFoundException("Specified class is not an extension of java.sql.Driver", exception);
}
}
/**
* Sets a driver for the server type. This method just adds a record to a
* drivers list and flushes it to a file.
*
* @param serverType A type of server - just a key for a driver.
* @param libraryName A name of .jar file with a library.
* @param className A name of class from a library which implements
* {@link java.sql.Driver}.
*
* @throws RuntimeException If there were some problems with writing drivers
* list to a file.
*/
public static void setDriver(String serverType, String libraryName, String className)
throws RuntimeException {
if (!initialized) {
initialize(DEFAULT_DRIVERS_LIST_FILE, DEFAULT_DRIVERS_DIRECTORY);
}
if (!isDriverExists(serverType)) {
return;
}
myDriversList.setProperty(serverType, libraryName + "#" + className);
try {
myDriversList.store(new FileWriter(myConfigurationFile), "");
} catch (IOException exception) {
throw new RuntimeException("Driver list could not be written", exception);
}
}
/**
* Checks whether driver is set for the specified server type or not.
* No library existing or file check is made - only a check for a list
* record
*
* @param serverType A server type.
* @return {@code true} If a default driver for the specified server type
* is set and {@code false} otherways.
*/
public static boolean isDriverExists(String serverType) {
if (!initialized) {
initialize(DEFAULT_DRIVERS_LIST_FILE, DEFAULT_DRIVERS_DIRECTORY);
}
return myDriversList.containsKey(serverType)
&& myDriversList.getProperty(serverType).length() != 0;
}
//////////////////
// Driver Proxy //
//////////////////
/**
* A proxy for dynamicly loaded JDBC Driver.
*
* @author Wisser
*/
public static class DriverProxy implements Driver {
private final Driver driver;
private DriverProxy(Driver driver) {
this.driver = driver;
}
public boolean acceptsURL(String u) throws SQLException {
return driver.acceptsURL(u);
}
public Connection connect(String u, Properties p) throws SQLException {
return driver.connect(u, p);
}
public int getMajorVersion() {
return driver.getMajorVersion();
}
public int getMinorVersion() {
return driver.getMinorVersion();
}
public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
return driver.getPropertyInfo(u, p);
}
public boolean jdbcCompliant() {
return driver.jdbcCompliant();
}
}
}
+3 -43
View File
@@ -19,13 +19,9 @@ import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -41,6 +37,7 @@ import net.sf.jailer.database.StatementExecutor;
import net.sf.jailer.modelbuilder.JDBCMetaDataBasedModelElementFinder;
import net.sf.jailer.util.CsvFile;
import net.sf.jailer.util.CsvFile.Line;
import net.sf.jailer.drivermanager.JDBCDriverManager;
/**
* "Connect with DB" dialog.
@@ -375,20 +372,9 @@ public class DbConnectionDialog extends javax.swing.JDialog {
if (d2.length() == 0) {
d2 = null;
}
try {
StatementExecutor.setClassLoaderForJdbcDriver(addJarToClasspath(d1, d2));
} catch (Exception e) {
UIUtil.showException(this, "Error loading driver jars", e);
return;
}
try {
if (StatementExecutor.classLoaderForJdbcDriver != null) {
Driver d = (Driver)Class.forName(driverClass.getText(), true, StatementExecutor.classLoaderForJdbcDriver).newInstance();
DriverManager.registerDriver(new StatementExecutor.DriverShim(d));
} else {
Class.forName(driverClass.getText());
}
DriverManager.registerDriver(JDBCDriverManager.getDriver(driverClass.getText()));
Connection con = DriverManager.getConnection(dbUrl.getText(), user.getText(), password.getText());
con.close();
isConnected = true;
@@ -400,32 +386,6 @@ public class DbConnectionDialog extends javax.swing.JDialog {
}//GEN-LAST:event_jButton1ActionPerformed
/**
* Adds one or two jars to classpath.
*
* @param jarName1 filename of jar 1
* @param jarName2 filename of jar 2
*/
private URLClassLoader addJarToClasspath(String jarName1, String jarName2) throws Exception {
URL[] urls;
if (jarName1 == null) {
if (jarName2 == null) {
return null;
}
jarName1 = jarName2;
jarName2 = null;
}
System.out.println("add '" + jarName1 + "' to classpath");
if (jarName2 == null) {
urls = new URL[] {new URL("file", null, jarName1)};
} else {
System.out.println("add '" + jarName2 + "' to classpath");
urls = new URL[] {new URL("file", null, jarName1), new URL("file", null, jarName2)};
}
URLClassLoader urlLoader = new URLClassLoader(urls);
return urlLoader;
}
/**
* Selects the DB-schema to for introspection.
*