Package org.exolab.castor.jdo.engine

Source Code of org.exolab.castor.jdo.engine.GlobalDatabaseImpl

/*
* Copyright 2005 Werner Guttmann
*
* Licensed 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.exolab.castor.jdo.engine;

import java.sql.Connection;

import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.castor.core.util.Messages;
import org.castor.persist.GlobalTransactionContext;
import org.exolab.castor.jdo.DatabaseNotFoundException;
import org.exolab.castor.jdo.OQLQuery;
import org.exolab.castor.jdo.PersistenceException;
import org.exolab.castor.jdo.TransactionAbortedException;
import org.exolab.castor.jdo.TransactionNotInProgressException;
import org.exolab.castor.persist.spi.CallbackInterceptor;
import org.exolab.castor.persist.spi.InstanceFactory;

/**
* An implementation of the JDO database supporting explicit transaction
* demarcation.
*
* @author <a href="werner DOT guttmann AT gmx DOT net">Werner Guttmann</a>
* @version $Revision: 7951 $ $Date: 2006-04-10 16:39:24 -0600 (Mon, 10 Apr 2006) $
*/
public class GlobalDatabaseImpl extends AbstractDatabaseImpl implements Synchronization {
    /** The <a href="http://jakarta.apache.org/commons/logging/">Jakarta
     *  Commons Logging</a> instance used for all logging. */
    private static Log _log = LogFactory.getFactory().getInstance(GlobalDatabaseImpl.class);

    /** The XA transaction to which this Database instance is attached. */
    private Transaction _transaction;

    /** The transaction to database map for database pooling. */
    private TxDatabaseMap _txMap;
   
    /** Flag to indicate whether Database instances should be cached on a per transaction base. */
    private boolean _isPoolInUseForGlobalTransactions = false;

    /**
     * Creates an instance of this class.
     *
     * @param dbName Database name.
     * @param lockTimeout Lock timeout.
     * @param callback Callback interceptors.
     * @param instanceFactory Instance factory to use.
     * @param transaction Current XA transaction.
     * @param classLoader Current class loader.
     * @param autoStore True if auto-storing is enabled.
     * @param isPoolInUseForGlobalTransactions True if Database instanced should be cached.
     * @throws DatabaseNotFoundException If the specified database cannot be found.
     */
    public GlobalDatabaseImpl(final String dbName, final int lockTimeout,
            final CallbackInterceptor callback, final InstanceFactory instanceFactory,
            final Transaction transaction, final ClassLoader classLoader, final boolean autoStore,
            final boolean isPoolInUseForGlobalTransactions) throws DatabaseNotFoundException {
       
        super (dbName, lockTimeout, callback, instanceFactory, classLoader, autoStore);
       
        _isPoolInUseForGlobalTransactions = isPoolInUseForGlobalTransactions;
        _transaction = transaction;

        try {
            _ctx = new GlobalTransactionContext(this);
            _ctx.setStatus(transaction.getStatus());
        } catch (javax.transaction.SystemException se) {
            throw new DatabaseNotFoundException(se);
        }
       
        _ctx.setLockTimeout(_lockTimeout);
        _ctx.setAutoStore(_autoStore);
        _ctx.setCallback(_callback);
        _ctx.setInstanceFactory(_instanceFactory);
        _classLoader = classLoader;
       
        loadSynchronizables();
    }

    /**
     * @inheritDoc
     * @see org.exolab.castor.jdo.Database#close()
     */
    public synchronized void close() throws PersistenceException {
        try {
            try {
                _ctx.close();
            } catch (Exception e) {
                throw new PersistenceException(e.getMessage(), e);
            }
        } finally {
            _scope = null;
        }
    }

    /**
     * Overrides Object.finalize().
     *
     * Outputs a warning message to the logs if the current DatabaseImpl
     * instance still has valid scope. In this condition - a condition that
     * ideally should not occur at all - we close the instance as well to
     * free up resources.
     *
     * @see java.lang.Object#finalize()
     */
    protected void finalize() throws Throwable {
        if (_scope != null || !isActive()) { return; }
           
        if (!_isPoolInUseForGlobalTransactions) {
            // retrieve SQL bound to this Database instance
            OQLQuery oqlQuery = getOQLQuery();
            String sql = ((OQLQueryImpl) oqlQuery).getSQL();
           
            _log.warn(Messages.format("jdo.finalize_close", this.toString(), _dbName, sql));
        }
       
        close();
    }

    /**
     * @inheritDoc
     */
    public void begin() throws PersistenceException {
        throw new IllegalStateException(Messages.message("jdo.txInJ2EE"));
    }

    /**
     * @inheritDoc
     */
    public void commit() throws TransactionNotInProgressException, TransactionAbortedException {
        throw new IllegalStateException(Messages.message("jdo.txInJ2EE"));
    }

    /**
     * @inheritDoc
     */
    public void rollback() throws TransactionNotInProgressException {
        throw new IllegalStateException(Messages.message("jdo.txInJ2EE"));
    }

    /**
     * @inheritDoc
     */
    public void beforeCompletion() {
        // XXX [SMH]: Find another test for txNotInProgress
        if (_transaction == null || _ctx == null || !_ctx.isOpen()) {
            throw new IllegalStateException(Messages.message("jdo.txNotInProgress"));
        }
        if (_ctx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
            try {
                _transaction.setRollbackOnly();
            } catch (SystemException except) {
                _log.warn(Messages.format("jdo.warnException", except));
            }
            return;
        }
        try {
            _ctx.prepare();
        } catch (TransactionAbortedException tae) {
            _log.error(Messages.format("jdo.txAbortedMarkRollback", tae.getMessage()), tae);       
            try {
                _transaction.setRollbackOnly();
            } catch (SystemException se) {
                _log.fatal(Messages.format("jdo.txMarkRollbackFailure", se.getMessage()), se);
            }
            _ctx.rollback();
        }
    }

    /**
     * @inheritDoc
     * @see javax.transaction.Synchronization#afterCompletion(int)
     */
    public void afterCompletion(final int status) {
        try {
            // XXX [SMH]: Find another test for txNotInProgress
            if (_transaction == null || _ctx == null) {
                throw new IllegalStateException(Messages.message("jdo.txNotInProgress"));
            }
            if (_ctx.getStatus() == Status.STATUS_ROLLEDBACK) {
                return;
            }
            if (_ctx.getStatus() != Status.STATUS_PREPARED && status != Status.STATUS_ROLLEDBACK) {
                throw new IllegalStateException(
                        "Unexpected state: afterCompletion called at status " + _ctx.getStatus());
            }
            switch (status) {
            case Status.STATUS_COMMITTED:
                try {
                    _ctx.commit();
                } catch (TransactionAbortedException except) {
                    _log.fatal(Messages.format("jdo.fatalException", except));
                    _ctx.rollback();
                }
                return;
            case Status.STATUS_ROLLEDBACK:
                _ctx.rollback();
                return;
            default:
                _ctx.rollback();
                throw new IllegalStateException(
                        "Unexpected state: afterCompletion called with status " + status);
            }
        } finally {
            if (_txMap != null && _transaction != null) {
                _txMap.remove(_transaction);
                _txMap = null;
            }
        }
    }

    void setTxMap(final TxDatabaseMap txMap) {
        _txMap = txMap;
    }

    /**
     * @inheritDoc
     */
    public Connection getJdbcConnection() throws PersistenceException {
        return _ctx.getConnection(_scope.getLockEngine());
    }
                               
TOP

Related Classes of org.exolab.castor.jdo.engine.GlobalDatabaseImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.