com.identity4j.connector.jdbc.JDBCConnector Maven / Gradle / Ivy
package com.identity4j.connector.jdbc;
/*
* #%L
* Identity4J JDBC
* %%
* Copyright (C) 2013 - 2017 LogonBox
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.identity4j.connector.AbstractConnector;
import com.identity4j.connector.ConnectorCapability;
import com.identity4j.connector.ConnectorConfigurationParameters;
import com.identity4j.connector.Media;
import com.identity4j.connector.exception.ConnectorException;
import com.identity4j.connector.exception.PasswordChangeRequiredException;
import com.identity4j.connector.exception.PrincipalNotFoundException;
import com.identity4j.connector.principal.AccountStatus;
import com.identity4j.connector.principal.Identity;
import com.identity4j.connector.principal.PasswordStatus;
import com.identity4j.connector.principal.PasswordStatusType;
import com.identity4j.connector.principal.Role;
import com.identity4j.util.StringUtil;
import com.identity4j.util.crypt.EncoderManager;
import com.identity4j.util.crypt.impl.DefaultEncoderManager;
public abstract class JDBCConnector extends AbstractConnector
{
protected final static EncoderManager encoderManager = DefaultEncoderManager.getInstance();
protected Connection connect = null;
protected JDBCConfiguration configuration = null;
static Log log = LogFactory.getLog(JDBCConnector.class);
static Set capabilities = new HashSet(
Arrays.asList(new ConnectorCapability[] { ConnectorCapability.passwordChange,
ConnectorCapability.passwordSet, ConnectorCapability.identities }));
@Override
public Set getCapabilities() {
Set caps = new LinkedHashSet();
caps.addAll(capabilities);
if (configuration != null) {
if (!StringUtil.isNullOrEmpty(configuration.getIdentityFullnameColumn())) {
caps.add(ConnectorCapability.hasFullName);
}
if (!StringUtil.isNullOrEmpty(configuration.getRoleTable())) {
caps.add(ConnectorCapability.roles);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityPasswordColumn())) {
caps.add(ConnectorCapability.authentication);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityEmailColumn())) {
caps.add(ConnectorCapability.hasEmail);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityEnabledColumn())) {
caps.add(ConnectorCapability.accountDisable);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityLockedColumn())) {
caps.add(ConnectorCapability.accountLocking);
}
if (!StringUtil.isNullOrEmpty(configuration.getConfigurationParameters()
.getString(JDBCConfiguration.SQL_IDENTITY_TABLE_UPDATE))) {
caps.add(ConnectorCapability.updateUser);
}
if (!StringUtil.isNullOrEmpty(configuration.getConfigurationParameters()
.getString(JDBCConfiguration.SQL_IDENTITY_TABLE_CREATE))) {
caps.add(ConnectorCapability.createUser);
}
if (!StringUtil.isNullOrEmpty(configuration.getConfigurationParameters()
.getString(JDBCConfiguration.SQL_IDENTITY_TABLE_DELETE))) {
caps.add(ConnectorCapability.deleteUser);
}
}
return caps;
}
public Iterator allIdentities() throws ConnectorException {
List identities = new ArrayList();
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getSelectIdentitiesSQL();
resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
identities.add(createIdentity(resultSet));
}
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
return identities.iterator();
}
public Identity getIdentityByName(String name) throws PrincipalNotFoundException, ConnectorException {
String sql = configuration.getSelectIdentitySQL(name);
if (sql.equals("")) {
return super.getIdentityByName(name);
} else {
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
return createIdentity(resultSet);
}
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
throw new PrincipalNotFoundException(name + " not found.");
}
protected List getGrantedRoles(Identity identity) {
List roles = new ArrayList();
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getSelectIdentitiesRolesSQL(identity);
if (sql.length() > 0) {
resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
roles.add(createRoleFromGrantResults(resultSet));
}
}
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
return roles;
}
protected Role createRoleFromGrantResults(ResultSet resultSet) throws SQLException {
return createRole(resultSet);
}
protected Date getAsDate(ResultSet resultSet, int colidx) throws SQLException {
// TODO This makes some big assumptions and will need tweaking
// once we get some real use
int columnType = resultSet.getMetaData().getColumnType(colidx);
if (columnType == Types.DATE) {
java.sql.Date date = resultSet.getDate(colidx);
if (date != null)
return date;
} else if (columnType == Types.TIME || columnType == 2013) {
// 2013 = Types.TIME_WITH_TIMEZONE (Java 8 only)
Time time = resultSet.getTime(colidx);
if (time != null)
return new Date(time.getTime());
} else if (columnType == Types.TIMESTAMP || columnType == 2014) {
// 2014 = Types.TIMESTAMP_WITH_TIMEZONE (Java 8 only)
Timestamp timestamp = resultSet.getTimestamp(colidx);
if (timestamp != null)
return new Date(timestamp.getTime());
} else if (columnType == Types.BIGINT) {
return new Date(resultSet.getLong(colidx));
} else if (columnType == Types.INTEGER) {
return new Date(resultSet.getLong(colidx) * 1000l);
}
return null;
}
protected Identity createIdentity(ResultSet resultSet) throws SQLException {
JDBCIdentity i = new JDBCIdentity(resultSet.getString(configuration.getIdentityGuidColumn()),
resultSet.getString(configuration.getIdentityPrincipalNameColumn()));
if (!StringUtil.isNullOrEmpty(configuration.getIdentityEmailColumn())) {
i.setAddress(Media.email, resultSet.getString(configuration.getIdentityEmailColumn()));
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityMobileColumn())) {
i.setAddress(Media.mobile, resultSet.getString(configuration.getIdentityMobileColumn()));
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityFullnameColumn())) {
i.setFullName(resultSet.getString(configuration.getIdentityFullnameColumn()));
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityOtherNameColumn())) {
i.setOtherName(resultSet.getString(configuration.getIdentityOtherNameColumn()));
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityLastSignOnColumn())) {
int colidx = getColumnIndex(configuration.getIdentityLastSignOnColumn(), resultSet);
if (colidx != -1) {
Date d = getAsDate(resultSet, colidx);
if (d != null)
i.setLastSignOnDate(d);
}
}
i.setRoles(getGrantedRoles(i));
AccountStatus status = new AccountStatus();
if (!StringUtil.isNullOrEmpty(configuration.getIdentityEnabledColumn())) {
if (Objects.equals(String.valueOf(resultSet.getObject(configuration.getIdentityEnabledColumn())),
configuration.getIdentityEnabledValue()))
status.setDisabled(false);
else if (Objects.equals(String.valueOf(resultSet.getObject(configuration.getIdentityEnabledColumn())),
configuration.getIdentityDisabledValue()))
status.setDisabled(true);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityLockedColumn())) {
if (Objects.equals(String.valueOf(resultSet.getObject(configuration.getIdentityLockedColumn())),
configuration.getIdentityLockedValue()))
// TODO get the lock date if possible?
status.setLocked(new Date(0));
else if (Objects.equals(String.valueOf(resultSet.getObject(configuration.getIdentityLockedColumn())),
configuration.getIdentityUnlockedValue()))
status.setLocked(null);
}
status.calculateType();
i.setAccountStatus(status);
// Password status is currently unsupported
PasswordStatus pwdStatus = new PasswordStatus();
if (!StringUtil.isNullOrEmpty(configuration.getIdentityForcePasswordChangeColumn())) {
if (Objects.equals(
String.valueOf(resultSet.getObject(configuration.getIdentityForcePasswordChangeColumn())),
configuration.getIdentityForcePasswordChangeValue()))
pwdStatus.setNeedChange(true);
else if (Objects.equals(
String.valueOf(resultSet.getObject(configuration.getIdentityForcePasswordChangeColumn())),
configuration.getIdentityNoForcePasswordChangeValue()))
pwdStatus.setNeedChange(false);
}
if (!StringUtil.isNullOrEmpty(configuration.getIdentityLastPasswordChangeColumn())) {
int colidx = getColumnIndex(configuration.getIdentityLastPasswordChangeColumn(), resultSet);
if (colidx != -1) {
Date d = getAsDate(resultSet, colidx);
if (d != null)
pwdStatus.setLastChange(d);
}
}
pwdStatus.calculateType();
i.setPasswordStatus(pwdStatus);
// This should always be false
i.setSystem(false);
return i;
}
private int getColumnIndex(String name, ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
for (int i = 0; i < metaData.getColumnCount(); i++) {
if (metaData.getColumnName(i + 1).equals(name))
return i;
}
return -1;
}
protected Role createRole(ResultSet resultSet) throws SQLException {
JDBCRole r = new JDBCRole(resultSet.getString(configuration.getRoleGuidColumn()),
resultSet.getString(configuration.getRolePrincipalNameColumn()));
// This should always be false
r.setSystem(false);
return r;
}
protected void closeStatement(Statement statement) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
}
}
}
protected void closeResultSet(ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
}
}
}
public Iterator allRoles() throws ConnectorException {
List roles = new ArrayList();
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
resultSet = statement.executeQuery(configuration.getSelectRolesSQL());
while (resultSet.next()) {
roles.add(createRole(resultSet));
}
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
return roles.iterator();
}
public boolean isOpen() {
try {
return connect != null && !connect.isClosed();
} catch (SQLException e) {
return false;
}
}
public void onClose() {
if (isOpen()) {
try {
connect.close();
} catch (SQLException e) {
} finally {
connect = null;
configuration = null;
}
}
}
public boolean isReadOnly() {
// TODO Auto-generated method stub
return false;
}
public Role createRole(Role role) throws ConnectorException {
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getCreateRoleSQL(role);
statement.executeUpdate(sql);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
return getRoleByName(role.getPrincipalName());
}
public void updateRole(Role role) throws ConnectorException {
throw new UnsupportedOperationException();
}
public void deleteRole(String principleName) throws ConnectorException {
String sql = configuration.getDeleteRoleSQL(principleName);
if (sql.equals("")) {
super.deleteRole(principleName);
} else {
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
statement.executeUpdate(sql);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
}
@Override
protected void onOpen(ConnectorConfigurationParameters parameters) throws ConnectorException {
configuration = (JDBCConfiguration) parameters;
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName(configuration.getDriverClassName());
// Setup the connection with the DB
String username = configuration.getJDBCUsername();
if (username != null) {
char[] password = configuration.getJDBCPassword();
connect = DriverManager.getConnection(configuration.generateJDBCUrl(), username,
password == null ? null : new String(password));
} else
connect = DriverManager.getConnection(configuration.generateJDBCUrl());
} catch (Exception e) {
log.error("Failed to open JDBC connection " + configuration.generateJDBCUrl(), e);
close();
}
}
@Override
protected boolean areCredentialsValid(Identity identity, char[] password) throws ConnectorException {
// Encode the password, if its 'plain' then the database will encode it
// most likely using PASSWORD() function or similar.
String encodedPassword = new String(encoderManager.encode(password, configuration.getIdentityPasswordEncoding(),
configuration.getCharset(), null, null));
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getSelectPasswordSQL(identity, encodedPassword, new String(password));
if (sql.length() > 0) {
resultSet = statement.executeQuery(sql);
return resultSet.next();
} else {
sql = configuration.getSelectIdentitySQL(identity.getPrincipalName());
resultSet = statement.executeQuery(sql);
if (resultSet.next()) {
String val = resultSet.getString(configuration.getIdentityPasswordColumn());
boolean ok = encoderManager.getEncoderById(configuration.getIdentityPasswordEncoding())
.match(val.getBytes("UTF-8"), new String(password).getBytes("UTF-8"), null, "UTF-8");
if (ok) {
Identity id = createIdentity(resultSet);
if (id.getPasswordStatus().getType() == PasswordStatusType.changeRequired) {
throw new PasswordChangeRequiredException();
}
}
return ok;
}
return false;
}
} catch (SQLException e) {
throw new ConnectorException(e);
} catch (UnsupportedEncodingException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
@Override
protected void setPassword(Identity identity, char[] password, boolean forcePasswordChangeAtLogon,
PasswordResetType type) throws ConnectorException {
String encodedPassword = new String(encoderManager.encode(password, configuration.getIdentityPasswordEncoding(),
configuration.getCharset(), null, null));
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getUpdatePasswordSQL(identity, encodedPassword, new String(password),
forcePasswordChangeAtLogon, type);
statement.executeUpdate(sql);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
@Override
public Identity createIdentity(Identity identity, char[] password) throws ConnectorException {
String encodedPassword = new String(encoderManager.encode(password, configuration.getIdentityPasswordEncoding(),
configuration.getCharset(), null, null));
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
String sql = configuration.getCreateSQL(identity, encodedPassword, new String(password));
statement.executeUpdate(sql);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
return getIdentityByName(identity.getPrincipalName());
}
@Override
public void updateIdentity(Identity identity) throws ConnectorException {
Statement statement = null;
ResultSet resultSet = null;
try {
connect.setAutoCommit(false);
Identity existingIdentity = getIdentityByName(identity.getPrincipalName());
statement = connect.createStatement();
String sql = configuration.getUpdateSQL(identity);
statement.executeUpdate(sql);
updateIdentityRoles(existingIdentity, identity);
connect.commit();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
try {
connect.setAutoCommit(true);
} catch (SQLException e) {
}
}
}
protected void updateIdentityRoles(Identity oldIdentity, Identity newIdentity) throws SQLException {
Map oldRoles = getRoleNames(oldIdentity);
Map newRoles = getRoleNames(newIdentity);
/* Revoke any roles that are no longer valid */
for (Map.Entry n : oldRoles.entrySet()) {
if (!newRoles.containsKey(n.getKey())) {
Statement statement = connect.createStatement();
try {
String sql = configuration.getRevokeFromRoleSQL(oldIdentity, n.getValue());
statement.executeUpdate(sql);
} finally {
statement.close();
}
}
}
/* Add any roles that are now granted */
for (Map.Entry n : newRoles.entrySet()) {
if (!oldRoles.containsKey(n.getKey())) {
Statement statement = connect.createStatement();
try {
String sql = configuration.getGrantToRoleSQL(newIdentity, n.getValue());
statement.executeUpdate(sql);
} finally {
statement.close();
}
}
}
}
protected Map getRoleNames(Identity identity) {
Role[] r = identity.getRoles();
Map l = new HashMap();
if (r != null)
for (Role a : r)
l.put(a.getPrincipalName(), a);
return l;
}
@Override
public void deleteIdentity(String principalName) throws ConnectorException {
String sql = configuration.getDeleteSQL(principalName);
if (sql.equals("")) {
super.deleteIdentity(principalName);
} else {
Statement statement = null;
ResultSet resultSet = null;
try {
statement = connect.createStatement();
statement.executeUpdate(sql);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
}
@Override
public void lockIdentity(Identity identity) throws ConnectorException {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connect.prepareStatement(
configuration.getSql(String.format("UPDATE ${identityTable} SET ${identityTableLocked} = ?")));
statement.setObject(1, configuration.getIdentityLockedValue());
statement.executeUpdate();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
@Override
public void disableIdentity(Identity identity) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connect.prepareStatement(
configuration.getSql(String.format("UPDATE ${identityTable} SET ${identityTableEnabled} = ?")));
statement.setObject(1, configuration.getIdentityDisabledValue());
statement.executeUpdate();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
@Override
public void enableIdentity(Identity identity) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connect.prepareStatement(
configuration.getSql(String.format("UPDATE ${identityTable} SET ${identityTableEnabled} = ?")));
statement.setObject(1, configuration.getIdentityEnabledValue());
statement.executeUpdate();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
@Override
public void unlockIdentity(Identity identity) throws ConnectorException {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
String sql = configuration.getSql(String.format("UPDATE ${identityTable} SET ${identityTableLocked} = ?"));
statement = connect.prepareStatement(sql);
statement.setObject(1, configuration.getIdentityUnlockedValue());
statement.executeUpdate();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
closeResultSet(resultSet);
}
}
/**
* Checks for failed sql command in a batch transaction. If any code matches
* {@link Statement.EXECUTE_FAILED} the transaction is declared as failed
* and ConnectorException is thrown.
*
* @param codes
*/
protected void checkBatchCommit(int[] codes) {
for (int i = 0; i < codes.length; i++) {
if (codes[i] == Statement.EXECUTE_FAILED) {
throw new ConnectorException(
String.format("Batch commit failed with code %d at index %d", Statement.EXECUTE_FAILED, i));
}
}
}
/**
* Sets the auto commit flag to true on a JDBC Connection.
*
* @param connection
*/
protected void autoCommitTrue(Connection connection) {
try {
connect.setAutoCommit(true);
} catch (SQLException e) {
throw new ConnectorException("Problem in setting auto commit to true.", e);
}
}
/**
* Marks a transaction currently held by connection for rollback.
*
* @param connection
*/
protected void rollback(Connection connection) {
try {
connect.rollback();
} catch (SQLException e) {
throw new ConnectorException("Problem in rollback.", e);
}
}
/**
* Helper function which executes a sql query with arguments passed and
* process the result set as per the logic in JDBCResultsetBlock.
*
* @param sql
* query to be processed
* @param params
* parameters if any to be passed on to sql query
* @param block
* custom logic to be executed on result set producing a result
* of type T
* @return object instance as per the logic in block
*/
protected T jdbcAction(String sql, Object[] params, JDBCResultsetBlock block) {
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connect.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i + 1, params[i]);
}
resultSet = statement.executeQuery();
return block.apply(resultSet);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeResultSet(resultSet);
closeStatement(statement);
}
}
/**
* Update helper which executes a SQL DML query.
*
* @param sql
* DML query to be executed
* @param params
* parameters any to be passed to DML query.
*
*/
protected void updateHelper(String sql, Object... params) {
PreparedStatement statement = null;
try {
statement = connect.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
statement.setObject(i + 1, params[i]);
}
statement.executeUpdate();
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
closeStatement(statement);
}
}
/**
* Helper method which performs the query in a transaction.
* @param sql
* @param block
*/
protected void inTransaction(JDBCTransaction tx) {
try {
connect.setAutoCommit(false);
tx.apply(connect);
connect.commit();
} catch (SQLException e) {
rollback(connect);
throw new ConnectorException(e);
} finally {
autoCommitTrue(connect);
}
}
/**
* Helper method which performs the query in a transaction and return a result.
* @param sql
* @param block
*/
protected T jdbcAction(JDBCAction tx) {
try {
return tx.apply(connect);
} catch (SQLException e) {
throw new ConnectorException(e);
} finally {
}
}
/**
* Helper method which performs the query in a transaction.
* The method handles both {@link PreparedStatement} and {@link Statement}.
* If a SQL query is passed PreparedStatement instance is created else
* Statement. The logic to act on Statement is passed in JDBCBlock
*
* @param sql
* @param block
*/
protected void inTransaction(String sql, JDBCBlock block) {
Statement statement = null;
try {
connect.setAutoCommit(false);
if (!StringUtil.isNullOrEmpty(sql)) {
statement = connect.prepareStatement(sql);
} else {
statement = connect.createStatement();
}
block.apply(statement);
int[] codes = statement.executeBatch();
checkBatchCommit(codes);
connect.commit();
} catch (SQLException e) {
rollback(connect);
throw new ConnectorException(e);
} finally {
autoCommitTrue(connect);
closeStatement(statement);
}
}
/**
* Helper method to perform JDBC transaction. The logic passed inside
* JDBCBlock is executed in a transaction.
*
*
* Note : Since no SQL query is passed, the logic will use
* {@link Statement}
*
* @param block
*/
protected void inTransaction(JDBCBlock block) {
inTransaction(null, block);
}
/**
* Provides a hook method apply which will act on JDBC statement.
*
* @author gaurav
*
*/
public interface JDBCBlock {
public void apply(Statement statement) throws SQLException;
}
/**
* Provides a hook method apply which will act on JDBC connection.
*
* @author gaurav
*
*/
public interface JDBCTransaction {
public void apply(Connection connection) throws SQLException;
}
/**
* Provides a hook method apply which will act on JDBC connection
* and provide a result
*
* @author gaurav
*
*/
public interface JDBCAction {
public T apply(Connection connection) throws SQLException;
}
/**
* Provides a hook method apply which will act on JDBC result set and
* produce an instance of type T.
*
* @author gaurav
*
* @param
*/
public interface JDBCResultsetBlock {
public T apply(ResultSet resultSet) throws SQLException;
}
public static boolean hasColumn(ResultSet rs, String columnName) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
int columns = rsmd.getColumnCount();
for (int x = 1; x <= columns; x++) {
if (columnName.equals(rsmd.getColumnName(x))) {
return true;
}
}
return false;
}
}