⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connectionpool.java

📁 POS is a Java&#174 platform-based, mission-critical, ISO-8583 based financial transaction library/fr
💻 JAVA
字号:
/* * jPOS Project [http://jpos.org] * Copyright (C) 2000-2008 Alejandro P. Revilla * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program.  If not, see <http://www.gnu.org/licenses/>. */package org.jpos.tpl;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.Vector;import org.jpos.core.Configurable;import org.jpos.core.Configuration;import org.jpos.core.ConfigurationException;import org.jpos.util.LogSource;import org.jpos.util.Logger;import org.jpos.util.LogEvent;import org.jpos.util.NameRegistrar;/** A class for preallocating, recycling, and managing *  JDBC connections. *  <P> *  Taken from Core Servlets and JavaServer Pages *  from Prentice Hall and Sun Microsystems Press, *  http://www.coreservlets.com/. *  &copy; 2000 Marty Hall; may be freely used or adapted. *  @author Rajal Shah *  @version $Revision: 2594 $ $Date: 2008-01-22 14:41:31 -0200 (Tue, 22 Jan 2008) $ */public class ConnectionPool implements Runnable, LogSource, Configurable {    Configuration cfg;    Logger logger;    String realm;    private String driver, url, username, password;    private int maxConnections;    private boolean waitIfBusy;    private Vector availableConnections, busyConnections;    private boolean connectionPending = false;   /**    * no args constructor    */    public ConnectionPool () {        super();    }    public void setConfiguration (Configuration cfg)        throws ConfigurationException    {        this.cfg = cfg;        initEngine();    }    private void initEngine () throws ConfigurationException {        initJDBC();    }    private void initJDBC() throws ConfigurationException {        try {            Class.forName(cfg.get("jdbc.driver")).newInstance();        } catch (Exception e) {            throw new ConfigurationException (e);        }        driver = cfg.get("jdbc.driver");        url    = cfg.get("jdbc.url");        username = cfg.get("jdbc.user");        password = cfg.get("jdbc.password");        int initialConnections = cfg.getInt("initial-connections");        maxConnections = cfg.getInt("max-connections");        waitIfBusy = cfg.getBoolean("wait-if-busy");        if (initialConnections > maxConnections) {            initialConnections = maxConnections;        }        availableConnections = new Vector(initialConnections);        busyConnections = new Vector();        for(int i=0; i<initialConnections; i++) {            try {                availableConnections.addElement(makeNewConnection());            } catch(SQLException e) {                throw new ConfigurationException(e);            }        }    }   /**    * To invoke the Connection Pool object directly without jPOS.    */    public ConnectionPool(String driver, String url,                        String username, String password,                        int initialConnections,                        int maxConnections,                        boolean waitIfBusy)        throws SQLException    {        this.driver = driver;        this.url = url;        this.username = username;        this.password = password;        this.maxConnections = maxConnections;        this.waitIfBusy = waitIfBusy;        if (initialConnections > maxConnections) {            initialConnections = maxConnections;        }        availableConnections = new Vector(initialConnections);        busyConnections = new Vector();        for(int i=0; i<initialConnections; i++) {            availableConnections.addElement(makeNewConnection());        }    }    public synchronized Connection getConnection()        throws SQLException    {        if (!availableConnections.isEmpty()) {            Connection existingConnection =                (Connection)availableConnections.lastElement();            int lastIndex = availableConnections.size() - 1;            availableConnections.removeElementAt(lastIndex);            // If connection on available list is closed (e.g.,            // it timed out), then remove it from available list            // and repeat the process of obtaining a connection.            // Also wake up threads that were waiting for a            // connection because maxConnection limit was reached.            if (existingConnection.isClosed()) {                notifyAll(); // Freed up a spot for anybody waiting                return(getConnection());            } else {                busyConnections.addElement(existingConnection);                return(existingConnection);            }        } else {            // Three possible cases:            // 1) You haven't reached maxConnections limit. So            //    establish one in the background if there isn't            //    already one pending, then wait for            //    the next available connection (whether or not            //    it was the newly established one).            // 2) You reached maxConnections limit and waitIfBusy            //    flag is false. Throw SQLException in such a case.            // 3) You reached maxConnections limit and waitIfBusy            //    flag is true. Then do the same thing as in second            //    part of step 1: wait for next available connection.            if ((totalConnections() < maxConnections) && !connectionPending) {                makeBackgroundConnection();            } else if (!waitIfBusy && !connectionPending) {                throw new SQLException("Connection limit reached");            }            // Wait for either a new connection to be established            // (if you called makeBackgroundConnection) or for            // an existing connection to be freed up.            try {                wait();            } catch (InterruptedException ie) {}            // Someone freed up a connection, so try again.            return(getConnection());        }    }    // You can't just make a new connection in the foreground    // when none are available, since this can take several    // seconds with a slow network connection. Instead,    // start a thread that establishes a new connection,    // then wait. You get woken up either when the new connection    // is established or if someone finishes with an existing    // connection.    private void makeBackgroundConnection() {        connectionPending = true;        try {            Thread connectThread = new Thread(this,"ConnectionPool-connect");            connectThread.start();        } catch(OutOfMemoryError oome) {        // Give up on new connection        }    }    public void run() {        Connection connection = null;        while (connection == null) {            try {                connection = makeNewConnection();                synchronized(this) {                    availableConnections.addElement(connection);                    connectionPending = false;                    notifyAll();                }            } catch(Exception e) { // SQLException or OutOfMemory                LogEvent evt = new LogEvent (this, "error");                evt.addMessage ("An error occurred while trying to make a background connection");                evt.addMessage (e);                Logger.log (evt);                try {                    Thread.sleep (3000); // don't get too crazy about retrying                } catch (InterruptedException ie) {                    // this one, we don't care.                }            }        }    }    // This explicitly makes a new connection. Called in    // the foreground when initializing the ConnectionPool,    // and called in the background when running.    private Connection makeNewConnection()        throws SQLException {        try {            // Load database driver if not already loaded            Class.forName(driver);            // Establish network connection to database            Connection connection =                DriverManager.getConnection(url, username, password);            return(connection);        } catch(ClassNotFoundException cnfe) {            // Simplify try/catch blocks of people using this by            // throwing only one exception type.            throw new SQLException("Can't find class for driver: " +                                driver);        }    }    public synchronized void free(Connection connection) {        if(busyConnections.removeElement(connection)) {            availableConnections.addElement(connection);        }        // Wake up threads that are waiting for a connection        notifyAll();    }    public synchronized int totalConnections() {        return(availableConnections.size() + busyConnections.size());    }    public synchronized int getTotalConnections(){        return (availableConnections.size() + busyConnections.size());    }    /** Close all the connections. Use with caution:    *  be sure no connections are in use before    *  calling. Note that you are not <I>required</I> to    *  call this when done with a ConnectionPool, since    *  connections are guaranteed to be closed when    *  garbage collected. But this method gives more control    *  regarding when the connections are closed.    */    public synchronized void closeAllConnections() {        closeConnections(availableConnections);        availableConnections = new Vector();        closeConnections(busyConnections);        busyConnections = new Vector();    }    private void closeConnections(Vector connections) {        try {            for(int i=0; i<connections.size(); i++) {                Connection connection = (Connection)connections.elementAt(i);                if (!connection.isClosed()) {                    connection.close();                }            }        } catch(SQLException sqle) {            // Ignore errors; garbage collect anyhow        }    }    public synchronized String toString() {        String info =            "ConnectionPool(" + url + "," + username + ")" +            ", available=" + availableConnections.size() +            ", busy=" + busyConnections.size() +            ", max=" + maxConnections;        return(info);    }    public void setLogger (Logger logger, String realm) {        this.logger = logger;        this.realm  = realm;    }    public String getRealm () {        return realm;    }    public Logger getLogger() {        return logger;    }    /**     * @return ISOMUX instance with given name.     * @throws NameRegistrar.NotFoundException;     * @see NameRegistrar     */    public static ConnectionPool getConnectionPool (String name)        throws NameRegistrar.NotFoundException    {        return (ConnectionPool) NameRegistrar.get ("connection.pool."+name);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -