001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.jdbc;
017:
018: import java.io.IOException;
019: import java.sql.Connection;
020: import java.sql.SQLException;
021:
022: import javax.sql.DataSource;
023:
024: import org.geotools.data.DataSourceException;
025: import org.geotools.data.Transaction;
026: import org.geotools.data.Transaction.State;
027:
028: /**
029: * Holds a JDBC Connectino for JDBCDataStore.
030: * <p>
031: * An alternative would be to hold the connection pool in the Transaction
032: * State and only construct a connection when setTransaction is called.
033: * </p>
034: * @author Jody Garnett, Refractions Research
035: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/JDBCTransactionState.java $
036: */
037: public class JDBCTransactionState implements State {
038: private Connection connection;
039:
040: public JDBCTransactionState(Connection connection)
041: throws IOException {
042: this .connection = connection;
043: }
044:
045: public JDBCTransactionState(DataSource pool) throws IOException {
046: try {
047: connection = pool.getConnection();
048: connection.setAutoCommit(false);
049: } catch (SQLException e) {
050: connection = null;
051: // This has not harmed the Transaction yet
052: // so we don't need to force a rollback :-)
053: throw new DataSourceException(
054: "Transaction could not acquire connection", e);
055: }
056: }
057:
058: /**
059: * Retrieve connection for JDBC operation.
060: * <p>
061: * This connection may be used to issue JDBC operations against
062: * this transaction.
063: * </p>
064: * <p>
065: * Please do not use:
066: * </p>
067: * <ul>
068: * <li>setAutoCommit()</li>
069: * <li>commit()</li>
070: * <li>rollback()</li>
071: * </ul>
072: */
073: public Connection getConnection() {
074: // We could make a wrapper to prevent the above
075: // restricted operations
076: return connection;
077: }
078:
079: /**
080: * Closes internal connection returns it to the ConnectionPool.
081: *
082: * @see org.geotools.data.Transaction.State#setTransaction(org.geotools.data.Transaction)
083: * @param transaction
084: */
085: public void setTransaction(Transaction transaction) {
086: if (transaction == null) {
087: if (connection != null) {
088: try {
089: // return to pool
090: connection.close();
091: } catch (SQLException e) {
092: // does this need to fail quiet?
093: // (at least it won't mess up the transaction)
094: }
095: connection = null;
096: } else {
097: // connection was already closed !
098: // We will be quiet on this one to
099: // allow finally blocks a bit a of leaway
100: }
101: }
102: }
103:
104: /**
105: * Not used by JDBCTransactionState
106: * <p>
107: * Postgis will need to override this method to use strong transaction
108: * support.
109: * </p>
110: * @see org.geotools.data.Transaction.State#addAuthorization(java.lang.String)
111: * @param AuthID
112: * @throws IOException
113: */
114: public void addAuthorization(String AuthID) throws IOException {
115: // not needed (yet)
116: }
117:
118: /**
119: * Commit the maintained state.
120: * <p>
121: * JDBCTransactionState offers native support for this operation
122: * </p>
123: * @see org.geotools.data.Transaction.State#commit()
124: * @throws IOException
125: */
126: public void commit() throws IOException {
127: try {
128: connection.commit();
129: } catch (SQLException e) {
130: // TODO: a rock and a hard place
131: //
132: // This is a horrible situation.
133: // I assume the commit failed meaning that this connection was
134: // transaction was rolled back.
135: // This is the worse though as we are calling this in a
136: // loop as we commit all other Transaction.State!
137: //
138: // That is we should rollback, but we cannot! (As we may have already
139: // commited someone else)
140: // We are absolutely going to have an inconsistent state here
141: // and there is nothing I can do about it :-(
142: //
143: // This would be a design flaw, if there was anything we
144: // could do about it
145: throw new DataSourceException("Transaction commit", e);
146: }
147: }
148:
149: /**
150: * Rollback state of Transacstion.
151: * <p>
152: * JDBCTransactionState offers native support for this operation
153: * </p>
154: * @see org.geotools.data.Transaction.State#rollback()
155: * @throws IOException
156: */
157: public void rollback() throws IOException {
158: try {
159: // TODO: does conneciton rollback clear warnings?
160: connection.rollback();
161: } catch (SQLException e) {
162: // TODO: between a rock and a rock
163: // I am not sure how a rollback can fail, but we managed it
164: // since the correct response is to rollback the Transaciton
165: // we will continue on
166: throw new DataSourceException("Transaction rollback", e);
167: }
168: }
169: }
|