/**
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.objectweb.speedo.mapper.rdb;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PMapper;
import org.objectweb.perseus.persistence.api.ConnectionHolder;
import org.objectweb.perseus.persistence.api.PersistenceException;
import org.objectweb.perseus.persistence.api.WorkingSet;
import org.objectweb.speedo.workingset.api.TransactionItf;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Is an holder of JDBC connection. It can works in managed or non-managed
* transactional environnement.
*
* @author S.Chassande-Barrioz
*/
public class JDBCConnectionHolder implements ConnectionHolder {
/**
* the mapper allocating JDBC connections
*/
protected PMapper mapper;
/**
* The workingSet attached to this connection holder
*/
protected TransactionItf workingSet;
/**
* The SQL connection held. Can be null if no connectioin has been used
*/
protected Connection connection;
/**
* Indicates the access through the connection must be done inside a
* transaction.
*/
protected boolean transactional = false;
/**
* Indicates if the transaction demarcations must tbe done by the
* ConnectionHolder or there are already done by an environment
* (an Application Server for example).
*/
protected boolean txManagedExternaly = false;
protected Logger logger;
public JDBCConnectionHolder(PMapper mapper, Logger logger) {
this.mapper = mapper;
this.logger = logger;
}
/**
* Primitive method demarcating the begining of a local transaction on the
* current connection.
*/
protected void beginLocalTransaction() throws PersistenceException {
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG,
"Begin a local transaction on the connection: " + connection);
}
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* primitive method demarcating the end of a local transaction by a commit
*/
protected void commitLocalTransaction() throws PersistenceException {
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG,
"Commit the local transaction on the connection: " + connection);
}
try {
connection.commit();
connection.setAutoCommit(true);
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* primitive method demarcating the end of a local transaction by a rollback
*/
protected void rollbackLocalTransaction() throws PersistenceException {
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG,
"Rollback the local transaction on the connection: " + connection);
}
try {
connection.rollback();
connection.setAutoCommit(true);
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
// IMPLEMENTATION OF THE ConnectionHolder INTERFACE //
//--------------------------------------------------//
public WorkingSet getWorkingSet() {
return workingSet;
}
public void bindWorkingSet(WorkingSet ws) {
this.workingSet = (TransactionItf) ws;
}
public Object getCHConnectionForRead() throws PersistenceException {
return getCHConnectionForWrite();
}
public Object getCHConnectionForWrite() throws PersistenceException {
if (connection == null) {
Object cs = null;
cs = workingSet.getPOManager().getConnectionSpec();
txManagedExternaly = workingSet.isManagedEnv();
try {
if (cs == null) {
connection = (Connection) mapper.getConnection();
} else {
connection = (Connection) mapper.getConnection(cs);
}
} catch (PException e) {
throw new PersistenceException("Impossible to fetch a SQL connection", e);
}
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Allocate a connection: " + connection);
}
if (transactional && !txManagedExternaly) {
beginLocalTransaction();
}
}
return connection;
}
/**
* If there is no connection already allocated, the transaction being will
* be during the next connection request (getConnectionFor...(...)
*
* @throws org.objectweb.perseus.persistence.api.PersistenceException
*/
public void begin() throws PersistenceException {
transactional = true;
if (connection != null) {
beginLocalTransaction();
}
}
public void commitCH() throws PersistenceException {
try {
if (connection != null && !txManagedExternaly && transactional) {
commitLocalTransaction();
}
} finally {
transactional = false;
}
}
public void rollbackCH() throws PersistenceException {
try {
if (connection != null && !txManagedExternaly && transactional) {
rollbackLocalTransaction();
}
} finally {
transactional = false;
}
}
public void releaseCHConnection() throws PersistenceException {
if (connection != null && txManagedExternaly) {
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Release the connection " + connection);
}
closeCHConnection();
}
}
public void closeCHConnection() throws PersistenceException {
if (connection != null) {
if (logger !=null && logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Close the connection: " + connection);
}
try {
mapper.closeConnection(connection);
} catch (PException e) {
throw new PersistenceException(e);
} finally {
connection = null;
}
}
}
}