All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.firebirdsql.ds.FBXADataSource Maven / Gradle / Ivy

There is a newer version: 4.0.10.java7
Show newest version
/*
 * Firebird Open Source JavaEE Connector - JDBC Driver
 *
 * Distributable under LGPL license.
 * You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * LGPL License for more details.
 *
 * This file was created by members of the firebird development team.
 * All individual contributions remain the Copyright (C) of those
 * individuals.  Contributors to this file are either listed here or
 * can be obtained from a source control history command.
 *
 * All rights reserved.
 */
package org.firebirdsql.ds;

import java.io.PrintWriter;
import java.sql.SQLException;

import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ConnectionEventListener;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.ManagedConnectionFactory;
import javax.sql.XAConnection;
import javax.sql.XADataSource;

import org.firebirdsql.gds.impl.GDSFactory;
import org.firebirdsql.gds.impl.GDSType;
import org.firebirdsql.jca.FBManagedConnection;
import org.firebirdsql.jca.FBManagedConnectionFactory;
import org.firebirdsql.jdbc.FBConnection;
import org.firebirdsql.jdbc.FBDataSource;
import org.firebirdsql.jdbc.FBSQLException;

/**
 * Bare-bones implementation of {@link javax.sql.XADataSource}.
 * 
 * @author Mark Rotteveel
 * @since 2.2
 */
public class FBXADataSource extends FBAbstractCommonDataSource implements XADataSource, Referenceable {

    private volatile transient FBDataSource internalDs;

    public XAConnection getXAConnection() throws SQLException {
        return getXAConnection(getUser(), getPassword());
    }

    public XAConnection getXAConnection(String user, String password) throws SQLException {
        if (internalDs == null) {
            initialize();
        }
        FBConnection connection = (FBConnection) internalDs.getConnection(user,
                password);
        return new FBXAConnection(connection);
    }

    private void initialize() throws SQLException {
        synchronized (lock) {
            if (internalDs != null) {
                return;
            }
            try {
                GDSType gdsType = GDSType.getType(getType());
                if (gdsType == null) {
                    gdsType = GDSFactory.getDefaultGDSType();
                }
                FBManagedConnectionFactory mcf = new FBManagedConnectionFactory(gdsType,
                        getConnectionProperties());
                mcf.setDefaultConnectionManager(new XAConnectionManager());
                internalDs = (FBDataSource) mcf.createConnectionFactory();
                internalDs.setLogWriter(getLogWriter());
            } catch (ResourceException e) {
                throw new FBSQLException(e);
            }
        }
    }

    protected void checkNotStarted() throws IllegalStateException {
        if (internalDs != null) {
            throw new IllegalStateException("DataSource already in use. Change of this property is not allowed");
        }
    }

    private static class XAConnectionManager implements ConnectionManager, ConnectionEventListener {

        private static final long serialVersionUID = 2615167799315401379L;

        public Object allocateConnection(ManagedConnectionFactory mcf,
                ConnectionRequestInfo cxRequestInfo) throws ResourceException {

            FBManagedConnection mc = (FBManagedConnection) mcf.createManagedConnection(null, cxRequestInfo);
            mc.setManagedEnvironment(true);
            mc.setConnectionSharing(false);
            mc.addConnectionEventListener(this);
            return mc.getConnection(null, cxRequestInfo);
        }

        // javax.resource.spi.ConnectionEventListener implementation

        /**
         * javax.resource.spi.ConnectionEventListener callback for
         * when a ManagedConnection is closed.
         * 
         * @param ce
         *            contains information about the connection that has be
         *            closed
         */
        public void connectionClosed(ConnectionEvent ce) {
            PrintWriter externalLog = ((FBManagedConnection) ce.getSource()).getLogWriter();
            try {
                ((FBManagedConnection) ce.getSource()).destroy();
            } catch (ResourceException e) {
                if (externalLog != null)
                    externalLog.println("Exception closing unmanaged connection: " + e);
            }
        }

        /**
         * javax.resource.spi.ConnectionEventListener callback for
         * when a Local Transaction was rolled back within the context of a
         * ManagedConnection.
         * 
         * @param ce
         *            contains information about the connection
         */
        public void connectionErrorOccurred(ConnectionEvent ce) {
            PrintWriter externalLog = ((FBManagedConnection) ce.getSource()).getLogWriter();
            try {
                ((FBManagedConnection) ce.getSource()).destroy();
            } catch (ResourceException e) {
                if (externalLog != null)
                    externalLog.println("Exception closing unmanaged connection: " + e);
            }
        }

        // We are only supposed to be notified of local transactions that a
        // Connection started.
        // Not much we can do with this info...

        /**
         * Ignored event callback
         */
        public void localTransactionStarted(ConnectionEvent event) {
        }

        /**
         * Ignored event callback
         */
        public void localTransactionCommitted(ConnectionEvent event) {
        }

        /**
         * Ignored event callback
         */
        public void localTransactionRolledback(ConnectionEvent event) {
        }
    }

    public Reference getReference() throws NamingException {
        Reference ref = new Reference(getClass().getName(), DataSourceFactory.class.getName(), null);

        FBAbstractCommonDataSource.updateReference(ref, this);

        return ref;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy