com.arjuna.ats.internal.jdbc.recovery.JDBCXARecovery Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
/*
* Copyright (C) 2004, 2005,
*
* Arjuna Technologies Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id$
*/
package com.arjuna.ats.internal.jdbc.recovery;
import java.sql.SQLException;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.XAResource;
import com.arjuna.ats.jdbc.logging.jdbcLogger;
import com.arjuna.ats.jta.recovery.XAResourceRecovery;
import com.arjuna.common.util.propertyservice.PropertiesFactory;
/**
* This provides recovery for compliant JDBC drivers. It is not meant to be
* implementation specific.
*
* Users are responsible for deploying an appropriate XADataSource into JNDI and
* then providing the relevant JNDI lookup information in a property file to an
* instance of this class. Username and password values may also be provided in
* the same property file.
*/
public class JDBCXARecovery implements XAResourceRecovery
{
public static final String DATABASE_JNDI_NAME = "DatabaseJNDIName";
public static final String USER_NAME = "UserName";
public static final String PASSWORD = "Password";
/*
* Some XAResourceRecovery implementations will do their startup work here,
* and then do little or nothing in setDetails. Since this one needs to know
* dynamic class name, the constructor does nothing.
*/
public JDBCXARecovery()
throws SQLException
{
if (jdbcLogger.logger.isDebugEnabled())
jdbcLogger.logger.debug("JDBCXARecovery()");
_props = null;
_hasMoreResources = false;
_connectionEventListener = new LocalConnectionEventListener();
}
/**
* The recovery module will have chopped off this class name already. The
* parameter should specify a property file from which the jndi name, user name,
* password can be read.
*/
public boolean initialise(String parameter)
throws SQLException
{
if (jdbcLogger.logger.isDebugEnabled())
jdbcLogger.logger.debug("JDBCXARecovery.initialise(" + parameter + ")");
if (parameter == null)
return false;
try
{
_props = PropertiesFactory.getPropertiesFromFile(parameter, JDBCXARecovery.class.getClassLoader());
_dbName = _props.getProperty(DATABASE_JNDI_NAME);
_user = _props.getProperty(USER_NAME);
_password = _props.getProperty(PASSWORD);
}
catch (Exception e)
{
jdbcLogger.i18NLogger.warn_recovery_xa_initexp(e);
return false;
}
return true;
}
public synchronized XAResource getXAResource()
throws SQLException
{
createConnection();
return _connection.getXAResource();
}
public boolean hasMoreResources()
{
if (_dataSource == null)
try
{
createDataSource();
}
catch (SQLException sqlException)
{
return false;
}
if (_dataSource != null)
{
_hasMoreResources = ! _hasMoreResources;
return _hasMoreResources;
}
else
return false;
}
/**
* Lookup the XADataSource in JNDI. We got the relevant information from the
* property file provided at input to this instance.
*/
private final void createDataSource()
throws SQLException
{
try
{
if (_dataSource == null)
{
Context context = new InitialContext();
_dataSource = (XADataSource) context.lookup(_dbName);
if (_dataSource == null)
throw new SQLException(jdbcLogger.i18NLogger.get_xa_recjndierror());
}
}
catch (SQLException ex)
{
ex.printStackTrace();
throw ex;
}
catch (Exception e)
{
e.printStackTrace();
SQLException sqlException = new SQLException(e.toString());
sqlException.initCause(e);
throw sqlException;
}
}
/**
* Create the XAConnection from the XADataSource.
*/
private final void createConnection()
throws SQLException
{
try
{
if (_dataSource == null)
createDataSource();
if (_connection == null)
{
if ((_user == null) && (_password == null))
_connection = _dataSource.getXAConnection();
else
_connection = _dataSource.getXAConnection(_user, _password);
_connection.addConnectionEventListener(_connectionEventListener);
}
}
catch (SQLException ex)
{
ex.printStackTrace();
throw ex;
}
catch (Exception e)
{
e.printStackTrace();
SQLException sqlException = new SQLException(e.toString());
sqlException.initCause(e);
throw sqlException;
}
}
private class LocalConnectionEventListener implements ConnectionEventListener
{
public void connectionErrorOccurred(ConnectionEvent connectionEvent)
{
_connection.removeConnectionEventListener(_connectionEventListener);
_connection = null;
}
public void connectionClosed(ConnectionEvent connectionEvent)
{
_connection.removeConnectionEventListener(_connectionEventListener);
_connection = null;
}
}
private XAConnection _connection;
private XADataSource _dataSource;
private LocalConnectionEventListener _connectionEventListener;
private Properties _props;
private String _dbName;
private String _user;
private String _password;
private boolean _hasMoreResources;
}