📄 legacydbconnectionfactory.java
字号:
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc. All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.//// Modifications://// 2003 Jan 31: Cleaned up some unused imports.//// Original code base Copyright (C) 1999-2001 Oculan Corp. All rights reserved.//// This program 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 2 of the License, or// (at your option) any later version.//// This program 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 this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // For more information contact: // OpenNMS Licensing <license@opennms.org>// http://www.opennms.org/// http://www.opennms.com///// Tab Size = 8//package org.opennms.netmgt.config;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Savepoint;import java.sql.Statement;import java.util.LinkedList;import java.util.Map;import org.apache.log4j.Category;import org.opennms.core.utils.ThreadCategory;/** * <p> * This is the singleton class used to load the OpenNMS database configuration * from the opennms-database.xml. This provides convenience methods to create * database connections to the database configured in this default xml * </p> * * <p> * <strong>Note: </strong>Users of this class should make sure the * <em>init()</em> is called before calling any other method to ensure the * config is loaded before accessing other convenience methods * </p> * * @author <a href="mailto:weave@oculan.com">Brian Weaver </a> * @author <a href="http://www.opennms.org/">OpenNMS </a> */public final class LegacyDbConnectionFactory implements DbConnectionFactory { /** * The maximum age before a connection is closed */ private static final int MAX_AGE = 5 * 60 * 1000; /** * Configuation of the database */ private DbConfiguration m_dbConfig; /** * The linked list of cached connections that are reused if the garbage * collector has not finalized them yet. */ private LinkedList m_dbcCache = null; /** * This class is used to represent a cached database connection within this * factory. The cached connection may or may not have been collected by the * main java garbage collector thread. If the connection still exists and is * not in use and does not have any errors then it may be reissued to * another thread requestor. * * @author <a href="mailto:weave@oculan.com">Brian Weaver </a> * @author <a href="http://www.opennms.org/">OpenNMS </a> * */ static final class CachedConnection implements Connection { /** * The cached connection */ private final Connection m_delegate; /** * The owner of the cached connection */ private final LegacyDbConnectionFactory m_owner; /** * This flag is set to true if the connection is currently in use. */ private boolean m_inUse; /** * This flag is set to true if the connection experienced an error. */ private boolean m_hadError; /** * This value is used to mark the last time the connection was returned * to the pool. If the last use reaches a certian time and the * connection is on the bottom of the stack, then it is released. This * time is set via the system time. * * @see java.lang.System#currentTimeMillis */ private long m_lastUse; /** * The class constructor used to create a new cached connection for a * particular factory. * * @param dbc * The database connection to cache. * @param owner * The owner of the cached connection. * */ CachedConnection(Connection dbc, LegacyDbConnectionFactory owner) { // this must remain simple and not manipulate factory data as // the DbConnectionFactory is not locked when the constructor is called m_delegate = dbc; m_owner = owner; m_inUse = false; m_hadError = false; m_lastUse = System.currentTimeMillis(); } /** * This method checks the access of the connection. If the connection is * not marked <em>in use</em> then access is denied via an exception. * * @throws java.sql.SQLException * Thrown if access is denied. */ private synchronized void checkAccess() throws SQLException { if (!m_inUse) { ThreadCategory.getInstance(getClass()).warn("Attempting to used closed connection", new Throwable()); throw new SQLException("The connection has already been closed"); } } /** * Returns true if the cached connection is available for use. */ synchronized boolean isAvailable() { return !m_inUse; } /** * Marks the connection as in use */ synchronized void markUsed() { m_inUse = true; } /** * Returns true if the connection has experienced any errors. */ synchronized boolean isBad() { return m_hadError; } /** * Returns the current age of the connection since it was last used in * milliseconds. The time is based upon the last time the connection was * returned to the database pool. If the connection is kept in use then * the value returned by this method is of no value. * * @return The time since the connection was last closed. */ synchronized long age() { return System.currentTimeMillis() - m_lastUse; } /** * Closes the SQL connection for the owner of the conneciton. The close * request may be forwarded to the encapsulate connection if an error * has occured or the connection is read-only. Otherwise the connection * is returned to the connection pool for reuse. * * @throws java.sql.SQLException * May be thrown by the encapsulated connection */ public synchronized void close() throws SQLException { Category log = ThreadCategory.getInstance(getClass()); boolean isTracing = log.isDebugEnabled(); if (!m_inUse) log.warn("The in use flag was not set but the connection is being closed!", new Throwable()); try { // re-enable auto commit on close // if (m_delegate.getAutoCommit() == false) m_delegate.setAutoCommit(true); // don't reuse read-only connections // if (m_delegate.isReadOnly()) { if (isTracing) log.debug("connection is read-only, setting bad flag"); m_hadError = true; } // don't reuse closed connections // if (m_delegate.isClosed()) { if (isTracing) log.debug("connection is closed, setting bad flag"); m_hadError = true; } } catch (SQLException ex) { if (isTracing) log.debug("setting bad flag true", ex); m_hadError = true; } // If the connection had errors then close // the connection. If the connection is cool // then push the conneciton onto the pool // stack. // m_inUse = false; if (m_hadError) { m_delegate.close(); } else // m_hadError == false { synchronized (m_owner.m_dbcCache) { if (isTracing) log.debug("adding connection back into pool [id=" + this + "]"); m_owner.m_dbcCache.addFirst(this); } m_lastUse = System.currentTimeMillis(); } } /** * Forwards the request to the encapuslated connection, or returns true * if the connection is not in use. * * @throws java.sql.SQLException * May be thrown by the encapsulated connection */ public synchronized boolean isClosed() throws SQLException { try { if (m_inUse) return m_delegate.isClosed(); else return true; } catch (SQLException ex) { m_hadError = true; ThreadCategory.getInstance(getClass()).debug("setting bad flag [id=" + this + "]", ex); throw ex; } } /** * Forwards the request to the encapsulated connection after access to * the connection is granted. * * @throws java.sql.SQLException * May be thrown by the encapsulated connection */ public Statement createStatement() throws SQLException { checkAccess(); try { return m_delegate.createStatement(); } catch (SQLException ex) { m_hadError = true; ThreadCategory.getInstance(getClass()).debug("setting bad flag [id=" + this + "]", ex); throw ex; } } /** * Forwards the request to the encapsulated connection after access to * the connection is granted. * * @throws java.sql.SQLException * May be thrown by the encapsulated connection */ public PreparedStatement prepareStatement(String sql) throws SQLException { checkAccess(); try { return m_delegate.prepareStatement(sql); } catch (SQLException ex) { m_hadError = true; ThreadCategory.getInstance(getClass()).debug("setting bad flag [id=" + this + "]", ex); throw ex; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -