Package org.apache.ojb.odmg

Source Code of org.apache.ojb.odmg.DatabaseImpl

package org.apache.ojb.odmg;

/* Copyright 2002-2004 The Apache Software Foundation
*
* 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.
*/

import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PBFactoryException;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.PersistenceBrokerFactory;
import org.apache.ojb.broker.util.BrokerHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.odmg.DatabaseClosedException;
import org.odmg.DatabaseNotFoundException;
import org.odmg.DatabaseOpenException;
import org.odmg.ODMGException;
import org.odmg.ObjectNameNotFoundException;
import org.odmg.ObjectNameNotUniqueException;
import org.odmg.Transaction;
import org.odmg.TransactionInProgressException;
import org.odmg.TransactionNotInProgressException;

/**
*
* @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
* @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: DatabaseImpl.java,v 1.26.2.3 2005/03/22 17:08:37 arminw Exp $
*/
public class DatabaseImpl implements org.odmg.Database
{
    private Logger log = LoggerFactory.getLogger(DatabaseImpl.class);

    private PBKey pbKey;
    private boolean isOpen;
    private ImplementationImpl odmg;
    /**
     * the broker instance for persistence operations
     * the named roots map;
     */
    private NamedRootsMap nrm;

    public DatabaseImpl(ImplementationImpl ojb)
    {
        nrm = NamedRootsMap.getInstance();
        isOpen = false;
        this.odmg = ojb;
    }

    private TransactionImpl getTransaction()
    {
        Object result = odmg.currentTransaction();
        // TODO: remove this workaround
        // In managed environments only wrapped tx are returned, so
        // we have to extract the real tx first
        if(result instanceof NarrowTransaction)
        {
            return ((NarrowTransaction) result).getRealTransaction();
        }
        return (TransactionImpl) result;
    }

    /**
     * Return the {@link org.apache.ojb.broker.PBKey} associated with this Database.
     */
    public PBKey getPBKey()
    {
        if (pbKey == null)
        {
            log.error("## PBKey not set, Database isOpen=" + isOpen + " ##");
            if (!isOpen) throw new DatabaseClosedException("Database is not open");
        }
        return pbKey;
    }

    public boolean isOpen()
    {
        return this.isOpen;
    }

    /**
     * Open the named database with the specified access mode.
     * Attempts to open a database when it has already been opened will result in
     * the throwing of the exception <code>DatabaseOpenException</code>.
     * A <code>DatabaseNotFoundException</code> is thrown if the database does not exist.
     * Some implementations may throw additional exceptions that are also derived from
     * <code>ODMGException</code>.
     * @param name The name of the database.
     * @param accessMode The access mode, which should be one of the static fields:
     * <code>OPEN_READ_ONLY</code>, <code>OPEN_READ_WRITE</code>,
     * or <code>OPEN_EXCLUSIVE</code>.
     * @exception ODMGException The database could not be opened.
     */
    public synchronized void open(String name, int accessMode) throws ODMGException
    {
        if (isOpen())
        {
            throw new DatabaseOpenException("Database is already open");
        }
        PersistenceBroker broker = null;
        try
        {
            if (name == null)
            {
                log.info("Given argument was 'null', open default database");
                broker = PersistenceBrokerFactory.defaultPersistenceBroker();
            }
            else
            {
                broker = PersistenceBrokerFactory.createPersistenceBroker(
                        BrokerHelper.extractAllTokens(name));
            }
            pbKey = broker.getPBKey();
            isOpen = true;
            //register opened database
            odmg.registerOpenDatabase(this);
            if (log.isDebugEnabled()) log.debug("Open database using PBKey " + pbKey);
        }
        catch (PBFactoryException ex)
        {
            log.error("Open database failed: " + ex.getMessage(), ex);
            throw new DatabaseNotFoundException(
                    "OJB can't open database " + name + "\n" + ex.getMessage());
        }
        finally
        {
            // broker must be immediately closed
            if (broker != null)
            {
                broker.close();
            }
        }
    }

    /**
     * Close the database.
     * After you have closed a database, further attempts to access objects in the
     * database will cause the exception <code>DatabaseClosedException</code> to be thrown.
     * Some implementations may throw additional exceptions that are also derived
     * from <code>ODMGException</code>.
     * @exception ODMGException Unable to close the database.
     */
    public void close() throws ODMGException
    {
        /**
         * is the DB open? ODMG 3.0 says we can't close an already open database.
         */
        if (!isOpen())
        {
            throw new DatabaseClosedException("Database is not Open. Must have an open DB to call close.");
        }
        /**
         * is the associated Tx open? ODMG 3.0 says we can't close the database with an open Tx pending.
         * check if a tx was found, the tx was associated with database
         */
        if (odmg.hasOpenTransaction() &&
                getTransaction().getAssociatedDatabase().equals(this))
        {
            String msg = "Database cannot be closed, associated Tx is still open." +
                    " Transaction status is '" + TxUtil.getStatusString(getTransaction().getStatus()) + "'." +
                    " Used PBKey was "+getTransaction().getBroker().getPBKey();
            log.error(msg);
            TransactionInProgressException ex = new TransactionInProgressException(msg);
            throw ex;
        }
        isOpen = false;
        // remove the current PBKey
        pbKey = null;
        // if we close current database, we have to notify implementation instance
        if (this == odmg.getCurrentDatabase())
        {
            odmg.setCurrentDatabase(null);
        }
    }

    /**
     * Associate a name with an object and make it persistent.
     * An object instance may be bound to more than one name.
     * Binding a previously transient object to a name makes that object persistent.
     * @param object The object to be named.
     * @param name The name to be given to the object.
     * @exception org.odmg.ObjectNameNotUniqueException
     * If an attempt is made to bind a name to an object and that name is already bound
     * to an object.
     */
    public void bind(Object object, String name)
            throws ObjectNameNotUniqueException
    {
        /**
         * Is DB open? ODMG 3.0 says it has to be to call bind.
         */
        if (!this.isOpen())
        {
            throw new DatabaseClosedException("Database is not open. Must have an open DB to call bind.");
        }
        /**
         * Is Tx open? ODMG 3.0 says it has to be to call bind.
         */
        TransactionImpl tx = getTransaction();
        if (tx == null || !tx.isOpen())
        {
            throw new TransactionNotInProgressException("Tx is not open. Must have an open TX to call bind.");
        }

        Identity identity = new Identity(object, tx.getBroker());
        // mark object as persistent first
        this.makePersistent(object);
        nrm.put(name, identity);

        // to make nrm entries visble during running transactions, transactions maintain
        // a temporary map which contains uncommited nrm bindings.
        tx.putNrmEntry(name, identity);
    }

    /**
     * Lookup an object via its name.
     * @param name The name of an object.
     * @return The object with that name.
     * @exception ObjectNameNotFoundException There is no object with the specified name.
     * ObjectNameNotFoundException
     */
    public Object lookup(String name) throws ObjectNameNotFoundException
    {
        /**
         * Is DB open? ODMG 3.0 says it has to be to call bind.
         */
        if (!this.isOpen())
        {
            throw new DatabaseClosedException("Database is not open. Must have an open DB to call lookup");
        }
        /**
         * Is Tx open? ODMG 3.0 says it has to be to call bind.
         */
        TransactionImpl tx = getTransaction();
        if (tx == null || !tx.isOpen())
        {
            throw new TransactionNotInProgressException("Tx is not open. Must have an open TX to call lookup.");
        }

        Identity oid = nrm.get(name);
        // if not found in persistent table, lookup transaction temporay table
        if (oid == null)
        {
            oid = tx.getNrmEntry(name);
        }
        // if identity could be looked up, materialize respective object.
        if (oid != null)
        {
            try
            {
                Object result = tx.getObjectByIdentity(oid);
                if (result != null)
                {
                    tx.lock(result, Transaction.READ);
                }
                return result;
            }
            catch (PersistenceBrokerException ex)
            {
                throw new ObjectNameNotFoundException(
                        "Error in lookup of: " + name + ", " + ex.getMessage());
            }
        }
        else
        {
            throw new ObjectNameNotFoundException("Name not found: " + name);
        }
    }

    /**
     * Disassociate a name with an object
     * @param name The name of an object.
     * @exception ObjectNameNotFoundException No object exists in the database with that name.
     */
    public void unbind(String name) throws ObjectNameNotFoundException
    {
        /**
         * Is DB open? ODMG 3.0 says it has to be to call unbind.
         */
        if (!this.isOpen())
        {
            throw new DatabaseClosedException("Database is not open. Must have an open DB to call unbind");
        }

        /**
         * Is Tx open? ODMG 3.0 says it has to be to call unbind.
         */
        TransactionImpl tx = getTransaction();
        if (tx == null || !tx.isOpen())
        {
            throw new TransactionNotInProgressException("Tx is not open. Must have an open TX to call unbind.");
        }
        boolean failedPersistent = false;
        boolean failedCurrentTx = false;

        // to make nrm entries visible during running transactions, transactions maintain
        // a temporary map which contains uncommited nrm bindings.
        // first check if name is bound during current tx.
        if (!tx.unbindNrmEntry(name))
        {
            failedCurrentTx = true;
        }

        // try to unbind from persistent storage
        try
        {
            nrm.unbind(name);
        }
        catch (ObjectNameNotFoundException ex)
        {
            failedPersistent = true;
        }

        // if name not found in current tx AND in persistent storage throw an ObjectNameNotFoundException
        if (failedCurrentTx && failedPersistent)
        {
            throw new ObjectNameNotFoundException("don't know about " + name);
        }
    }

    /**
     * Make a transient object durable in the database.
     * It must be executed in the context of an open transaction.
     * If the transaction in which this method is executed commits,
     * then the object is made durable.
     * If the transaction aborts,
     * then the makePersistent operation is considered not to have been executed,
     * and the target object is again transient.
     * ClassNotPersistenceCapableException is thrown if the implementation cannot make
     * the object persistent because of the type of the object.
     * @param  object  The object to make persistent.
     * @throws TransactionNotInProgressException if there is no current transaction.
     */
    public void makePersistent(Object object)
    {
        /**
         * Is DB open? ODMG 3.0 says it has to be to call makePersistent.
         */

        if (!this.isOpen())
        {
            throw new DatabaseClosedException("Database is not open");
        }
        /**
         * Is Tx open? ODMG 3.0 says it has to be to call makePersistent.
         */
        TransactionImpl tx = getTransaction();
        if (tx == null || !tx.isOpen())
        {
            throw new TransactionNotInProgressException("No transaction in progress, cannot persist");
        }

        try
        {
            // if a ClassDescriptor was found, OJB knows how to persist the object
            // lock object for write in tx
            //tx.lock(object, Transaction.WRITE);
            RuntimeObject rt = new RuntimeObject(object, tx);
            tx.lockAndRegister(rt, Transaction.WRITE, false);
            tx.markPersistent(rt);
        }
        catch (org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException ex)
        {
            log.error("Persistence object failed: " + object, ex);
            throw new org.odmg.ClassNotPersistenceCapableException(
                    ex.getMessage());
        }
    }

    /**
     * Deletes an object from the database.
     * It must be executed in the context of an open transaction.
     * If the object is not persistent, then ObjectNotPersistent is thrown.
     * If the transaction in which this method is executed commits,
     * then the object is removed from the database.
     * If the transaction aborts,
     * then the deletePersistent operation is considered not to have been executed,
     * and the target object is again in the database.
     * @param  object  The object to delete.
     */
    public void deletePersistent(Object object)
    {
        if (!this.isOpen())
        {
            throw new DatabaseClosedException("Database is not open");
        }
        TransactionImpl tx = getTransaction();
        if (tx == null || !tx.isOpen())
        {
            throw new TransactionNotInProgressException("No transaction in progress, cannot delete persistent");
        }
        tx.lockAndRegister(new RuntimeObject(object, tx), Transaction.WRITE, false);
        tx.markDelete(object);
    }
}
TOP

Related Classes of org.apache.ojb.odmg.DatabaseImpl

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.