/******************************************************************************* * Copyright 2012 University of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This code was developed by the Information Integration Group as part * of the Karma project at the Information Sciences Institute of the * University of Southern California. For more information, publications, * and related projects, please see: http://www.isi.edu/integration ******************************************************************************/ package edu.isi.karma.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractJDBCUtil { private static Logger logger = LoggerFactory .getLogger(AbstractJDBCUtil.class); public enum DBType { Oracle, MySQL, SQLServer, PostGIS } protected abstract String getDriver(); protected abstract String getConnectStringTemplate(); /** * Enclose input string between escape chars specific for each type of DB. * @param name * @return */ public abstract String prepareName(String name); public abstract ArrayList<ArrayList<String>> getDataForLimitedRows(DBType dbType, String hostname, int portnumber, String username, String password, String tableName, String dBorSIDName, int rowCount) throws SQLException, ClassNotFoundException; public abstract ArrayList<String> getListOfTables(Connection conn) throws SQLException, ClassNotFoundException; public Connection getConnection(String driver, String connectString) throws SQLException, ClassNotFoundException { Connection localConn = null; Class.forName(driver); localConn = DriverManager.getConnection(connectString); return localConn; } public Connection getConnection(String hostname, int portnumber, String username, String password, String dBorSIDName) throws SQLException, ClassNotFoundException { String connectString = getConnectString(hostname, portnumber, username, password, dBorSIDName); logger.debug("Connect to:" + hostname + ":" +portnumber + "/" + dBorSIDName); logger.debug("Conn string:"+ connectString); Connection conn = getConnection(getDriver(), connectString); return conn; } protected String getConnectString (String hostname, int portnumber, String username, String password, String dBorSIDName) { String connectString = getConnectStringTemplate(); connectString = connectString.replaceAll("host", hostname); connectString = connectString.replaceAll("port", Integer.toString(portnumber)); connectString = connectString.replaceAll("dbname", dBorSIDName); connectString = connectString.replaceAll("username", username); //passwords could have special chars that are not being handles properly in //reg expr; so for pwd do the replace differently int pwdInd = connectString.indexOf("pwd"); if(pwdInd>=0){ connectString = connectString.substring(0,pwdInd)+password+connectString.substring(pwdInd+3); } return connectString; } public ArrayList<String> getListOfTables(DBType dbType, String hostname, int portnumber, String username, String password, String dBorSIDName) throws SQLException, ClassNotFoundException { String connectString = getConnectString(hostname, portnumber, username, password, dBorSIDName); Connection conn = getConnection(getDriver(), connectString); return getListOfTables(conn); } public ArrayList<ArrayList<String>> getDataForTable(DBType dbType, String hostname, int portnumber, String username, String password, String tableName, String dBorSIDName) throws SQLException, ClassNotFoundException { String connectString = getConnectString(hostname, portnumber, username, password, dBorSIDName); Connection conn = getConnection(getDriver(), connectString); return getDataForTable(conn, tableName); } public ArrayList<ArrayList<String>> getDataForTable(Connection conn, String tableName) throws SQLException { String query = "SELECT * FROM " + tableName; Statement s = conn.createStatement(); ResultSet r = s.executeQuery(query); if (r == null) { s.close(); return null; } ArrayList<ArrayList<String>> vals = parseResultSetIntoArrayListOfRows(r); r.close(); s.close(); return vals; } protected ArrayList<ArrayList<String>> parseResultSetIntoArrayListOfRows(ResultSet r) throws SQLException { ArrayList<ArrayList<String>> vals = new ArrayList<ArrayList<String>>(); ResultSetMetaData meta = r.getMetaData(); // Add the column names ArrayList<String> columnNamesRow = new ArrayList<String>(); for (int i = 1; i <= meta.getColumnCount(); i++) { columnNamesRow.add(meta.getColumnName(i)); } vals.add(columnNamesRow); // Add an ArrayList for each row while (r.next()) { ArrayList<String> row = new ArrayList<String>(); for (int i = 1; i <= meta.getColumnCount(); i++) { String val = r.getString(i); row.add(val); } vals.add(row); } return vals; } /** * Returns true if given table exists in DB; false otherwise. * @param tableName * @param conn * @return * true if given table exists in DB; false otherwise. * @throws SQLException * @throws ClassNotFoundException */ public boolean tableExists(String tableName, Connection conn) throws SQLException, ClassNotFoundException { ArrayList<String> tn = getListOfTables(conn); if (tn.contains(tableName)) { return true; } return false; } /** * Returns the column names for a given table. * @param tableName * @param conn * @return * column names for a given table. * @throws SQLException */ public ArrayList<String> getColumnNames(String tableName, Connection conn) throws SQLException { ArrayList<String> columnNames = new ArrayList<String>(); String query = "select * from " + tableName; if (conn == null) return columnNames; try { Statement s = conn.createStatement(); ResultSet r = s.executeQuery(query); ResultSetMetaData meta = null; if (r == null) { s.close(); return null; } meta = r.getMetaData(); for (int i = 1; i <= meta.getColumnCount(); i++) { columnNames.add(meta.getColumnName(i)); } r.close(); s.close(); } catch (SQLException e) { throw e; } return columnNames; } /** * Returns the column types for a given table. * @param tableName * @param conn * @return * column types for a given table. * @throws SQLException */ public ArrayList<String> getColumnTypes(String tableName, Connection conn) throws SQLException { ArrayList<String> columnTypes = new ArrayList<String>(); String query = "select * from " + tableName; // String res = executeQuery(connectString, query); // logger.debug("RES="+res); if (conn == null) return columnTypes; try { Statement s = conn.createStatement(); ResultSet r = s.executeQuery(query); ResultSetMetaData meta = null; if (r == null) { s.close(); return null; } meta = r.getMetaData(); for (int i = 1; i <= meta.getColumnCount(); i++) { logger.debug("Type= " + meta.getColumnTypeName(i)); columnTypes.add(meta.getColumnTypeName(i)); } r.close(); s.close(); } catch (SQLException e) { throw e; } return columnTypes; } /** * Executes a SQL query. * @param conn * @param query * @throws SQLException */ public void execute(Connection conn, String query) throws SQLException { if (conn != null) { //logger.debug("query=" + query); try { Statement s = conn.createStatement(); s.execute(query); s.close(); } catch (SQLException e) { logger.error("sendSQL ..." + query); logger.error("MSG=" + e.getMessage()); logger.error("STATE=" + e.getSQLState()); if (query.startsWith("drop") && e.getMessage().startsWith("Unknown table")) { } else { throw e; } } } } /** * Executes an update query. (e.g. insert ...) * @param conn * @param query * @throws SQLException */ public void executeUpdate(Connection conn, String query) throws SQLException { if (conn != null) { logger.debug("query=" + query); try { Statement s = conn.createStatement(); s.executeUpdate(query); s.close(); } catch (SQLException e) { if (query.startsWith("insert") && e.getMessage().startsWith("Duplicate entry")) { } else { logger.debug("sendSQL ..." + query); logger.debug("MSG=" + e.getMessage()); logger.debug("STATE=" + e.getSQLState()); logger.error("Error occured while executing update!", e); throw e; } } } } }