EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.jdbcx]

COVERAGE SUMMARY FOR SOURCE FILE [JdbcConnectionPool.java]

nameclass, %method, %block, %line, %
JdbcConnectionPool.java100% (1/1)81%  (17/21)95%  (266/281)91%  (74/81)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcConnectionPool100% (1/1)81%  (17/21)95%  (266/281)91%  (74/81)
connectionErrorOccurred (ConnectionEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
getParentLogger (): Logger 0%   (0/1)0%   (0/2)0%   (0/1)
isWrapperFor (Class): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
unwrap (Class): Object 0%   (0/1)0%   (0/3)0%   (0/1)
recycleConnection (PooledConnection): void 100% (1/1)90%  (36/40)89%  (8/9)
JdbcConnectionPool (ConnectionPoolDataSource): void 100% (1/1)96%  (22/23)90%  (9/10)
getConnection (): Connection 100% (1/1)98%  (45/46)90%  (9/10)
closeConnection (PooledConnection): void 100% (1/1)100% (12/12)100% (6/6)
connectionClosed (ConnectionEvent): void 100% (1/1)100% (11/11)100% (4/4)
create (ConnectionPoolDataSource): JdbcConnectionPool 100% (1/1)100% (5/5)100% (1/1)
create (String, String, String): JdbcConnectionPool 100% (1/1)100% (18/18)100% (5/5)
dispose (): void 100% (1/1)100% (27/27)100% (7/7)
getActiveConnections (): int 100% (1/1)100% (3/3)100% (1/1)
getConnection (String, String): Connection 100% (1/1)100% (4/4)100% (1/1)
getConnectionNow (): Connection 100% (1/1)100% (41/41)100% (9/9)
getLogWriter (): PrintWriter 100% (1/1)100% (3/3)100% (1/1)
getLoginTimeout (): int 100% (1/1)100% (3/3)100% (1/1)
getMaxConnections (): int 100% (1/1)100% (3/3)100% (1/1)
setLogWriter (PrintWriter): void 100% (1/1)100% (4/4)100% (2/2)
setLoginTimeout (int): void 100% (1/1)100% (8/8)100% (4/4)
setMaxConnections (int): void 100% (1/1)100% (21/21)100% (5/5)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: Christian d'Heureuse, www.source-code.biz
5 *
6 * This class is multi-licensed under LGPL, MPL 2.0, and EPL 1.0.
7 *
8 * This module is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation, either
11 * version 3 of the License, or (at your option) any later version.
12 * See http://www.gnu.org/licenses/lgpl.html
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A
17 * PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 */
20package org.h2.jdbcx;
21 
22import java.io.PrintWriter;
23import java.sql.Connection;
24import java.sql.SQLException;
25import java.util.ArrayList;
26import javax.sql.ConnectionEvent;
27import javax.sql.ConnectionEventListener;
28import javax.sql.ConnectionPoolDataSource;
29import javax.sql.DataSource;
30import javax.sql.PooledConnection;
31import org.h2.util.New;
32import org.h2.message.DbException;
33 
34//## Java 1.7 ##
35import java.util.logging.Logger;
36//*/
37 
38/**
39 * A simple standalone JDBC connection pool.
40 * It is based on the
41 * <a href="http://www.source-code.biz/snippets/java/8.htm">
42 *  MiniConnectionPoolManager written by Christian d'Heureuse (Java 1.5)
43 * </a>. It is used as follows:
44 * <pre>
45 * import java.sql.*;
46 * import org.h2.jdbcx.JdbcConnectionPool;
47 * public class Test {
48 *     public static void main(String... args) throws Exception {
49 *         JdbcConnectionPool cp = JdbcConnectionPool.create(
50 *             "jdbc:h2:~/test", "sa", "sa");
51 *         for (String sql : args) {
52 *             Connection conn = cp.getConnection();
53 *             conn.createStatement().execute(sql);
54 *             conn.close();
55 *         }
56 *         cp.dispose();
57 *     }
58 * }
59 * </pre>
60 *
61 * @author Christian d'Heureuse
62 *      (<a href="http://www.source-code.biz">www.source-code.biz</a>)
63 * @author Thomas Mueller
64 */
65public class JdbcConnectionPool implements DataSource, ConnectionEventListener {
66 
67    private static final int DEFAULT_TIMEOUT = 30;
68    private static final int DEFAULT_MAX_CONNECTIONS = 10;
69 
70    private final ConnectionPoolDataSource dataSource;
71    private final ArrayList<PooledConnection> recycledConnections = New.arrayList();
72    private PrintWriter logWriter;
73    private int maxConnections = DEFAULT_MAX_CONNECTIONS;
74    private int timeout = DEFAULT_TIMEOUT;
75    private int activeConnections;
76    private boolean isDisposed;
77 
78    protected JdbcConnectionPool(ConnectionPoolDataSource dataSource) {
79        this.dataSource = dataSource;
80        if (dataSource != null) {
81            try {
82                logWriter = dataSource.getLogWriter();
83            } catch (SQLException e) {
84                // ignore
85            }
86        }
87    }
88 
89    /**
90     * Constructs a new connection pool.
91     *
92     * @param dataSource the data source to create connections
93     * @return the connection pool
94     */
95    public static JdbcConnectionPool create(ConnectionPoolDataSource dataSource) {
96        return new JdbcConnectionPool(dataSource);
97    }
98 
99    /**
100     * Constructs a new connection pool for H2 databases.
101     *
102     * @param url the database URL of the H2 connection
103     * @param user the user name
104     * @param password the password
105     * @return the connection pool
106     */
107    public static JdbcConnectionPool create(String url, String user,
108            String password) {
109        JdbcDataSource ds = new JdbcDataSource();
110        ds.setURL(url);
111        ds.setUser(user);
112        ds.setPassword(password);
113        return new JdbcConnectionPool(ds);
114    }
115 
116    /**
117     * Sets the maximum number of connections to use from now on.
118     * The default value is 10 connections.
119     *
120     * @param max the maximum number of connections
121     */
122    public synchronized void setMaxConnections(int max) {
123        if (max < 1) {
124            throw new IllegalArgumentException("Invalid maxConnections value: " + max);
125        }
126        this.maxConnections = max;
127        // notify waiting threads if the value was increased
128        notifyAll();
129    }
130 
131    /**
132     * Gets the maximum number of connections to use.
133     *
134     * @return the max the maximum number of connections
135     */
136    public synchronized int getMaxConnections() {
137        return maxConnections;
138    }
139 
140    /**
141     * Gets the maximum time in seconds to wait for a free connection.
142     *
143     * @return the timeout in seconds
144     */
145    @Override
146    public synchronized int getLoginTimeout() {
147        return timeout;
148    }
149 
150    /**
151     * Sets the maximum time in seconds to wait for a free connection.
152     * The default timeout is 30 seconds. Calling this method with the
153     * value 0 will set the timeout to the default value.
154     *
155     * @param seconds the timeout, 0 meaning the default
156     */
157    @Override
158    public synchronized void setLoginTimeout(int seconds) {
159        if (seconds == 0) {
160            seconds = DEFAULT_TIMEOUT;
161        }
162        this.timeout = seconds;
163    }
164 
165    /**
166     * Closes all unused pooled connections.
167     * Exceptions while closing are written to the log stream (if set).
168     */
169    public synchronized void dispose() {
170        if (isDisposed) {
171            return;
172        }
173        isDisposed = true;
174        ArrayList<PooledConnection> list = recycledConnections;
175        for (int i = 0, size = list.size(); i < size; i++) {
176            closeConnection(list.get(i));
177        }
178    }
179 
180    /**
181     * Retrieves a connection from the connection pool. If
182     * <code>maxConnections</code> connections are already in use, the method
183     * waits until a connection becomes available or <code>timeout</code>
184     * seconds elapsed. When the application is finished using the connection,
185     * it must close it in order to return it to the pool.
186     * If no connection becomes available within the given timeout, an exception
187     * with SQL state 08001 and vendor code 8001 is thrown.
188     *
189     * @return a new Connection object.
190     * @throws SQLException when a new connection could not be established,
191     *      or a timeout occurred
192     */
193    @Override
194    public Connection getConnection() throws SQLException {
195        long max = System.currentTimeMillis() + timeout * 1000;
196        do {
197            synchronized (this) {
198                if (activeConnections < maxConnections) {
199                    return getConnectionNow();
200                }
201                try {
202                    wait(1000);
203                } catch (InterruptedException e) {
204                    // ignore
205                }
206            }
207        } while (System.currentTimeMillis() <= max);
208        throw new SQLException("Login timeout", "08001", 8001);
209    }
210 
211    /**
212     * INTERNAL
213     */
214    @Override
215    public Connection getConnection(String user, String password) {
216        throw new UnsupportedOperationException();
217    }
218 
219    private Connection getConnectionNow() throws SQLException {
220        if (isDisposed) {
221            throw new IllegalStateException("Connection pool has been disposed.");
222        }
223        PooledConnection pc;
224        if (!recycledConnections.isEmpty()) {
225            pc = recycledConnections.remove(recycledConnections.size() - 1);
226        } else {
227            pc = dataSource.getPooledConnection();
228        }
229        Connection conn = pc.getConnection();
230        activeConnections++;
231        pc.addConnectionEventListener(this);
232        return conn;
233    }
234 
235    /**
236     * This method usually puts the connection back into the pool. There are
237     * some exceptions: if the pool is disposed, the connection is disposed as
238     * well. If the pool is full, the connection is closed.
239     *
240     * @param pc the pooled connection
241     */
242    synchronized void recycleConnection(PooledConnection pc) {
243        if (activeConnections <= 0) {
244            throw new AssertionError();
245        }
246        activeConnections--;
247        if (!isDisposed && activeConnections < maxConnections) {
248            recycledConnections.add(pc);
249        } else {
250            closeConnection(pc);
251        }
252        if (activeConnections >= maxConnections - 1) {
253            notifyAll();
254        }
255    }
256 
257    private void closeConnection(PooledConnection pc) {
258        try {
259            pc.close();
260        } catch (SQLException e) {
261            if (logWriter != null) {
262                e.printStackTrace(logWriter);
263            }
264        }
265    }
266 
267    /**
268     * INTERNAL
269     */
270    @Override
271    public void connectionClosed(ConnectionEvent event) {
272        PooledConnection pc = (PooledConnection) event.getSource();
273        pc.removeConnectionEventListener(this);
274        recycleConnection(pc);
275    }
276 
277    /**
278     * INTERNAL
279     */
280    @Override
281    public void connectionErrorOccurred(ConnectionEvent event) {
282        // not used
283    }
284 
285    /**
286     * Returns the number of active (open) connections of this pool. This is the
287     * number of <code>Connection</code> objects that have been issued by
288     * getConnection() for which <code>Connection.close()</code> has
289     * not yet been called.
290     *
291     * @return the number of active connections.
292     */
293    public synchronized int getActiveConnections() {
294        return activeConnections;
295    }
296 
297    /**
298     * INTERNAL
299     */
300    @Override
301    public PrintWriter getLogWriter() {
302        return logWriter;
303    }
304 
305    /**
306     * INTERNAL
307     */
308    @Override
309    public void setLogWriter(PrintWriter logWriter) {
310        this.logWriter = logWriter;
311    }
312 
313    /**
314     * [Not supported] Return an object of this class if possible.
315     *
316     * @param iface the class
317     */
318    @Override
319    public <T> T unwrap(Class<T> iface) throws SQLException {
320        throw DbException.getUnsupportedException("unwrap");
321    }
322 
323    /**
324     * [Not supported] Checks if unwrap can return an object of this class.
325     *
326     * @param iface the class
327     */
328    @Override
329    public boolean isWrapperFor(Class<?> iface) throws SQLException {
330        throw DbException.getUnsupportedException("isWrapperFor");
331    }
332 
333    /**
334     * [Not supported]
335     */
336//## Java 1.7 ##
337    @Override
338    public Logger getParentLogger() {
339        return null;
340    }
341//*/
342 
343 
344}

[all classes][org.h2.jdbcx]
EMMA 2.0.5312 (C) Vladimir Roubtsov