<classpathentry kind="var" path="TOMCAT_LIBS_BASE/tomcat6-deps/dbcp/tomcat-dbcp.jar" sourcepath="/TOMCAT_LIBS_BASE/tomcat6-deps/dbcp/src/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/development/tomcat/trunk/trunk/modules/jdbc-pool/includes/h2/bin/h2-1.1.115.jar"/>
+ <classpathentry kind="lib" path="/development/tomcat/trunk/trunk/modules/jdbc-pool/includes/mysql-connector-java-5.1.7-bin.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<li>Get JMX notifications and log entries when connections are suspected for being abandoned. This is similar to
the <code>removeAbandonedTimeout</code> but it doesn't take any action, only reports the information.
This is achieved using the <code>suspectTimeout</code> attribute.</li>
+ <li>Connections can be retrieved from a <code>java.sql.Driver</code> or a <code>javax.sql.DataSource</code>
+ This is achieved using the <code>dataSource</code> and <code>dataSourceJNDI</code> attributes.</li>
+ <li>XA connection support</li>
</ol>
</p>
logged and a JMX notification gets sent once.
</p>
</attribute>
+ <attribute name="dataSource" required="false">
+ <p>(javax.sql.DataSource)
+ </p>
+ </attribute>
+ <attribute name="dataSourceJNDI" required="false">
+ <p>(String)
+ </p>
+ </attribute>
</attributes>
</subsection>
</section>
}
try {
- getProxyConstructor(con.getConnection() instanceof XAConnection);
+ getProxyConstructor(con.getXAConnection() != null);
//create the proxy
//TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade
Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler });
protected static final String PROP_USE_EQUALS = "useEquals";
protected static final String PROP_USE_CON_LOCK = "useLock";
+ protected static final String PROP_DATASOURCE= "dataSource";
+ protected static final String PROP_DATASOURCE_JNDI = "dataSourceJNDI";
+
+
public static final int UNKNOWN_TRANSACTIONISOLATION = -1;
public static final String OBJECT_NAME = "object_name";
OBJECT_NAME,
PROP_ABANDONWHENPERCENTAGEFULL,
PROP_MAXAGE,
- PROP_USE_CON_LOCK
+ PROP_USE_CON_LOCK,
+ PROP_DATASOURCE,
+ PROP_DATASOURCE_JNDI,
};
// -------------------------------------------------- ObjectFactory Methods
poolProperties.setUseLock(Boolean.parseBoolean(value));
}
+ value = properties.getProperty(PROP_DATASOURCE);
+ if (value != null) {
+ //this should never happen
+ log.error("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
+ }
+
+ value = properties.getProperty(PROP_DATASOURCE_JNDI);
+ if (value != null) {
+ poolProperties.setDataSourceJNDI(value);
+ }
return poolProperties;
}
getPoolProperties().setName(name);
}
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSource(javax.sql.DataSource ds) {
+ getPoolProperties().setDataSource(ds);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public javax.sql.DataSource getDataSource() {
+ return getPoolProperties().getDataSource();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSourceJNDI(String jndiDS) {
+ getPoolProperties().setDataSourceJNDI(jndiDS);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDataSourceJNDI() {
+ return getPoolProperties().getDataSourceJNDI();
+ }
+
}
*/
public int getSuspectTimeout();
+ /**
+ * Injects a datasource that will be used to retrieve/create connections.
+ * If a data source is set, the {@link PoolConfiguration#getUrl()} and {@link PoolConfiguration#getDriverClassName()} methods are ignored
+ * and not used by the pool. If the {@link PoolConfiguration#getUsername()} and {@link PoolConfiguration#getPassword()}
+ * values are set, the method {@link javax.sql.DataSource#getConnection(String, String)} method will be called instead of the
+ * {@link javax.sql.DataSource#getConnection()} method.
+ * If the data source implements {@link javax.sql.XADataSource} the methods
+ * {@link javax.sql.XADataSource#getXAConnection()} and {@link javax.sql.XADataSource#getXAConnection(String,String)}
+ * will be invoked.
+ * @param ds the {@link javax.sql.DataSource} to be used for creating connections to be pooled.
+ */
+ public void setDataSource(javax.sql.DataSource ds);
+
+ /**
+ * Returns a datasource, if one exists that is being used to create connections.
+ * This method will return null if the pool is using a {@link java.sql.Driver}
+ * @return the {@link javax.sql.DataSource} to be used for creating connections to be pooled or null if a Driver is used.
+ */
+ public javax.sql.DataSource getDataSource();
+
+ /**
+ * Configure the connection pool to use a DataSource according to {@link PoolConfiguration#setDataSource(javax.sql.DataSource)}
+ * But instead of injecting the object, specify the JNDI location.
+ * After a successful JNDI look, the {@link PoolConfiguration#getDataSource()} will not return null.
+ * @param jndiDS -the JNDI string @TODO specify the rules here.
+ */
+ public void setDataSourceJNDI(String jndiDS);
+
+ /**
+ * Returns the JNDI string configured for data source usage.
+ * @return
+ */
+ public String getDataSourceJNDI();
+
}
\ No newline at end of file
protected int abandonWhenPercentageFull = 0;
protected long maxAge = 0;
protected boolean useLock = false;
- private InterceptorDefinition[] interceptors = null;
+ protected InterceptorDefinition[] interceptors = null;
protected int suspectTimeout = 0;
+ protected javax.sql.DataSource dataSource = null;
+ protected String dataSourceJNDI = null;
/**
this.useLock = useLock;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSource(javax.sql.DataSource ds) {
+ this.dataSource = ds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public javax.sql.DataSource getDataSource() {
+ return dataSource;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSourceJNDI(String jndiDS) {
+ this.dataSourceJNDI = jndiDS;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDataSourceJNDI() {
+ return this.dataSourceJNDI;
+ }
+
public static Properties getProperties(String propText, Properties props) {
if (props==null) props = new Properties();
* The underlying database connection
*/
private volatile java.sql.Connection connection;
+
+ /**
+ * If using a XAConnection underneath.
+ */
+ private volatile javax.sql.XAConnection xaConnection;
/**
* When we track abandon traces, this string holds the thread dump
*/
log.debug("Unable to disconnect previous connection.", x);
} //catch
} //end if
+ if (poolProperties.getDataSource()==null && poolProperties.getDataSourceJNDI()!=null) {
+ //TODO lookup JNDI name
+ }
+
+ if (poolProperties.getDataSource()!=null) {
+ connectUsingDataSource();
+ } else {
+ connectUsingDriver();
+ }
+
+ //set up the default state, unless we expect the interceptor to do it
+ if (poolProperties.getJdbcInterceptors()==null || poolProperties.getJdbcInterceptors().indexOf(ConnectionState.class.getName())<0) {
+ if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
+ if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
+ if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());
+ if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
+ }
+ this.discarded = false;
+ this.lastConnected = System.currentTimeMillis();
+ }
+
+ protected void connectUsingDataSource() throws SQLException {
+ if (poolProperties.getDataSource() instanceof javax.sql.XADataSource) {
+ javax.sql.XADataSource xds = (javax.sql.XADataSource)poolProperties.getDataSource();
+ if (poolProperties.getUsername()!=null && poolProperties.getPassword()!=null) {
+ xaConnection = xds.getXAConnection(poolProperties.getUsername(), poolProperties.getPassword());
+ connection = xaConnection.getConnection();
+ } else {
+ xaConnection = xds.getXAConnection();
+ connection = xaConnection.getConnection();
+ }
+ } else {
+ javax.sql.DataSource ds = poolProperties.getDataSource();
+ if (poolProperties.getUsername()!=null && poolProperties.getPassword()!=null) {
+ connection = ds.getConnection(poolProperties.getUsername(), poolProperties.getPassword());
+ } else {
+ connection = ds.getConnection();
+ }
+ }
+ }
+ protected void connectUsingDriver() throws SQLException {
java.sql.Driver driver = null;
try {
driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(),
if (connection==null) {
throw new SQLException("Driver:"+driver+" returned null for URL:"+driverURL);
}
-
- //set up the default state, unless we expect the interceptor to do it
- if (poolProperties.getJdbcInterceptors()==null || poolProperties.getJdbcInterceptors().indexOf(ConnectionState.class.getName())<0) {
- if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
- if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
- if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());
- if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
- }
- this.discarded = false;
- this.lastConnected = System.currentTimeMillis();
}
/**
}
}
connection = null;
+ xaConnection = null;
lastConnected = -1;
if (finalize) parent.finalize(this);
}
return this.connection;
}
+ /**
+ * Returns the underlying XA connection
+ * @return the underlying XA connection as it was returned from the Datasource
+ */
+ public javax.sql.XAConnection getXAConnection() {
+ return this.xaConnection;
+ }
+
/**
* Returns the timestamp of when the connection was last connected to the database.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
+
+import javax.sql.XAConnection;
/**
* A ProxyConnection object is the bottom most interceptor that wraps an object of type
* {@link PooledConnection}. The ProxyConnection intercepts three methods:
return this.toString();
} else if (compare(GETCONNECTION_VAL,method) && connection!=null) {
return connection.getConnection();
+ } else if (method.getClass().equals(XAConnection.class)) {
+ try {
+ return method.invoke(connection.getXAConnection(),args);
+ }catch (Throwable t) {
+ if (t instanceof InvocationTargetException) {
+ InvocationTargetException it = (InvocationTargetException)t;
+ throw it.getCause()!=null?it.getCause():it;
+ } else {
+ throw t;
+ }
+ }
}
if (isClosed()) throw new SQLException("Connection has already been closed.");
if (compare(UNWRAP_VAL,method)) {
public void setSuspectTimeout(int seconds) {
//no op
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSource(javax.sql.DataSource ds) {
+ getPoolProperties().setDataSource(ds);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public javax.sql.DataSource getDataSource() {
+ return getPoolProperties().getDataSource();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDataSourceJNDI(String jndiDS) {
+ //noop
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDataSourceJNDI() {
+ return getPoolProperties().getDataSourceJNDI();
+ }
}