/*
* ThunderNetwork - Server Client Architecture to send Off-Chain Bitcoin Payments
* Copyright (C) 2015 Mats Jerratsch <matsjj@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package network.thunder.core.etc;
/*
* Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class
* from the iBATIS Apache project. Only removed dependency on Resource class
* and a constructor
*/
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.sql.*;
// TODO: Auto-generated Javadoc
/**
* Tool to run database scripts.
*/
public class ScriptRunner {
/**
* The Constant DEFAULT_DELIMITER.
*/
private static final String DEFAULT_DELIMITER = ";";
/**
* The connection.
*/
private Connection connection;
/**
* The stop on error.
*/
private boolean stopOnError;
/**
* The auto commit.
*/
private boolean autoCommit;
/**
* The log writer.
*/
private PrintWriter logWriter = new PrintWriter(System.out);
/**
* The error log writer.
*/
private PrintWriter errorLogWriter = new PrintWriter(System.err);
/**
* The delimiter.
*/
private String delimiter = DEFAULT_DELIMITER;
/**
* The full line delimiter.
*/
private boolean fullLineDelimiter = false;
/**
* Default constructor.
*
* @param connection the connection
* @param autoCommit the auto commit
* @param stopOnError the stop on error
*/
public ScriptRunner (Connection connection, boolean autoCommit, boolean stopOnError) {
this.connection = connection;
this.autoCommit = autoCommit;
this.stopOnError = stopOnError;
}
/**
* Flush.
*/
private void flush () {
if (logWriter != null) {
logWriter.flush();
}
if (errorLogWriter != null) {
errorLogWriter.flush();
}
}
/**
* Gets the delimiter.
*
* @return the delimiter
*/
private String getDelimiter () {
return delimiter;
}
/**
* Prints the.
*
* @param o the o
*/
private void print (Object o) {
if (logWriter != null) {
System.out.print(o);
}
}
/**
* Println.
*
* @param o the o
*/
private void println (Object o) {
if (logWriter != null) {
logWriter.println(o);
}
}
/**
* Println error.
*
* @param o the o
*/
private void printlnError (Object o) {
if (errorLogWriter != null) {
errorLogWriter.println(o);
}
}
/**
* Runs an SQL script (read in using the Reader parameter).
*
* @param reader - the source of the script
* @throws IOException Signals that an I/O exception has occurred.
* @throws SQLException the SQL exception
*/
public void runScript (Reader reader) throws IOException, SQLException {
try {
boolean originalAutoCommit = connection.getAutoCommit();
try {
if (originalAutoCommit != this.autoCommit) {
connection.setAutoCommit(this.autoCommit);
}
runScript(connection, reader);
} finally {
connection.setAutoCommit(originalAutoCommit);
}
} catch (IOException e) {
throw e;
} catch (SQLException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error running script. Cause: " + e, e);
}
}
/**
* Runs an SQL script (read in using the Reader parameter) using the
* connection passed in.
*
* @param conn - the connection to use for the script
* @param reader - the source of the script
* @throws IOException if there is an error reading from the Reader
* @throws SQLException if any SQL errors occur
*/
private void runScript (Connection conn, Reader reader) throws IOException, SQLException {
StringBuffer command = null;
try {
LineNumberReader lineReader = new LineNumberReader(reader);
String line = null;
while ((line = lineReader.readLine()) != null) {
if (command == null) {
command = new StringBuffer();
}
String trimmedLine = line.trim();
if (trimmedLine.startsWith("--")) {
println(trimmedLine);
} else if (trimmedLine.length() < 1 || trimmedLine.startsWith("//")) {
// Do nothing
} else if (trimmedLine.length() < 1 || trimmedLine.startsWith("--")) {
// Do nothing
} else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter()) || fullLineDelimiter && trimmedLine.equals(getDelimiter())) {
command.append(line.substring(0, line.lastIndexOf(getDelimiter())));
command.append(" ");
Statement statement = conn.createStatement();
println(command);
boolean hasResults = false;
if (stopOnError) {
hasResults = statement.execute(command.toString());
} else {
try {
statement.execute(command.toString());
} catch (SQLException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
}
}
if (autoCommit && !conn.getAutoCommit()) {
conn.commit();
}
ResultSet rs = statement.getResultSet();
if (hasResults && rs != null) {
ResultSetMetaData md = rs.getMetaData();
int cols = md.getColumnCount();
for (int i = 0; i < cols; i++) {
String name = md.getColumnLabel(i);
print(name + "\t");
}
println("");
while (rs.next()) {
for (int i = 0; i < cols; i++) {
String value = rs.getString(i);
print(value + "\t");
}
println("");
}
}
command = null;
try {
statement.close();
} catch (Exception e) {
// Ignore to workaround a bug in Jakarta DBCP
}
Thread.yield();
} else {
command.append(line);
command.append(" ");
}
}
if (!autoCommit) {
conn.commit();
}
} catch (SQLException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
throw e;
} catch (IOException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
throw e;
} finally {
conn.rollback();
flush();
}
}
/**
* Sets the delimiter.
*
* @param delimiter the delimiter
* @param fullLineDelimiter the full line delimiter
*/
public void setDelimiter (String delimiter, boolean fullLineDelimiter) {
this.delimiter = delimiter;
this.fullLineDelimiter = fullLineDelimiter;
}
/**
* Setter for errorLogWriter property.
*
* @param errorLogWriter - the new value of the errorLogWriter property
*/
public void setErrorLogWriter (PrintWriter errorLogWriter) {
this.errorLogWriter = errorLogWriter;
}
/**
* Setter for logWriter property.
*
* @param logWriter - the new value of the logWriter property
*/
public void setLogWriter (PrintWriter logWriter) {
this.logWriter = logWriter;
}
}