001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.mapper.rdb;
018:
019: import org.objectweb.jorm.api.PException;
020: import org.objectweb.jorm.api.PMapper;
021: import org.objectweb.perseus.persistence.api.ConnectionHolder;
022: import org.objectweb.perseus.persistence.api.PersistenceException;
023: import org.objectweb.perseus.persistence.api.WorkingSet;
024: import org.objectweb.speedo.workingset.api.TransactionItf;
025: import org.objectweb.util.monolog.api.BasicLevel;
026: import org.objectweb.util.monolog.api.Logger;
027:
028: import java.sql.Connection;
029: import java.sql.SQLException;
030:
031: /**
032: * Is an holder of JDBC connection. It can works in managed or non-managed
033: * transactional environnement.
034: *
035: * @author S.Chassande-Barrioz
036: */
037: public class JDBCConnectionHolder implements ConnectionHolder {
038:
039: /**
040: * the mapper allocating JDBC connections
041: */
042: protected PMapper mapper;
043:
044: /**
045: * The workingSet attached to this connection holder
046: */
047: protected TransactionItf workingSet;
048:
049: /**
050: * The SQL connection held. Can be null if no connectioin has been used
051: */
052: protected Connection connection;
053:
054: /**
055: * Indicates the access through the connection must be done inside a
056: * transaction.
057: */
058: protected boolean transactional = false;
059:
060: /**
061: * Indicates if the transaction demarcations must tbe done by the
062: * ConnectionHolder or there are already done by an environment
063: * (an Application Server for example).
064: */
065: protected boolean txManagedExternaly = false;
066:
067: protected Logger logger;
068:
069: public JDBCConnectionHolder(PMapper mapper, Logger logger) {
070: this .mapper = mapper;
071: this .logger = logger;
072: }
073:
074: /**
075: * Primitive method demarcating the begining of a local transaction on the
076: * current connection.
077: */
078: protected void beginLocalTransaction() throws PersistenceException {
079: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
080: logger.log(BasicLevel.DEBUG,
081: "Begin a local transaction on the connection: "
082: + connection);
083: }
084: try {
085: connection.setAutoCommit(false);
086: } catch (SQLException e) {
087: throw new PersistenceException(e);
088: }
089: }
090:
091: /**
092: * primitive method demarcating the end of a local transaction by a commit
093: */
094: protected void commitLocalTransaction() throws PersistenceException {
095: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
096: logger.log(BasicLevel.DEBUG,
097: "Commit the local transaction on the connection: "
098: + connection);
099: }
100: try {
101: connection.commit();
102: connection.setAutoCommit(true);
103: } catch (SQLException e) {
104: throw new PersistenceException(e);
105: }
106: }
107:
108: /**
109: * primitive method demarcating the end of a local transaction by a rollback
110: */
111: protected void rollbackLocalTransaction()
112: throws PersistenceException {
113: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
114: logger.log(BasicLevel.DEBUG,
115: "Rollback the local transaction on the connection: "
116: + connection);
117: }
118: try {
119: connection.rollback();
120: connection.setAutoCommit(true);
121: } catch (SQLException e) {
122: throw new PersistenceException(e);
123: }
124: }
125:
126: // IMPLEMENTATION OF THE ConnectionHolder INTERFACE //
127: //--------------------------------------------------//
128:
129: public WorkingSet getWorkingSet() {
130: return workingSet;
131: }
132:
133: public void bindWorkingSet(WorkingSet ws) {
134: this .workingSet = (TransactionItf) ws;
135: }
136:
137: public Object getCHConnectionForRead() throws PersistenceException {
138: return getCHConnectionForWrite();
139: }
140:
141: public Object getCHConnectionForWrite() throws PersistenceException {
142: if (connection == null) {
143: Object cs = null;
144: cs = workingSet.getPOManager().getConnectionSpec();
145: txManagedExternaly = workingSet.isManagedEnv();
146: try {
147: if (cs == null) {
148: connection = (Connection) mapper.getConnection();
149: } else {
150: connection = (Connection) mapper.getConnection(cs);
151: }
152: } catch (PException e) {
153: throw new PersistenceException(
154: "Impossible to fetch a SQL connection", e);
155: }
156: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
157: logger.log(BasicLevel.DEBUG, "Allocate a connection: "
158: + connection);
159: }
160: if (transactional && !txManagedExternaly) {
161: beginLocalTransaction();
162: }
163: }
164: return connection;
165: }
166:
167: /**
168: * If there is no connection already allocated, the transaction being will
169: * be during the next connection request (getConnectionFor...(...)
170: *
171: * @throws org.objectweb.perseus.persistence.api.PersistenceException
172: */
173: public void begin() throws PersistenceException {
174: transactional = true;
175: if (connection != null) {
176: beginLocalTransaction();
177: }
178: }
179:
180: public void commitCH() throws PersistenceException {
181: try {
182: if (connection != null && !txManagedExternaly
183: && transactional) {
184: commitLocalTransaction();
185: }
186: } finally {
187: transactional = false;
188: }
189: }
190:
191: public void rollbackCH() throws PersistenceException {
192: try {
193: if (connection != null && !txManagedExternaly
194: && transactional) {
195: rollbackLocalTransaction();
196: }
197: } finally {
198: transactional = false;
199: }
200: }
201:
202: public void releaseCHConnection() throws PersistenceException {
203: if (connection != null && txManagedExternaly) {
204: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
205: logger.log(BasicLevel.DEBUG, "Release the connection "
206: + connection);
207: }
208: closeCHConnection();
209: }
210: }
211:
212: public void closeCHConnection() throws PersistenceException {
213: if (connection != null) {
214: if (logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
215: logger.log(BasicLevel.DEBUG, "Close the connection: "
216: + connection);
217: }
218: try {
219: mapper.closeConnection(connection);
220: } catch (PException e) {
221: throw new PersistenceException(e);
222: } finally {
223: connection = null;
224: }
225: }
226: }
227: }
|