Package org.apache.slide.store.impl.rdbms

Source Code of org.apache.slide.store.impl.rdbms.AbstractRDBMSStore$TransactionId

/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/AbstractRDBMSStore.java,v 1.2.2.1 2004/02/05 16:07:52 mholz Exp $
* $Revision: 1.2.2.1 $
* $Date: 2004/02/05 16:07:52 $
*
* ====================================================================
*
* Copyright 1999-2003 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.
*
*/

package org.apache.slide.store.impl.rdbms;

import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import org.apache.slide.common.AbstractXAService;
import org.apache.slide.common.Service;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.ServiceConnectionFailedException;
import org.apache.slide.common.ServiceDisconnectionFailedException;
import org.apache.slide.common.ServiceInitializationFailedException;
import org.apache.slide.common.ServiceParameterErrorException;
import org.apache.slide.common.ServiceParameterMissingException;
import org.apache.slide.common.ServiceResetFailedException;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionAlreadyExistException;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.lock.LockTokenNotFoundException;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.security.NodePermission;
import org.apache.slide.store.ContentStore;
import org.apache.slide.store.LockStore;
import org.apache.slide.store.NodeStore;
import org.apache.slide.store.RevisionDescriptorStore;
import org.apache.slide.store.RevisionDescriptorsStore;
import org.apache.slide.store.SecurityStore;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.util.logger.Logger;

/**
* J2EE store implementation - implements the shared parts of
* the two (content, descriptors) J2EE stores for the new Indexed DB Schema.
*
* @author <a href="mailto:msmith@apache.org">Michael Smith</a>
* @author <a href="mailto:akumar@metatomix.com">Ashok Kumar</a>
* @author <a href="mailto:cmlenz@apache.org">Christopher Lenz</a>
* @author <a href="mailto:ozeigermann@c1-fse.de">Oliver Zeigermann</a>
* @version $Revision: 1.2.2.1 $
*/
public abstract class AbstractRDBMSStore
    extends AbstractXAService
    implements LockStore, NodeStore, RevisionDescriptorsStore, RevisionDescriptorStore, SecurityStore, ContentStore {

    protected String LOG_CHANNEL = this.getClass().getName();

    protected static final int TX_IDLE = 0;

    protected static final int TX_PREPARED = 1;

    protected static final int TX_SUSPENDED = 2;

    protected ThreadLocal activeTransactionContext = new ThreadLocal();

    protected RDBMSAdapter adapter;

    protected boolean alreadyInitialized = false;

    /**
     * Indicates whether the transaction manager will commit / rollback
     * the transaction or the store is in charge of it. Slide's internal
     * TM does not commit / rollback, but TMs more aligned to the spec (e.g. JBoss' TM) do.
     */
    protected boolean tmCommits = false;

    /**
     * Initializes the data source with a set of parameters.
     *
     * @param parameters Hashtable containing the parameters' name
     *                   and associated value
     * @exception ServiceParameterErrorException   Incorrect service parameter
     * @exception ServiceParameterMissingException Service parameter missing
     */
    public void setParameters(Hashtable parameters)
        throws ServiceParameterErrorException, ServiceParameterMissingException {

        // Adapter class
        String value = (String) parameters.get("adapter");
        if (value == null) {
            adapter = new StandardRDBMSAdapter(this, getLogger());
        } else {
            try {
                Class adapterClass = Class.forName(value);
                Constructor ctor = adapterClass.getConstructor(new Class[] { Service.class, Logger.class });
                adapter = (RDBMSAdapter) ctor.newInstance(new Object[] { this, getLogger()});
            } catch (Exception e) {
                // reflection exception
                getLogger().log(
                    "Error instantiating Adapter '" + value + "' (" + e.getMessage() + ")",
                    LOG_CHANNEL,
                    Logger.ERROR);
            }
        }

        if (adapter != null) {
            adapter.setParameters(parameters);
        }

        // XXX need to initialize it here, as some security requests access the store before initialization
        try {
            initialize(null);
        } catch (ServiceInitializationFailedException e) {
            // XXX this is not very satisfactory...
            throw new ServiceParameterErrorException(this, e.getMessage());
        }
    }

    /**
     * Establishes the global connection to the data source.
     *
     * @exception ServiceConnectionFailedException if the connection failed
     */
    public synchronized void connect() throws ServiceConnectionFailedException {
    }

    /**
     * Returns connection status.
     */
    public boolean isConnected() {
        return true;
    }

    /**
     * Closes the global connection to the data source.
     *
     * @exception ServiceDisconnectionFailedException if closing the connection
     *            failed
     */
    public void disconnect() throws ServiceDisconnectionFailedException {
    }

    /**
     * Does nothing.
     *
     * @exception ServiceResetFailedException Reset failed
     */
    public synchronized void reset() throws ServiceResetFailedException {

    }

    // ----------------------------------------------------- XAResource Methods

    /**
     * Get the transaction timeout value for this XAResource.
     * Just returns 0, we don't have a way of doing transaction timeouts
     * with the connection.
     */
    public int getTransactionTimeout() throws XAException {
        return 0;
    }

    /**
     * Set transaction timeout, not implemented (returns false).
     */
    public boolean setTransactionTimeout(int timeout) throws XAException {
        return false;
    }

    public Xid[] recover(int flag) throws XAException {

        getLogger().log("recover() for thread: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        TransactionId id = getActiveTransactionContext();

        if (id != null && id.status == TX_PREPARED) {
            Xid[] xids = new Xid[1];
            xids[0] = id.xid;
            return xids;
        } else
            return new Xid[0];
    }

    public int prepare(Xid xid) throws XAException {

        getLogger().log("prepare() for thread: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        TransactionId id = getActiveTransactionContext();

        if (id == null)
            throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);

        if (id.status != TX_IDLE && id.status != TX_SUSPENDED)
            throw new XAException(XAException.XAER_PROTO);

        if (id.rollbackOnly)
            throw new XAException(XAException.XA_RBROLLBACK);

        id.status = TX_PREPARED;

        return XAResource.XA_OK;
    }

    public boolean isSameRM(XAResource xares) throws XAException {
        if (xares == null)
            return false;
        else
            return this == xares;
    }

    public void forget(Xid xid) throws XAException {

        getLogger().log("forget() for thread: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        TransactionId id = getActiveTransactionContext();

        if (id == null || id.xid == null)
            throw new XAException(XAException.XAER_NOTA);

        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);

        try {
            id.connection.close();
        } catch (SQLException e) {
            getLogger().log("Couldn't close connection.", LOG_CHANNEL, Logger.ERROR);
        }
        getLogger().log("forget(): removing from map: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        activeTransactionContext.set(null);
    }

    public void end(Xid xid, int flags) throws XAException {

        getLogger().log("end() for thread: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        TransactionId id = getActiveTransactionContext();
        if (id == null || id.xid == null)
            throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);

        if (flags == XAResource.TMSUSPEND)
            id.status = TX_SUSPENDED;

        if (flags == XAResource.TMFAIL)
            id.rollbackOnly = true;

    }

    /**
     * Commit the global transaction specified by xid.
     */
    public void commit(Xid xid, boolean onePhase) throws XAException {

        getLogger().log(
            "commit() for thread " + Thread.currentThread() + ", removing from map",
            LOG_CHANNEL,
            Logger.DEBUG);

        TransactionId id = getActiveTransactionContext();
        if (id == null) {
            getLogger().log(
                "Error committing: no transaction associated with current thread",
                LOG_CHANNEL,
                Logger.ERROR);
            throw new XAException(XAException.XAER_NOTA);
        }
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);

        if (!onePhase && id.status != TX_PREPARED)
            throw new XAException(XAException.XAER_PROTO);
        if (onePhase && (!(id.status == TX_IDLE || id.status == TX_SUSPENDED)))
            throw new XAException(XAException.XAER_PROTO);

        Connection conn = id.connection;

        if (conn == null) {
            getLogger().log(
                "commit(): No connection in connectionMap for id \"" + id + "\"",
                LOG_CHANNEL,
                Logger.ERROR);
            throw new XAException(XAException.XAER_NOTA);
        }

        try {
            if (!tmCommits) {
                if (id.rollbackOnly) {

                    conn.rollback();
                } else {
                    conn.commit();
                }
            }
            activeTransactionContext.set(null);
        } catch (Exception e) {
            throw new XAException(XAException.XA_RBCOMMFAIL);
        } finally {
            try {
                conn.close();
                /* We must always return connections to the pool,
                                                or we'd eventually run out. */
            } catch (SQLException e) {
                getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
            }
        }
    }

    /**
     * Inform the resource manager to roll back work done on behalf of a
     * transaction branch.
     */
    public void rollback(Xid xid) throws XAException {

        getLogger().log(
            "rollback() for thread " + Thread.currentThread() + ", removing from map",
            LOG_CHANNEL,
            Logger.DEBUG);

        TransactionId id = getActiveTransactionContext();
        if (id == null) {
            getLogger().log("No transaction associated with current thread, can't rollback", LOG_CHANNEL, Logger.ERROR);
            throw new XAException(XAException.XAER_NOTA);
        }

        Connection conn = id.connection;
        if (conn == null) {
            getLogger().log(
                "rollback(): No connection in connectionMap for id \"" + id + "\"",
                LOG_CHANNEL,
                Logger.ERROR);
            throw new XAException(XAException.XAER_NOTA);
        }

        try {
            if (!tmCommits) {
                conn.rollback();
            }
            activeTransactionContext.set(null);
           
        } catch (Exception e) {
            throw new XAException(XAException.XA_HEURCOM);
        } finally {
            try {
                conn.close();
                /* We must always return connections to the pool,
                                                or we'd eventually run out. */
            } catch (SQLException e) {
                getLogger().log(e, LOG_CHANNEL, Logger.ERROR);
            }
        }
    }

    /**
     * Start work on behalf of a transaction branch specified in xid.
     */
    public void start(Xid xid, int flags) throws XAException {
        getLogger().log("start(): beginning transaction with xid " + xid, LOG_CHANNEL, Logger.DEBUG);

        TransactionId id = getActiveTransactionContext();

        switch (flags) {
            case XAResource.TMNOFLAGS :
                if (id != null)
                    throw new XAException(XAException.XAER_INVAL);
                try {
                    id = new TransactionId(xid, TX_IDLE);
                } catch (SQLException e) {
                    throw new XAException(XAException.XAER_RMFAIL); // XXX or is it an error?
                }

                getLogger().log("start(): adding to map for " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);

                activeTransactionContext.set(id);
                break;
            case XAResource.TMJOIN :
                getLogger().log(
                    "TMJOIN for transaction in thread: " + Thread.currentThread(),
                    LOG_CHANNEL,
                    Logger.DEBUG);
                if (id == null)
                    throw new XAException(XAException.XAER_NOTA);
                break;
            case XAResource.TMRESUME :
                getLogger().log(
                    "TMRESUME for transaction in thread: " + Thread.currentThread(),
                    LOG_CHANNEL,
                    Logger.DEBUG);
                if (id == null)
                    throw new XAException(XAException.XAER_NOTA);
                if (id.status != TX_SUSPENDED)
                    throw new XAException(XAException.XAER_INVAL);
                id.status = TX_IDLE;
                break;
        }
    }

    // ----------------------------------------------- NodeStore Implementation

    /**
     * Retrieve an object.
     *
     * @param uri Uri of the object we want to retrieve
     * @exception ServiceAccessException Error accessing the Service
     * @exception ObjectNotFoundException The object to retrieve was not found
     */
    public ObjectNode retrieveObject(Uri uri) throws ServiceAccessException, ObjectNotFoundException {

        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.retrieveObject(connection, uri);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
            }
        } else {
            return adapter.retrieveObject(getCurrentConnection(), uri);
        }
    }

    /**
     * Update an object.
     *
     * @param object Object to update
     * @exception ServiceAccessException Error accessing the Service
     * @exception ObjectNotFoundException The object to update was not found
     */
    public void storeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException {

        adapter.storeObject(getCurrentConnection(), uri, object);
    }

    /**
     * Create a new object.
     *
     * @param object ObjectNode
     * @param uri Uri of the object we want to create
     * @exception ServiceAccessException Error accessing the Service
     * @exception ObjectAlreadyExistsException An object already exists
     *            at this Uri
     */
    public void createObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectAlreadyExistsException {

        adapter.createObject(getCurrentConnection(), uri, object);
    }

    /**
     * Remove an object.
     *
     * @param object Object to remove
     * @exception ServiceAccessException Error accessing the Service
     * @exception ObjectNotFoundException The object to remove was not found
     */
    public void removeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException {

        adapter.removeObject(getCurrentConnection(), uri, object);
    }

    // ------------------------------------------- SecurityStore Implementation

    /**
     * Grant a new permission.
     *
     * @param permission Permission we want to create
     * @exception ServiceAccessException Error accessing the Service
     */
    public void grantPermission(Uri uri, NodePermission permission) throws ServiceAccessException {

        adapter.grantPermission(getCurrentConnection(), uri, permission);
    }

    /**
     * Revoke a permission.
     *
     * @param permission Permission we want to create
     * @exception ServiceAccessException Error accessing the Service
     */
    public void revokePermission(Uri uri, NodePermission permission) throws ServiceAccessException {

        adapter.revokePermission(getCurrentConnection(), uri, permission);
    }

    /**
     * Revoke all the permissions on an object.
     *
     * @param permission Permission we want to create
     * @exception ServiceAccessException Error accessing the Service
     */
    public void revokePermissions(Uri uri) throws ServiceAccessException {

        adapter.revokePermissions(getCurrentConnection(), uri);
    }

    /**
     * Enumerate permissions on an object.
     *
     * @param permission Permission we want to create
     * @exception ServiceAccessException Error accessing the Service
     */
    public Enumeration enumeratePermissions(Uri uri) throws ServiceAccessException {
        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.enumeratePermissions(connection, uri);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
            }
        } else {
            return adapter.enumeratePermissions(getCurrentConnection(), uri);
        }
    }

    // ----------------------------------------------- LockStore Implementation

    /**
     * Create a new lock.
     *
     * @param lock Lock token
     * @exception ServiceAccessException Service access error
     */
    public void putLock(Uri uri, NodeLock lock) throws ServiceAccessException {

        adapter.putLock(getCurrentConnection(), uri, lock);
    }

    /**
     * Refresh a lock.
     *
     * @param lock the lock to renew
     * @exception ServiceAccessException Service access error
     * @exception LockTokenNotFoundException Lock token was not found
     */
    public void renewLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

        adapter.renewLock(getCurrentConnection(), uri, lock);
    }

    /**
     * Unlock.
     *
     * @param lock Token to remove
     * @exception ServiceAccessException Service access error
     * @exception LockTokenNotFoundException Lock token was not found
     */
    public void removeLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

        adapter.removeLock(getCurrentConnection(), uri, lock);
    }

    /**
     * Kill a lock.
     *
     * @param lock Token to remove
     * @exception ServiceAccessException Service access error
     * @exception LockTokenNotFoundException Lock token was not found
     */
    public void killLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException {

        adapter.killLock(getCurrentConnection(), uri, lock);
    }

    /**
     * Enumerate locks on an object.
     *
     * @param subject Subject
     * @return Enumeration List of locks which have been put on the subject
     * @exception ServiceAccessException Service access error
     */
    public Enumeration enumerateLocks(Uri uri) throws ServiceAccessException {
        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.enumerateLocks(connection, uri);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
            }
        } else {
            return adapter.enumerateLocks(getCurrentConnection(), uri);
        }
    }

    // -------------------------------- RevisionDescriptorsStore Implementation

    /**
     * Retrieve the revisions informations of an object.
     *
     * @param uri Uri
     * @exception ServiceAccessException Service access error
     * @exception RevisionDescriptorNotFoundException Revision descriptor
     * was not found
     */
    public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.retrieveRevisionDescriptors(connection, uri);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
            }
        } else {
            return adapter.retrieveRevisionDescriptors(getCurrentConnection(), uri);
        }
    }

    /**
     * Create a new revision information object.
     *
     * @param uri Uri
     * @param revisionDescriptors Node revision descriptors
     * @exception ServiceAccessException Service access error
     */
    public void createRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors)
        throws ServiceAccessException {

        adapter.createRevisionDescriptors(getCurrentConnection(), uri, revisionDescriptors);
    }

    /**
     * Update revision information.
     *
     * @param uri Uri
     * @param revisionDescriptors Node revision descriptors
     * @exception ServiceAccessException Service access error
     * @exception RevisionDescriptorNotFoundException Revision descriptor
     * was not found
     */
    public void storeRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {

        adapter.storeRevisionDescriptors(getCurrentConnection(), uri, revisionDescriptors);
    }

    /**
     * Remove revision information.
     *
     * @param uri Uri
     * @exception ServiceAccessException Service access error
     */
    public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException {

        adapter.removeRevisionDescriptors(getCurrentConnection(), uri);
    }

    // --------------------------------- RevisionDescriptorStore Implementation

    /**
     * Retrieve an individual object's revision descriptor.
     *
     * @param Uri uri
     * @param revisionNumber Node revision number
     */
    public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.retrieveRevisionDescriptor(connection, uri, revisionNumber);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
            }
        } else {
            return adapter.retrieveRevisionDescriptor(getCurrentConnection(), uri, revisionNumber);
        }
    }

    /**
     * Create a new revision descriptor.
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @exception ServiceAccessException Service access error
     */
    public void createRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException {

        adapter.createRevisionDescriptor(getCurrentConnection(), uri, revisionDescriptor);
    }

    /**
     * Update a revision descriptor.
     *
     * @param uri Uri
     * @param revisionDescriptors Node revision descriptor
     * @exception ServiceAccessException Service access error
     * @exception RevisionDescriptorNotFoundException Revision descriptor
     * was not found
     */
    public void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {

        adapter.storeRevisionDescriptor(getCurrentConnection(), uri, revisionDescriptor);
    }

    /**
     * Remove a revision descriptor.
     *
     * @param uri Uri
     * @param revisionNumber Revision number
     * @exception ServiceAccessException Service access error
     */
    public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) throws ServiceAccessException {

        adapter.removeRevisionDescriptor(getCurrentConnection(), uri, revisionNumber);
    }

    // -------------------------------------------- ContentStore Implementation

    /**
     * Retrieve revision content.
     *
     * @param uri Uri
     * @param revisionNumber Node revision number
     */
    public NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException, RevisionNotFoundException {
        if (getActiveTransactionContext() == null) {
            Connection connection = null;
            try {
                connection = getNewConnection();
                return adapter.retrieveRevisionContent(connection, uri, revisionDescriptor, true);
            } catch (SQLException e) {
                throw new ServiceAccessException(this, e);
            } finally {
                // will be done in adapter or upon closing of stream
                /*
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        getLogger().log(e, LOG_CHANNEL, Logger.WARNING);
                    }
                }
                */
            }
        } else {
            return adapter.retrieveRevisionContent(getCurrentConnection(), uri, revisionDescriptor, false);
        }
    }

    /**
     * Create a new revision
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @param revisionContent Node revision content
     */
    public void createRevisionContent(
        Uri uri,
        NodeRevisionDescriptor revisionDescriptor,
        NodeRevisionContent revisionContent)
        throws ServiceAccessException, RevisionAlreadyExistException {

        adapter.createRevisionContent(getCurrentConnection(), uri, revisionDescriptor, revisionContent);
    }

    /**
     * Modify the latest revision of an object.
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @param revisionContent Node revision content
     */
    public void storeRevisionContent(
        Uri uri,
        NodeRevisionDescriptor revisionDescriptor,
        NodeRevisionContent revisionContent)
        throws ServiceAccessException, RevisionNotFoundException {

        adapter.storeRevisionContent(getCurrentConnection(), uri, revisionDescriptor, revisionContent);
    }

    /**
     * Remove revision.
     *
     * @param uri Uri
     * @param revisionNumber Node revision number
     */
    public void removeRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException {

        adapter.removeRevisionContent(getCurrentConnection(), uri, revisionDescriptor);
    }

    // ------------------------------------------------------ Protected Methods

    /**
     * Get the Connection object associated with the current transaction.
     */
    protected Connection getCurrentConnection() throws ServiceAccessException {

        getLogger().log("Getting current connection for thread " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
        TransactionId id = getActiveTransactionContext();
        if (id == null) {
            getLogger().log("No id for current thread - called outside transaction?", LOG_CHANNEL, Logger.DEBUG);
            return null;
        }
        return id.connection;
    }

    protected TransactionId getActiveTransactionContext() {
        Object txId = activeTransactionContext.get();
        return (TransactionId) txId;
    }

    abstract protected Connection getNewConnection() throws SQLException;

    // ---------------------------------------------------------- Inner Classes

    private class TransactionId {
        Xid xid;
        int status;
        boolean rollbackOnly;
        Connection connection;

        TransactionId(Xid xid, int status) throws SQLException {
            this.xid = xid;
            this.status = status;
            this.rollbackOnly = false;

            connection = getNewConnection();
        }

    }

}
TOP

Related Classes of org.apache.slide.store.impl.rdbms.AbstractRDBMSStore$TransactionId

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.