XADataSource.java
/*
* 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.jdbc.pool;
import java.sql.SQLException;
import javax.sql.XAConnection;
import org.apache.tomcat.jdbc.pool.util.MessageFactory;
/**
* XA-enabled data source for distributed transaction support.
* <p>
* Note that XA support is not provided by this class itself: XA connections are obtained from the data source
* configured through the {@code dataSource} or {@code dataSourceJNDI} attribute, which must implement
* {@link javax.sql.XADataSource} (see {@link PoolConfiguration#setDataSource(Object)}). A pool configured with only
* {@code driverClassName} and {@code url} pools plain JDBC connections; a request for an XA connection from such a pool
* fails with an explicit message naming the missing configuration rather than later, inside the transaction manager.
*/
public class XADataSource extends DataSource implements javax.sql.XADataSource {
/**
* Constructor for reflection only. A default set of pool properties will be created.
*/
public XADataSource() {
super();
}
/**
* Constructs a DataSource object wrapping a connection
*
* @param poolProperties The pool configuration
*/
public XADataSource(PoolConfiguration poolProperties) {
super(poolProperties);
}
/**
* {@inheritDoc}
* <p>
* This implementation first checks that the pool can provide XA connections at all, and fails with an explicit
* configuration hint when it cannot.
*/
@Override
public XAConnection getXAConnection() throws SQLException {
requireXABacking();
return super.getXAConnection();
}
/**
* {@inheritDoc}
* <p>
* This implementation first checks that the pool can provide XA connections at all, and fails with an explicit
* configuration hint when it cannot.
*
* @param username The user name
* @param password The password
*/
@Override
public XAConnection getXAConnection(String username, String password) throws SQLException {
requireXABacking();
return super.getXAConnection(username, password);
}
/**
* Verifies that the pool is backed by an XA data source, matching the condition under which
* {@link PooledConnection} creates XA connections.
*
* @throws SQLException if the pool cannot hold XA connections, with a message naming the configuration that is
* missing
*/
private void requireXABacking() throws SQLException {
Object ds = getPoolProperties().getDataSource();
if (ds instanceof javax.sql.XADataSource) {
return;
}
if (ds == null) {
// A configured JNDI name only reaches the pool as a data source
// through the DataSourceFactory, which fails pool creation when
// the name cannot be resolved; a name set on a programmatically
// configured pool therefore never becomes a data source at all.
String jndiName = getPoolProperties().getDataSourceJNDI();
if (jndiName != null) {
throw new SQLException(MessageFactory.get("xaDataSource.jndiNotResolved", getName(), jndiName));
}
throw new SQLException(MessageFactory.get("xaDataSource.noDataSource", getName()));
}
throw new SQLException(MessageFactory.get("xaDataSource.dataSourceNotXA", getName(),
ds.getClass().getName()));
}
}