// ********************************************************************** // // Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** // // A SQL request context encapsulates SQL resources allocated in the // process of executing a request, such as the database connection, // and associated SQL statements. // // The request context is automatically destroyed at the end of a // request, or if obtain is called it must be destroyed manually by // calling destroy. // // When the request context is destroyed, the transaction is rolled // back, if not already committed, and all allocated resources are // released, // class SQLRequestContext { public static SQLRequestContext getCurrentContext() { synchronized(_contextMap) { SQLRequestContext context = _contextMap.get(Thread.currentThread()); if(context != null) { //context._logger.trace("SQLRequestContext", "getCurrentContext: thread " + Thread.currentThread() + //": connection: " + context._conn); } return context; } } public java.sql.PreparedStatement prepareStatement(String sql) throws java.sql.SQLException { java.sql.PreparedStatement stmt = _conn.prepareStatement(sql); _statements.add(stmt); return stmt; } public java.sql.PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws java.sql.SQLException { java.sql.PreparedStatement stmt = _conn.prepareStatement(sql, autoGeneratedKeys); _statements.add(stmt); return stmt; } // Called to obtain ownership of the context. The context is no // longer destroyed automatically when the current request has // completed. public void obtain() { // Remove the current context from the map. synchronized(_contextMap) { //_logger.trace("SQLRequestContext", "obtain: connection: " + _conn); _contextMap.remove(Thread.currentThread()); } } public void destroy() { synchronized(_contextMap) { SQLRequestContext context = _contextMap.remove(Thread.currentThread()); assert context == null; } //_logger.trace("SQLRequestContext", "destroy: connection: " + _conn); // Release all resources. try { // Rollback the transaction if it was not committed. if(!_commit) { //_logger.trace("SQLRequestContext", "rollback: thread " + Thread.currentThread() + ": connection: " + _conn); _conn.rollback(); } java.util.Iterator p = _statements.iterator(); while(p.hasNext()) { p.next().close(); } } catch(java.sql.SQLException e) { error(e); } _pool.release(_conn); _statements.clear(); _conn = null; _pool = null; } public void commit() throws java.sql.SQLException { _conn.commit(); //_logger.trace("SQLRequestContext", "commit: thread " + Thread.currentThread() + ": connection: " + _conn); _commit = true; } SQLRequestContext(Ice.Logger logger, ConnectionPool pool) { _logger = logger; _pool = pool; _conn = pool.acquire(); synchronized(_contextMap) { //_logger.trace("SQLRequestContext", "associate: thread " + Thread.currentThread() + ": connection: " + _conn); _contextMap.put(Thread.currentThread(), this); } } // Called only by the servant locator. void destroyFromLocator() { synchronized(_contextMap) { //_logger.trace("SQLRequestContext", "release: connection: " + _conn); // Remove the current context from the map. SQLRequestContext context = _contextMap.remove(Thread.currentThread()); assert context == this; } destroy(); } private void error(Exception ex) { java.io.StringWriter sw = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(sw); ex.printStackTrace(pw); pw.flush(); _logger.error("SQLRequestContext: error:\n" + sw.toString()); } // A map of threads to request contexts. private static java.util.Map _contextMap = new java.util.HashMap(); private Ice.Logger _logger; private ConnectionPool _pool; private java.util.List _statements = new java.util.LinkedList(); private java.sql.Connection _conn; private boolean _commit = false; }