/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.vacuumd; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.opennms.core.utils.DBUtils; import org.opennms.core.utils.ThreadCategory; import org.opennms.netmgt.config.DataSourceFactory; /** * <p>Transaction class.</p> * * @author ranger * @version $Id: $ */ public class Transaction { private static ThreadLocal<Transaction> s_threadTX = new ThreadLocal<Transaction>(); private static Transaction getTX() { Transaction tx = s_threadTX.get(); if (tx == null) { throw new IllegalStateException("No transaction has been started for this thread!"); } return tx; } private static void clearTX() { s_threadTX.set(null); } /** * <p>begin</p> */ public static void begin() { log().debug("About to begin Transaction for "+Thread.currentThread()); Transaction tx = s_threadTX.get(); if (tx != null) { throw new IllegalStateException("Cannot begin a transaction.. one has already been begun"); } log().debug("Began Transaction for "+Thread.currentThread()); s_threadTX.set(new Transaction()); } private static ThreadCategory log() { return ThreadCategory.getInstance(Transaction.class); } /** * <p>getConnection</p> * * @param dsName a {@link java.lang.String} object. * @return a {@link java.sql.Connection} object. * @throws java.sql.SQLException if any. */ public static Connection getConnection(String dsName) throws SQLException { return getTX().doGetConnection(dsName); } /** * <p>register</p> * * @param stmt a {@link java.sql.Statement} object. */ public static void register(Statement stmt) { getTX().doRegister(stmt); } /** * <p>register</p> * * @param rs a {@link java.sql.ResultSet} object. */ public static void register(ResultSet rs) { getTX().doRegister(rs); } /** * <p>rollbackOnly</p> * * @throws java.sql.SQLException if any. */ public static void rollbackOnly() throws SQLException { getTX().doRollbackOnly(); } /** * <p>end</p> * * @throws java.sql.SQLException if any. */ public static void end() throws SQLException { log().debug("Ending transaction for "+Thread.currentThread()); try { Transaction tx = getTX(); tx.doEnd(); log().debug((tx.m_rollbackOnly ? "Rolled Back" : "Committed") + " transaction for "+Thread.currentThread()); } finally { clearTX(); } } private Map<String, Connection> m_connections = new HashMap<String, Connection>(); private List<Statement> m_statements = new LinkedList<Statement>(); private List<ResultSet> m_resultSets = new LinkedList<ResultSet>(); private boolean m_rollbackOnly = false; private DBUtils m_dbUtils = new DBUtils(Transaction.class); private void doRegister(Statement stmt) { m_dbUtils.watch(stmt); m_statements.add(stmt); } private void doRegister(ResultSet rs) { m_dbUtils.watch(rs); m_resultSets.add(rs); } private void doClose() throws SQLException { m_dbUtils.cleanUp(); } private void doEnd() throws SQLException { try { for(Connection conn : m_connections.values()) { if (m_rollbackOnly) { conn.rollback(); } else { conn.commit(); } } } finally { doClose(); } } private void doRollbackOnly() throws SQLException { m_rollbackOnly = true; } private Connection doGetConnection(String dsName) throws SQLException { if (!m_connections.containsKey(dsName)) { DataSource ds = DataSourceFactory.getDataSource(dsName); if (ds == null) { throw new IllegalArgumentException("Could not find this datasource by using the DataSourceFactory: " + dsName); } Connection conn = ds.getConnection(); m_dbUtils.watch(conn); m_connections.put(dsName, conn); conn.setAutoCommit(false); } return m_connections.get(dsName); } /** * <p>finalize</p> */ public void finalize() { m_dbUtils.cleanUp(); } }