/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You 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.
*/
package com.esri.gpt.framework.sql;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.naming.NamingException;
/**
* Acts as a wrapper for a JDBC connection.
* <p>
* This class is intended for use by a single execution thread.
*/
public final class ManagedConnection {
// class variables =============================================================
// instance variables ==========================================================
private DatabaseReference _databaseReference = null;
private Connection _jdbcConnection = null;
private TransactionCounter _transactionCounter = new TransactionCounter();
/**
* Construct based upon a supplied DatabaseReference.
* <p>
* During construction, a JDBC connection is established based upon
* the associated with a DatabaseReference.
* @param databaseReference the associated DatabaseReference
* @throws ClassNotFoundException if the database driver class was not found
* @throws NamingException if a JNDI naming exception occurs
* @throws SQLException if an SQL exception occurs while establishing the connection
*/
protected ManagedConnection(DatabaseReference databaseReference)
throws ClassNotFoundException, NamingException, SQLException {
if (databaseReference == null) {
throw new IllegalArgumentException("databaseReference cannot be null");
} else {
setDatabaseReference(databaseReference);
setJdbcConnection(getDatabaseReference().openConnection());
}
}
// properties ==================================================================
/**
* Gets the underlying JDBC connection.
* @return the underlying JDBC connection
*/
public Connection getJdbcConnection() {
return _jdbcConnection;
}
/**
* Sets the underlying JDBC connection.
* @param con the underlying JDBC connection
*/
private void setJdbcConnection(Connection con) {
_jdbcConnection = con;
}
/**
* Gets the DatabaseReference for this connection.
* @return the associated DatabaseReference
*/
protected DatabaseReference getDatabaseReference() {
return _databaseReference;
}
/**
* Sets the DatabaseReference for this connection.
* @param databaseReference the associated DatabaseReference
*/
private void setDatabaseReference(DatabaseReference databaseReference) {
_databaseReference = databaseReference;
}
/**
* Gets the transaction counter.
* @return the transaction counter
*/
private TransactionCounter getTransactionCounter() {
return _transactionCounter;
}
// methods =====================================================================
/**
* Closes the underlying JDBC connection.
* <br/>The underlying TransactionCounter is reset.
*/
protected void close() {
Connection con = getJdbcConnection();
getTransactionCounter().reset(con);
getDatabaseReference().closeConnection(con);
setJdbcConnection(null);
}
/**
* Handles the commit for the transaction.
* <br/>If this ManagedConnection was not prepared for transactions,
* no commit is executed.
* <br/>If the underlying transaction count is zero, no commit is executed.
* @throws SQLException if an exception occurs
*/
public void commit() throws SQLException {
getTransactionCounter().commit(getJdbcConnection());
}
/**
* Finalize on garbage collection.
* @throws Throwable
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
close();
}
/**
* Increments the underlying TransactionCounter by one.
*/
public void incrementTransactionCount() {
getTransactionCounter().increment();
}
/**
* Compare the underlying JDBC connection with another.
* @param connection the connection to compare
* @return true if the underlying JDBC connection == the passed connection
*/
protected boolean isJdbcConnection(Connection connection) {
return ((connection != null) && (connection == getJdbcConnection()));
}
/**
* Prepares the underlying TransactionCounter prior to any edits.
* <br/>Auto commit is set to false for the underlying JDBC connection.
* <br/>This method must be executed prior to any commit or rollback.
* @throws SQLException if an exception occurs
*/
public void prepareForTransactions() throws SQLException {
getTransactionCounter().prepare(getJdbcConnection());
}
/**
* Handles the rollback for the transaction.
* <br/>A single rolback is executed for each incremented transaction count.
* <br/>If this ManagedConnection was not prepared for transactions,
* no rollback is executed.
*/
public void rollback() {
getTransactionCounter().rollback(getJdbcConnection());
}
/**
* Gets clob mutator.
* @return clob mutator
* @throws java.sql.SQLException if error getting clob mutator
*/
public IClobMutator getClobMutator() throws SQLException {
DatabaseMetaData dmt = this.getJdbcConnection().getMetaData();
String database = dmt.getDatabaseProductName().toLowerCase();
if (database.contains("postgresql")) {
return new TextClobMutator();
}
if (database.contains("oracle")) {
return new StdClobMutator();
}
if (database.contains("microsoft")) {
return new TextClobMutator();
}
if (database.contains("db2")) {
return new StdClobMutator();
}
if (database.contains("mysql")) {
return new StdClobMutator();
}
return new StdClobMutator();
}
}