init
This commit is contained in:
180
java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
Normal file
180
java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.TrackedUse;
|
||||
|
||||
/**
|
||||
* Tracks db connection usage for recovering and reporting abandoned db connections.
|
||||
* <p>
|
||||
* The JDBC Connection, Statement, and ResultSet classes extend this class.
|
||||
* </p>
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AbandonedTrace implements TrackedUse {
|
||||
|
||||
/** A list of objects created by children of this object. */
|
||||
private final List<WeakReference<AbandonedTrace>> traceList = new ArrayList<>();
|
||||
|
||||
/** Last time this connection was used. */
|
||||
private volatile long lastUsedMillis = 0;
|
||||
|
||||
/**
|
||||
* Creates a new AbandonedTrace without config and without doing abandoned tracing.
|
||||
*/
|
||||
public AbandonedTrace() {
|
||||
init(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AbandonedTrace with a parent object.
|
||||
*
|
||||
* @param parent
|
||||
* AbandonedTrace parent object.
|
||||
*/
|
||||
public AbandonedTrace(final AbandonedTrace parent) {
|
||||
init(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects being traced.
|
||||
*
|
||||
* @param trace
|
||||
* AbandonedTrace object to add.
|
||||
*/
|
||||
protected void addTrace(final AbandonedTrace trace) {
|
||||
synchronized (this.traceList) {
|
||||
this.traceList.add(new WeakReference<>(trace));
|
||||
}
|
||||
setLastUsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the list of objects being traced by this object.
|
||||
*/
|
||||
protected void clearTrace() {
|
||||
synchronized (this.traceList) {
|
||||
this.traceList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last time this object was used in milliseconds.
|
||||
*
|
||||
* @return long time in milliseconds.
|
||||
*/
|
||||
@Override
|
||||
public long getLastUsed() {
|
||||
return lastUsedMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of objects being traced by this object.
|
||||
*
|
||||
* @return List of objects.
|
||||
*/
|
||||
protected List<AbandonedTrace> getTrace() {
|
||||
final int size = traceList.size();
|
||||
if (size == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final ArrayList<AbandonedTrace> result = new ArrayList<>(size);
|
||||
synchronized (this.traceList) {
|
||||
final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final AbandonedTrace trace = iter.next().get();
|
||||
if (trace == null) {
|
||||
// Clean-up since we are here anyway
|
||||
iter.remove();
|
||||
} else {
|
||||
result.add(trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes abandoned tracing for this object.
|
||||
*
|
||||
* @param parent
|
||||
* AbandonedTrace parent object.
|
||||
*/
|
||||
private void init(final AbandonedTrace parent) {
|
||||
if (parent != null) {
|
||||
parent.addTrace(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this object the source object is tracing.
|
||||
*
|
||||
* @param source The object tracing
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected void removeThisTrace(final Object source) {
|
||||
if (source instanceof AbandonedTrace) {
|
||||
AbandonedTrace.class.cast(source).removeTrace(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child object this object is tracing.
|
||||
*
|
||||
* @param trace
|
||||
* AbandonedTrace object to remove.
|
||||
*/
|
||||
protected void removeTrace(final AbandonedTrace trace) {
|
||||
synchronized (this.traceList) {
|
||||
final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final AbandonedTrace traceInList = iter.next().get();
|
||||
if (trace != null && trace.equals(traceInList)) {
|
||||
iter.remove();
|
||||
break;
|
||||
} else if (traceInList == null) {
|
||||
// Clean-up since we are here anyway
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time this object was last used to the current time in milliseconds.
|
||||
*/
|
||||
protected void setLastUsed() {
|
||||
lastUsedMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time in milliseconds this object was last used.
|
||||
*
|
||||
* @param lastUsedMillis
|
||||
* time in milliseconds.
|
||||
*/
|
||||
protected void setLastUsed(final long lastUsedMillis) {
|
||||
this.lastUsedMillis = lastUsedMillis;
|
||||
}
|
||||
}
|
||||
2460
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
Normal file
2460
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
Normal file
File diff suppressed because it is too large
Load Diff
602
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
Normal file
602
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
316
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
Normal file
316
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Defines the methods that will be made available via JMX.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface BasicDataSourceMXBean {
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getAbandonedUsageTracking()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getAbandonedUsageTracking()}
|
||||
*/
|
||||
boolean getAbandonedUsageTracking();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultAutoCommit()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultAutoCommit()}
|
||||
*/
|
||||
Boolean getDefaultAutoCommit();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultReadOnly()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultReadOnly()}
|
||||
*/
|
||||
Boolean getDefaultReadOnly();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultTransactionIsolation()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultTransactionIsolation()}
|
||||
*/
|
||||
int getDefaultTransactionIsolation();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultCatalog()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultCatalog()}
|
||||
*/
|
||||
String getDefaultCatalog();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultSchema()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultSchema()}
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String getDefaultSchema();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getCacheState()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getCacheState()}
|
||||
*/
|
||||
boolean getCacheState();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDriverClassName()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDriverClassName()}
|
||||
*/
|
||||
String getDriverClassName();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLifo()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLifo()}
|
||||
*/
|
||||
boolean getLifo();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxTotal()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxTotal()}
|
||||
*/
|
||||
int getMaxTotal();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxIdle()}
|
||||
*/
|
||||
int getMaxIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMinIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMinIdle()}
|
||||
*/
|
||||
int getMinIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getInitialSize()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getInitialSize()}
|
||||
*/
|
||||
int getInitialSize();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxWaitMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxWaitMillis()}
|
||||
*/
|
||||
long getMaxWaitMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isPoolPreparedStatements()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isPoolPreparedStatements()}
|
||||
*/
|
||||
boolean isPoolPreparedStatements();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxOpenPreparedStatements()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxOpenPreparedStatements()}
|
||||
*/
|
||||
int getMaxOpenPreparedStatements();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestOnCreate()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestOnCreate()}
|
||||
*/
|
||||
boolean getTestOnCreate();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestOnBorrow()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestOnBorrow()}
|
||||
*/
|
||||
boolean getTestOnBorrow();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
|
||||
*/
|
||||
long getTimeBetweenEvictionRunsMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumTestsPerEvictionRun()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumTestsPerEvictionRun()}
|
||||
*/
|
||||
int getNumTestsPerEvictionRun();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
|
||||
*/
|
||||
long getMinEvictableIdleTimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
|
||||
*/
|
||||
long getSoftMinEvictableIdleTimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestWhileIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestWhileIdle()}
|
||||
*/
|
||||
boolean getTestWhileIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumActive()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumActive()}
|
||||
*/
|
||||
int getNumActive();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumIdle()}
|
||||
*/
|
||||
int getNumIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getPassword()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getPassword()}
|
||||
*/
|
||||
String getPassword();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getUrl()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getUrl()}
|
||||
*/
|
||||
String getUrl();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getUsername()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getUsername()}
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getValidationQuery()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getValidationQuery()}
|
||||
*/
|
||||
String getValidationQuery();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getValidationQueryTimeout()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getValidationQueryTimeout()}
|
||||
*/
|
||||
int getValidationQueryTimeout();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getConnectionInitSqlsAsArray()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}
|
||||
*/
|
||||
String[] getConnectionInitSqlsAsArray();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
|
||||
*/
|
||||
boolean isAccessToUnderlyingConnectionAllowed();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxConnLifetimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxConnLifetimeMillis()}
|
||||
*/
|
||||
long getMaxConnLifetimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLogExpiredConnections()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLogExpiredConnections()}
|
||||
* @since 2.1
|
||||
*/
|
||||
boolean getLogExpiredConnections();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
|
||||
*/
|
||||
boolean getRemoveAbandonedOnBorrow();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
|
||||
*/
|
||||
boolean getRemoveAbandonedOnMaintenance();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedTimeout()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedTimeout()}
|
||||
*/
|
||||
int getRemoveAbandonedTimeout();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLogAbandoned()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLogAbandoned()}
|
||||
*/
|
||||
boolean getLogAbandoned();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isClosed()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isClosed()}
|
||||
*/
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getFastFailValidation()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getFastFailValidation()}
|
||||
* @since 2.1
|
||||
*/
|
||||
boolean getFastFailValidation();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
|
||||
* @since 2.1
|
||||
*/
|
||||
String[] getDisconnectionSqlCodesAsArray();
|
||||
}
|
||||
36
java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java
Normal file
36
java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.SQLException;
|
||||
|
||||
/**
|
||||
* Abstract factory interface for creating {@link java.sql.Connection}s.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ConnectionFactory {
|
||||
/**
|
||||
* Create a new {@link java.sql.Connection} in an implementation specific fashion.
|
||||
*
|
||||
* @return a new {@link java.sql.Connection}
|
||||
* @throws SQLException
|
||||
* if a database error occurs creating the connection
|
||||
*/
|
||||
Connection createConnection() throws SQLException;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/*
|
||||
* Creates {@link ConnectionFactory} instances.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class ConnectionFactoryFactory {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DriverConnectionFactory} allowing for an override through
|
||||
* {@link BasicDataSource#getDriverClassName()}.
|
||||
*
|
||||
* @param basicDataSource Configures creation.
|
||||
* @param driver The JDBC driver.
|
||||
* @return a new {@link DriverConnectionFactory} allowing for a {@link BasicDataSource#getDriverClassName()}
|
||||
* override.
|
||||
* @throws SQLException Thrown when instantiation fails.
|
||||
*/
|
||||
static ConnectionFactory createConnectionFactory(final BasicDataSource basicDataSource, final Driver driver)
|
||||
throws SQLException {
|
||||
final Properties connectionProperties = basicDataSource.getConnectionProperties();
|
||||
final String url = basicDataSource.getUrl();
|
||||
// Set up the driver connection factory we will use
|
||||
final String user = basicDataSource.getUsername();
|
||||
if (user != null) {
|
||||
connectionProperties.put("user", user);
|
||||
} else {
|
||||
basicDataSource.log("DBCP DataSource configured without a 'username'");
|
||||
}
|
||||
|
||||
final String pwd = basicDataSource.getPassword();
|
||||
if (pwd != null) {
|
||||
connectionProperties.put("password", pwd);
|
||||
} else {
|
||||
basicDataSource.log("DBCP DataSource configured without a 'password'");
|
||||
}
|
||||
final String connectionFactoryClassName = basicDataSource.getConnectionFactoryClassName();
|
||||
if (connectionFactoryClassName != null) {
|
||||
try {
|
||||
final Class<?> connectionFactoryFromCCL = Class.forName(connectionFactoryClassName);
|
||||
return (ConnectionFactory) connectionFactoryFromCCL
|
||||
.getConstructor(Driver.class, String.class, Properties.class)
|
||||
.newInstance(driver, url, connectionProperties);
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot load ConnectionFactory implementation '" + connectionFactoryClassName
|
||||
+ "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
// Defaults to DriverConnectionFactory
|
||||
return new DriverConnectionFactory(driver, url, connectionProperties);
|
||||
}
|
||||
|
||||
}
|
||||
34
java/org/apache/tomcat/dbcp/dbcp2/Constants.java
Normal file
34
java/org/apache/tomcat/dbcp/dbcp2/Constants.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constants for use with JMX.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool=";
|
||||
public static final String JMX_CONNECTION_POOL_PREFIX = "connections";
|
||||
|
||||
public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX
|
||||
+ ",connection=";
|
||||
|
||||
public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT;
|
||||
public static final String JMX_STATEMENT_POOL_PREFIX = ",statementpool=statements";
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* A {@link DataSource}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DataSourceConnectionFactory implements ConnectionFactory {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final String userName;
|
||||
|
||||
private final char[] userPassword;
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource) {
|
||||
this(dataSource, null, (char[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
* @param userName
|
||||
* The user name.
|
||||
* @param userPassword
|
||||
* The user password.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final char[] userPassword) {
|
||||
this.dataSource = dataSource;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.clone(userPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
* @param userName
|
||||
* The user name.
|
||||
* @param password
|
||||
* The user password.
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final String password) {
|
||||
this.dataSource = dataSource;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.toCharArray(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
if (null == userName && null == userPassword) {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
return dataSource.getConnection(userName, Utils.toString(userPassword));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The data source.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user name.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user password.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public char[] getUserPassword() {
|
||||
return userPassword;
|
||||
}
|
||||
}
|
||||
1271
java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java
Normal file
1271
java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java
Normal file
File diff suppressed because it is too large
Load Diff
1001
java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
Normal file
1001
java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
Normal file
File diff suppressed because it is too large
Load Diff
1917
java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
Normal file
1917
java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2026
java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
Normal file
2026
java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
Normal file
File diff suppressed because it is too large
Load Diff
710
java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
Normal file
710
java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@link Driver}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DriverConnectionFactory implements ConnectionFactory {
|
||||
|
||||
private final String connectionString;
|
||||
|
||||
private final Driver driver;
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* Constructs a connection factory for a given Driver.
|
||||
*
|
||||
* @param driver
|
||||
* The Driver.
|
||||
* @param connectString
|
||||
* The connection string.
|
||||
* @param properties
|
||||
* The connection properties.
|
||||
*/
|
||||
public DriverConnectionFactory(final Driver driver, final String connectString, final Properties properties) {
|
||||
this.driver = driver;
|
||||
this.connectionString = connectString;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
return driver.connect(connectionString, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The connection String.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getConnectionString() {
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Driver.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Driver getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Properties.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";"
|
||||
+ String.valueOf(properties) + "]";
|
||||
}
|
||||
}
|
||||
81
java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
Normal file
81
java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/*
|
||||
* Creates {@link Driver} instances.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class DriverFactory {
|
||||
|
||||
static Driver createDriver(final BasicDataSource basicDataSource) throws SQLException {
|
||||
// Load the JDBC driver class
|
||||
Driver driverToUse = basicDataSource.getDriver();
|
||||
String driverClassName = basicDataSource.getDriverClassName();
|
||||
ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader();
|
||||
String url = basicDataSource.getUrl();
|
||||
|
||||
if (driverToUse == null) {
|
||||
Class<?> driverFromCCL = null;
|
||||
if (driverClassName != null) {
|
||||
try {
|
||||
try {
|
||||
if (driverClassLoader == null) {
|
||||
driverFromCCL = Class.forName(driverClassName);
|
||||
} else {
|
||||
driverFromCCL = Class.forName(driverClassName, true, driverClassLoader);
|
||||
}
|
||||
} catch (final ClassNotFoundException cnfe) {
|
||||
driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(driverClassName);
|
||||
}
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot load JDBC driver class '" + driverClassName + "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (driverFromCCL == null) {
|
||||
driverToUse = DriverManager.getDriver(url);
|
||||
} else {
|
||||
// Usage of DriverManager is not possible, as it does not
|
||||
// respect the ContextClassLoader
|
||||
// N.B. This cast may cause ClassCastException which is
|
||||
// handled below
|
||||
driverToUse = (Driver) driverFromCCL.getConstructor().newInstance();
|
||||
if (!driverToUse.acceptsURL(url)) {
|
||||
throw new SQLException("No suitable driver", "08001");
|
||||
}
|
||||
}
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot create JDBC driver of class '"
|
||||
+ (driverClassName != null ? driverClassName : "") + "' for connect URL '" + url + "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
return driverToUse;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@link DriverManager}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DriverManagerConnectionFactory implements ConnectionFactory {
|
||||
|
||||
static {
|
||||
// Related to DBCP-212
|
||||
// Driver manager does not sync loading of drivers that use the service
|
||||
// provider interface. This will cause issues is multi-threaded
|
||||
// environments. This hack makes sure the drivers are loaded before
|
||||
// DBCP tries to use them.
|
||||
DriverManager.getDrivers();
|
||||
}
|
||||
|
||||
private final String connectionUri;
|
||||
|
||||
private final String userName;
|
||||
|
||||
private final char[] userPassword;
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @since 2.2
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.properties = new Properties();
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param properties
|
||||
* a list of arbitrary string tag/value pairs as connection arguments; normally at least a "user" and
|
||||
* "password" property should be included.
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final Properties properties) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.properties = properties;
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param userName
|
||||
* the database user
|
||||
* @param userPassword
|
||||
* the user's password
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final String userName,
|
||||
final char[] userPassword) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.clone(userPassword);
|
||||
this.properties = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param userName
|
||||
* the database user
|
||||
* @param userPassword
|
||||
* the user's password
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final String userName,
|
||||
final String userPassword) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.toCharArray(userPassword);
|
||||
this.properties = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
if (null == properties) {
|
||||
if (userName == null && userPassword == null) {
|
||||
return DriverManager.getConnection(connectionUri);
|
||||
}
|
||||
return DriverManager.getConnection(connectionUri, userName, Utils.toString(userPassword));
|
||||
}
|
||||
return DriverManager.getConnection(connectionUri, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The connection URI.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getConnectionUri() {
|
||||
return connectionUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Properties.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user name.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
}
|
||||
482
java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
Normal file
482
java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
Normal file
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* 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.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URL;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.Date;
|
||||
import java.sql.Ref;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.RowId;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.sql.CommonDataSource;
|
||||
|
||||
/**
|
||||
* Defines bridge methods to JDBC 4.1 (Java 7) methods to allow call sites to operate safely (without
|
||||
* {@link AbstractMethodError}) when using a JDBC driver written for JDBC 4.0 (Java 6).
|
||||
*
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public class Jdbc41Bridge {
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#abort(Executor)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#abort(Executor)}, then call {@link Connection#close()}.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param executor
|
||||
* See {@link Connection#abort(Executor)}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#abort(Executor)}.
|
||||
* @see Connection#abort(Executor)
|
||||
*/
|
||||
public static void abort(final Connection connection, final Executor executor) throws SQLException {
|
||||
try {
|
||||
connection.abort(executor);
|
||||
} catch (final AbstractMethodError e) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link DatabaseMetaData#generatedKeyAlwaysReturned()} without throwing a
|
||||
* {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link DatabaseMetaData#generatedKeyAlwaysReturned()}, then return false.
|
||||
* </p>
|
||||
*
|
||||
* @param databaseMetaData
|
||||
* See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @return See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @throws SQLException
|
||||
* See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @see DatabaseMetaData#generatedKeyAlwaysReturned()
|
||||
*/
|
||||
public static boolean generatedKeyAlwaysReturned(final DatabaseMetaData databaseMetaData) throws SQLException {
|
||||
try {
|
||||
return databaseMetaData.generatedKeyAlwaysReturned();
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#getNetworkTimeout()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#getNetworkTimeout()}, then return 0.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @return See {@link Connection#getNetworkTimeout()}
|
||||
* @throws SQLException
|
||||
* See {@link Connection#getNetworkTimeout()}
|
||||
* @see Connection#getNetworkTimeout()
|
||||
*/
|
||||
public static int getNetworkTimeout(final Connection connection) throws SQLException {
|
||||
try {
|
||||
return connection.getNetworkTimeout();
|
||||
} catch (final AbstractMethodError e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link ResultSet#getObject(int, Class)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link ResultSet#getObject(int, Class)}, then return 0.
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param resultSet
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param columnIndex
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param type
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @return See {@link ResultSet#getObject(int, Class)}
|
||||
* @throws SQLException
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @see ResultSet#getObject(int, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getObject(final ResultSet resultSet, final int columnIndex, final Class<T> type)
|
||||
throws SQLException {
|
||||
try {
|
||||
return resultSet.getObject(columnIndex, type);
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (type == String.class) {
|
||||
return (T) resultSet.getString(columnIndex);
|
||||
}
|
||||
// Numbers
|
||||
if (type == Integer.class) {
|
||||
return (T) Integer.valueOf(resultSet.getInt(columnIndex));
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return (T) Long.valueOf(resultSet.getLong(columnIndex));
|
||||
}
|
||||
if (type == Double.class) {
|
||||
return (T) Double.valueOf(resultSet.getDouble(columnIndex));
|
||||
}
|
||||
if (type == Float.class) {
|
||||
return (T) Float.valueOf(resultSet.getFloat(columnIndex));
|
||||
}
|
||||
if (type == Short.class) {
|
||||
return (T) Short.valueOf(resultSet.getShort(columnIndex));
|
||||
}
|
||||
if (type == BigDecimal.class) {
|
||||
return (T) resultSet.getBigDecimal(columnIndex);
|
||||
}
|
||||
if (type == Byte.class) {
|
||||
return (T) Byte.valueOf(resultSet.getByte(columnIndex));
|
||||
}
|
||||
// Dates
|
||||
if (type == Date.class) {
|
||||
return (T) resultSet.getDate(columnIndex);
|
||||
}
|
||||
if (type == Time.class) {
|
||||
return (T) resultSet.getTime(columnIndex);
|
||||
}
|
||||
if (type == Timestamp.class) {
|
||||
return (T) resultSet.getTimestamp(columnIndex);
|
||||
}
|
||||
// Streams
|
||||
if (type == InputStream.class) {
|
||||
return (T) resultSet.getBinaryStream(columnIndex);
|
||||
}
|
||||
if (type == Reader.class) {
|
||||
return (T) resultSet.getCharacterStream(columnIndex);
|
||||
}
|
||||
// Other
|
||||
if (type == Object.class) {
|
||||
return (T) resultSet.getObject(columnIndex);
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return (T) Boolean.valueOf(resultSet.getBoolean(columnIndex));
|
||||
}
|
||||
if (type == Array.class) {
|
||||
return (T) resultSet.getArray(columnIndex);
|
||||
}
|
||||
if (type == Blob.class) {
|
||||
return (T) resultSet.getBlob(columnIndex);
|
||||
}
|
||||
if (type == Clob.class) {
|
||||
return (T) resultSet.getClob(columnIndex);
|
||||
}
|
||||
if (type == Ref.class) {
|
||||
return (T) resultSet.getRef(columnIndex);
|
||||
}
|
||||
if (type == RowId.class) {
|
||||
return (T) resultSet.getRowId(columnIndex);
|
||||
}
|
||||
if (type == SQLXML.class) {
|
||||
return (T) resultSet.getSQLXML(columnIndex);
|
||||
}
|
||||
if (type == URL.class) {
|
||||
return (T) resultSet.getURL(columnIndex);
|
||||
}
|
||||
throw new SQLFeatureNotSupportedException(
|
||||
String.format("resultSet=%s, columnIndex=%,d, type=%s", resultSet, Integer.valueOf(columnIndex), type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link ResultSet#getObject(String, Class)} without throwing a {@link AbstractMethodError}.
|
||||
*
|
||||
* @param <T>
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param resultSet
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param columnLabel
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param type
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @return See {@link ResultSet#getObject(String, Class)}
|
||||
* @throws SQLException
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @see ResultSet#getObject(int, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getObject(final ResultSet resultSet, final String columnLabel, final Class<T> type)
|
||||
throws SQLException {
|
||||
try {
|
||||
return resultSet.getObject(columnLabel, type);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// Numbers
|
||||
if (type == Integer.class) {
|
||||
return (T) Integer.valueOf(resultSet.getInt(columnLabel));
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return (T) Long.valueOf(resultSet.getLong(columnLabel));
|
||||
}
|
||||
if (type == Double.class) {
|
||||
return (T) Double.valueOf(resultSet.getDouble(columnLabel));
|
||||
}
|
||||
if (type == Float.class) {
|
||||
return (T) Float.valueOf(resultSet.getFloat(columnLabel));
|
||||
}
|
||||
if (type == Short.class) {
|
||||
return (T) Short.valueOf(resultSet.getShort(columnLabel));
|
||||
}
|
||||
if (type == BigDecimal.class) {
|
||||
return (T) resultSet.getBigDecimal(columnLabel);
|
||||
}
|
||||
if (type == Byte.class) {
|
||||
return (T) Byte.valueOf(resultSet.getByte(columnLabel));
|
||||
}
|
||||
// Dates
|
||||
if (type == Date.class) {
|
||||
return (T) resultSet.getDate(columnLabel);
|
||||
}
|
||||
if (type == Time.class) {
|
||||
return (T) resultSet.getTime(columnLabel);
|
||||
}
|
||||
if (type == Timestamp.class) {
|
||||
return (T) resultSet.getTimestamp(columnLabel);
|
||||
}
|
||||
// Streams
|
||||
if (type == InputStream.class) {
|
||||
return (T) resultSet.getBinaryStream(columnLabel);
|
||||
}
|
||||
if (type == Reader.class) {
|
||||
return (T) resultSet.getCharacterStream(columnLabel);
|
||||
}
|
||||
// Other
|
||||
if (type == Object.class) {
|
||||
return (T) resultSet.getObject(columnLabel);
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return (T) Boolean.valueOf(resultSet.getBoolean(columnLabel));
|
||||
}
|
||||
if (type == Array.class) {
|
||||
return (T) resultSet.getArray(columnLabel);
|
||||
}
|
||||
if (type == Blob.class) {
|
||||
return (T) resultSet.getBlob(columnLabel);
|
||||
}
|
||||
if (type == Clob.class) {
|
||||
return (T) resultSet.getClob(columnLabel);
|
||||
}
|
||||
if (type == Ref.class) {
|
||||
return (T) resultSet.getRef(columnLabel);
|
||||
}
|
||||
if (type == RowId.class) {
|
||||
return (T) resultSet.getRowId(columnLabel);
|
||||
}
|
||||
if (type == SQLXML.class) {
|
||||
return (T) resultSet.getSQLXML(columnLabel);
|
||||
}
|
||||
if (type == URL.class) {
|
||||
return (T) resultSet.getURL(columnLabel);
|
||||
}
|
||||
throw new SQLFeatureNotSupportedException(
|
||||
String.format("resultSet=%s, columnLabel=%s, type=%s", resultSet, columnLabel, type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} without throwing a
|
||||
* {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)},
|
||||
* then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param databaseMetaData
|
||||
* the receiver
|
||||
* @param catalog
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param schemaPattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param tableNamePattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param columnNamePattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @return See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @throws SQLException
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @see DatabaseMetaData#getPseudoColumns(String, String, String, String)
|
||||
*/
|
||||
public static ResultSet getPseudoColumns(final DatabaseMetaData databaseMetaData, final String catalog,
|
||||
final String schemaPattern, final String tableNamePattern, final String columnNamePattern)
|
||||
throws SQLException {
|
||||
try {
|
||||
return databaseMetaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#getSchema()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#getSchema()}, then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @return null for a JDBC 4 driver or a value per {@link Connection#getSchema()}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#getSchema()}.
|
||||
* @see Connection#getSchema()
|
||||
*/
|
||||
public static String getSchema(final Connection connection) throws SQLException {
|
||||
try {
|
||||
return connection.getSchema();
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#setNetworkTimeout(Executor, int)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#setNetworkTimeout(Executor, int)}, then do nothing.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param executor
|
||||
* See {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @param milliseconds
|
||||
* {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @throws SQLException
|
||||
* {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @see Connection#setNetworkTimeout(Executor, int)
|
||||
*/
|
||||
public static void setNetworkTimeout(final Connection connection, final Executor executor, final int milliseconds)
|
||||
throws SQLException {
|
||||
try {
|
||||
connection.setNetworkTimeout(executor, milliseconds);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#setSchema(String)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#setSchema(String)}, then do nothing.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param schema
|
||||
* See {@link Connection#setSchema(String)}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#setSchema(String)}.
|
||||
* @see Connection#setSchema(String)
|
||||
*/
|
||||
public static void setSchema(final Connection connection, final String schema) throws SQLException {
|
||||
try {
|
||||
connection.setSchema(schema);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Statement#closeOnCompletion()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Statement#closeOnCompletion()}, then just check that the connection
|
||||
* is closed to then throw an SQLException.
|
||||
* </p>
|
||||
*
|
||||
* @param statement
|
||||
* See {@link Statement#closeOnCompletion()}
|
||||
* @throws SQLException
|
||||
* See {@link Statement#closeOnCompletion()}
|
||||
* @see Statement#closeOnCompletion()
|
||||
*/
|
||||
public static void closeOnCompletion(final Statement statement) throws SQLException {
|
||||
try {
|
||||
statement.closeOnCompletion();
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (statement.isClosed()) {
|
||||
throw new SQLException("Statement closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Statement#isCloseOnCompletion()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Statement#isCloseOnCompletion()}, then just check that the
|
||||
* connection is closed to then throw an SQLException.
|
||||
* </p>
|
||||
*
|
||||
* @param statement
|
||||
* See {@link Statement#isCloseOnCompletion()}
|
||||
* @return See {@link Statement#isCloseOnCompletion()}
|
||||
* @throws SQLException
|
||||
* See {@link Statement#isCloseOnCompletion()}
|
||||
* @see Statement#closeOnCompletion()
|
||||
*/
|
||||
public static boolean isCloseOnCompletion(final Statement statement) throws SQLException {
|
||||
try {
|
||||
return statement.isCloseOnCompletion();
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (statement.isClosed()) {
|
||||
throw new SQLException("Statement closed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link CommonDataSource#getParentLogger()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link CommonDataSource#getParentLogger()}, then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param commonDataSource
|
||||
* See {@link CommonDataSource#getParentLogger()}
|
||||
* @return See {@link CommonDataSource#getParentLogger()}
|
||||
* @throws SQLFeatureNotSupportedException
|
||||
* See {@link CommonDataSource#getParentLogger()}
|
||||
*/
|
||||
public static Logger getParentLogger(final CommonDataSource commonDataSource) throws SQLFeatureNotSupportedException {
|
||||
try {
|
||||
return commonDataSource.getParentLogger();
|
||||
} catch (final AbstractMethodError e) {
|
||||
throw new SQLFeatureNotSupportedException("javax.sql.CommonDataSource#getParentLogger()");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown when a connection's maximum lifetime has been exceeded.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
class LifetimeExceededException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3783783104516492659L;
|
||||
|
||||
/**
|
||||
* Create a LifetimeExceededException.
|
||||
*/
|
||||
public LifetimeExceededException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LifetimeExceededException with the given message.
|
||||
*
|
||||
* @param message
|
||||
* The message with which to create the exception
|
||||
*/
|
||||
public LifetimeExceededException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
57
java/org/apache/tomcat/dbcp/dbcp2/ListException.java
Normal file
57
java/org/apache/tomcat/dbcp/dbcp2/ListException.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.util.List;
|
||||
|
||||
/**
|
||||
* An exception wrapping a list of exceptions.
|
||||
*
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class ListException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Throwable> exceptionList;
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
|
||||
* be initialized by a call to {@link #initCause}.
|
||||
*
|
||||
* @param message
|
||||
* the detail message. The detail message is saved for later retrieval by the {@link #getMessage()}
|
||||
* method.
|
||||
* @param exceptionList
|
||||
* a list of exceptions.
|
||||
*/
|
||||
public ListException(final String message, final List<Throwable> exceptionList) {
|
||||
super(message);
|
||||
this.exceptionList = exceptionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of exceptions.
|
||||
*
|
||||
* @return the list of exceptions.
|
||||
*/
|
||||
public List<Throwable> getExceptionList() {
|
||||
return exceptionList;
|
||||
}
|
||||
|
||||
}
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] milliseconds exceeds the maximum permitted value of [{1}] milliseconds
|
||||
|
||||
pool.close.fail=Cannot close connection pool.
|
||||
|
||||
poolableConnection.validate.fastFail=Fatal SQLException was thrown previously on this connection.
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Failed to validate a poolable connection.
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory not linked to pool. Calling setPool() to fix the configuration.
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=An internal object pool swallowed an Exception.
|
||||
16
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_de.properties
Normal file
16
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_de.properties
Normal file
@@ -0,0 +1,16 @@
|
||||
# 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.
|
||||
|
||||
poolableConnection.validate.fastFail=Fatale SQLException wurde bereits vorher von dieser Verbindung geworfen
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_fr.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=La durée de vie de la connection de [{0}] millisecondes excède la valeur maximale permis de [{1}] millisecondes
|
||||
|
||||
pool.close.fail=Impossible de fermer le pool de connections
|
||||
|
||||
poolableConnection.validate.fastFail=Une exception fatale SQLException avait déjà été lancée pour cette connection
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Impossible de valider la connection poolable
|
||||
|
||||
poolingDataSource.factoryConfig=La PoolableConnectionFactory n'est pas liée au pool, il faut appeler setPool() pour y remédier et corriger la configuration
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=Un object interne du pool a avalé une exception
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ja.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=コネクション[{0}]ミリ秒の有効期間が[{1}]ミリ秒の許容最大値を超えています
|
||||
|
||||
pool.close.fail=コネクションプールを停止できません。
|
||||
|
||||
poolableConnection.validate.fastFail=このコネクションは過去に致命的な SQLException を送出したことがあります。
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=プール可能なコネクションを検証できません。
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory がコネクションプールに接続していません。構成を修復するには setPool() を呼び出してください。
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=内部オブジェクトプールが例外を飲み込みました。
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ko.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=해당 연결의 존속시간 [{0}] 밀리초가, 최대 허용치인 [{1}] 밀리초를 초과합니다.
|
||||
|
||||
pool.close.fail=데이터베이스 연결 풀을 닫을 수 없습니다.
|
||||
|
||||
poolableConnection.validate.fastFail=이 연결에서, 심각한 SQLException이 이전에 발생했습니다.
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Poolable connection이 유효한지 확인하지 못했습니다.
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory가 풀에 연결되지 않았습니다. setPool()을 호출하여 이 설정 문제를 해결합니다.
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=내부 객체 풀이 예외 발생을 무시했습니다.
|
||||
@@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
poolableConnection.validate.fastFail=此连接上预先抛出了致命的 SQLException。
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory 未连接到连接池。请调用 setPool() 修复此配置。
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=一个内部对象池吞并了一个异常。
|
||||
105
java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
Normal file
105
java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.lang.management.ManagementFactory;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Internal wrapper class that allows JMX to be a noop if absent or disabled.
|
||||
*
|
||||
* @since 2.2.1
|
||||
*/
|
||||
class ObjectNameWrapper {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ObjectNameWrapper.class);
|
||||
|
||||
private static MBeanServer MBEAN_SERVER = getPlatformMBeanServer();
|
||||
|
||||
private static MBeanServer getPlatformMBeanServer() {
|
||||
try {
|
||||
return ManagementFactory.getPlatformMBeanServer();
|
||||
} catch (LinkageError | Exception e) {
|
||||
// ignore - JMX not available
|
||||
log.debug("Failed to get platform MBeanServer", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectName unwrap(final ObjectNameWrapper wrapper) {
|
||||
return wrapper == null ? null : wrapper.unwrap();
|
||||
}
|
||||
|
||||
public static ObjectNameWrapper wrap(final ObjectName objectName) {
|
||||
return new ObjectNameWrapper(objectName);
|
||||
}
|
||||
|
||||
public static ObjectNameWrapper wrap(final String name) throws MalformedObjectNameException {
|
||||
return wrap(new ObjectName(name));
|
||||
}
|
||||
|
||||
private final ObjectName objectName;
|
||||
|
||||
public ObjectNameWrapper(final ObjectName objectName) {
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
public void registerMBean(final Object object) {
|
||||
if (MBEAN_SERVER == null || objectName == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
MBEAN_SERVER.registerMBean(object, objectName);
|
||||
} catch (LinkageError | Exception e) {
|
||||
log.warn("Failed to complete JMX registration for " + objectName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7.0
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toString(objectName);
|
||||
}
|
||||
|
||||
public void unregisterMBean() {
|
||||
if (MBEAN_SERVER == null || objectName == null) {
|
||||
return;
|
||||
}
|
||||
if (MBEAN_SERVER.isRegistered(objectName)) {
|
||||
try {
|
||||
MBEAN_SERVER.unregisterMBean(objectName);
|
||||
} catch (LinkageError | Exception e) {
|
||||
log.warn("Failed to complete JMX unregistration for " + objectName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectName unwrap() {
|
||||
return objectName;
|
||||
}
|
||||
|
||||
}
|
||||
998
java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
Normal file
998
java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
Normal file
File diff suppressed because it is too large
Load Diff
145
java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
Normal file
145
java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
|
||||
|
||||
/**
|
||||
* A {@link DelegatingCallableStatement} that cooperates with {@link PoolingConnection} to implement a pool of
|
||||
* {@link CallableStatement}s.
|
||||
* <p>
|
||||
* The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.)
|
||||
*
|
||||
* @see PoolingConnection
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolableCallableStatement extends DelegatingCallableStatement {
|
||||
|
||||
/**
|
||||
* The {@link KeyedObjectPool} from which this CallableStatement was obtained.
|
||||
*/
|
||||
private final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool;
|
||||
|
||||
/**
|
||||
* Key for this statement in the containing {@link KeyedObjectPool}.
|
||||
*/
|
||||
private final PStmtKey key;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param callableStatement
|
||||
* the underlying {@link CallableStatement}
|
||||
* @param key
|
||||
* the key for this statement in the {@link KeyedObjectPool}
|
||||
* @param pool
|
||||
* the {@link KeyedObjectPool} from which this CallableStatement was obtained
|
||||
* @param connection
|
||||
* the {@link DelegatingConnection} that created this CallableStatement
|
||||
*/
|
||||
public PoolableCallableStatement(final CallableStatement callableStatement, final PStmtKey key,
|
||||
final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool,
|
||||
final DelegatingConnection<Connection> connection) {
|
||||
super(connection, callableStatement);
|
||||
this.pool = pool;
|
||||
this.key = key;
|
||||
|
||||
// Remove from trace now because this statement will be
|
||||
// added by the activate method.
|
||||
removeThisTrace(getConnectionInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CallableStatement to the pool. If {{@link #isClosed()}, this is a No-op.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
// calling close twice should have no effect
|
||||
if (!isClosed()) {
|
||||
try {
|
||||
pool.returnObject(key, this);
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close CallableStatement (return to pool failed)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection that created
|
||||
* it.
|
||||
*
|
||||
* @since 2.4.0 made public, was protected in 2.3.0.
|
||||
*/
|
||||
@Override
|
||||
public void activate() throws SQLException {
|
||||
setClosedInternal(false);
|
||||
if (getConnectionInternal() != null) {
|
||||
getConnectionInternal().addTrace(this);
|
||||
}
|
||||
super.activate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Passivates to prepare for return to the pool. Removes the trace associated with this CallableStatement from the
|
||||
* Connection that created it. Also closes any associated ResultSets.
|
||||
*
|
||||
* @since 2.4.0 made public, was protected in 2.3.0.
|
||||
*/
|
||||
@Override
|
||||
public void passivate() throws SQLException {
|
||||
setClosedInternal(true);
|
||||
removeThisTrace(getConnectionInternal());
|
||||
|
||||
// The JDBC spec requires that a statement close any open
|
||||
// ResultSet's when it is closed.
|
||||
// FIXME The PreparedStatement we're wrapping should handle this for us.
|
||||
// See DBCP-10 for what could happen when ResultSets are closed twice.
|
||||
final List<AbandonedTrace> resultSetList = getTrace();
|
||||
if (resultSetList != null) {
|
||||
final List<Exception> thrownList = new ArrayList<>();
|
||||
final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]);
|
||||
for (final ResultSet resultSet : resultSets) {
|
||||
if (resultSet != null) {
|
||||
try {
|
||||
resultSet.close();
|
||||
} catch (Exception e) {
|
||||
thrownList.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTrace();
|
||||
if (!thrownList.isEmpty()) {
|
||||
throw new SQLExceptionList(thrownList);
|
||||
}
|
||||
}
|
||||
|
||||
super.passivate();
|
||||
}
|
||||
|
||||
}
|
||||
348
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
Normal file
348
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* 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.lang.management.ManagementFactory;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.MBeanRegistrationException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.ObjectPool;
|
||||
|
||||
/**
|
||||
* A delegating connection that, rather than closing the underlying connection, returns itself to an {@link ObjectPool}
|
||||
* when closed.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolableConnection extends DelegatingConnection<Connection> implements PoolableConnectionMXBean {
|
||||
|
||||
private static MBeanServer MBEAN_SERVER;
|
||||
|
||||
static {
|
||||
try {
|
||||
MBEAN_SERVER = ManagementFactory.getPlatformMBeanServer();
|
||||
} catch (NoClassDefFoundError | Exception ex) {
|
||||
// ignore - JMX not available
|
||||
}
|
||||
}
|
||||
|
||||
/** The pool to which I should return. */
|
||||
private final ObjectPool<PoolableConnection> pool;
|
||||
|
||||
private final ObjectNameWrapper jmxObjectName;
|
||||
|
||||
// Use a prepared statement for validation, retaining the last used SQL to
|
||||
// check if the validation query has changed.
|
||||
private PreparedStatement validationPreparedStatement;
|
||||
private String lastValidationSql;
|
||||
|
||||
/**
|
||||
* Indicate that unrecoverable SQLException was thrown when using this connection. Such a connection should be
|
||||
* considered broken and not pass validation in the future.
|
||||
*/
|
||||
private boolean fatalSqlExceptionThrown = false;
|
||||
|
||||
/**
|
||||
* SQL_STATE codes considered to signal fatal conditions. Overrides the defaults in
|
||||
* {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}).
|
||||
*/
|
||||
private final Collection<String> disconnectionSqlCodes;
|
||||
|
||||
/** Whether or not to fast fail validation after fatal connection errors */
|
||||
private final boolean fastFailValidation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param conn
|
||||
* my underlying connection
|
||||
* @param pool
|
||||
* the pool to which I should return when closed
|
||||
* @param jmxObjectName
|
||||
* JMX name
|
||||
* @param disconnectSqlCodes
|
||||
* SQL_STATE codes considered fatal disconnection errors
|
||||
* @param fastFailValidation
|
||||
* true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to
|
||||
* run query or isValid)
|
||||
*/
|
||||
public PoolableConnection(final Connection conn, final ObjectPool<PoolableConnection> pool,
|
||||
final ObjectName jmxObjectName, final Collection<String> disconnectSqlCodes,
|
||||
final boolean fastFailValidation) {
|
||||
super(conn);
|
||||
this.pool = pool;
|
||||
this.jmxObjectName = ObjectNameWrapper.wrap(jmxObjectName);
|
||||
this.disconnectionSqlCodes = disconnectSqlCodes;
|
||||
this.fastFailValidation = fastFailValidation;
|
||||
|
||||
if (jmxObjectName != null) {
|
||||
try {
|
||||
MBEAN_SERVER.registerMBean(this, jmxObjectName);
|
||||
} catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
|
||||
// For now, simply skip registration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param conn
|
||||
* my underlying connection
|
||||
* @param pool
|
||||
* the pool to which I should return when closed
|
||||
* @param jmxName
|
||||
* JMX name
|
||||
*/
|
||||
public PoolableConnection(final Connection conn, final ObjectPool<PoolableConnection> pool,
|
||||
final ObjectName jmxName) {
|
||||
this(conn, pool, jmxName, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void passivate() throws SQLException {
|
||||
super.passivate();
|
||||
setClosedInternal(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This method should not be used by a client to determine whether or not a connection should be return to the
|
||||
* connection pool (by calling {@link #close()}). Clients should always attempt to return a connection to the pool
|
||||
* once it is no longer required.
|
||||
*/
|
||||
@Override
|
||||
public boolean isClosed() throws SQLException {
|
||||
if (isClosedInternal()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getDelegateInternal().isClosed()) {
|
||||
// Something has gone wrong. The underlying connection has been
|
||||
// closed without the connection being returned to the pool. Return
|
||||
// it now.
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns me to my pool.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws SQLException {
|
||||
if (isClosedInternal()) {
|
||||
// already closed
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isUnderlyingConnectionClosed;
|
||||
try {
|
||||
isUnderlyingConnectionClosed = getDelegateInternal().isClosed();
|
||||
} catch (final SQLException e) {
|
||||
try {
|
||||
pool.invalidateObject(this);
|
||||
} catch (final IllegalStateException ise) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final Exception ie) {
|
||||
// DO NOTHING the original exception will be rethrown
|
||||
}
|
||||
throw new SQLException("Cannot close connection (isClosed check failed)", e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't set close before this code block since the connection needs to be open when validation runs. Can't set
|
||||
* close after this code block since by then the connection will have been returned to the pool and may have
|
||||
* been borrowed by another thread. Therefore, the close flag is set in passivate().
|
||||
*/
|
||||
if (isUnderlyingConnectionClosed) {
|
||||
// Abnormal close: underlying connection closed unexpectedly, so we
|
||||
// must destroy this proxy
|
||||
try {
|
||||
pool.invalidateObject(this);
|
||||
} catch (final IllegalStateException e) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close connection (invalidating pooled object failed)", e);
|
||||
}
|
||||
} else {
|
||||
// Normal close: underlying connection is still open, so we
|
||||
// simply need to return this proxy to the pool
|
||||
try {
|
||||
pool.returnObject(this);
|
||||
} catch (final IllegalStateException e) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close connection (return to pool failed)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually close my underlying {@link Connection}.
|
||||
*/
|
||||
@Override
|
||||
public void reallyClose() throws SQLException {
|
||||
if (jmxObjectName != null) {
|
||||
jmxObjectName.unregisterMBean();
|
||||
}
|
||||
|
||||
if (validationPreparedStatement != null) {
|
||||
try {
|
||||
validationPreparedStatement.close();
|
||||
} catch (final SQLException sqle) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
super.closeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the {@link #toString()} method via a bean getter so it can be read as a property via JMX.
|
||||
*/
|
||||
@Override
|
||||
public String getToString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the connection, using the following algorithm:
|
||||
* <ol>
|
||||
* <li>If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously
|
||||
* thrown a fatal disconnection exception, a {@code SQLException} is thrown.</li>
|
||||
* <li>If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it
|
||||
* returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.</li>
|
||||
* <li>If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at
|
||||
* least one row, this method returns successfully. If not, {@code SQLException} is thrown.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param sql
|
||||
* The validation SQL query.
|
||||
* @param timeoutSeconds
|
||||
* The validation timeout in seconds.
|
||||
* @throws SQLException
|
||||
* Thrown when validation fails or an SQLException occurs during validation
|
||||
*/
|
||||
public void validate(final String sql, int timeoutSeconds) throws SQLException {
|
||||
if (fastFailValidation && fatalSqlExceptionThrown) {
|
||||
throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail"));
|
||||
}
|
||||
|
||||
if (sql == null || sql.length() == 0) {
|
||||
if (timeoutSeconds < 0) {
|
||||
timeoutSeconds = 0;
|
||||
}
|
||||
if (!isValid(timeoutSeconds)) {
|
||||
throw new SQLException("isValid() returned false");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sql.equals(lastValidationSql)) {
|
||||
lastValidationSql = sql;
|
||||
// Has to be the innermost delegate else the prepared statement will
|
||||
// be closed when the pooled connection is passivated.
|
||||
validationPreparedStatement = getInnermostDelegateInternal().prepareStatement(sql);
|
||||
}
|
||||
|
||||
if (timeoutSeconds > 0) {
|
||||
validationPreparedStatement.setQueryTimeout(timeoutSeconds);
|
||||
}
|
||||
|
||||
try (ResultSet rs = validationPreparedStatement.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
throw new SQLException("validationQuery didn't return a row");
|
||||
}
|
||||
} catch (final SQLException sqle) {
|
||||
throw sqle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the SQLState of the input exception and any nested SQLExceptions it wraps.
|
||||
* <p>
|
||||
* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the
|
||||
* configured list of fatal exception codes. If this property is not set, codes are compared against the default
|
||||
* codes in {@link Utils#DISCONNECTION_SQL_CODES} and in this case anything starting with #{link
|
||||
* Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection.
|
||||
* </p>
|
||||
*
|
||||
* @param e
|
||||
* SQLException to be examined
|
||||
* @return true if the exception signals a disconnection
|
||||
*/
|
||||
private boolean isDisconnectionSqlException(final SQLException e) {
|
||||
boolean fatalException = false;
|
||||
final String sqlState = e.getSQLState();
|
||||
if (sqlState != null) {
|
||||
fatalException = disconnectionSqlCodes == null
|
||||
? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX)
|
||||
|| Utils.DISCONNECTION_SQL_CODES.contains(sqlState)
|
||||
: disconnectionSqlCodes.contains(sqlState);
|
||||
if (!fatalException) {
|
||||
final SQLException nextException = e.getNextException();
|
||||
if (nextException != null && nextException != e) {
|
||||
fatalException = isDisconnectionSqlException(e.getNextException());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fatalException;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleException(final SQLException e) throws SQLException {
|
||||
fatalSqlExceptionThrown |= isDisconnectionSqlException(e);
|
||||
super.handleException(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The disconnection SQL codes.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Collection<String> getDisconnectionSqlCodes() {
|
||||
return disconnectionSqlCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether to fail-fast.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public boolean isFastFailValidation() {
|
||||
return fastFailValidation;
|
||||
}
|
||||
}
|
||||
657
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
Normal file
657
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.SQLException;
|
||||
|
||||
/**
|
||||
* Defines the attributes and methods that will be exposed via JMX for {@link PoolableConnection} instances.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface PoolableConnectionMXBean {
|
||||
// Read-only properties
|
||||
boolean isClosed() throws SQLException;
|
||||
|
||||
// SQLWarning getWarnings() throws SQLException;
|
||||
String getToString();
|
||||
|
||||
// Read-write properties
|
||||
boolean getAutoCommit() throws SQLException;
|
||||
|
||||
void setAutoCommit(boolean autoCommit) throws SQLException;
|
||||
|
||||
boolean getCacheState();
|
||||
|
||||
void setCacheState(boolean cacheState);
|
||||
|
||||
String getCatalog() throws SQLException;
|
||||
|
||||
void setCatalog(String catalog) throws SQLException;
|
||||
|
||||
int getHoldability() throws SQLException;
|
||||
|
||||
void setHoldability(int holdability) throws SQLException;
|
||||
|
||||
boolean isReadOnly() throws SQLException;
|
||||
|
||||
void setReadOnly(boolean readOnly) throws SQLException;
|
||||
|
||||
String getSchema() throws SQLException;
|
||||
|
||||
void setSchema(String schema) throws SQLException;
|
||||
|
||||
int getTransactionIsolation() throws SQLException;
|
||||
|
||||
void setTransactionIsolation(int level) throws SQLException;
|
||||
|
||||
// Methods
|
||||
void clearCachedState();
|
||||
|
||||
void clearWarnings() throws SQLException;
|
||||
|
||||
void close() throws SQLException;
|
||||
|
||||
void reallyClose() throws SQLException;
|
||||
}
|
||||
159
java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
Normal file
159
java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
|
||||
|
||||
/**
|
||||
* A {@link DelegatingPreparedStatement} that cooperates with {@link PoolingConnection} to implement a pool of
|
||||
* {@link PreparedStatement}s.
|
||||
* <p>
|
||||
* My {@link #close} method returns me to my containing pool. (See {@link PoolingConnection}.)
|
||||
* </p>
|
||||
*
|
||||
* @param <K>
|
||||
* the key type
|
||||
*
|
||||
* @see PoolingConnection
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
|
||||
|
||||
/**
|
||||
* The {@link KeyedObjectPool} from which I was obtained.
|
||||
*/
|
||||
private final KeyedObjectPool<K, PoolablePreparedStatement<K>> pool;
|
||||
|
||||
/**
|
||||
* My "key" as used by {@link KeyedObjectPool}.
|
||||
*/
|
||||
private final K key;
|
||||
|
||||
private volatile boolean batchAdded = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param stmt
|
||||
* my underlying {@link PreparedStatement}
|
||||
* @param key
|
||||
* my key" as used by {@link KeyedObjectPool}
|
||||
* @param pool
|
||||
* the {@link KeyedObjectPool} from which I was obtained.
|
||||
* @param conn
|
||||
* the {@link java.sql.Connection Connection} from which I was created
|
||||
*/
|
||||
public PoolablePreparedStatement(final PreparedStatement stmt, final K key,
|
||||
final KeyedObjectPool<K, PoolablePreparedStatement<K>> pool, final DelegatingConnection<?> conn) {
|
||||
super(conn, stmt);
|
||||
this.pool = pool;
|
||||
this.key = key;
|
||||
|
||||
// Remove from trace now because this statement will be
|
||||
// added by the activate method.
|
||||
removeThisTrace(getConnectionInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add batch.
|
||||
*/
|
||||
@Override
|
||||
public void addBatch() throws SQLException {
|
||||
super.addBatch();
|
||||
batchAdded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Batch.
|
||||
*/
|
||||
@Override
|
||||
public void clearBatch() throws SQLException {
|
||||
batchAdded = false;
|
||||
super.clearBatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return me to my pool.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
// calling close twice should have no effect
|
||||
if (!isClosed()) {
|
||||
try {
|
||||
pool.returnObject(key, this);
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close preparedstatement (return to pool failed)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() throws SQLException {
|
||||
setClosedInternal(false);
|
||||
if (getConnectionInternal() != null) {
|
||||
getConnectionInternal().addTrace(this);
|
||||
}
|
||||
super.activate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivate() throws SQLException {
|
||||
// DBCP-372. clearBatch with throw an exception if called when the
|
||||
// connection is marked as closed.
|
||||
if (batchAdded) {
|
||||
clearBatch();
|
||||
}
|
||||
setClosedInternal(true);
|
||||
removeThisTrace(getConnectionInternal());
|
||||
|
||||
// The JDBC spec requires that a statement closes any open
|
||||
// ResultSet's when it is closed.
|
||||
// FIXME The PreparedStatement we're wrapping should handle this for us.
|
||||
// See bug 17301 for what could happen when ResultSets are closed twice.
|
||||
final List<AbandonedTrace> resultSetList = getTrace();
|
||||
if (resultSetList != null) {
|
||||
final List<Exception> thrownList = new ArrayList<>();
|
||||
final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]);
|
||||
for (final ResultSet resultSet : resultSets) {
|
||||
if (resultSet != null) {
|
||||
try {
|
||||
resultSet.close();
|
||||
} catch (Exception e) {
|
||||
thrownList.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTrace();
|
||||
if (!thrownList.isEmpty()) {
|
||||
throw new SQLExceptionList(thrownList);
|
||||
}
|
||||
}
|
||||
|
||||
super.passivate();
|
||||
}
|
||||
}
|
||||
602
java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
Normal file
602
java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
Normal file
File diff suppressed because it is too large
Load Diff
257
java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java
Normal file
257
java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.dbcp.pool2.ObjectPool;
|
||||
import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
|
||||
|
||||
/**
|
||||
* A simple {@link DataSource} implementation that obtains {@link Connection}s from the specified {@link ObjectPool}.
|
||||
*
|
||||
* @param <C>
|
||||
* The connection type
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolingDataSource<C extends Connection> implements DataSource, AutoCloseable {
|
||||
|
||||
private static final Log log = LogFactory.getLog(PoolingDataSource.class);
|
||||
|
||||
/** Controls access to the underlying connection */
|
||||
private boolean accessToUnderlyingConnectionAllowed;
|
||||
|
||||
/**
|
||||
* Constructs a new instance backed by the given connection pool.
|
||||
*
|
||||
* @param pool
|
||||
* the given connection pool.
|
||||
*/
|
||||
public PoolingDataSource(final ObjectPool<C> pool) {
|
||||
Objects.requireNonNull(pool, "Pool must not be null.");
|
||||
this.pool = pool;
|
||||
// Verify that pool's factory refers back to it. If not, log a warning and try to fix.
|
||||
if (this.pool instanceof GenericObjectPool<?>) {
|
||||
final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ((GenericObjectPool<?>) this.pool)
|
||||
.getFactory();
|
||||
Objects.requireNonNull(pcf, "PoolableConnectionFactory must not be null.");
|
||||
if (pcf.getPool() != this.pool) {
|
||||
log.warn(Utils.getMessage("poolingDataSource.factoryConfig"));
|
||||
@SuppressWarnings("unchecked") // PCF must have a pool of PCs
|
||||
final ObjectPool<PoolableConnection> p = (ObjectPool<PoolableConnection>) this.pool;
|
||||
pcf.setPool(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes and free all {@link Connection}s from the pool.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
@Override
|
||||
public void close() throws RuntimeException, SQLException {
|
||||
try {
|
||||
pool.close();
|
||||
} catch (final RuntimeException rte) {
|
||||
throw new RuntimeException(Utils.getMessage("pool.close.fail"), rte);
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException(Utils.getMessage("pool.close.fail"), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the accessToUnderlyingConnectionAllowed property.
|
||||
*
|
||||
* @return true if access to the underlying {@link Connection} is allowed, false otherwise.
|
||||
*/
|
||||
public boolean isAccessToUnderlyingConnectionAllowed() {
|
||||
return this.accessToUnderlyingConnectionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
|
||||
* the underlying connection. (Default: false)
|
||||
*
|
||||
* @param allow
|
||||
* Access to the underlying connection is granted when true.
|
||||
*/
|
||||
public void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
|
||||
this.accessToUnderlyingConnectionAllowed = allow;
|
||||
}
|
||||
|
||||
/* JDBC_4_ANT_KEY_BEGIN */
|
||||
@Override
|
||||
public boolean isWrapperFor(final Class<?> iface) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(final Class<T> iface) throws SQLException {
|
||||
throw new SQLException("PoolingDataSource is not a wrapper.");
|
||||
}
|
||||
/* JDBC_4_ANT_KEY_END */
|
||||
|
||||
@Override
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
throw new SQLFeatureNotSupportedException();
|
||||
}
|
||||
|
||||
// --- DataSource methods -----------------------------------------
|
||||
|
||||
/**
|
||||
* Returns a {@link java.sql.Connection} from my pool, according to the contract specified by
|
||||
* {@link ObjectPool#borrowObject}.
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
try {
|
||||
final C conn = pool.borrowObject();
|
||||
if (conn == null) {
|
||||
return null;
|
||||
}
|
||||
return new PoolGuardConnectionWrapper<>(conn);
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final NoSuchElementException e) {
|
||||
throw new SQLException("Cannot get a connection, pool error " + e.getMessage(), e);
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final InterruptedException e) {
|
||||
// Reset the interrupt status so it is visible to callers
|
||||
Thread.currentThread().interrupt();
|
||||
throw new SQLException("Cannot get a connection, general error", e);
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot get a connection, general error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* always thrown
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection(final String uname, final String passwd) throws SQLException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns my log writer.
|
||||
*
|
||||
* @return my log writer
|
||||
* @see DataSource#getLogWriter
|
||||
*/
|
||||
@Override
|
||||
public PrintWriter getLogWriter() {
|
||||
return logWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* As this implementation does not support this feature.
|
||||
*/
|
||||
@Override
|
||||
public int getLoginTimeout() {
|
||||
throw new UnsupportedOperationException("Login timeout is not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* As this implementation does not support this feature.
|
||||
*/
|
||||
@Override
|
||||
public void setLoginTimeout(final int seconds) {
|
||||
throw new UnsupportedOperationException("Login timeout is not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets my log writer.
|
||||
*
|
||||
* @see DataSource#setLogWriter
|
||||
*/
|
||||
@Override
|
||||
public void setLogWriter(final PrintWriter out) {
|
||||
logWriter = out;
|
||||
}
|
||||
|
||||
/** My log writer. */
|
||||
private PrintWriter logWriter = null;
|
||||
|
||||
private final ObjectPool<C> pool;
|
||||
|
||||
protected ObjectPool<C> getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* PoolGuardConnectionWrapper is a Connection wrapper that makes sure a closed connection cannot be used anymore.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
private class PoolGuardConnectionWrapper<D extends Connection> extends DelegatingConnection<D> {
|
||||
|
||||
PoolGuardConnectionWrapper(final D delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.tomcat.dbcp.dbcp2.DelegatingConnection#getDelegate()
|
||||
*/
|
||||
@Override
|
||||
public D getDelegate() {
|
||||
return isAccessToUnderlyingConnectionAllowed() ? super.getDelegate() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.tomcat.dbcp.dbcp2.DelegatingConnection#getInnermostDelegate()
|
||||
*/
|
||||
@Override
|
||||
public Connection getInnermostDelegate() {
|
||||
return isAccessToUnderlyingConnectionAllowed() ? super.getInnermostDelegate() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
if (getDelegateInternal() != null) {
|
||||
super.close();
|
||||
super.setDelegate(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() throws SQLException {
|
||||
return getDelegateInternal() == null ? true : super.isClosed();
|
||||
}
|
||||
}
|
||||
}
|
||||
263
java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
Normal file
263
java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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.Set;
|
||||
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 {
|
||||
|
||||
/** Register myself with the {@link DriverManager}. */
|
||||
static {
|
||||
try {
|
||||
DriverManager.registerDriver(new PoolingDriver());
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/** The map of registered pools. */
|
||||
protected static final HashMap<String, ObjectPool<? extends Connection>> pools = new HashMap<>();
|
||||
|
||||
/** Controls access to the underlying connection */
|
||||
private final boolean accessToUnderlyingConnectionAllowed;
|
||||
|
||||
/**
|
||||
* Constructs a new driver with <code>accessToUnderlyingConnectionAllowed</code> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the accessToUnderlyingConnectionAllowed property.
|
||||
*
|
||||
* @return true if access to the underlying is allowed, false otherwise.
|
||||
*/
|
||||
protected boolean isAccessToUnderlyingConnectionAllowed() {
|
||||
return accessToUnderlyingConnectionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
@SuppressWarnings("resource")
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pool names.
|
||||
*
|
||||
* @return the pool names.
|
||||
*/
|
||||
public synchronized String[] getPoolNames() {
|
||||
final Set<String> names = pools.keySet();
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsURL(final String url) throws SQLException {
|
||||
return url == null ? false : url.startsWith(URL_PREFIX);
|
||||
}
|
||||
|
||||
@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 SQLException e) {
|
||||
throw e;
|
||||
} catch (final NoSuchElementException e) {
|
||||
throw new SQLException("Cannot get a connection, pool error: " + e.getMessage(), e);
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot get a connection, general error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
throw new SQLFeatureNotSupportedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the given connection.
|
||||
*
|
||||
* @param conn
|
||||
* connection to invalidate
|
||||
* @throws SQLException
|
||||
* if the connection is not a <code>PoolGuardConnectionWrapper</code> or an error occurs invalidating
|
||||
* the connection
|
||||
*/
|
||||
public void invalidateConnection(final Connection conn) throws SQLException {
|
||||
if (conn instanceof PoolGuardConnectionWrapper) { // normal case
|
||||
final PoolGuardConnectionWrapper pgconn = (PoolGuardConnectionWrapper) conn;
|
||||
@SuppressWarnings("unchecked")
|
||||
final ObjectPool<Connection> pool = (ObjectPool<Connection>) pgconn.pool;
|
||||
try {
|
||||
pool.invalidateObject(pgconn.getDelegateInternal());
|
||||
} catch (final Exception e) {
|
||||
// Ignore.
|
||||
}
|
||||
} else {
|
||||
throw new SQLException("Invalid connection class");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion() {
|
||||
return MAJOR_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion() {
|
||||
return MINOR_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean jdbcCompliant() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
|
||||
return new DriverPropertyInfo[0];
|
||||
}
|
||||
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java
Normal file
57
java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An SQLException based on a list of Throwable causes.
|
||||
* <p>
|
||||
* The first exception in the list is used as this exception's cause and is accessible with the usual
|
||||
* {@link #getCause()} while the complete list is accessible with {@link #getCauseList()}.
|
||||
* </p>
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public class SQLExceptionList extends SQLException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final List<? extends Throwable> causeList;
|
||||
|
||||
/**
|
||||
* Creates a new exception caused by a list of exceptions.
|
||||
*
|
||||
* @param causeList a list of cause exceptions.
|
||||
*/
|
||||
public SQLExceptionList(List<? extends Throwable> causeList) {
|
||||
super(String.format("%,d exceptions: %s", Integer.valueOf(causeList == null ? 0 : causeList.size()), causeList),
|
||||
causeList == null ? null : causeList.get(0));
|
||||
this.causeList = causeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause list.
|
||||
*
|
||||
* @return The list of causes.
|
||||
*/
|
||||
public List<? extends Throwable> getCauseList() {
|
||||
return causeList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 org.apache.juli.logging.Log;
|
||||
import org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener;
|
||||
|
||||
/**
|
||||
* Class for logging swallowed exceptions.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SwallowedExceptionLogger implements SwallowedExceptionListener {
|
||||
|
||||
private final Log log;
|
||||
private final boolean logExpiredConnections;
|
||||
|
||||
/**
|
||||
* Create a SwallowedExceptionLogger with the given logger. By default, expired connection logging is turned on.
|
||||
*
|
||||
* @param log
|
||||
* logger
|
||||
*/
|
||||
public SwallowedExceptionLogger(final Log log) {
|
||||
this(log, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SwallowedExceptionLogger with the given logger and expired connection logging property.
|
||||
*
|
||||
* @param log
|
||||
* logger
|
||||
* @param logExpiredConnections
|
||||
* false suppresses logging of expired connection events
|
||||
*/
|
||||
public SwallowedExceptionLogger(final Log log, final boolean logExpiredConnections) {
|
||||
this.log = log;
|
||||
this.logExpiredConnections = logExpiredConnections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwallowException(final Exception e) {
|
||||
if (logExpiredConnections || !(e instanceof LifetimeExceededException)) {
|
||||
log.warn(Utils.getMessage("swallowedExceptionLogger.onSwallowedException"), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
150
java/org/apache/tomcat/dbcp/dbcp2/Utils.java
Normal file
150
java/org/apache/tomcat/dbcp/dbcp2/Utils.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.text.MessageFormat;
|
||||
import java.util.HashSet;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility methods.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public final class Utils {
|
||||
|
||||
private static final ResourceBundle messages = ResourceBundle
|
||||
.getBundle(Utils.class.getPackage().getName() + ".LocalStrings");
|
||||
|
||||
/**
|
||||
* Whether the security manager is enabled.
|
||||
*/
|
||||
public static final boolean IS_SECURITY_ENABLED = System.getSecurityManager() != null;
|
||||
|
||||
/** Any SQL_STATE starting with this value is considered a fatal disconnect */
|
||||
public static final String DISCONNECTION_SQL_CODE_PREFIX = "08";
|
||||
|
||||
/**
|
||||
* SQL codes of fatal connection errors.
|
||||
* <ul>
|
||||
* <li>57P01 (Admin shutdown)</li>
|
||||
* <li>57P02 (Crash shutdown)</li>
|
||||
* <li>57P03 (Cannot connect now)</li>
|
||||
* <li>01002 (SQL92 disconnect error)</li>
|
||||
* <li>JZ0C0 (Sybase disconnect error)</li>
|
||||
* <li>JZ0C1 (Sybase disconnect error)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final Set<String> DISCONNECTION_SQL_CODES;
|
||||
|
||||
static {
|
||||
DISCONNECTION_SQL_CODES = new HashSet<>();
|
||||
DISCONNECTION_SQL_CODES.add("57P01"); // Admin shutdown
|
||||
DISCONNECTION_SQL_CODES.add("57P02"); // Crash shutdown
|
||||
DISCONNECTION_SQL_CODES.add("57P03"); // Cannot connect now
|
||||
DISCONNECTION_SQL_CODES.add("01002"); // SQL92 disconnect error
|
||||
DISCONNECTION_SQL_CODES.add("JZ0C0"); // Sybase disconnect error
|
||||
DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the given char[] if not null.
|
||||
*
|
||||
* @param value
|
||||
* may be null.
|
||||
* @return a cloned char[] or null.
|
||||
*/
|
||||
public static char[] clone(final char[] value) {
|
||||
return value == null ? null : value.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the AutoCloseable (which may be null).
|
||||
*
|
||||
* @param autoCloseable
|
||||
* an AutoCloseable, may be {@code null}
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public static void closeQuietly(final AutoCloseable autoCloseable) {
|
||||
if (autoCloseable != null) {
|
||||
try {
|
||||
autoCloseable.close();
|
||||
} catch (final Exception e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct i18n message for the given key.
|
||||
*
|
||||
* @param key
|
||||
* The key to look up an i18n message.
|
||||
* @return The i18n message.
|
||||
*/
|
||||
public static String getMessage(final String key) {
|
||||
return getMessage(key, (Object[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct i18n message for the given key with placeholders replaced by the supplied arguments.
|
||||
*
|
||||
* @param key
|
||||
* A message key.
|
||||
* @param args
|
||||
* The message arguments.
|
||||
* @return An i18n message.
|
||||
*/
|
||||
public static String getMessage(final String key, final Object... args) {
|
||||
final String msg = messages.getString(key);
|
||||
if (args == null || args.length == 0) {
|
||||
return msg;
|
||||
}
|
||||
final MessageFormat mf = new MessageFormat(msg);
|
||||
return mf.format(args, new StringBuffer(), null).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given String to a char[].
|
||||
*
|
||||
* @param value
|
||||
* may be null.
|
||||
* @return a char[] or null.
|
||||
*/
|
||||
public static char[] toCharArray(final String value) {
|
||||
return value != null ? value.toCharArray() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given char[] to a String.
|
||||
*
|
||||
* @param value
|
||||
* may be null.
|
||||
* @return a String or null.
|
||||
*/
|
||||
public static String toString(final char[] value) {
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
|
||||
private Utils() {
|
||||
// not instantiable
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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.cpdsadapter;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.tomcat.dbcp.dbcp2.DelegatingCallableStatement;
|
||||
import org.apache.tomcat.dbcp.dbcp2.DelegatingConnection;
|
||||
import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
|
||||
|
||||
/**
|
||||
* This class is the <code>Connection</code> that will be returned from
|
||||
* <code>PooledConnectionImpl.getConnection()</code>. Most methods are wrappers around the JDBC 1.x
|
||||
* <code>Connection</code>. A few exceptions include preparedStatement and close. In accordance with the JDBC
|
||||
* specification this Connection cannot be used after closed() is called. Any further usage will result in an
|
||||
* SQLException.
|
||||
* <p>
|
||||
* ConnectionImpl extends DelegatingConnection to enable access to the underlying connection.
|
||||
* </p>
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class ConnectionImpl extends DelegatingConnection<Connection> {
|
||||
|
||||
private final boolean accessToUnderlyingConnectionAllowed;
|
||||
|
||||
/** The object that instantiated this object */
|
||||
private final PooledConnectionImpl pooledConnection;
|
||||
|
||||
/**
|
||||
* Creates a <code>ConnectionImpl</code>.
|
||||
*
|
||||
* @param pooledConnection
|
||||
* The PooledConnection that is calling the ctor.
|
||||
* @param connection
|
||||
* The JDBC 1.x Connection to wrap.
|
||||
* @param accessToUnderlyingConnectionAllowed
|
||||
* if true, then access is allowed to the underlying connection
|
||||
*/
|
||||
ConnectionImpl(final PooledConnectionImpl pooledConnection, final Connection connection,
|
||||
final boolean accessToUnderlyingConnectionAllowed) {
|
||||
super(connection);
|
||||
this.pooledConnection = pooledConnection;
|
||||
this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the Connection as closed, and notifies the pool that the pooled connection is available.
|
||||
* <p>
|
||||
* In accordance with the JDBC specification this Connection cannot be used after closed() is called. Any further
|
||||
* usage will result in an SQLException.
|
||||
* </p>
|
||||
*
|
||||
* @throws SQLException
|
||||
* The database connection couldn't be closed.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
if (!isClosedInternal()) {
|
||||
try {
|
||||
passivate();
|
||||
} finally {
|
||||
setClosedInternal(true);
|
||||
pooledConnection.notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
|
||||
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
|
||||
*
|
||||
* @param sql
|
||||
* an SQL statement that may contain one or more '?' parameter placeholders. Typically this statement is
|
||||
* specified using JDBC call escape syntax.
|
||||
* @return a default <code>CallableStatement</code> object containing the pre-compiled SQL statement.
|
||||
* @exception SQLException
|
||||
* Thrown if a database access error occurs or this method is called on a closed connection.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Override
|
||||
public CallableStatement prepareCall(final String sql) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingCallableStatement(this, pooledConnection.prepareCall(sql));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e); // Does not return
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
|
||||
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
|
||||
*
|
||||
* @param sql
|
||||
* a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
|
||||
* more '?' parameters.
|
||||
* @param resultSetType
|
||||
* a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
|
||||
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
|
||||
* @param resultSetConcurrency
|
||||
* a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
|
||||
* <code>ResultSet.CONCUR_UPDATABLE</code>.
|
||||
* @return a <code>CallableStatement</code> object containing the pre-compiled SQL statement that will produce
|
||||
* <code>ResultSet</code> objects with the given type and concurrency.
|
||||
* @throws SQLException
|
||||
* Thrown if a database access error occurs, this method is called on a closed connection or the given
|
||||
* parameters are not <code>ResultSet</code> constants indicating type and concurrency.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Override
|
||||
public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingCallableStatement(this,
|
||||
pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e); // Does not return
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
|
||||
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
|
||||
*
|
||||
* @param sql
|
||||
* a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
|
||||
* more '?' parameters.
|
||||
* @param resultSetType
|
||||
* one of the following <code>ResultSet</code> constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
|
||||
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
|
||||
* @param resultSetConcurrency
|
||||
* one of the following <code>ResultSet</code> constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
|
||||
* <code>ResultSet.CONCUR_UPDATABLE</code>.
|
||||
* @param resultSetHoldability
|
||||
* one of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
|
||||
* or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
|
||||
* @return a new <code>CallableStatement</code> object, containing the pre-compiled SQL statement, that will
|
||||
* generate <code>ResultSet</code> objects with the given type, concurrency, and holdability.
|
||||
* @throws SQLException
|
||||
* Thrown if a database access error occurs, this method is called on a closed connection or the given
|
||||
* parameters are not <code>ResultSet</code> constants indicating type, concurrency, and holdability.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Override
|
||||
public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency,
|
||||
final int resultSetHoldability) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingCallableStatement(this,
|
||||
pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e); // Does not return
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If pooling of <code>PreparedStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
|
||||
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
|
||||
*
|
||||
* @param sql
|
||||
* SQL statement to be prepared
|
||||
* @return the prepared statement
|
||||
* @throws SQLException
|
||||
* if this connection is closed or an error occurs in the wrapped connection.
|
||||
*/
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e); // Does not return
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If pooling of <code>PreparedStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
|
||||
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
|
||||
*
|
||||
* @throws SQLException
|
||||
* if this connection is closed or an error occurs in the wrapped connection.
|
||||
*/
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this,
|
||||
pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency,
|
||||
final int resultSetHoldability) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this,
|
||||
pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, autoGeneratedKeys));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnIndexes));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
|
||||
checkOpen();
|
||||
try {
|
||||
return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnNames));
|
||||
} catch (final SQLException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Methods for accessing the delegate connection
|
||||
//
|
||||
|
||||
/**
|
||||
* If false, getDelegate() and getInnermostDelegate() will return null.
|
||||
*
|
||||
* @return true if access is allowed to the underlying connection
|
||||
* @see ConnectionImpl
|
||||
*/
|
||||
public boolean isAccessToUnderlyingConnectionAllowed() {
|
||||
return accessToUnderlyingConnectionAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delegated connection, if allowed.
|
||||
*
|
||||
* @return the internal connection, or null if access is not allowed.
|
||||
* @see #isAccessToUnderlyingConnectionAllowed()
|
||||
*/
|
||||
@Override
|
||||
public Connection getDelegate() {
|
||||
if (isAccessToUnderlyingConnectionAllowed()) {
|
||||
return getDelegateInternal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the innermost connection, if allowed.
|
||||
*
|
||||
* @return the innermost internal connection, or null if access is not allowed.
|
||||
* @see #isAccessToUnderlyingConnectionAllowed()
|
||||
*/
|
||||
@Override
|
||||
public Connection getInnermostDelegate() {
|
||||
if (isAccessToUnderlyingConnectionAllowed()) {
|
||||
return super.getInnermostDelegateInternal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
113
java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
Normal file
113
java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.cpdsadapter;
|
||||
|
||||
import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
|
||||
|
||||
/**
|
||||
* A key uniquely identifying a {@link java.sql.PreparedStatement PreparedStatement}.
|
||||
*
|
||||
* @since 2.0
|
||||
* @deprecated Use {@link PStmtKey}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PStmtKeyCPDS extends PStmtKey {
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql) {
|
||||
super(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
* @param autoGeneratedKeys
|
||||
* A flag indicating whether auto-generated keys should be returned; one of
|
||||
* <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql, final int autoGeneratedKeys) {
|
||||
super(sql, null, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
* @param resultSetType
|
||||
* A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
|
||||
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
|
||||
* @param resultSetConcurrency
|
||||
* A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
|
||||
* <code>ResultSet.CONCUR_UPDATABLE</code>.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency) {
|
||||
super(sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
* @param resultSetType
|
||||
* a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
|
||||
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
|
||||
* @param resultSetConcurrency
|
||||
* A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
|
||||
* <code>ResultSet.CONCUR_UPDATABLE</code>
|
||||
* @param resultSetHoldability
|
||||
* One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
|
||||
* or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency,
|
||||
final int resultSetHoldability) {
|
||||
super(sql, null, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
* @param columnIndexes
|
||||
* An array of column indexes indicating the columns that should be returned from the inserted row or
|
||||
* rows.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql, final int columnIndexes[]) {
|
||||
super(sql, null, columnIndexes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a key to uniquely identify a prepared statement.
|
||||
*
|
||||
* @param sql
|
||||
* The SQL statement.
|
||||
* @param columnNames
|
||||
* An array of column names indicating the columns that should be returned from the inserted row or rows.
|
||||
*/
|
||||
public PStmtKeyCPDS(final String sql, final String columnNames[]) {
|
||||
super(sql, null, columnNames);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This package contains one public class which is a
|
||||
* <code>ConnectionPoolDataSource</code> (CPDS) implementation that can be used to
|
||||
* adapt older <code>Driver</code> based JDBC implementations. Below is an
|
||||
* example of setting up the CPDS to be available via JNDI in the
|
||||
* catalina servlet container.
|
||||
* </p>
|
||||
* <p>In server.xml, the following would be added to the <Context> for your
|
||||
* webapp:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <Resource name="jdbc/bookstoreCPDS" auth="Container"
|
||||
* type="org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS"/>
|
||||
* <ResourceParams name="jdbc/bookstoreCPDS">
|
||||
* <parameter>
|
||||
* <name>factory</name>
|
||||
* <value>org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS</value>
|
||||
* </parameter>
|
||||
* <parameter><name>user</name><value>root</value></parameter>
|
||||
* <parameter><name>password</name><value></value></parameter>
|
||||
* <parameter>
|
||||
* <name>driver</name>
|
||||
* <value>org.gjt.mm.mysql.Driver</value></parameter>
|
||||
* <parameter>
|
||||
* <name>url</name>
|
||||
* <value>jdbc:mysql://localhost:3306/bookstore</value>
|
||||
* </parameter>
|
||||
* </ResourceParams>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* In web.xml. Note that elements must be given in the order of the dtd
|
||||
* described in the servlet specification:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <resource-ref>
|
||||
* <description>
|
||||
* Resource reference to a factory for java.sql.Connection
|
||||
* instances that may be used for talking to a particular
|
||||
* database that is configured in the server.xml file.
|
||||
* </description>
|
||||
* <res-ref-name>
|
||||
* jdbc/bookstoreCPDS
|
||||
* </res-ref-name>
|
||||
* <res-type>
|
||||
* org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS
|
||||
* </res-type>
|
||||
* <res-auth>
|
||||
* Container
|
||||
* </res-auth>
|
||||
* </resource-ref>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Catalina deploys all objects configured similarly to above within the
|
||||
* <strong>java:comp/env</strong> namespace.
|
||||
* </p>
|
||||
*/
|
||||
package org.apache.tomcat.dbcp.dbcp2.cpdsadapter;
|
||||
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* 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.datasources;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.sql.ConnectionEvent;
|
||||
import javax.sql.ConnectionEventListener;
|
||||
import javax.sql.ConnectionPoolDataSource;
|
||||
import javax.sql.PooledConnection;
|
||||
|
||||
import org.apache.tomcat.dbcp.dbcp2.Utils;
|
||||
import org.apache.tomcat.dbcp.pool2.ObjectPool;
|
||||
import org.apache.tomcat.dbcp.pool2.PooledObject;
|
||||
import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
|
||||
import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
|
||||
|
||||
/**
|
||||
* A {@link PooledObjectFactory} that creates
|
||||
* {@link org.apache.tomcat.dbcp.dbcp2.PoolableConnection PoolableConnection}s.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class CPDSConnectionFactory
|
||||
implements PooledObjectFactory<PooledConnectionAndInfo>, ConnectionEventListener, PooledConnectionManager {
|
||||
|
||||
private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but I have no record of the underlying PooledConnection.";
|
||||
|
||||
private final ConnectionPoolDataSource cpds;
|
||||
private final String validationQuery;
|
||||
private final int validationQueryTimeoutSeconds;
|
||||
private final boolean rollbackAfterValidation;
|
||||
private ObjectPool<PooledConnectionAndInfo> pool;
|
||||
private final String userName;
|
||||
private char[] userPassword;
|
||||
private long maxConnLifetimeMillis = -1;
|
||||
|
||||
/**
|
||||
* Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated.
|
||||
*/
|
||||
private final Set<PooledConnection> validatingSet = Collections
|
||||
.newSetFromMap(new ConcurrentHashMap<PooledConnection, Boolean>());
|
||||
|
||||
/**
|
||||
* Map of PooledConnectionAndInfo instances
|
||||
*/
|
||||
private final Map<PooledConnection, PooledConnectionAndInfo> pcMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a new {@code PoolableConnectionFactory}.
|
||||
*
|
||||
* @param cpds
|
||||
* the ConnectionPoolDataSource from which to obtain PooledConnection's
|
||||
* @param validationQuery
|
||||
* a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one
|
||||
* row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate
|
||||
* connections.
|
||||
* @param validationQueryTimeoutSeconds
|
||||
* Timeout in seconds before validation fails
|
||||
* @param rollbackAfterValidation
|
||||
* whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s.
|
||||
* @param userName
|
||||
* The user name to use to create connections
|
||||
* @param userPassword
|
||||
* The password to use to create connections
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery,
|
||||
final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation, final String userName,
|
||||
final char[] userPassword) {
|
||||
this.cpds = cpds;
|
||||
this.validationQuery = validationQuery;
|
||||
this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds;
|
||||
this.userName = userName;
|
||||
this.userPassword = userPassword;
|
||||
this.rollbackAfterValidation = rollbackAfterValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code PoolableConnectionFactory}.
|
||||
*
|
||||
* @param cpds
|
||||
* the ConnectionPoolDataSource from which to obtain PooledConnection's
|
||||
* @param validationQuery
|
||||
* a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one
|
||||
* row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate
|
||||
* connections.
|
||||
* @param validationQueryTimeoutSeconds
|
||||
* Timeout in seconds before validation fails
|
||||
* @param rollbackAfterValidation
|
||||
* whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s.
|
||||
* @param userName
|
||||
* The user name to use to create connections
|
||||
* @param userPassword
|
||||
* The password to use to create connections
|
||||
*/
|
||||
public CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery,
|
||||
final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation, final String userName,
|
||||
final String userPassword) {
|
||||
this(cpds, validationQuery, validationQueryTimeoutSeconds, rollbackAfterValidation, userName,
|
||||
Utils.toCharArray(userPassword));
|
||||
}
|
||||
|
||||
/**
|
||||
* (Testing API) Gets the value of password for the default user.
|
||||
*
|
||||
* @return value of password.
|
||||
*/
|
||||
char[] getPasswordCharArray() {
|
||||
return userPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object pool used to pool connections created by this factory.
|
||||
*
|
||||
* @return ObjectPool managing pooled connections
|
||||
*/
|
||||
public ObjectPool<PooledConnectionAndInfo> getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pool
|
||||
* the {@link ObjectPool} in which to pool those {@link Connection}s
|
||||
*/
|
||||
public void setPool(final ObjectPool<PooledConnectionAndInfo> pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized PooledObject<PooledConnectionAndInfo> makeObject() {
|
||||
PooledConnectionAndInfo pci;
|
||||
try {
|
||||
PooledConnection pc = null;
|
||||
if (userName == null) {
|
||||
pc = cpds.getPooledConnection();
|
||||
} else {
|
||||
pc = cpds.getPooledConnection(userName, Utils.toString(userPassword));
|
||||
}
|
||||
|
||||
if (pc == null) {
|
||||
throw new IllegalStateException("Connection pool data source returned null from getPooledConnection");
|
||||
}
|
||||
|
||||
// should we add this object as a listener or the pool.
|
||||
// consider the validateObject method in decision
|
||||
pc.addConnectionEventListener(this);
|
||||
pci = new PooledConnectionAndInfo(pc, userName, userPassword);
|
||||
pcMap.put(pc, pci);
|
||||
} catch (final SQLException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return new DefaultPooledObject<>(pci);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the PooledConnection and stops listening for events from it.
|
||||
*/
|
||||
@Override
|
||||
public void destroyObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
doDestroyObject(p.getObject());
|
||||
}
|
||||
|
||||
private void doDestroyObject(final PooledConnectionAndInfo pci) throws Exception {
|
||||
final PooledConnection pc = pci.getPooledConnection();
|
||||
pc.removeConnectionEventListener(this);
|
||||
pcMap.remove(pc);
|
||||
pc.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(final PooledObject<PooledConnectionAndInfo> p) {
|
||||
try {
|
||||
validateLifetime(p);
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
boolean valid = false;
|
||||
final PooledConnection pconn = p.getObject().getPooledConnection();
|
||||
Connection conn = null;
|
||||
validatingSet.add(pconn);
|
||||
if (null == validationQuery) {
|
||||
int timeoutSeconds = validationQueryTimeoutSeconds;
|
||||
if (timeoutSeconds < 0) {
|
||||
timeoutSeconds = 0;
|
||||
}
|
||||
try {
|
||||
conn = pconn.getConnection();
|
||||
valid = conn.isValid(timeoutSeconds);
|
||||
} catch (final SQLException e) {
|
||||
valid = false;
|
||||
} finally {
|
||||
Utils.closeQuietly(conn);
|
||||
validatingSet.remove(pconn);
|
||||
}
|
||||
} else {
|
||||
Statement stmt = null;
|
||||
ResultSet rset = null;
|
||||
// logical Connection from the PooledConnection must be closed
|
||||
// before another one can be requested and closing it will
|
||||
// generate an event. Keep track so we know not to return
|
||||
// the PooledConnection
|
||||
validatingSet.add(pconn);
|
||||
try {
|
||||
conn = pconn.getConnection();
|
||||
stmt = conn.createStatement();
|
||||
rset = stmt.executeQuery(validationQuery);
|
||||
if (rset.next()) {
|
||||
valid = true;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
if (rollbackAfterValidation) {
|
||||
conn.rollback();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
valid = false;
|
||||
} finally {
|
||||
Utils.closeQuietly(rset);
|
||||
Utils.closeQuietly(stmt);
|
||||
Utils.closeQuietly(conn);
|
||||
validatingSet.remove(pconn);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
validateLifetime(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
validateLifetime(p);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// java.sql.ConnectionEventListener implementation
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* This will be called if the Connection returned by the getConnection method came from a PooledConnection, and the
|
||||
* user calls the close() method of this connection object. What we need to do here is to release this
|
||||
* PooledConnection from our pool...
|
||||
*/
|
||||
@Override
|
||||
public void connectionClosed(final ConnectionEvent event) {
|
||||
final PooledConnection pc = (PooledConnection) event.getSource();
|
||||
// if this event occurred because we were validating, ignore it
|
||||
// otherwise return the connection to the pool.
|
||||
if (!validatingSet.contains(pc)) {
|
||||
final PooledConnectionAndInfo pci = pcMap.get(pc);
|
||||
if (pci == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
|
||||
try {
|
||||
pool.returnObject(pci);
|
||||
} catch (final Exception e) {
|
||||
System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL");
|
||||
pc.removeConnectionEventListener(this);
|
||||
try {
|
||||
doDestroyObject(pci);
|
||||
} catch (final Exception e2) {
|
||||
System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci);
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a fatal error occurs, close the underlying physical connection so as not to be returned in the future
|
||||
*/
|
||||
@Override
|
||||
public void connectionErrorOccurred(final ConnectionEvent event) {
|
||||
final PooledConnection pc = (PooledConnection) event.getSource();
|
||||
if (null != event.getSQLException()) {
|
||||
System.err.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR (" + event.getSQLException() + ")");
|
||||
}
|
||||
pc.removeConnectionEventListener(this);
|
||||
|
||||
final PooledConnectionAndInfo pci = pcMap.get(pc);
|
||||
if (pci == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
try {
|
||||
pool.invalidateObject(pci);
|
||||
} catch (final Exception e) {
|
||||
System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// PooledConnectionManager implementation
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* Invalidates the PooledConnection in the pool. The CPDSConnectionFactory closes the connection and pool counters
|
||||
* are updated appropriately. Also closes the pool. This ensures that all idle connections are closed and
|
||||
* connections that are checked out are closed on return.
|
||||
*/
|
||||
@Override
|
||||
public void invalidate(final PooledConnection pc) throws SQLException {
|
||||
final PooledConnectionAndInfo pci = pcMap.get(pc);
|
||||
if (pci == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
try {
|
||||
pool.invalidateObject(pci); // Destroy instance and update pool counters
|
||||
pool.close(); // Clear any other instances in this pool and kill others as they come back
|
||||
} catch (final Exception ex) {
|
||||
throw new SQLException("Error invalidating connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database password used when creating new connections.
|
||||
*
|
||||
* @param userPassword
|
||||
* new password
|
||||
*/
|
||||
public synchronized void setPassword(final char[] userPassword) {
|
||||
this.userPassword = Utils.clone(userPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database password used when creating new connections.
|
||||
*
|
||||
* @param userPassword
|
||||
* new password
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setPassword(final String userPassword) {
|
||||
this.userPassword = Utils.toCharArray(userPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
|
||||
* passivation and validation.
|
||||
*
|
||||
* @param maxConnLifetimeMillis
|
||||
* A value of zero or less indicates an infinite lifetime. The default value is -1.
|
||||
*/
|
||||
public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
|
||||
this.maxConnLifetimeMillis = maxConnLifetimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the user name matches the user whose connections are being managed by this factory and closes the
|
||||
* pool if this is the case; otherwise does nothing.
|
||||
*/
|
||||
@Override
|
||||
public void closePool(final String userName) throws SQLException {
|
||||
synchronized (this) {
|
||||
if (userName == null || !userName.equals(this.userName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
pool.close();
|
||||
} catch (final Exception ex) {
|
||||
throw new SQLException("Error closing connection pool", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLifetime(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
if (maxConnLifetimeMillis > 0) {
|
||||
final long lifetime = System.currentTimeMillis() - p.getCreateTime();
|
||||
if (lifetime > maxConnLifetimeMillis) {
|
||||
throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", Long.valueOf(lifetime),
|
||||
Long.valueOf(maxConnLifetimeMillis)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
*/
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
final StringBuilder builder = new StringBuilder(super.toString());
|
||||
builder.append("[cpds=");
|
||||
builder.append(cpds);
|
||||
builder.append(", validationQuery=");
|
||||
builder.append(validationQuery);
|
||||
builder.append(", validationQueryTimeoutSeconds=");
|
||||
builder.append(validationQueryTimeoutSeconds);
|
||||
builder.append(", rollbackAfterValidation=");
|
||||
builder.append(rollbackAfterValidation);
|
||||
builder.append(", pool=");
|
||||
builder.append(pool);
|
||||
builder.append(", maxConnLifetimeMillis=");
|
||||
builder.append(maxConnLifetimeMillis);
|
||||
builder.append(", validatingSet=");
|
||||
builder.append(validatingSet);
|
||||
builder.append(", pcMap=");
|
||||
builder.append(pcMap);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* 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.datasources;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
|
||||
import org.apache.tomcat.dbcp.dbcp2.ListException;
|
||||
|
||||
/**
|
||||
* A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s or <code>PerUserPoolDataSource</code>s
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
|
||||
|
||||
private static final Map<String, InstanceKeyDataSource> instanceMap = new ConcurrentHashMap<>();
|
||||
|
||||
static synchronized String registerNewInstance(final InstanceKeyDataSource ds) {
|
||||
int max = 0;
|
||||
final Iterator<String> iterator = instanceMap.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final String s = iterator.next();
|
||||
if (s != null) {
|
||||
try {
|
||||
max = Math.max(max, Integer.parseInt(s));
|
||||
} catch (final NumberFormatException e) {
|
||||
// no sweat, ignore those keys
|
||||
}
|
||||
}
|
||||
}
|
||||
final String instanceKey = String.valueOf(max + 1);
|
||||
// Put a placeholder here for now, so other instances will not
|
||||
// take our key. We will replace with a pool when ready.
|
||||
instanceMap.put(instanceKey, ds);
|
||||
return instanceKey;
|
||||
}
|
||||
|
||||
static void removeInstance(final String key) {
|
||||
if (key != null) {
|
||||
instanceMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all pools associated with this class.
|
||||
*
|
||||
* @throws Exception
|
||||
* a {@link ListException} containing all exceptions thrown by {@link InstanceKeyDataSource#close()}
|
||||
* @see InstanceKeyDataSource#close()
|
||||
* @see ListException
|
||||
* @since 2.4.0 throws a {@link ListException} instead of, in 2.3.0 and before, the first exception thrown by
|
||||
* {@link InstanceKeyDataSource#close()}.
|
||||
*/
|
||||
public static void closeAll() throws Exception {
|
||||
// Get iterator to loop over all instances of this data source.
|
||||
final List<Throwable> exceptionList = new ArrayList<>(instanceMap.size());
|
||||
final Iterator<Entry<String, InstanceKeyDataSource>> instanceIterator = instanceMap.entrySet().iterator();
|
||||
while (instanceIterator.hasNext()) {
|
||||
// Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close().
|
||||
final Entry<String, InstanceKeyDataSource> next = instanceIterator.next();
|
||||
if (next != null) {
|
||||
@SuppressWarnings("resource")
|
||||
final InstanceKeyDataSource value = next.getValue();
|
||||
if (value != null) {
|
||||
try {
|
||||
value.close();
|
||||
} catch (final Exception e) {
|
||||
exceptionList.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
instanceMap.clear();
|
||||
if (!exceptionList.isEmpty()) {
|
||||
throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ObjectFactory to create an instance of SharedPoolDataSource or PerUserPoolDataSource
|
||||
*/
|
||||
@Override
|
||||
public Object getObjectInstance(final Object refObj, final Name name, final Context context,
|
||||
final Hashtable<?, ?> env) throws IOException, ClassNotFoundException {
|
||||
// The spec says to return null if we can't create an instance
|
||||
// of the reference
|
||||
Object obj = null;
|
||||
if (refObj instanceof Reference) {
|
||||
final Reference ref = (Reference) refObj;
|
||||
if (isCorrectClass(ref.getClassName())) {
|
||||
final RefAddr refAddr = ref.get("instanceKey");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
// object was bound to JNDI via Referenceable API.
|
||||
obj = instanceMap.get(refAddr.getContent());
|
||||
} else {
|
||||
// Tomcat JNDI creates a Reference out of server.xml
|
||||
// <ResourceParam> configuration and passes it to an
|
||||
// instance of the factory given in server.xml.
|
||||
String key = null;
|
||||
if (name != null) {
|
||||
key = name.toString();
|
||||
obj = instanceMap.get(key);
|
||||
}
|
||||
if (obj == null) {
|
||||
final InstanceKeyDataSource ds = getNewInstance(ref);
|
||||
setCommonProperties(ref, ds);
|
||||
obj = ds;
|
||||
if (key != null) {
|
||||
instanceMap.put(key, ds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void setCommonProperties(final Reference ref, final InstanceKeyDataSource ikds)
|
||||
throws IOException, ClassNotFoundException {
|
||||
|
||||
RefAddr refAddr = ref.get("dataSourceName");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDataSourceName(refAddr.getContent().toString());
|
||||
}
|
||||
|
||||
refAddr = ref.get("description");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDescription(refAddr.getContent().toString());
|
||||
}
|
||||
|
||||
refAddr = ref.get("jndiEnvironment");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) refAddr.getContent();
|
||||
ikds.setJndiEnvironment((Properties) deserialize(serialized));
|
||||
}
|
||||
|
||||
refAddr = ref.get("loginTimeout");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setLoginTimeout(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
// Pool properties
|
||||
refAddr = ref.get("blockWhenExhausted");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultBlockWhenExhausted(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("evictionPolicyClassName");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultEvictionPolicyClassName(refAddr.getContent().toString());
|
||||
}
|
||||
|
||||
// Pool properties
|
||||
refAddr = ref.get("lifo");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultLifo(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("maxIdlePerKey");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultMaxIdle(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("maxTotalPerKey");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultMaxTotal(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("maxWaitMillis");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultMaxWaitMillis(Long.parseLong(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("minEvictableIdleTimeMillis");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("minIdlePerKey");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultMinIdle(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("numTestsPerEvictionRun");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultNumTestsPerEvictionRun(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("softMinEvictableIdleTimeMillis");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultSoftMinEvictableIdleTimeMillis(Long.parseLong(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("testOnCreate");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTestOnCreate(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("testOnBorrow");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTestOnBorrow(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("testOnReturn");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTestOnReturn(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("testWhileIdle");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTestWhileIdle(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("timeBetweenEvictionRunsMillis");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTimeBetweenEvictionRunsMillis(Long.parseLong(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
// Connection factory properties
|
||||
|
||||
refAddr = ref.get("validationQuery");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setValidationQuery(refAddr.getContent().toString());
|
||||
}
|
||||
|
||||
refAddr = ref.get("validationQueryTimeout");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setValidationQueryTimeout(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("rollbackAfterValidation");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setRollbackAfterValidation(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
|
||||
}
|
||||
|
||||
refAddr = ref.get("maxConnLifetimeMillis");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setMaxConnLifetimeMillis(Long.parseLong(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
// Connection properties
|
||||
|
||||
refAddr = ref.get("defaultAutoCommit");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultAutoCommit(Boolean.valueOf(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("defaultTransactionIsolation");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultTransactionIsolation(Integer.parseInt(refAddr.getContent().toString()));
|
||||
}
|
||||
|
||||
refAddr = ref.get("defaultReadOnly");
|
||||
if (refAddr != null && refAddr.getContent() != null) {
|
||||
ikds.setDefaultReadOnly(Boolean.valueOf(refAddr.getContent().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param className
|
||||
* The class name to test.
|
||||
*
|
||||
* @return true if and only if className is the value returned from getClass().getName().toString()
|
||||
*/
|
||||
protected abstract boolean isCorrectClass(String className);
|
||||
|
||||
/**
|
||||
* Creates an instance of the subclass and sets any properties contained in the Reference.
|
||||
*
|
||||
* @param ref
|
||||
* The properties to be set on the created DataSource
|
||||
*
|
||||
* @return A configured DataSource of the appropriate type.
|
||||
*
|
||||
* @throws ClassNotFoundException
|
||||
* If a class cannot be found during the deserialization of a configuration parameter.
|
||||
* @throws IOException
|
||||
* If an I/O error occurs during the deserialization of a configuration parameter.
|
||||
*/
|
||||
protected abstract InstanceKeyDataSource getNewInstance(Reference ref) throws IOException, ClassNotFoundException;
|
||||
|
||||
/**
|
||||
* Deserializes the provided byte array to create an object.
|
||||
*
|
||||
* @param data
|
||||
* Data to deserialize to create the configuration parameter.
|
||||
*
|
||||
* @return The Object created by deserializing the data.
|
||||
*
|
||||
* @throws ClassNotFoundException
|
||||
* If a class cannot be found during the deserialization of a configuration parameter.
|
||||
* @throws IOException
|
||||
* If an I/O error occurs during the deserialization of a configuration parameter.
|
||||
*/
|
||||
protected static final Object deserialize(final byte[] data) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream in = null;
|
||||
try {
|
||||
in = new ObjectInputStream(new ByteArrayInputStream(data));
|
||||
return in.readObject();
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (final IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* 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.datasources;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.sql.ConnectionEvent;
|
||||
import javax.sql.ConnectionEventListener;
|
||||
import javax.sql.ConnectionPoolDataSource;
|
||||
import javax.sql.PooledConnection;
|
||||
|
||||
import org.apache.tomcat.dbcp.dbcp2.Utils;
|
||||
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
|
||||
import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
|
||||
import org.apache.tomcat.dbcp.pool2.PooledObject;
|
||||
import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
|
||||
|
||||
/**
|
||||
* A {@link KeyedPooledObjectFactory} that creates {@link org.apache.tomcat.dbcp.dbcp2.PoolableConnection
|
||||
* PoolableConnection}s.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey, PooledConnectionAndInfo>,
|
||||
ConnectionEventListener, PooledConnectionManager {
|
||||
|
||||
private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but "
|
||||
+ "I have no record of the underlying PooledConnection.";
|
||||
|
||||
private final ConnectionPoolDataSource cpds;
|
||||
private final String validationQuery;
|
||||
private final int validationQueryTimeoutSeconds;
|
||||
private final boolean rollbackAfterValidation;
|
||||
private KeyedObjectPool<UserPassKey, PooledConnectionAndInfo> pool;
|
||||
private long maxConnLifetimeMillis = -1;
|
||||
|
||||
/**
|
||||
* Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated.
|
||||
*/
|
||||
private final Set<PooledConnection> validatingSet = Collections
|
||||
.newSetFromMap(new ConcurrentHashMap<PooledConnection, Boolean>());
|
||||
|
||||
/**
|
||||
* Map of PooledConnectionAndInfo instances
|
||||
*/
|
||||
private final Map<PooledConnection, PooledConnectionAndInfo> pcMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new {@code KeyedPoolableConnectionFactory}.
|
||||
*
|
||||
* @param cpds
|
||||
* the ConnectionPoolDataSource from which to obtain PooledConnections
|
||||
* @param validationQuery
|
||||
* a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one
|
||||
* row. May be {@code null} in which case3 {@link Connection#isValid(int)} will be used to validate
|
||||
* connections.
|
||||
* @param validationQueryTimeoutSeconds
|
||||
* The time, in seconds, to allow for the validation query to complete
|
||||
* @param rollbackAfterValidation
|
||||
* whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s.
|
||||
*/
|
||||
public KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery,
|
||||
final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) {
|
||||
this.cpds = cpds;
|
||||
this.validationQuery = validationQuery;
|
||||
this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds;
|
||||
this.rollbackAfterValidation = rollbackAfterValidation;
|
||||
}
|
||||
|
||||
public void setPool(final KeyedObjectPool<UserPassKey, PooledConnectionAndInfo> pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keyed object pool used to pool connections created by this factory.
|
||||
*
|
||||
* @return KeyedObjectPool managing pooled connections
|
||||
*/
|
||||
public KeyedObjectPool<UserPassKey, PooledConnectionAndInfo> getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link PooledConnectionAndInfo} from the given {@link UserPassKey}.
|
||||
*
|
||||
* @param upkey
|
||||
* {@link UserPassKey} containing user credentials
|
||||
* @throws SQLException
|
||||
* if the connection could not be created.
|
||||
* @see org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory#makeObject(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public synchronized PooledObject<PooledConnectionAndInfo> makeObject(final UserPassKey upkey) throws Exception {
|
||||
PooledConnectionAndInfo pci = null;
|
||||
|
||||
PooledConnection pc = null;
|
||||
final String userName = upkey.getUsername();
|
||||
final String password = upkey.getPassword();
|
||||
if (userName == null) {
|
||||
pc = cpds.getPooledConnection();
|
||||
} else {
|
||||
pc = cpds.getPooledConnection(userName, password);
|
||||
}
|
||||
|
||||
if (pc == null) {
|
||||
throw new IllegalStateException("Connection pool data source returned null from getPooledConnection");
|
||||
}
|
||||
|
||||
// should we add this object as a listener or the pool.
|
||||
// consider the validateObject method in decision
|
||||
pc.addConnectionEventListener(this);
|
||||
pci = new PooledConnectionAndInfo(pc, userName, upkey.getPasswordCharArray());
|
||||
pcMap.put(pc, pci);
|
||||
|
||||
return new DefaultPooledObject<>(pci);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the PooledConnection and stops listening for events from it.
|
||||
*/
|
||||
@Override
|
||||
public void destroyObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
final PooledConnection pc = p.getObject().getPooledConnection();
|
||||
pc.removeConnectionEventListener(this);
|
||||
pcMap.remove(pc);
|
||||
pc.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a pooled connection.
|
||||
*
|
||||
* @param key
|
||||
* ignored
|
||||
* @param pooledObject
|
||||
* wrapped {@link PooledConnectionAndInfo} containing the connection to validate
|
||||
* @return true if validation succeeds
|
||||
*/
|
||||
@Override
|
||||
public boolean validateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> pooledObject) {
|
||||
try {
|
||||
validateLifetime(pooledObject);
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
boolean valid = false;
|
||||
final PooledConnection pconn = pooledObject.getObject().getPooledConnection();
|
||||
Connection conn = null;
|
||||
validatingSet.add(pconn);
|
||||
if (null == validationQuery) {
|
||||
int timeoutSeconds = validationQueryTimeoutSeconds;
|
||||
if (timeoutSeconds < 0) {
|
||||
timeoutSeconds = 0;
|
||||
}
|
||||
try {
|
||||
conn = pconn.getConnection();
|
||||
valid = conn.isValid(timeoutSeconds);
|
||||
} catch (final SQLException e) {
|
||||
valid = false;
|
||||
} finally {
|
||||
Utils.closeQuietly(conn);
|
||||
validatingSet.remove(pconn);
|
||||
}
|
||||
} else {
|
||||
Statement stmt = null;
|
||||
ResultSet rset = null;
|
||||
// logical Connection from the PooledConnection must be closed
|
||||
// before another one can be requested and closing it will
|
||||
// generate an event. Keep track so we know not to return
|
||||
// the PooledConnection
|
||||
validatingSet.add(pconn);
|
||||
try {
|
||||
conn = pconn.getConnection();
|
||||
stmt = conn.createStatement();
|
||||
rset = stmt.executeQuery(validationQuery);
|
||||
if (rset.next()) {
|
||||
valid = true;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
if (rollbackAfterValidation) {
|
||||
conn.rollback();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
valid = false;
|
||||
} finally {
|
||||
Utils.closeQuietly(rset);
|
||||
Utils.closeQuietly(stmt);
|
||||
Utils.closeQuietly(conn);
|
||||
validatingSet.remove(pconn);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
validateLifetime(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
validateLifetime(p);
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// java.sql.ConnectionEventListener implementation
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* This will be called if the Connection returned by the getConnection method came from a PooledConnection, and the
|
||||
* user calls the close() method of this connection object. What we need to do here is to release this
|
||||
* PooledConnection from our pool...
|
||||
*/
|
||||
@Override
|
||||
public void connectionClosed(final ConnectionEvent event) {
|
||||
final PooledConnection pc = (PooledConnection) event.getSource();
|
||||
// if this event occurred because we were validating, or if this
|
||||
// connection has been marked for removal, ignore it
|
||||
// otherwise return the connection to the pool.
|
||||
if (!validatingSet.contains(pc)) {
|
||||
final PooledConnectionAndInfo pci = pcMap.get(pc);
|
||||
if (pci == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
try {
|
||||
pool.returnObject(pci.getUserPassKey(), pci);
|
||||
} catch (final Exception e) {
|
||||
System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL");
|
||||
pc.removeConnectionEventListener(this);
|
||||
try {
|
||||
pool.invalidateObject(pci.getUserPassKey(), pci);
|
||||
} catch (final Exception e3) {
|
||||
System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + pci);
|
||||
e3.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a fatal error occurs, close the underlying physical connection so as not to be returned in the future
|
||||
*/
|
||||
@Override
|
||||
public void connectionErrorOccurred(final ConnectionEvent event) {
|
||||
final PooledConnection pc = (PooledConnection) event.getSource();
|
||||
if (null != event.getSQLException()) {
|
||||
System.err.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR (" + event.getSQLException() + ")");
|
||||
}
|
||||
pc.removeConnectionEventListener(this);
|
||||
|
||||
final PooledConnectionAndInfo info = pcMap.get(pc);
|
||||
if (info == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
try {
|
||||
pool.invalidateObject(info.getUserPassKey(), info);
|
||||
} catch (final Exception e) {
|
||||
System.err.println("EXCEPTION WHILE DESTROYING OBJECT " + info);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// ***********************************************************************
|
||||
// PooledConnectionManager implementation
|
||||
// ***********************************************************************
|
||||
|
||||
/**
|
||||
* Invalidates the PooledConnection in the pool. The KeyedCPDSConnectionFactory closes the connection and pool
|
||||
* counters are updated appropriately. Also clears any idle instances associated with the user name that was used to
|
||||
* create the PooledConnection. Connections associated with this user are not affected and they will not be
|
||||
* automatically closed on return to the pool.
|
||||
*/
|
||||
@Override
|
||||
public void invalidate(final PooledConnection pc) throws SQLException {
|
||||
final PooledConnectionAndInfo info = pcMap.get(pc);
|
||||
if (info == null) {
|
||||
throw new IllegalStateException(NO_KEY_MESSAGE);
|
||||
}
|
||||
final UserPassKey key = info.getUserPassKey();
|
||||
try {
|
||||
pool.invalidateObject(key, info); // Destroy and update pool counters
|
||||
pool.clear(key); // Remove any idle instances with this key
|
||||
} catch (final Exception ex) {
|
||||
throw new SQLException("Error invalidating connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing. This factory does not cache user credentials.
|
||||
*/
|
||||
@Override
|
||||
public void setPassword(final String password) {
|
||||
// Does nothing. This factory does not cache user credentials.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
|
||||
* passivation and validation.
|
||||
*
|
||||
* @param maxConnLifetimeMillis
|
||||
* A value of zero or less indicates an infinite lifetime. The default value is -1.
|
||||
*/
|
||||
public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
|
||||
this.maxConnLifetimeMillis = maxConnLifetimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation does not fully close the KeyedObjectPool, as this would affect all users. Instead, it clears
|
||||
* the pool associated with the given user. This method is not currently used.
|
||||
*/
|
||||
@Override
|
||||
public void closePool(final String userName) throws SQLException {
|
||||
try {
|
||||
pool.clear(new UserPassKey(userName));
|
||||
} catch (final Exception ex) {
|
||||
throw new SQLException("Error closing connection pool", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLifetime(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
|
||||
if (maxConnLifetimeMillis > 0) {
|
||||
final long lifetime = System.currentTimeMillis() - p.getCreateTime();
|
||||
if (lifetime > maxConnLifetimeMillis) {
|
||||
throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", Long.valueOf(lifetime),
|
||||
Long.valueOf(maxConnLifetimeMillis)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.datasources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
|
||||
/**
|
||||
* A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PerUserPoolDataSourceFactory extends InstanceKeyDataSourceFactory {
|
||||
private static final String PER_USER_POOL_CLASSNAME = PerUserPoolDataSource.class.getName();
|
||||
|
||||
@Override
|
||||
protected boolean isCorrectClass(final String className) {
|
||||
return PER_USER_POOL_CLASSNAME.equals(className);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // Avoid warnings on deserialization
|
||||
@Override
|
||||
protected InstanceKeyDataSource getNewInstance(final Reference ref) throws IOException, ClassNotFoundException {
|
||||
final PerUserPoolDataSource pupds = new PerUserPoolDataSource();
|
||||
RefAddr ra = ref.get("defaultMaxTotal");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
pupds.setDefaultMaxTotal(Integer.parseInt(ra.getContent().toString()));
|
||||
}
|
||||
|
||||
ra = ref.get("defaultMaxIdle");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
pupds.setDefaultMaxIdle(Integer.parseInt(ra.getContent().toString()));
|
||||
}
|
||||
|
||||
ra = ref.get("defaultMaxWaitMillis");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
pupds.setDefaultMaxWaitMillis(Integer.parseInt(ra.getContent().toString()));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserDefaultAutoCommit");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserDefaultAutoCommit((Map<String, Boolean>) deserialize(serialized));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserDefaultTransactionIsolation");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserDefaultTransactionIsolation((Map<String, Integer>) deserialize(serialized));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserMaxTotal");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserMaxTotal((Map<String, Integer>) deserialize(serialized));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserMaxIdle");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserMaxIdle((Map<String, Integer>) deserialize(serialized));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserMaxWaitMillis");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserMaxWaitMillis((Map<String, Long>) deserialize(serialized));
|
||||
}
|
||||
|
||||
ra = ref.get("perUserDefaultReadOnly");
|
||||
if (ra != null && ra.getContent() != null) {
|
||||
final byte[] serialized = (byte[]) ra.getContent();
|
||||
pupds.setPerUserDefaultReadOnly((Map<String, Boolean>) deserialize(serialized));
|
||||
}
|
||||
return pupds;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user