/*
* PermissionsEx - Permissions plugin for Bukkit
* Copyright (C) 2011 t3hk0d3 http://www.tehkode.ru
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package pex.permissions.backends.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import pex.utils.StringUtils;
public class SQLConnection {
protected static Pattern placeholderPattern = Pattern.compile("\\`([^\\`]+)\\`");
protected Connection db;
protected String uri;
protected String user;
protected String password;
protected String dbDriver;
protected Map<String, String> aliases = new HashMap<String, String>();
public SQLConnection(String uri, String user, String password, String dbDriver) {
try {
Class.forName(getDriverClass(dbDriver)).newInstance();
this.uri = uri;
this.user = user;
this.password = password;
connect();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void setAlias(String tableName, String alias) {
aliases.put(tableName, alias);
}
public String getAlias(String tableName) {
if (aliases.containsKey(tableName)) {
return aliases.get(tableName);
}
return tableName;
}
public ResultSet select(String sql, Object... params) throws SQLException {
checkConnection();
SQLSelectQuery query = new SQLSelectQuery(sql, params);
query.execute();
return query.getResults();
}
@SuppressWarnings("unchecked")
public <T> T selectSingle(String sql, T fallback, Object... params) {
try {
checkConnection();
ResultSet result = select(sql, params);
if (!result.next()) {
return fallback;
}
return (T) result.getObject(1);
} catch (SQLException e) {
Logger.getLogger("Minecraft").severe("SQL Error: " + e.getMessage());
}
return fallback;
}
public void executeUpdate(String sql, Object... params) throws SQLException {
checkConnection();
SQLQuery query = new SQLQuery(sql, params);
query.execute();
}
public void insert(String table, String[] fields, List<Object[]> rows) throws SQLException {
checkConnection();
String[] fieldPlaceholders = new String[fields.length];
Arrays.fill(fieldPlaceholders, "?");
String sql = "INSERT INTO `" + table + "` (`" + StringUtils.implode(fields, "`, `") + "`) VALUES (" + StringUtils.implode(fieldPlaceholders, ", ") + ");";
SQLQuery query = new SQLQuery(sql);
for (Object[] params : rows) {
query.bindParams(params);
query.execute();
}
}
public boolean isTableExist(String tableName) {
try {
checkConnection();
return db.getMetaData().getTables(null, null, getAlias(tableName), null).next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public boolean isFieldExists(String tableName, String fieldName) {
try {
checkConnection();
return db.getMetaData().getColumns(null, null, getAlias(tableName), fieldName).next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
protected void checkConnection() throws SQLException {
if (db.getClass().getName().startsWith("org.sqlite")) {
return;
}
if (!db.isValid(3)) {
Logger.getLogger("Minecraft").warning("Lost connection with sql server. Reconnecting.");
connect();
}
}
protected final void connect() throws SQLException {
Logger.getLogger("Minecraft").info("[PermissionsEx-SQL] Connecting to database \"" + uri + "\"");
db = DriverManager.getConnection("jdbc:" + uri, user, password);
}
protected static String getDriverClass(String alias) {
if (alias.equals("mysql")) {
alias = "com.mysql.jdbc.Driver";
} else if (alias.equals("sqlite")) {
alias = "org.sqlite.JDBC";
} else if (alias.equals("postgre")) {
alias = "org.postgresql.Driver";
}
return alias;
}
protected final String prepareQuery(String sql) {
Matcher match = placeholderPattern.matcher(sql);
while (match.find()) {
sql = sql.replace(match.group(0), "`" + getAlias(match.group(1)) + "`");
}
return sql;
}
@Override
protected void finalize() throws Throwable {
try {
db.close();
} catch (SQLException e) {
Logger.getLogger("Minecraft").log(Level.WARNING, "Error while disconnecting from database: {0}", e.getMessage());
} finally {
super.finalize();
}
}
public class SQLQuery extends BasicSQLQuery {
public SQLQuery(String sql, Object... params) throws SQLException {
super(db.prepareStatement(prepareQuery(sql)));
if (params != null) {
bindParams(params);
}
}
}
public class SQLSelectQuery extends BasicSQLSelectQuery {
public SQLSelectQuery(String sql, Object[] params) throws SQLException {
super(db.prepareStatement(prepareQuery(sql)));
if (params != null) {
bindParams(params);
}
}
}
}