001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.enterprise.spi.j2eeimpl;
016:
017: import java.sql.Connection;
018: import java.sql.SQLException;
019:
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022:
023: import javax.naming.Context;
024: import javax.naming.InitialContext;
025: import javax.naming.NamingException;
026: import javax.transaction.Status;
027: import javax.transaction.SystemException;
028: import javax.transaction.UserTransaction;
029:
030: import com.metaboss.enterprise.spi.JDBCConnectionProvider;
031:
032: /** Interface to the JDBC connection provider */
033: public class JDBCConnectionProviderImpl implements
034: JDBCConnectionProvider {
035: // initialise Logger instance
036: private static final Log sLogger = LogFactory
037: .getLog(JDBCConnectionProviderImpl.class);
038:
039: /* Returns JDBC connection to the named datasource */
040: public Connection getConnection(String pDatasourceName)
041: throws SQLException {
042: // Look up transaction and understand if we need to use XA or nonXA connection
043: // Note that we used to implement whole lot based on XA connection (just return it all the time)
044: // and may be this is what we should do here. Need to come back to it latter and understand
045: // implications. (I think it should just work and do 1phase commit whenever possible)
046: try {
047: Context lContext = new InitialContext();
048: UserTransaction lUserTransaction = (UserTransaction) lContext
049: .lookup("UserTransaction");
050: if (lUserTransaction != null
051: && lUserTransaction.getStatus() == Status.STATUS_ACTIVE) {
052: String lDataSourceName = pDatasourceName + "_XA";
053: String lDataSourceURL = "java:/" + lDataSourceName;
054: javax.sql.DataSource lDataSource = (javax.sql.DataSource) lContext
055: .lookup(lDataSourceURL);
056: Connection lConnectionToReturn = lDataSource
057: .getConnection();
058: if (lConnectionToReturn.getAutoCommit())
059: lConnectionToReturn.setAutoCommit(false);
060: sLogger
061: .debug("Opened datasource connection in transaction. DataSource : "
062: + lDataSourceName
063: + ". Connection : "
064: + lConnectionToReturn);
065: return lConnectionToReturn;
066: } else {
067: String lDataSourceName = pDatasourceName + "_NonXA";
068: String lDataSourceURL = "java:/" + lDataSourceName;
069: javax.sql.DataSource lDataSource = (javax.sql.DataSource) lContext
070: .lookup(lDataSourceURL);
071: Connection lConnectionToReturn = lDataSource
072: .getConnection();
073: if (lConnectionToReturn.getAutoCommit())
074: lConnectionToReturn.setAutoCommit(false);
075: sLogger
076: .debug("Opened datasource connection out of transaction. DataSource : "
077: + lDataSourceName
078: + ". Connection : "
079: + lConnectionToReturn);
080: return lConnectionToReturn;
081: }
082: } catch (SystemException e) {
083: throw new java.sql.SQLException(
084: "Unable to obtain "
085: + pDatasourceName
086: + " Connection. Caught javax.transaction.SystemException : "
087: + e.toString());
088: } catch (NamingException e) {
089: throw new java.sql.SQLException(
090: "Unable to obtain "
091: + pDatasourceName
092: + " Connection. Caught javax.naming.NamingException : "
093: + e.toString());
094: }
095: }
096:
097: /* Releases JDBC connection to the named datasource */
098: public void closeConnection(Connection pConnection)
099: throws SQLException {
100: try {
101: // It appears that we need to close connection regardless. App server
102: // has probably given us a proxy to connection and not the real thing
103: // therefore it has a chance to implement close in any way it likes
104: Context lContext = new InitialContext();
105: UserTransaction lUserTransaction = (UserTransaction) lContext
106: .lookup("UserTransaction");
107: if (lUserTransaction != null
108: && lUserTransaction.getStatus() == Status.STATUS_ACTIVE)
109: sLogger
110: .debug("Closing datasource connection in transaction. Connection : "
111: + pConnection);
112: else
113: sLogger
114: .debug("Closing datasource connection out of transaction. Connection : "
115: + pConnection);
116: // Just do the usual close
117: pConnection.close();
118: } catch (SystemException e) {
119: throw new java.sql.SQLException(
120: "Unable to close connection. Caught javax.transaction.SystemException : "
121: + e.toString());
122: } catch (NamingException e) {
123: throw new java.sql.SQLException(
124: "Unable to close connection. Caught javax.naming.NamingException : "
125: + e.toString());
126: }
127: }
128: }
|