/*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed with
* this work for additional information regarding copyright ownership .
* The ASF licenses this file to You under the Apache License , Version 2 . 0
* ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
package org.apache.tomcat.dbcp.dbcp2;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.HashMap;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.tomcat.dbcp.pool2.ObjectPool;
/**
* A { @ link Driver } implementation that obtains { @ link Connection } s from a registered { @ link ObjectPool } .
*
* @ since 2 . 0
*/
public class PoolingDriver implements Driver {
/**
* PoolGuardConnectionWrapper is a Connection wrapper that makes sure a closed connection cannot be used anymore .
*
* @ since 2 . 0
*/
private class PoolGuardConnectionWrapper extends DelegatingConnection<Connection> {
private final ObjectPool<? extends Connection> pool;
PoolGuardConnectionWrapper(final ObjectPool<? extends Connection> pool, final Connection delegate) {
super (delegate);
this .pool = pool;
}
/**
* @ see org . apache . tomcat . dbcp . dbcp2 . DelegatingConnection # getDelegate ( )
*/
@Override
public Connection getDelegate() {
if (isAccessToUnderlyingConnectionAllowed()) {
return super .getDelegate();
}
return null ;
}
/**
* @ see org . apache . tomcat . dbcp . dbcp2 . DelegatingConnection # getInnermostDelegate ( )
*/
@Override
public Connection getInnermostDelegate() {
if (isAccessToUnderlyingConnectionAllowed()) {
return super .getInnermostDelegate();
}
return null ;
}
}
private static final DriverPropertyInfo[] EMPTY_DRIVER_PROPERTY_INFO_ARRAY = {};
/* Register myself with the {@link DriverManager}. */
static {
try {
DriverManager.registerDriver(new PoolingDriver());
} catch (final Exception ignored) {
// Ignored
}
}
/** The map of registered pools. */
protected static final HashMap<String, ObjectPool<? extends Connection>> pools = new HashMap<>();
/** My URL prefix */
public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:" ;
protected static final int URL_PREFIX_LEN = URL_PREFIX.length();
// version numbers
protected static final int MAJOR_VERSION = 1 ;
protected static final int MINOR_VERSION = 0 ;
/** Controls access to the underlying connection */
private final boolean accessToUnderlyingConnectionAllowed;
/**
* Constructs a new driver with { @ code accessToUnderlyingConnectionAllowed } enabled .
*/
public PoolingDriver() {
this (true );
}
/**
* For unit testing purposes .
*
* @ param accessToUnderlyingConnectionAllowed
* Do { @ link DelegatingConnection } s created by this driver permit access to the delegate ?
*/
protected PoolingDriver(final boolean accessToUnderlyingConnectionAllowed) {
this .accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed;
}
@Override
public boolean acceptsURL(final String url) throws SQLException {
return url != null && url.startsWith(URL_PREFIX);
}
/**
* Closes a named pool .
*
* @ param name
* The pool name .
* @ throws SQLException
* Thrown when a problem is caught closing the pool .
*/
public synchronized void closePool(final String name) throws SQLException {
final ObjectPool<? extends Connection> pool = pools.get(name);
if (pool != null ) {
pools.remove(name);
try {
pool.close();
} catch (final Exception e) {
throw new SQLException("Error closing pool " + name, e);
}
}
}
@Override
public Connection connect(final String url, final Properties info) throws SQLException {
if (acceptsURL(url)) {
final ObjectPool<? extends Connection> pool = getConnectionPool(url.substring(URL_PREFIX_LEN));
try {
final Connection conn = pool.borrowObject();
if (conn == null ) {
return null ;
}
return new PoolGuardConnectionWrapper(pool, conn);
} catch (final NoSuchElementException e) {
throw new SQLException("Cannot get a connection, pool error: " + e.getMessage(), e);
} catch (final SQLException | RuntimeException e) {
throw e;
} catch (final Exception e) {
throw new SQLException("Cannot get a connection, general error: " + e.getMessage(), e);
}
}
return null ;
}
/**
* Gets the connection pool for the given name .
*
* @ param name
* The pool name
* @ return The pool
* @ throws SQLException
* Thrown when the named pool is not registered .
*/
public synchronized ObjectPool<? extends Connection> getConnectionPool(final String name) throws SQLException {
final ObjectPool<? extends Connection> pool = pools.get(name);
if (null == pool) {
throw new SQLException("Pool not registered: " + name);
}
return pool;
}
@Override
public int getMajorVersion() {
return MAJOR_VERSION;
}
@Override
public int getMinorVersion() {
return MINOR_VERSION;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
/**
* Gets the pool names .
*
* @ return the pool names .
*/
public synchronized String[] getPoolNames() {
return pools.keySet().toArray(Utils.EMPTY_STRING_ARRAY);
}
@Override
public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
return EMPTY_DRIVER_PROPERTY_INFO_ARRAY;
}
/**
* Invalidates the given connection .
*
* @ param conn
* connection to invalidate
* @ throws SQLException
* if the connection is not a { @ code PoolGuardConnectionWrapper } or an error occurs invalidating
* the connection
*/
public void invalidateConnection(final Connection conn) throws SQLException {
if (!(conn instanceof PoolGuardConnectionWrapper)) {
throw new SQLException("Invalid connection class" );
}
final PoolGuardConnectionWrapper pgconn = (PoolGuardConnectionWrapper) conn;
@SuppressWarnings("unchecked" )
final ObjectPool<Connection> pool = (ObjectPool<Connection>) pgconn.pool;
try {
pool.invalidateObject(pgconn.getDelegateInternal());
} catch (final Exception ignored) {
// Ignored.
}
}
/**
* Returns the value of the accessToUnderlyingConnectionAllowed property .
*
* @ return true if access to the underlying is allowed , false otherwise .
*/
protected boolean isAccessToUnderlyingConnectionAllowed() {
return accessToUnderlyingConnectionAllowed;
}
@Override
public boolean jdbcCompliant() {
return true ;
}
/**
* Registers a named pool .
*
* @ param name
* The pool name .
* @ param pool
* The pool .
*/
public synchronized void registerPool(final String name, final ObjectPool<? extends Connection> pool) {
pools.put(name, pool);
}
}
Messung V0.5 in Prozent C=93 H=94 G=93
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-10-03)
¤
*© Formatika GbR, Deutschland