Package org.exolab.castor.jdo.engine

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

/*
* 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 java.util.ArrayList;
import java.util.Iterator;

import org.castor.core.util.AbstractProperties;
import org.castor.core.util.Messages;
import org.castor.cpa.CPAProperties;
import org.castor.jdo.engine.AbstractConnectionFactory;
import org.castor.jdo.engine.DatabaseRegistry;
import org.castor.persist.ProposedEntity;
import org.castor.persist.TransactionContext;
import org.exolab.castor.jdo.CacheManager;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.DatabaseNotFoundException;
import org.exolab.castor.jdo.OQLQuery;
import org.exolab.castor.jdo.PersistenceException;
import org.exolab.castor.jdo.Query;
import org.exolab.castor.jdo.TransactionAbortedException;
import org.exolab.castor.jdo.TransactionNotInProgressException;
import org.exolab.castor.mapping.AccessMode;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.persist.ClassMolder;
import org.exolab.castor.persist.LockEngine;
import org.exolab.castor.persist.PersistenceInfoGroup;
import org.exolab.castor.persist.TxSynchronizable;
import org.exolab.castor.persist.spi.CallbackInterceptor;
import org.exolab.castor.persist.spi.Identity;
import org.exolab.castor.persist.spi.InstanceFactory;

/**
* An implementation of the JDO database supporting explicit transaction
* demarcation.
*
* @author <a href="arkin@intalio.com">Assaf Arkin</a>
* @author <a href="mailto:ferret AT frii dot com">Bruce Snyder</a>
* @version $Revision: 8034 $ $Date: 2006-04-22 11:05:30 -0600 (Sat, 22 Apr 2006) $
*/
public abstract class AbstractDatabaseImpl implements Database {
    /** The database engine used to access the underlying SQL database. */
    protected PersistenceInfoGroup _scope;

    /** The transaction context is this database was accessed with an
     *  {@link javax.transaction.xa.XAResource}. */
    protected TransactionContext _ctx;

    /** List of TxSynchronizeable implementations that should all be
     *  informed about changes after commit of transactions. */
    private ArrayList < TxSynchronizable > _synchronizables;

    /** The lock timeout for this database. Zero for immediate timeout,
     *  an infinite value for no timeout. The timeout is specified in
     *  seconds. */
    protected int _lockTimeout;

    /** The default callback interceptor for transaction. */
    protected CallbackInterceptor _callback;

    /** The instance factory to that creates new instances of data object. */
    protected InstanceFactory _instanceFactory;

    /** The name of this database. */
    protected String _dbName;

    /** True if user prefer all reachable object to be stored automatically. False if user
     *  want only dependent object to be stored. */
    protected boolean _autoStore;

    /** The class loader for application classes (may be null). */
    protected ClassLoader _classLoader;

    /** CacheManager instance. */
    private CacheManager _cacheManager;

    /**
     * Creates an instance of this class.
     *
     * @param dbName Name of the database.
     * @param lockTimeout Lock timeout to use.
     * @param callback Callback interceptors.
     * @param instanceFactory Instance factory.
     * @param classLoader Current class loader.
     * @param autoStore True if auto storing is enabled.
     * @throws DatabaseNotFoundException If there's no database configuration for the given name.
     */
    public AbstractDatabaseImpl(final String dbName,
            final int lockTimeout,
            final CallbackInterceptor callback,
            final InstanceFactory instanceFactory,
            final ClassLoader classLoader,
            final boolean autoStore)
    throws DatabaseNotFoundException {
       
        _autoStore = autoStore;
       
        // Locate a suitable ConnectionFactory and LockEngine
        // and report if not mapping registered any of the two.
        // A new ODMG engine is created each time with different
        // locking mode.
        AbstractConnectionFactory factory = null;
        try {
            factory = DatabaseRegistry.getConnectionFactory(dbName);
        } catch (MappingException ex) {
            throw new DatabaseNotFoundException(Messages.format("jdo.dbNoMapping", dbName));
        }
        _scope = new PersistenceInfoGroup(new LockEngine[] {factory.getEngine()});
       
        _callback = callback;
        _instanceFactory = instanceFactory;
        _dbName = dbName;
        _lockTimeout = lockTimeout;
        _classLoader = classLoader;
       
        loadSynchronizables();
    }

    /**
     * Returns the {@link LockEngine} in use by this database instance.
     * 
     * @return the {@link LockEngine} in use by this database instance.
     */
    LockEngine getLockEngine() {
        return _scope.getLockEngine();
    }

    /**
     * @inheritDoc
     */
    public PersistenceInfoGroup getScope() {
        return _scope;
    }

    /**
     * Indicates whether user prefer all reachable object to be stored automatically;
     * false if user wants dependent object only to be stored.
     *
     * @param autoStore True to indicate that 'autoStore' mode should be used.
     */
    public void setAutoStore(final boolean autoStore) {
        _autoStore = autoStore;
    }

    /**
     * Return if the current transaction is set to autoStore, it there is
     * transaction active. If there is no active transaction, return if
     * the next transaction will be set to autoStore.
     *
     * @return True if 'auto-store' mode is in use.
     */
    public boolean isAutoStore() {
        if (_ctx != null) {
            return _ctx.isAutoStore();
        }

        return _autoStore;
    }

    /**
     * Gets the current application ClassLoader's instance.
     *
     * @return the current ClassLoader's instance, or <code>null</code> if not provided
     */
    public ClassLoader getClassLoader() {
        return _classLoader;
    }

    /**                             
     * Return the name of the database.
     *
     * @return Name of the database.
     */                              
    public String getDatabaseName() {                               
        return _dbName;                 
    }

    /**
     * {@inheritDoc}
     */
    public abstract void close()
        throws PersistenceException;

    /**
     * {@inheritDoc}
     */
    public boolean isClosed() {
        return (_scope == null);
    }
   
    /**
     * {@inheritDoc}
     */
    public boolean isLocked(final Class cls, final Object identity) throws PersistenceException {
        if (identity == null) {
            throw new PersistenceException("Identities can't be null!");
        }
        if (_scope == null) {
            throw new PersistenceException(Messages.message("jdo.dbClosed"));
        }
        if (isActive()) {
            return _ctx.isLocked(cls, new Identity(identity), _scope.getLockEngine());
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Object load(final Class type, final Object identity) throws PersistenceException {
        return load(type, identity, null, null);
    }

    /**
     * {@inheritDoc}
     */
    public Object load(final Class type, final Object identity, final Object object)
    throws PersistenceException {
        return load(type, identity, object, null);
    }
   
    /**
     * {@inheritDoc}
     */
    public Object load(final Class type, final Object identity, final AccessMode mode)
    throws PersistenceException {
        return load(type, identity, null, mode);
    }

    /**
     * Loads on object instance of the specified type and its identity.
     *
     * @param type Object type.
     * @param identity Object identity
     * @param object Object instance to be filled with loaded values (optional)
     * @param mode Access mode to use during load.
     * @return An object instance matching the specified criteria.
     * @throws PersistenceException If the object identified by the parameter can not be found.
     *         If the required access mode cannot be granted. If there's no active transaction
     *         in progress.
     */
    private Object load(final Class type, final Object identity, final Object object,
            final AccessMode mode) throws PersistenceException {
        if (identity == null) {
            throw new PersistenceException("Identities can't be null!");
        }
        if (_scope == null) {
            throw new PersistenceException(Messages.message("jdo.dbClosed"));
        }
        TransactionContext tx = getTransaction();
        ClassMolder molder = _scope.getClassMolder(type);
        ProposedEntity proposedObject = new ProposedEntity(molder);
        return tx.load(new Identity(identity), proposedObject, mode);
    }

    /**
     * {@inheritDoc}
     */
    public void create(final Object object) throws PersistenceException {
        TransactionContext tx = getTransaction();
        ClassMolder molder = _scope.getClassMolder(object.getClass());
        tx.create(molder, object, null);
    }
   
    /**
     * {@inheritDoc}
     */
    public CacheManager getCacheManager() {
        if (_cacheManager == null) {
            _cacheManager = new CacheManager(this, _ctx, getLockEngine());
        }
        return _cacheManager;
    }

    /**
     * {@inheritDoc}
     */
    public void update(final Object object) throws PersistenceException {
       
        TransactionContext tx = getTransaction();
        ClassMolder molder = _scope.getClassMolder(object.getClass());
        tx.update(molder, object, null);
    }

    /**
     * {@inheritDoc}
     */
    public void remove(final Object object) throws PersistenceException {
       
        TransactionContext tx = getTransaction();
        _scope.getClassMolder(object.getClass());
        tx.delete(object);
    }

    /**
     * {@inheritDoc}
     */
    public boolean isPersistent(final Object object) {
        if (_scope == null) {
            throw new IllegalStateException(Messages.message("jdo.dbClosed"));
        }
        if (isActive()) {
            return _ctx.isPersistent(object);
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public Identity getIdentity(final Object object) throws PersistenceException {
        if (_scope == null) {
            throw new PersistenceException(Messages.message("jdo.dbClosed"));
        }

        ClassMolder molder = _scope.getClassMolder(object.getClass());
        return molder.getActualIdentity(_classLoader, object);
    }


    /**
     * {@inheritDoc}
     */
    public void lock(final Object object) throws PersistenceException {
        if (!isActive()) {
            throw new TransactionNotInProgressException(Messages.message("jdo.txNotInProgress"));
        }
        _ctx.writeLock(object, _lockTimeout);
    }

    /**
     * {@inheritDoc}
     */
    public OQLQuery getOQLQuery() {
        return new OQLQueryImpl(this);
    }

    /**
     * {@inheritDoc}
     */
    public OQLQuery getNamedQuery(final String name) throws PersistenceException {
        String oql = _ctx.getNamedQuery(_scope.findClassMolderByQuery(name), name);
        return getOQLQuery(oql);
    }


    /**
     * {@inheritDoc}
     */
    public OQLQuery getOQLQuery(final String oql) throws PersistenceException {
        OQLQuery oqlImpl;

        oqlImpl = new OQLQueryImpl(this);
        oqlImpl.create(oql);
        return oqlImpl;
    }
   
    /**
     * {@inheritDoc}
     */
    public Query getQuery() {
        return new OQLQueryImpl(this);
    }

    /**
     * Returns the currently active transaction, if any.
     *
     * @return The current active transaction.
     * @throws TransactionNotInProgressException If there's no active transaction.
     */
    protected TransactionContext getTransaction() throws TransactionNotInProgressException {
        if (_scope == null) {
            throw new TransactionNotInProgressException(Messages.message("jdo.dbClosed"));
        }
        if (isActive()) {
            return _ctx;
        }
        throw new TransactionNotInProgressException(Messages.message("jdo.dbTxNotInProgress"));
    }

    /**
     * {@inheritDoc}
     */
    public abstract void begin() throws PersistenceException;

    /**
     * {@inheritDoc}
     */
    public abstract void commit()
        throws TransactionNotInProgressException, TransactionAbortedException;

    /**
     * {@inheritDoc}
     */
    public abstract void rollback()
        throws TransactionNotInProgressException;

    /**
     * {@inheritDoc}
     */
    public boolean isActive() {
        return (_ctx != null && _ctx.isOpen());
    }

    /**
     * {@inheritDoc}
     */
    public String toString() {
        return super.toString() + ":" + _dbName;
    }

    /**
     * {@inheritDoc}
     */
    public abstract Connection getJdbcConnection() throws PersistenceException;

    /**
     * Load the {@link TxSynchronizable} implementations from the
     * properties file, if not loaded before.
     */
    protected void loadSynchronizables() {
        if (_synchronizables == null) {
            _synchronizables = new ArrayList < TxSynchronizable > ();
           
            AbstractProperties properties = CPAProperties.getInstance();
            Object[] objects = properties.getObjectArray(
                    CPAProperties.TX_SYNCHRONIZABLE, properties.getApplicationClassLoader());
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    TxSynchronizable sync = (TxSynchronizable) objects[i];
                    _synchronizables.add(sync);
                }
            }
           
            if (_synchronizables.size() == 0) { _synchronizables = null; }
        }
    }
   
    /**
     * Register the {@link TxSynchronizable} implementations at the
     * TransactionContect at end of begin().
     */
    protected void registerSynchronizables() {
        if (_synchronizables != null && _synchronizables.size() > 0) {
            Iterator < TxSynchronizable > iter = _synchronizables.iterator();
            while (iter.hasNext()) {
                _ctx.addTxSynchronizable(iter.next());
            }
        }
    }
   
    /**
     * Unregister the {@link TxSynchronizable} implementations at the
     * TransactionContect after commit() or rollback().
     */
    protected void unregisterSynchronizables() {
        if (_synchronizables != null  && _synchronizables.size() > 0) {
            Iterator < TxSynchronizable > iter = _synchronizables.iterator();
            while (iter.hasNext()) {
                _ctx.removeTxSynchronizable(iter.next());
            }
        }
    }
   
       
    /**
     * Gets the current Castor transaction in use.
     *
     * @return the current Castor
     * @throws TransactionNotInProgressException If there's no transaction in progress.
     */
    public TransactionContext getCurrentTransaction()
    throws TransactionNotInProgressException  {
        return getTransaction();
    }
                              
TOP

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

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.