package org.needle4j.db.operation; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.needle4j.configuration.ConfigurationLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An abstract implementation of {@link DBOperation} with common jdbc * operations. */ public abstract class AbstractDBOperation implements DBOperation { private static final Logger LOG = LoggerFactory.getLogger(AbstractDBOperation.class); private final JdbcConfiguration configuration; private Connection connection; public AbstractDBOperation(final JdbcConfiguration jdbcConfiguration) { super(); this.configuration = jdbcConfiguration; } /** * Establish a connection to the given database. * * @throws SQLException * if a database access error occurs */ protected void openConnection() throws SQLException { if (connection == null) { try { Class.forName(configuration.getJdbcDriver()); } catch (NullPointerException npe) { throw new RuntimeException("error while lookup jdbc driver class. jdbc driver is not configured.", npe); } catch (ClassNotFoundException e) { throw new RuntimeException("jdbc driver not found", e); } connection = DriverManager.getConnection(configuration.getJdbcUrl(), configuration.getJdbcUser(), configuration.getJdbcPassword()); connection.setAutoCommit(false); } } /** * Close the connection to the database. * * @throws SQLException * if a database access error occurs */ protected void closeConnection() throws SQLException { if (connection != null && !connection.isClosed()) { connection.close(); connection = null; } } /** * Commits the current transaction. * * @throws SQLException * if a database access error occurs */ protected void commit() throws SQLException { if (connection != null) { connection.commit(); } } /** * Revoke the current transaction. * * @throws SQLException * if a database access error occurs */ protected void rollback() throws SQLException { if (connection != null) { connection.rollback(); } } /** * Returns the names of all tables in the database by using * {@linkplain DatabaseMetaData}. * * @param connection * the jdbc connection object * * @return a {@link List} of all table names * * @throws SQLException * if a database access error occurs */ protected List<String> getTableNames(final Connection connection) throws SQLException { ResultSet resultSet = null; try { final List<String> tables = new ArrayList<String>(); resultSet = connection.getMetaData().getTables(null, null, "%", new String[] { "TABLE" }); while (resultSet.next()) { tables.add(resultSet.getString("TABLE_NAME")); } return tables; } finally { if (resultSet != null) { resultSet.close(); } } } private void executeScript(final BufferedReader script, final Statement statement) throws SQLException { long lineNo = 0; StringBuffer sql = new StringBuffer(); String line; try { while ((line = script.readLine()) != null) { lineNo++; String trimmedLine = line.trim(); if (trimmedLine.length() == 0 || trimmedLine.startsWith("--") || trimmedLine.startsWith("//")) { continue; } else if (trimmedLine.startsWith("/*")) { while ((line = script.readLine()) != null) { if (line.endsWith("*/")) { LOG.debug("ignore " + line); break; } } } else { sql.append(trimmedLine); if (trimmedLine.endsWith(";")) { String sqlStatement = sql.toString(); sqlStatement = sqlStatement.substring(0, sqlStatement.length() - 1); LOG.info(sqlStatement); statement.execute(sqlStatement); sql = new StringBuffer(); } } } } catch (Exception e) { throw new SQLException("Error during import script execution at line " + lineNo, e); } } /** * Execute the given sql script. * * @param filename * the filename of the sql script * @param statement * the {@link Statement} to be used for executing a SQL * statement. * * @throws SQLException * if a database access error occurs */ protected void executeScript(final String filename, final Statement statement) throws SQLException { LOG.info("Executing sql script: " + filename); InputStream fileInputStream; try { fileInputStream = ConfigurationLoader.loadResource(filename); } catch (FileNotFoundException e) { LOG.error("could not execute script", e); return; } final BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream)); executeScript(reader, statement); } /** * Returns the sql connection object. If there is no connection a new * connection is established. * * @return the sql connection object * * @throws SQLException * if a database access error occurs */ protected Connection getConnection() throws SQLException { if (connection == null) { openConnection(); } return connection; } }