org.wso2.carbon.registry.core.jdbc.EmbeddedRegistry.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.registry.core.jdbc.EmbeddedRegistry.java

Source

/*
 * Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * 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.wso2.carbon.registry.core.jdbc;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.registry.core.ActionConstants;
import org.wso2.carbon.registry.core.Aspect;
import org.wso2.carbon.registry.core.Association;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.CollectionImpl;
import org.wso2.carbon.registry.core.Comment;
import org.wso2.carbon.registry.core.LogEntry;
import org.wso2.carbon.registry.core.LogEntryCollection;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.ResourceImpl;
import org.wso2.carbon.registry.core.ResourcePath;
import org.wso2.carbon.registry.core.Tag;
import org.wso2.carbon.registry.core.TaggedResourcePath;
import org.wso2.carbon.registry.core.config.RegistryContext;
import org.wso2.carbon.registry.core.config.StaticConfiguration;
import org.wso2.carbon.registry.core.dao.AssociationDAO;
import org.wso2.carbon.registry.core.dao.LogsDAO;
import org.wso2.carbon.registry.core.dao.RatingsDAO;
import org.wso2.carbon.registry.core.dao.TagsDAO;
import org.wso2.carbon.registry.core.dataaccess.DataAccessManager;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.exceptions.ResourceNotFoundException;
import org.wso2.carbon.registry.core.dao.CommentsDAO;
import org.wso2.carbon.registry.core.jdbc.handlers.Handler;
import org.wso2.carbon.registry.core.jdbc.handlers.HandlerLifecycleManager;
import org.wso2.carbon.registry.core.jdbc.handlers.HandlerManager;
import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext;
import org.wso2.carbon.registry.core.jdbc.queries.QueryProcessorManager;
import org.wso2.carbon.registry.core.jdbc.utils.DumpReader;
import org.wso2.carbon.registry.core.secure.AuthorizationFailedException;
import org.wso2.carbon.registry.core.session.CurrentSession;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.statistics.query.DBQueryStatisticsLog;
import org.wso2.carbon.registry.core.statistics.query.StatisticsRecord;
import org.wso2.carbon.registry.core.utils.AuthorizationUtils;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.core.utils.VersionedPath;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;

import java.io.Reader;
import java.io.Writer;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

/**
 * This is a core class of the Embedded JDBC Based implementation of the Registry. This will be used
 * mostly as the back-end by other Registry implementations. This can use either an in-memory
 * database or a external database configured using data source.
 */
public class EmbeddedRegistry implements Registry {

    private static final Log log = LogFactory.getLog(EmbeddedRegistry.class);

    // The instance of the logger to be used to log database query statistics.
    private static final Log dbQueryLog = DBQueryStatisticsLog.getLog();

    private static List<String> statEnabledOperations = new LinkedList<String>();

    private DataAccessManager dataAccessManager = null;

    // The executor service used to create threads to record connection statistics.
    private static ExecutorService executor = null;

    /**
     * Repository instance. This is used to handle basic resource storage operations of current
     * versions.
     */
    private Repository repository;
    /**
     * VersionRepository instance. This is used to handle resource storage operations of archived
     * (old) versions.
     */
    private VersionRepository versionRepository;

    /**
     * This is used to execute custom queries.
     */
    private QueryProcessorManager queryProcessorManager;

    /**
     * This is used to interact with the database layer to perform resource related operations.
     */
    private CommentsDAO commentsDAO;
    private RatingsDAO ratingsDAO;
    private TagsDAO tagsDAO;
    /**
     * This is used to interact with the database layer to perform associations related operations.
     */
    private AssociationDAO associationDAO = null;
    /**
     * This is used to interact with the database layer to perform activity logging related
     * operations.
     */
    private LogsDAO logsDAO = null;

    /**
     * The URL of the WS-Eventing Service
     */
    private String defaultEventingServiceURL;

    /**
     * Dictionary of URLs of the WS-Eventing Services
     */
    //TODO: Write new comparator for this map
    private Map<String, String> eventingServiceURLs = new TreeMap<String, String>();

    /**
     * Reference to the RegistryContext instance.
     */
    private RegistryContext registryContext;

    /**
     * UserRealm instance
     */
    private RealmService realmService = null;

    /**
     * jdbcDir uses in content indexing
     */
    //    private JdbcDirectory jdbcDir;

    static {
        if (dbQueryLog.isDebugEnabled()) {
            initializeStatisticsLogging();
        }
        String property = System.getProperty("carbon.registry.statistics.operations");
        if (property != null) {
            statEnabledOperations.addAll(Arrays.asList(property.split(",")));
        }
    }

    private static synchronized void initializeStatisticsLogging() {
        if (executor != null) {
            return;
        }
        executor = Executors.newSingleThreadExecutor();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                executor.shutdownNow();
            }
        });
    }

    /**
     * Default constructor. Embedded registry should be configured using the {@link #configure}
     * method, if it is instantiated using this constructor.
     */
    public EmbeddedRegistry() {
    }

    /**
     * Constructs a Embedded registry to be used with secure registries. Default authorizations will
     * be applied on the resources created using this registry.
     *
     * @param registryContext RegistryContext containing our configuration and data access manager.
     *                        Note that this may or may not be the same data source as the User
     *                        Manager.
     * @param realmService    User manager realm service handle authorizations.
     *
     * @throws RegistryException If something went wrong
     */
    public EmbeddedRegistry(RegistryContext registryContext, RealmService realmService) throws RegistryException {
        this.registryContext = registryContext;
        this.dataAccessManager = registryContext.getDataAccessManager();
        this.logsDAO = dataAccessManager.getDAOManager().getLogsDAO();
        this.associationDAO = dataAccessManager.getDAOManager().getAssociationDAO();
        this.realmService = realmService;
        init();
    }

    /**
     * Configures and initiates the Embedded registry with a (new) data source and a realm. This is
     * useful for changing underlying databases at run-time.
     *
     * @param dataAccessManager the data access manager to use
     * @param realmService      the User manager realm service handle authorizations.
     *
     * @throws RegistryException If something went wrong while init
     */
    public void configure(DataAccessManager dataAccessManager, RealmService realmService) throws RegistryException {
        this.dataAccessManager = dataAccessManager;
        this.logsDAO = dataAccessManager.getDAOManager().getLogsDAO();
        this.associationDAO = dataAccessManager.getDAOManager().getAssociationDAO();
        this.realmService = realmService;
        init();
    }

    // initializing the registry, filling repository, versionRepository + initializing handlers
    // (This contains the code that used to be in EmbeddedRegistry constructor
    private void init() throws RegistryException {
        beginDBQueryLog(2);
        if (log.isTraceEnabled()) {
            log.trace("Initialing main registry");
        }

        if (registryContext == null) {
            registryContext = RegistryContext.getBaseInstance(realmService);
        }
        registryContext.setDataAccessManager(dataAccessManager);

        if (log.isTraceEnabled()) {
            log.trace("Initializing the version repository.");
        }
        versionRepository = new VersionRepository(dataAccessManager);

        if (log.isTraceEnabled()) {
            log.trace("Initializing the repository.");
        }
        repository = new Repository(dataAccessManager, versionRepository, registryContext.isVersionOnChange(),
                new RecursionRepository(this));

        if (log.isTraceEnabled()) {
            log.trace("Initializing the query manager for processing custom queries.");
        }
        queryProcessorManager = new QueryProcessorManager(dataAccessManager, registryContext);

        registryContext.setRepository(repository);
        registryContext.setVersionRepository(versionRepository);
        registryContext.setQueryProcessorManager(queryProcessorManager);

        if (log.isTraceEnabled()) {
            log.trace("Initialing the content indexing system.");
        }

        //        initializeIndex();
        //        registryContext.setJdbcDir(jdbcDir);

        if (log.isTraceEnabled()) {
            log.trace("Initializing DAOs depending on the static configurations.");
        }
        commentsDAO = dataAccessManager.getDAOManager().getCommentsDAO(StaticConfiguration.isVersioningComments());
        ratingsDAO = dataAccessManager.getDAOManager().getRatingsDAO(StaticConfiguration.isVersioningRatings());
        tagsDAO = dataAccessManager.getDAOManager().getTagsDAO(StaticConfiguration.isVersioningTags());

        if (log.isTraceEnabled()) {
            log.trace("Main registry initialized successfully.");
        }
        endDBQueryLog(2);
    }

    // Starts logging database query statistics.
    private void beginDBQueryLog(int level) {
        if (dbQueryLog.isDebugEnabled()) {
            StackTraceElement traceElement = Thread.currentThread().getStackTrace()[level];
            String methodName = traceElement.getMethodName();
            if (!statEnabledOperations.isEmpty() && statEnabledOperations.contains(methodName)) {
                if (traceElement.getClassName().equals(this.getClass().getCanonicalName())) {
                    StatisticsRecord statisticsRecord = DBQueryStatisticsLog.getStatisticsRecord();
                    if (statisticsRecord.increment() == 0) {
                        DBQueryStatisticsLog.clearStatisticsRecord();
                        statisticsRecord = DBQueryStatisticsLog.getStatisticsRecord();
                        statisticsRecord.increment();
                        statisticsRecord.setOperation(methodName);
                    }
                }
            }
        }
    }

    // Finishes logging database query statistics.
    private void endDBQueryLog(int level) {
        if (dbQueryLog.isDebugEnabled()) {
            StackTraceElement traceElement = Thread.currentThread().getStackTrace()[level];
            String methodName = traceElement.getMethodName();
            if (!statEnabledOperations.isEmpty() && statEnabledOperations.contains(methodName)) {
                if (traceElement.getClassName().equals(this.getClass().getCanonicalName())) {
                    StatisticsRecord statisticsRecord = DBQueryStatisticsLog.getStatisticsRecord();
                    if (statisticsRecord.decrement() == 0) {
                        final StatisticsRecord clone = new StatisticsRecord(statisticsRecord);
                        Runnable runnable = new Runnable() {
                            public void run() {
                                if (clone.getTableRecords().length > 0) {
                                    dbQueryLog.debug("");
                                    dbQueryLog.debug("---------------------------------------------------");
                                    dbQueryLog.debug("Registry Operation: " + clone.getOperation());
                                    dbQueryLog.debug("");
                                    for (String record : clone.getTableRecords()) {
                                        dbQueryLog.debug("Tables Accessed: " + record);
                                    }
                                    if (Boolean.toString(true).equals(System.getProperty(
                                            "carbon.registry.statistics.output." + "queries.executed"))) {
                                        dbQueryLog.debug("");
                                        StringBuffer sb = new StringBuffer();
                                        for (String query : clone.getQueries()) {
                                            sb.append("\n").append(query);
                                        }
                                        dbQueryLog.debug("Queries Executed:" + sb.toString());
                                    }
                                    dbQueryLog.debug("---------------------------------------------------");
                                    dbQueryLog.debug("");
                                }
                            }
                        };
                        if (executor != null) {
                            executor.submit(runnable);
                        } else {
                            initializeStatisticsLogging();
                            executor.submit(runnable);
                        }
                        DBQueryStatisticsLog.clearStatisticsRecord();
                    }
                }
            }
        }
    }

    // TODO: Add this back once this is in a working state.
    @SuppressWarnings("unused")
    private void initializeIndex() throws RegistryException {

        /*Connection conn = null;
        try {
        if (log.isTraceEnabled()) {
            log.trace("Initialing database for content indexing.");
        }
        conn = dataSource.getConnection();
        ResultSet rs = conn.getMetaData().getTables(null, null, "REG_CONTENT_INDEX", null);
        jdbcDir = new JdbcDirectory(dataSource, DialectFactory.getDialect(dataSource)
                , "REG_CONTENT_INDEX");
        if (!rs.next()) {
            if (log.isTraceEnabled()) {
                log.trace("Creating the database tables storing indexes.");
            }
            jdbcDir.create();
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Database tables for storing indexes are already created.");
            }
        }
        rs.close();
            
        if (log.isTraceEnabled()) {
            log.trace("Database for content indexing is initialized successfully.");
        }
            
        } catch (SQLException e) {
            
        // Note if Registry is running on multiple nodes in a cluster sharing a same database:
        // When nodes are started at the same time, the first node that reaches database
        // creation code, tries to create tables. But other nodes may also perform the check and
        // finds out that tables are not created (if the first node has not yet committed the
        // table creation operation). Then they may also try to create tables and only one node
        // succeeds in this process. All other nodes may fail in this table creation operation,
        // if they encounter this concurrency scenario. But all other nodes should continue,
        // if the tables are created by some other node.
            
        boolean indexTableCreated = false;
        try {
            ResultSet rs = conn.getMetaData().getTables(null, null, "REG_CONTENT_INDEX", null);
            if (rs.next()) {
                indexTableCreated = true;
            }
            rs.close();
            
        } catch (SQLException e1) {
            
            String msg = "Failed to check the existence of the table REG_CONTENT_INDEX.";
            log.error(msg, e1);
        }
            
        if (indexTableCreated) {
            
            String msg = "Attempt to create database tables for content index is " +
                    "unsuccessful. But all the required database tables are already created. " +
                    "If this Registry instance is started in a clustered environment " +
                    "simultaneously with other Registry nodes, this is an expected situation " +
                    "and considered as a successful start-up of this node. Complete error " +
                    "is also logged for reference. Ignore this error log if this " +
                    "instance is started in a cluster.";
            if (log.isDebugEnabled()) {
                log.debug(msg, e);
            }
            
        } else {
            String msg = "Failed to create table to store content index.";
            log.error(msg, e);
            throw new RegistryException(msg, e);
        }
            
        } catch (IOException e) {
            
        String msg = "Failed to create table to store content index.";
        log.error(msg, e);
        throw new RegistryException(msg, e);
            
        } finally {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            String msg = "Failed to close the connection used to create database tables " +
                    "for content index. Caused by: " + e.getMessage();
            log.error(msg, e);
        }
        }*/
    }

    public void beginTransaction() throws RegistryException {
        beginDBQueryLog(3);
        dataAccessManager.getTransactionManager().beginTransaction();
    }

    public void rollbackTransaction() throws RegistryException {
        dataAccessManager.getTransactionManager().rollbackTransaction();
        endDBQueryLog(3);
    }

    public void commitTransaction() throws RegistryException {
        dataAccessManager.getTransactionManager().commitTransaction();
        endDBQueryLog(3);
    }

    public RegistryContext getRegistryContext() {
        beginDBQueryLog(2);
        RequestContext context = new RequestContext(this, repository, versionRepository);
        // We need to set the path of the registry that is making the request for the registry
        // context so that the handler manager can figure out which handler to invoke. In here,
        // we use the chroot of the registry as the path.
        String chroot = CurrentSession.getChroot();
        if (chroot == null) {
            chroot = "/";
        } else if (!chroot.endsWith("/")) {
            chroot += "/";
        }
        context.setResourcePath(new ResourcePath(chroot));
        RegistryContext output = registryContext.getHandlerManager().getRegistryContext(context);
        endDBQueryLog(2);
        if (output != null) {
            return output;
        }
        return registryContext;
    }

    public Resource newResource() throws RegistryException {
        beginDBQueryLog(2);
        try {
            ResourceImpl resource = new ResourceImpl();
            resource.setAuthorUserName(CurrentSession.getUser());
            return resource;
        } finally {
            endDBQueryLog(2);
        }
    }

    public Collection newCollection() throws RegistryException {
        beginDBQueryLog(2);
        try {
            CollectionImpl coll = new CollectionImpl();
            coll.setAuthorUserName(CurrentSession.getUser());
            return coll;
        } finally {
            endDBQueryLog(2);
        }
    }

    public Resource get(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);

            // check if this path refers to a resource referred by a URL query (e.g. comment)
            context.setResourcePath(resourcePath);

            Resource resource = registryContext.getHandlerManager().get(context);

            if (!context.isSimulation()) {
                // resource may have been fetched from the repository, to be used by handlers. if
                // it is done, it has to be stored in the request context. we can just use that
                // resource without fetching it again from the repository.
                if (resource == null) {
                    resource = context.getResource();
                }

                if (resource == null) {
                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
                    if (versionedPath.getVersion() == -1) {
                        resource = repository.get(resourcePath.getPath());
                    } else {
                        resource = versionRepository.get(versionedPath);
                    }
                }

                if (resource == null) {
                    throw new ResourceNotFoundException(path);
                }

                context.setResource(resource);

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).get(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }

            return resource;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE).get(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public Resource getMetaData(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        try {
            // starting the transactional operation wrapper
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);
            Resource resource;

            VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
            if (versionedPath.getVersion() == -1) {
                resource = repository.getMetaData(resourcePath.getPath());
            } else {
                resource = versionRepository.getMetaData(versionedPath);
            }

            if (resource == null) {
                throw new ResourceNotFoundException(path);
            }

            // transaction successfully finished
            transactionSucceeded = true;

            return resource;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public String importResource(String suggestedPath, String sourceURL,
            org.wso2.carbon.registry.api.Resource resource) throws org.wso2.carbon.registry.api.RegistryException {
        return importResource(suggestedPath, sourceURL, (Resource) resource);
    }

    public Collection get(String path, int start, int pageSize) throws RegistryException {
        boolean transactionSucceeded = false;
        try {
            // starting the transactional operation wrapper
            beginTransaction();

            Collection collection;

            ResourcePath resourcePath = new ResourcePath(path);
            VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
            if (versionedPath.getVersion() == -1) {
                collection = repository.get(resourcePath.getPath(), start, pageSize);
            } else {
                collection = versionRepository.get(versionedPath, start, pageSize);
            }

            // transaction successfully finished
            transactionSucceeded = true;

            return collection;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public boolean resourceExists(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            // starting the transactional operation wrapper
            ResourcePath resourcePath = new ResourcePath(path);

            context.setResourcePath(resourcePath);
            boolean output = registryContext.getHandlerManager().resourceExists(context);

            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);

                    output = (versionedPath.getVersion() == -1) ? repository.resourceExists(resourcePath.getPath())
                            : versionRepository.resourceExists(versionedPath);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .resourceExists(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }

            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .resourceExists(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String put(String suggestedPath, org.wso2.carbon.registry.api.Resource resource)
            throws org.wso2.carbon.registry.api.RegistryException {
        return put(suggestedPath, (Resource) resource);
    }

    public String put(String suggestedPath, Resource resource) throws RegistryException {

        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        boolean mustPutChild = false;
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(suggestedPath);

            context.setResourcePath(resourcePath);
            context.setResource(resource);
            if (repository.resourceExists(suggestedPath)) {
                context.setOldResource(repository.get(suggestedPath));
            }

            if (!RegistryConstants.ROOT_PATH.equals(resourcePath.getPath())) {
                mustPutChild = true;
                registryContext.getHandlerManager().putChild(context);
            }

            registryContext.getHandlerManager().put(context);

            if (!context.isSimulation()) {
                String actualPath = context.getActualPath();

                if (!context.isProcessingComplete()) {
                    ((ResourceImpl) resource).prepareContentForPut();

                    actualPath = suggestedPath;
                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        repository.put(suggestedPath, resource);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                }

                if (mustPutChild) {
                    registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                            .putChild(context);
                }
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).put(context);
                transactionSucceeded = true;

                if (actualPath == null) {
                    return suggestedPath;
                } else {
                    return actualPath;
                }
            } else {
                return suggestedPath;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    if (mustPutChild) {
                        registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                                .putChild(context);
                    }
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE).put(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String importResource(String suggestedPath, String sourceURL, Resource metaResource)
            throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        RequestContext importChildContext = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(suggestedPath);

            importChildContext.setResourcePath(resourcePath);

            context.setResourcePath(resourcePath);
            context.setSourceURL(sourceURL);
            context.setResource(metaResource);

            if (repository.resourceExists(suggestedPath)) {
                Resource resource = repository.get(suggestedPath);
                importChildContext.setOldResource(resource);
                context.setOldResource(resource);
            }

            registryContext.getHandlerManager().importChild(importChildContext);
            registryContext.getHandlerManager().importResource(context);
            if (!context.isSimulation()) {
                String savedPath = context.getActualPath();

                if (!context.isProcessingComplete()) {
                    savedPath = suggestedPath;

                    // if some handlers have updated the meta data *without completing the request* we should
                    // capture the updated meta data here.
                    if (context.getResource() != null) {
                        metaResource = context.getResource();
                    }

                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        repository.importResource(resourcePath.getPath(), sourceURL, metaResource);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                }

                if (savedPath != null) {
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(savedPath, CurrentSession.getUser(), LogEntry.UPDATE,
                                null);
                    }
                }
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .importChild(importChildContext);
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .importResource(context);
                // transaction successfully finished
                transactionSucceeded = true;

                if (savedPath != null) {
                    return savedPath;
                }
            }
            return suggestedPath;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .importChild(importChildContext);
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .importResource(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void delete(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);
            context.setRegistryContext(registryContext);
            context.setResourcePath(resourcePath);

            registryContext.getHandlerManager().delete(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete() && repository.resourceExists(resourcePath.getPath())) {
                    repository.delete(resourcePath.getPath());
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(resourcePath.getPath(), CurrentSession.getUser(),
                                LogEntry.DELETE_RESOURCE, null);
                    }
                }
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).delete(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .delete(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }

    }

    public String rename(String currentPath, String newName) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(currentPath);
            context.setRegistryContext(registryContext);
            context.setSourcePath(currentPath);
            context.setTargetPath(newName);
            String newPath = registryContext.getHandlerManager().rename(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        newPath = repository.rename(resourcePath, newName);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                }
                if (context.isLoggingActivity()) {
                    registryContext.getLogWriter().addLog(newPath, CurrentSession.getUser(), LogEntry.RENAME,
                            currentPath);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).rename(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return newPath;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .rename(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String move(String currentPath, String newPath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath currentResourcePath = new ResourcePath(currentPath);
            context.setSourcePath(currentPath);
            context.setTargetPath(newPath);
            context.setRegistryContext(registryContext);
            String movedPath = registryContext.getHandlerManager().move(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        movedPath = repository.move(currentResourcePath, newPath);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                }
                if (context.isLoggingActivity()) {
                    registryContext.getLogWriter().addLog(newPath, CurrentSession.getUser(), LogEntry.MOVE,
                            currentPath);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).move(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return movedPath;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE).move(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String copy(String sourcePath, String targetPath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath sourceResourcePath = new ResourcePath(sourcePath);
            ResourcePath targetResourcePath = new ResourcePath(targetPath);
            context.setSourcePath(sourcePath);
            context.setTargetPath(targetPath);
            String copiedPath = registryContext.getHandlerManager().copy(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        copiedPath = repository.copy(sourceResourcePath, targetResourcePath);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                }
                if (context.isLoggingActivity()) {
                    registryContext.getLogWriter().addLog(sourcePath, CurrentSession.getUser(), LogEntry.COPY,
                            targetPath);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).copy(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return copiedPath;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE).copy(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void createVersion(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);

            context.setResourcePath(resourcePath);
            registryContext.getHandlerManager().createVersion(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    versionRepository.createSnapshot(resourcePath, true, true);
                }
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .createVersion(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .createVersion(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String[] getVersions(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setResourcePath(new ResourcePath(path));
            String[] output = registryContext.getHandlerManager().getVersions(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    output = versionRepository.getVersions(path);
                }
                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getVersions(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getVersions(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void restoreVersion(String versionPath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setVersionPath(versionPath);
            ResourcePath versionedResourcePath = new ResourcePath(versionPath);
            String path = versionedResourcePath.getPath();
            if (repository.resourceExists(path)) {
                context.setOldResource(repository.get(path));
            }
            registryContext.getHandlerManager().restoreVersion(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    if (repository.resourceExists(path)) {
                        // if the target already have resources, delete them..
                        repository.prepareVersionRestore(path);
                    }
                    versionRepository.restoreVersion(versionedResourcePath);
                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(versionedResourcePath);
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, CurrentSession.getUser(), LogEntry.RESTORE,
                                Long.toString(versionedPath.getVersion()));
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .restoreVersion(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .restoreVersion(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    ////////////////////////////////////////////////////////
    // Associations
    ////////////////////////////////////////////////////////

    public void addAssociation(String sourcePath, String targetPath, String associationType)
            throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            // Source and target of associations may or may not be resources in the registry. If they
            // don't refer to a resource, they can contain any string value. But if they refer to
            // resources, values should be proper resource paths.

            ResourcePath sourceResourcePath = new ResourcePath(sourcePath);
            if (repository.resourceExists(sourceResourcePath.getPath())) {
                sourcePath = sourceResourcePath.getPathWithVersion();
            }

            ResourcePath targetResourcePath = new ResourcePath(targetPath);
            if (repository.resourceExists(targetResourcePath.getPath())) {
                targetPath = targetResourcePath.getPathWithVersion();
            }

            context.setSourcePath(sourcePath);
            context.setTargetPath(targetPath);
            context.setAssociationType(associationType);
            context.setOldAssociationsOnSource(getAllAssociations(sourcePath));
            context.setOldAssociationsOnTarget(getAllAssociations(targetPath));

            registryContext.getHandlerManager().addAssociation(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    associationDAO.addAssociation(sourcePath, targetPath, associationType);
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(sourcePath, CurrentSession.getUser(),
                                LogEntry.ADD_ASSOCIATION, associationType + ";" + targetPath);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .addAssociation(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .addAssociation(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void removeAssociation(String sourcePath, String targetPath, String associationType)
            throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            // Source and target of associations may or may not be resources in the registry. If they
            // don't refer to a resource, they can contain any string value. But if they refer to
            // resources, values should be proper resource paths.

            ResourcePath sourceResourcePath = new ResourcePath(sourcePath);
            if (repository.resourceExists(sourceResourcePath.getPath())) {
                sourcePath = sourceResourcePath.getPathWithVersion();
            }

            ResourcePath targetResourcePath = new ResourcePath(targetPath);
            if (repository.resourceExists(targetResourcePath.getPath())) {
                targetPath = targetResourcePath.getPathWithVersion();
            }

            context.setSourcePath(sourcePath);
            context.setTargetPath(targetPath);
            context.setAssociationType(associationType);
            context.setOldAssociationsOnSource(getAllAssociations(sourcePath));
            context.setOldAssociationsOnTarget(getAllAssociations(targetPath));

            registryContext.getHandlerManager().removeAssociation(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    associationDAO.removeAssociation(sourcePath, targetPath, associationType);
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(sourcePath, CurrentSession.getUser(),
                                LogEntry.REMOVE_ASSOCIATION, associationType + ";" + targetPath);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .removeAssociation(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .removeAssociation(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public Association[] getAllAssociations(String resourcePath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            // Source and target of associations may or may not be resources in the registry. If they
            // don't refer to a resource, they can contain any string value. But if they refer to
            // resources, values should be proper resource paths.

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (repository.resourceExists(processedPath.getPath())) {
                resourcePath = processedPath.getPathWithVersion();
            }

            context.setResourcePath(new ResourcePath(resourcePath));

            Association[] associations = registryContext.getHandlerManager().getAllAssociations(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    associations = associationDAO.getAllAssociations(resourcePath);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getAllAssociations(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return associations;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getAllAssociations(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }

    }

    public Association[] getAssociations(String resourcePath, String associationType) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            // Source and target of associations may or may not be resources in the registry. If they
            // don't refer to a resource, they can contain any string value. But if they refer to
            // resources, values should be proper resource paths.

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (repository.resourceExists(processedPath.getPath())) {
                resourcePath = processedPath.getPathWithVersion();
            }

            context.setResourcePath(new ResourcePath(resourcePath));
            context.setAssociationType(associationType);

            Association[] associations = registryContext.getHandlerManager().getAssociations(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    associations = associationDAO.getAllAssociationsForType(resourcePath, associationType);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getAssociations(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return associations;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getAssociations(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    ////////////////////////////////////////////////////////
    // Tagging
    ////////////////////////////////////////////////////////

    public void applyTag(String resourcePath, String tag) throws RegistryException {
        final String ILLEGAL_CHARACTERS_FOR_TAG = ".*[~!@#;%^*+={}\\|\\\\<>\"\'].*";
        Pattern illegalCharactersPattern = Pattern.compile(ILLEGAL_CHARACTERS_FOR_TAG);
        if (illegalCharactersPattern.matcher(tag).matches()) { //"[~!@#;%^*()+={}[]|\\<>\"\']"
            throw new RegistryException(
                    "The tag '" + tag + "' contains one or more illegal " + "characters (~!@#;%^*()+={}|\\<>\"\')");
        }
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {

            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);

            context.setResourcePath(processedPath);
            context.setTag(tag);
            context.setOldTags(getTags(processedPath.getPath()));

            registryContext.getHandlerManager().applyTag(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    if (!processedPath.isCurrentVersion()) {
                        String msg = "Failed to apply tag to the resource " + processedPath
                                + ". Given path refers to an archived version of the resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    resourcePath = processedPath.getPath();

                    // break the comma separated words into multiple tags
                    String[] tags = tag.split(",");

                    ResourceImpl resource = tagsDAO.getResourceWithMinimumData(resourcePath);
                    if (resource == null) {
                        String msg = "Failed to apply tag " + tag + " on resource " + resourcePath + ". Resource "
                                + resourcePath + " does not exist.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    String userName = CurrentSession.getUser();

                    if (!AuthorizationUtils.authorize(resource.getPath(), ActionConstants.GET)) {
                        String msg = "Failed to apply tag " + tag + " on resource " + resourcePath + ". User "
                                + userName + " is not authorized to read the resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    for (int i = 0; i < tags.length; i++) {

                        tags[i] = tags[i].trim();

                        if (tags[i].length() == 0 || tags[i].equals(" ")) {
                            continue;
                        }

                        if (tagsDAO.taggingExists(tags[i], resource, userName)) {
                            // Already there, don't bother doing it again.
                            continue;
                        }

                        tagsDAO.addTagging(tags[i], resource, userName);
                        if (context.isLoggingActivity()) {
                            registryContext.getLogWriter().addLog(resourcePath, userName, LogEntry.TAG, tags[i]);
                        }
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).applyTag(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .applyTag(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public TaggedResourcePath[] getResourcePathsWithTag(String tag) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setTag(tag);

            TaggedResourcePath[] output = registryContext.getHandlerManager().getResourcePathsWithTag(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    // break the tags from spaces
                    String[] tags = tag.trim().split(",");

                    for (int i = 0; i < tags.length; i++) {
                        tags[i] = tags[i].trim();
                    }

                    Map<String, TaggedResourcePath> taggedPaths = new HashMap<String, TaggedResourcePath>();

                    // We know that the paths list contains strings.
                    @SuppressWarnings("unchecked")
                    List<String> pathList = tagsDAO.getPathsWithAnyTag(tags);
                    for (String path : pathList) {
                        TaggedResourcePath taggedResourcePath = new TaggedResourcePath();
                        taggedResourcePath.setResourcePath(path);

                        ResourceImpl resourceImpl = tagsDAO.getResourceWithMinimumData(path);

                        for (String currentTag : tags) {
                            long count = tagsDAO.getTagCount(resourceImpl, currentTag);
                            taggedResourcePath.addTagCount(currentTag, count);
                            taggedPaths.put(currentTag + path, taggedResourcePath);
                        }
                    }
                    if (output == null || output.length == 0) {
                        java.util.Collection<TaggedResourcePath> taggedPathsSet = taggedPaths.values();
                        output = taggedPathsSet.toArray(new TaggedResourcePath[taggedPathsSet.size()]);
                    } else {
                        for (TaggedResourcePath taggedResourcePath : output) {
                            for (String currentTag : taggedResourcePath.getTagCounts().keySet()) {
                                taggedPaths.put(currentTag + taggedResourcePath.getResourcePath(),
                                        taggedResourcePath);
                            }
                        }
                        java.util.Collection<TaggedResourcePath> taggedPathsSet = taggedPaths.values();
                        output = taggedPathsSet.toArray(new TaggedResourcePath[taggedPathsSet.size()]);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getResourcePathsWithTag(context);
                // transaction successfully finished
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getResourcePathsWithTag(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public Tag[] getTags(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setResourcePath(new ResourcePath(path));

            Tag[] output = registryContext.getHandlerManager().getTags(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    path = RegistryUtils.prepareGeneralPath(path);

                    ResourcePath resourcePath = new ResourcePath(path);
                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
                    ResourceImpl resourceImpl;
                    if (versionedPath.getVersion() == -1) {
                        resourceImpl = tagsDAO.getResourceWithMinimumData(resourcePath.getPath());
                    } else {
                        resourceImpl = (ResourceImpl) versionRepository.getMetaData(versionedPath);
                    }

                    if (resourceImpl == null) {
                        String msg = "Failed to get tags of " + path + ". The resource doesn't exists.";
                        log.debug(msg);
                        output = new Tag[0];
                    } else {
                        output = tagsDAO.getTagsWithCount(resourceImpl);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).getTags(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getTags(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void removeTag(String path, String tag) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(path);

            context.setResourcePath(processedPath);
            context.setTag(tag);
            context.setOldTags(getTags(processedPath.getPath()));

            registryContext.getHandlerManager().removeTag(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    if (!processedPath.isCurrentVersion()) {
                        String msg = "Failed to remove tag from the resource " + processedPath
                                + ". Given path refers to an archived version of the resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    path = processedPath.getPath();
                    path = RegistryUtils.prepareGeneralPath(path);

                    String user = CurrentSession.getUser();
                    UserRealm userRealm = CurrentSession.getUserRealm();

                    boolean adminUser = false;
                    // getting the realm config to get admin role, user details
                    RealmConfiguration realmConfig;
                    try {
                        realmConfig = userRealm.getRealmConfiguration();
                    } catch (UserStoreException e) {
                        String msg = "Failed to retrieve realm configuration.";
                        log.error(msg, e);
                        throw new RegistryException(msg, e);
                    }

                    // check is the user belongs to the admin role
                    try {
                        String[] roles = userRealm.getUserStoreManager().getRoleListOfUser(user);
                        String adminRoleName = realmConfig.getAdminRoleName();
                        if (RegistryUtils.containsString(adminRoleName, roles)) {
                            adminUser = true;
                        }

                    } catch (UserStoreException e) {

                        String msg = "Failed to get roles of the current user. "
                                + "User will be considered as non-admin user.\n" + e.getMessage();
                        log.error(msg, e);
                        adminUser = false;
                    }

                    // check if the user is the admin user
                    // TODO - do we really need to do this check?  Won't this user always be in the
                    // admin role?

                    String adminUsername = realmConfig.getAdminUserName();
                    if (adminUsername.equals(user)) {
                        adminUser = true;
                    }

                    if (adminUser) {
                        ResourceImpl resource = tagsDAO.getResourceWithMinimumData(path);
                        tagsDAO.removeTags(resource, tag);
                    } else {
                        ResourceImpl resource = (ResourceImpl) repository.getMetaData(path);

                        String author = resource.getAuthorUserName();
                        if (user.equals(author)) {
                            tagsDAO.removeTags(resource, tag);
                        } else {
                            tagsDAO.removeTags(resource, tag, user);
                        }
                    }
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, user, LogEntry.REMOVE_TAG, tag);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).removeTag(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .removeTag(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String addComment(String resourcePath, org.wso2.carbon.registry.api.Comment comment)
            throws org.wso2.carbon.registry.api.RegistryException {
        return addComment(resourcePath, (Comment) comment);
    }

    ////////////////////////////////////////////////////////
    // Commenting
    ////////////////////////////////////////////////////////

    public String addComment(String resourcePath, Comment comment) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);

            context.setResourcePath(processedPath);
            context.setComment(comment);
            context.setOldComments(getComments(processedPath.getPath()));
            String output = registryContext.getHandlerManager().addComment(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    if (!processedPath.isCurrentVersion()) {
                        String msg = "Failed to add comment to the resource " + processedPath
                                + ". Given path refers to an archived version of the resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    resourcePath = processedPath.getPath();

                    String userName = CurrentSession.getUser();

                    if (!AuthorizationUtils.authorize(resourcePath, ActionConstants.GET)) {
                        String msg = "Failed to apply comment " + comment.getText() + " on resource " + resourcePath
                                + ". User " + userName + " is not authorized to read the " + "resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    try {
                        ResourceImpl resource = commentsDAO.getResourceWithMinimumData(resourcePath);
                        if (resource == null) {
                            String msg = "Failed to add comment " + comment.getText() + " to resource "
                                    + resourcePath + ". Resource " + resourcePath + " does not exist.";
                            log.error(msg);
                            throw new RegistryException(msg);
                        }

                        int commentId = commentsDAO.addComment(resource, userName, comment);
                        String commentPath = resourcePath + RegistryConstants.URL_SEPARATOR + "comments:"
                                + commentId;
                        if (context.isLoggingActivity()) {
                            registryContext.getLogWriter().addLog(resourcePath, userName, LogEntry.COMMENT,
                                    comment.getText());
                        }

                        output = commentPath;
                    } catch (RegistryException e) {
                        String msg = "Failed to add comment " + comment.getText() + " on resource " + resourcePath
                                + ". User " + userName + ".";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).addComment(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .addComment(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void editComment(String commentPath, String text) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(commentPath);

            Comment comment = new Comment();
            comment.setCommentPath(commentPath);
            comment.setText(text);

            context.setResourcePath(processedPath);
            context.setComment(comment);
            context.setOldComments(getComments(commentPath));
            registryContext.getHandlerManager().editComment(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    String userName = CurrentSession.getUser();
                    String[] parts = commentPath.split(RegistryConstants.URL_SEPARATOR);
                    if (parts.length == 2) {
                        String resourcePath = parts[0];
                        String commentPart = parts[1];
                        if (!AuthorizationUtils.authorize(resourcePath, ActionConstants.GET)) {
                            String msg = "Failed to edit comment " + text + " on resource " + resourcePath
                                    + ". User " + userName + " is not authorized to read " + "the resource.";
                            log.error(msg);
                            throw new RegistryException(msg);
                        }
                        if (commentPart.startsWith("comments:")) {
                            String commentId = commentPart.substring(9);
                            commentsDAO.updateComment(Long.parseLong(commentId), text);
                        }
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .editComment(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .editComment(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void removeComment(String commentPath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(commentPath);

            Comment comment = new Comment();
            comment.setCommentPath(commentPath);

            context.setResourcePath(processedPath);
            context.setComment(comment);
            context.setOldComments(getComments(commentPath));
            registryContext.getHandlerManager().removeComment(context);

            if (!context.isProcessingComplete()) {

                if (!processedPath.isCurrentVersion()) {
                    String msg = "Failed to remove tag from the resource " + processedPath
                            + ". Given path refers to an archived version of the resource.";
                    log.error(msg);
                    throw new RegistryException(msg);
                }

                String user = CurrentSession.getUser();
                UserRealm userRealm = CurrentSession.getUserRealm();

                boolean adminUser = false;
                // getting the realm config to get admin role, user details
                RealmConfiguration realmConfig;
                try {
                    realmConfig = userRealm.getRealmConfiguration();
                } catch (UserStoreException e) {
                    String msg = "Failed to retrieve realm configuration.";
                    log.error(msg, e);
                    throw new RegistryException(msg, e);
                }

                // check is the user belongs to the admin role
                try {
                    String[] roles = userRealm.getUserStoreManager().getRoleListOfUser(user);
                    String adminRoleName = realmConfig.getAdminRoleName();
                    if (RegistryUtils.containsString(adminRoleName, roles)) {
                        adminUser = true;
                    }

                } catch (UserStoreException e) {

                    String msg = "Failed to get roles of the current user. "
                            + "User will be considered as non-admin user.\n" + e.getMessage();
                    log.error(msg, e);
                    adminUser = false;
                }

                // check if the user is the admin user
                // TODO - do we really need to do this check?  Won't this user always be in the
                // admin role?

                String adminUsername = realmConfig.getAdminUserName();
                if (adminUsername.equals(user)) {
                    adminUser = true;
                }

                String[] parts = commentPath.split(RegistryConstants.URL_SEPARATOR);
                String commentPart = parts[1];
                String commentId = null;
                if (parts.length == 2 && commentPart.startsWith("comments:")) {
                    commentId = parts[1].substring(9);
                }

                Comment temp = commentsDAO.getComment(Long.parseLong(commentId), processedPath.getPath());
                if (adminUser) {
                    commentsDAO.deleteComment(Long.parseLong(commentId));
                } else {
                    ResourceImpl resource = (ResourceImpl) repository.getMetaData(processedPath.getPath());

                    String author = resource.getAuthorUserName();
                    if (user.equals(author)) {
                        commentsDAO.deleteComment(Long.parseLong(commentId));
                    } else {
                        if (temp != null && user.equals(temp.getUser())) {
                            commentsDAO.deleteComment(Long.parseLong(commentId));
                        } else {
                            String msg = "User: " + user
                                    + " is not authorized to delete the comment on the resource: "
                                    + processedPath.getPath();
                            log.warn(msg);
                            throw new AuthorizationFailedException(msg);
                        }
                    }
                }
                if (context.isLoggingActivity()) {
                    if (temp != null) {
                        registryContext.getLogWriter().addLog(processedPath.getPath(), user,
                                LogEntry.DELETE_COMMENT, temp.getText());
                    } else {
                        registryContext.getLogWriter().addLog(processedPath.getPath(), user,
                                LogEntry.DELETE_COMMENT, commentPath);
                    }
                }
            }
            registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).removeComment(context);
            // transaction succeeded
            transactionSucceeded = true;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .removeComment(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public Comment[] getComments(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);

            context.setResourcePath(resourcePath);
            Comment[] output = registryContext.getHandlerManager().getComments(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
                    ResourceImpl resourceImpl;
                    if (versionedPath.getVersion() == -1) {
                        resourceImpl = commentsDAO.getResourceWithMinimumData(resourcePath.getPath());
                    } else {
                        resourceImpl = (ResourceImpl) versionRepository.getMetaData(versionedPath);
                    }

                    if (resourceImpl == null) {
                        output = new Comment[0];
                    } else {
                        output = commentsDAO.getComments(resourceImpl);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getComments(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getComments(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    ////////////////////////////////////////////////////////
    // Ratings
    ////////////////////////////////////////////////////////

    public void rateResource(String resourcePath, int rating) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            String userName = CurrentSession.getUser();

            context.setResourcePath(new ResourcePath(resourcePath));
            context.setRating(rating);
            context.setOldRating(getRating(resourcePath, userName));
            context.setOldAverageRating(getAverageRating(resourcePath));
            registryContext.getHandlerManager().rateResource(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    ResourcePath processedPath = new ResourcePath(resourcePath);
                    if (!processedPath.isCurrentVersion()) {
                        String msg = "Failed to apply rating to the resource " + processedPath
                                + ". Given path refers to an archived version of the resource.";
                        log.error(msg);
                        throw new RegistryException(msg);
                    }

                    resourcePath = processedPath.getPath();

                    ResourceImpl resourceImpl = ratingsDAO.getResourceWithMinimumData(resourcePath);

                    if (resourceImpl != null) {

                        if (!AuthorizationUtils.authorize(resourcePath, ActionConstants.GET)) {
                            String msg = "Failed to rate resource " + resourcePath + " with rating " + rating
                                    + ". User " + userName + " is not authorized to read the resource.";
                            log.error(msg);
                            throw new RegistryException(msg);
                        }

                        // check for the existing rating.
                        int rateID = ratingsDAO.getRateID(resourceImpl, userName);
                        if (rateID > -1) {
                            if (rating == 0) {
                                ratingsDAO.removeRating(resourceImpl, rateID);
                            } else {
                                ratingsDAO.updateRating(resourceImpl, rateID, rating);
                            }

                            if (log.isDebugEnabled()) {
                                log.debug("Updated the rating on the resource " + resourcePath + " by user "
                                        + userName);
                            }
                        } else {
                            ratingsDAO.addRating(resourceImpl, userName, rating);
                        }

                        if (context.isLoggingActivity()) {
                            registryContext.getLogWriter().addLog(resourcePath, userName, LogEntry.RATING,
                                    Integer.toString(rating));
                        }

                    } else {
                        String msg = "Rate on Null resource " + resourcePath;
                        log.error(msg);
                        throw new RegistryException(msg);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .rateResource(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .rateResource(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public float getAverageRating(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();
            ResourcePath resourcePath = new ResourcePath(path);

            context.setResourcePath(resourcePath);
            float rating = registryContext.getHandlerManager().getAverageRating(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
                    ResourceImpl resourceImpl;
                    if (versionedPath.getVersion() == -1) {
                        resourceImpl = ratingsDAO.getResourceWithMinimumData(resourcePath.getPath());
                    } else {
                        resourceImpl = (ResourceImpl) versionRepository.getMetaData(versionedPath);
                    }

                    if (resourceImpl == null) {
                        String msg = "Rate on Null resource " + path;
                        log.debug(msg);
                        rating = 0;
                    } else {
                        rating = ratingsDAO.getAverageRating(resourceImpl);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .getAverageRating(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return rating;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getAverageRating(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public int getRating(String path, String userName) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();
            ResourcePath resourcePath = new ResourcePath(path);

            context.setResourcePath(resourcePath);
            context.setUserName(userName);
            int rating = registryContext.getHandlerManager().getRating(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {

                    VersionedPath versionedPath = RegistryUtils.getVersionedPath(resourcePath);
                    ResourceImpl resourceImpl;
                    if (versionedPath.getVersion() == -1) {
                        resourceImpl = ratingsDAO.getResourceWithMinimumData(resourcePath.getPath());
                    } else {
                        resourceImpl = (ResourceImpl) versionRepository.getMetaData(versionedPath);
                    }
                    if (resourceImpl == null) {
                        String msg = "Rate on Null resource " + path;
                        log.error(msg);
                        throw new RegistryException(msg);
                    }
                    rating = ratingsDAO.getRating(resourceImpl, userName);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).getRating(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return rating;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .getRating(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    ////////////////////////////////////////////////////////
    // Extensible searching API
    ////////////////////////////////////////////////////////

    public Collection executeQuery(String path, Map parameters) throws RegistryException {
        boolean transactionSucceeded = false;
        boolean remote = false;
        if (parameters.get("remote") != null) {
            parameters.remove("remote");
            remote = true;
        }
        RequestContext context = new RequestContext(this, repository, versionRepository);
        Resource query = null;
        try {
            // start the transaction
            beginTransaction();

            Registry systemRegistry = new UserRegistry(CarbonConstants.REGISTRY_SYSTEM_USERNAME,
                    CurrentSession.getTenantId(), this, realmService, null);
            // we have to get the stored query without checking the user permissions.
            // all query actions are blocked for all users. they are allowed to read the
            // queries, only when executing them.
            if (path != null) {
                String purePath = RegistryUtils.getPureResourcePath(path);
                if (systemRegistry.resourceExists(purePath)) {
                    query = systemRegistry.get(purePath);
                    // If no media type was specified, the query should not work at all.
                    // This is also used in the remote registry scenario, where we send '/' as the
                    // query path, when path is null.
                    if (query != null && (query.getMediaType() == null || query.getMediaType().length() == 0)) {
                        query = null;
                    }
                }
            }
            /*// transaction succeeded
            transactionSucceeded = true;
            } finally {
            if (transactionSucceeded) {
            commitTransaction();
            } else {
            rollbackTransaction();
            }
            }
            // new transaction
            transactionSucceeded = false;
            context = new RequestContext(this, repository, versionRepository);
            try {
            // start the transaction
            beginTransaction();*/

            if (path != null) {
                context.setResourcePath(new ResourcePath(path));
            }
            context.setResource(query);
            context.setQueryParameters(parameters);
            Collection output = registryContext.getHandlerManager().executeQuery(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    if (query == null) {
                        query = newResource();
                        String mediaType = (String) parameters.get("mediaType");
                        query.setMediaType(mediaType != null ? mediaType : RegistryConstants.SQL_QUERY_MEDIA_TYPE);
                    }
                    //Resource query = repository.get(purePath);

                    Collection temp = queryProcessorManager.executeQuery(this, query, parameters);
                    Set<String> results = new LinkedHashSet<String>();
                    if (output != null) {
                        String[] children = output.getChildren();
                        if (children != null) {
                            for (String child : children) {
                                if (child != null && (remote || resourceExists(child))) {
                                    results.add(child);
                                }
                            }
                        }

                        if (temp != null) {
                            children = temp.getChildren();
                            if (children != null) {
                                for (String child : children) {
                                    if (child != null && (remote || resourceExists(child))) {
                                        results.add(child);
                                    }
                                }
                            }
                        } else {
                            temp = output;
                        }
                        temp.setContent(results.toArray(new String[results.size()]));
                    }
                    output = temp;
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .executeQuery(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
            return output;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .executeQuery(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public LogEntry[] getLogs(String resourcePath, int action, String userName, Date from, Date to,
            boolean recentFirst) throws RegistryException {
        boolean transactionSucceeded = false;
        try {
            // start the transaction
            beginTransaction();

            List logEntryList = logsDAO.getLogList(resourcePath, action, userName, from, to, recentFirst,
                    dataAccessManager);

            // We go on two iterations to avoid null values in the following array. Need better way
            // in a single iteration
            for (int i = logEntryList.size() - 1; i >= 0; i--) {
                LogEntry logEntry = (LogEntry) logEntryList.get(i);
                if (logEntry == null) {
                    logEntryList.remove(i);
                }
            }

            LogEntry[] logEntries = new LogEntry[logEntryList.size()];
            for (int i = 0; i < logEntryList.size(); i++) {
                logEntries[i] = (LogEntry) logEntryList.get(i);
            }

            // transaction succeeded
            transactionSucceeded = true;

            return logEntries;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public LogEntryCollection getLogCollection(String resourcePath, int action, String userName, Date from, Date to,
            boolean recentFirst) throws RegistryException {
        boolean transactionSucceeded = false;
        try {
            // start the transaction
            beginTransaction();

            LogEntryCollection logEntryCollection = new LogEntryCollection();
            logEntryCollection
                    .setLogCount(logsDAO.getLogsCount(resourcePath, action, userName, from, to, recentFirst));

            logEntryCollection.setDataAccessManager(dataAccessManager);
            logEntryCollection.setResourcePath(resourcePath);
            logEntryCollection.setAction(action);
            logEntryCollection.setUserName(userName);
            logEntryCollection.setFrom(from);
            logEntryCollection.setTo(to);
            logEntryCollection.setRecentFirst(recentFirst);

            // transaction succeeded
            transactionSucceeded = true;

            return logEntryCollection;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }

    }

    public String[] getAvailableAspects() {
        // we are using CallerTenantId instead of tenantId to preserve the tenant information
        // even this is called from a system registry, which anyway make just tenantId always = 0,
        // but keep the callerTenantId value to it is callers real tenant id
        return registryContext.getAspectNames(CurrentSession.getCallerTenantId());
    }

    public void associateAspect(String resourcePath, String aspectName) throws RegistryException {

        boolean transactionSucceeded = false;
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (!processedPath.isCurrentVersion()) {
                String msg = "Failed to associate aspectName to the resource " + processedPath
                        + ". Given path refers to an archived version of the resource.";
                log.error(msg);
                throw new RegistryException(msg);
            }

            resourcePath = processedPath.getPath();

            //TODO need to do the security validation here
            Resource resource = get(resourcePath);
            if ((resource.getAspects() == null) || (!resource.getAspects().contains(aspectName))) {
                Aspect aspect = getAspect(aspectName);
                if (aspect == null) {
                    throw new RegistryException("Couldn't find aspectName '" + aspectName + "'");
                }
                aspect.associate(resource, this);
                resource.addAspect(aspectName);
                String path = resource.getPath();
                put(path, resource);
                registryContext.getLogWriter().addLog(path, CurrentSession.getUser(), LogEntry.ASSOCIATE_ASPECT,
                        aspectName);
            }

            // transaction succeeded
            transactionSucceeded = true;

        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    private Aspect getAspect(String name) throws RegistryException {
        // we are using CallerTenantId instead of tenantId to preserve the tenant information
        // even this is called from a system registry, which anyway make just tenantId always = 0,
        // but keep the callerTenantId value to it is callers real tenant id
        return registryContext.getAspect(name, CurrentSession.getCallerTenantId());
    }

    public void invokeAspect(String resourcePath, String aspectName, String action) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (!processedPath.isCurrentVersion()) {
                String msg = "Failed to invoke aspect of the resource " + processedPath
                        + ". Given path refers to an archived version of the resource.";
                log.error(msg);
                throw new RegistryException(msg);
            }
            resourcePath = processedPath.getPath();

            Resource resource = get(resourcePath);

            Aspect aspect = getResourceAspect(resource, aspectName);
            context.setOldResource(get(resourcePath));
            context.setResource(resource);

            //        List aspectNames = resource.getPropertyValues(Aspect.AVAILABLE_ASPECTS);
            //        if (aspectNames == null) {
            //            throw new RegistryException("No aspect are associated with the resource");
            //        }
            context.setAspect(aspect);
            context.setAction(action);
            registryContext.getHandlerManager().invokeAspect(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    aspect.invoke(context, action);
                }
                resource.discard();

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .invokeAspect(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .invokeAspect(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void invokeAspect(String resourcePath, String aspectName, String action, Map<String, String> parameters)
            throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (!processedPath.isCurrentVersion()) {
                String msg = "Failed to invoke aspect of the resource " + processedPath
                        + ". Given path refers to an archived version of the resource.";
                log.error(msg);
                throw new RegistryException(msg);
            }
            resourcePath = processedPath.getPath();

            Resource resource = get(resourcePath);

            Aspect aspect = getResourceAspect(resource, aspectName);
            context.setOldResource(get(resourcePath));
            context.setResource(resource);

            for (Map.Entry<String, String> e : parameters.entrySet()) {
                context.setProperty(e.getKey(), e.getValue());
            }

            context.setProperty("parameterNames", Collections.unmodifiableSet(parameters.keySet()));

            //        List aspectNames = resource.getPropertyValues(Aspect.AVAILABLE_ASPECTS);
            //        if (aspectNames == null) {
            //            throw new RegistryException("No aspect are associated with the resource");
            //        }
            context.setAspect(aspect);
            context.setAction(action);
            registryContext.getHandlerManager().invokeAspect(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    aspect.invoke(context, action, parameters);
                }
                resource.discard();

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE)
                        .invokeAspect(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .invokeAspect(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    private Aspect getResourceAspect(Resource resource, String aspectName) throws RegistryException {

        boolean transactionSucceeded = false;
        try {
            // start the transaction
            beginTransaction();

            Aspect aspect = getAspect(aspectName);
            if (aspect == null) {
                throw new RegistryException("Aspect '" + aspectName + "' is not registered!");
            }

            // Confirm this aspect is associated with this Resource
            List<String> resourceAspects = resource.getAspects();
            if (resourceAspects == null || !resourceAspects.contains(aspectName)) {
                throw new RegistryException(
                        "Resource at '" + resource.getPath() + "' not associated with aspect '" + aspectName + "'");
            }

            // transaction succeeded
            transactionSucceeded = true;

            return aspect;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public String[] getAspectActions(String resourcePath, String aspectName) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath processedPath = new ResourcePath(resourcePath);
            if (!processedPath.isCurrentVersion()) {
                String msg = "Failed to get aspect actions of the resource " + processedPath
                        + ". Given path refers to an archived version of the resource.";
                log.error(msg);
                throw new RegistryException(msg);
            }
            resourcePath = processedPath.getPath();

            Resource resource = get(resourcePath);
            Aspect aspect = getResourceAspect(resource, aspectName);

            context.setResource(resource);
            String[] actions = aspect.getAvailableActions(context);

            // transaction succeeded
            transactionSucceeded = true;

            return actions;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public Collection searchContent(String keywords) throws RegistryException {

        /*RequestContext context = new RequestContext(this, repository, versionRepository);
            
        context.setKeywords(keywords);
        Collection output = registryContext.getHandlerManager().searchContent(context);
        if (!context.isSimulation()) {
        if (!context.isProcessingComplete()) {
            try {
                Searcher searcher = new IndexSearcher(registryContext.getJdbcDir());
                Query query =
                        new QueryParser("content", new StandardAnalyzer()).parse(keywords);
                Hits hits = searcher.search(query);
                org.wso2.carbon.registry.core.Collection collection = new CollectionImpl();
                String[] paths = new String[hits.length()];
                for (int i = 0; i < hits.length(); i++) {
                    paths[i] = hits.doc(i).get("id");
                }
                collection.setContent(paths);
                output = collection;
            } catch (IOException e) {
                String msg = "Failed to search content";
                log.error(msg, e);
                throw new RegistryException(msg, e);
            } catch (ParseException e) {
                String msg = "Failed to parse the query";
                log.error(msg, e);
                throw new RegistryException(msg, e);
            }
        }
        }
        return output;*/
        return null;
    }

    public void createLink(String path, String target) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            if (path.equals(target)) {
                String msg = "Path and target are same, path = target = " + path
                        + ". You can't create a symbolic link to itself.";
                log.error(msg);
                throw new RegistryException(msg);
            }
            // first put the data..
            Resource oldResource = repository.getMetaData(target);
            Resource resource;
            if (repository.resourceExists(path)) {
                resource = repository.get(path);
                resource.addProperty(RegistryConstants.REGISTRY_EXISTING_RESOURCE, "true");
            } else if (oldResource != null) {
                if (oldResource instanceof Collection) {
                    resource = new CollectionImpl();
                } else {
                    resource = new ResourceImpl();
                }
            } else {
                resource = new CollectionImpl();
            }
            resource.addProperty(RegistryConstants.REGISTRY_NON_RECURSIVE, "true");
            resource.addProperty(RegistryConstants.REGISTRY_LINK_RESTORATION, path + RegistryConstants.URL_SEPARATOR
                    + target + RegistryConstants.URL_SEPARATOR + CurrentSession.getUser());
            resource.setMediaType(RegistryConstants.LINK_MEDIA_TYPE);
            try {
                CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, false);
                repository.put(path, resource);
            } finally {
                CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
            }
            resource.discard();
            HandlerManager hm = registryContext.getHandlerManager();

            ResourcePath resourcePath = new ResourcePath(path);
            context.setResourcePath(resourcePath);
            context.setTargetPath(target);
            hm.createLink(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    RegistryUtils.registerHandlerForSymbolicLinks(registryContext, path, target,
                            CurrentSession.getUser());

                    String author = CurrentSession.getUser();
                    RegistryUtils.addMountEntry(RegistryUtils.getSystemRegistry(this), registryContext, path,
                            target, false, author);

                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, CurrentSession.getUser(),
                                LogEntry.CREATE_SYMBOLIC_LINK, target);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).createLink(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .createLink(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void createLink(String path, String target, String targetSubPath) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            Resource resource;

            if (repository.resourceExists(path)) {
                resource = repository.get(path);
                resource.addProperty(RegistryConstants.REGISTRY_EXISTING_RESOURCE, "true");
            } else {
                resource = new CollectionImpl();
            }
            resource.addProperty(RegistryConstants.REGISTRY_NON_RECURSIVE, "true");
            resource.addProperty(RegistryConstants.REGISTRY_LINK_RESTORATION,
                    path + RegistryConstants.URL_SEPARATOR + target + RegistryConstants.URL_SEPARATOR
                            + targetSubPath + RegistryConstants.URL_SEPARATOR + CurrentSession.getUser());
            resource.setMediaType(RegistryConstants.LINK_MEDIA_TYPE);
            try {
                CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, false);
                repository.put(path, resource);
            } finally {
                CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
            }
            resource.discard();

            HandlerManager hm = registryContext.getHandlerManager();

            ResourcePath resourcePath = new ResourcePath(path);
            context.setResourcePath(resourcePath);
            context.setTargetPath(target);
            context.setTargetSubPath(targetSubPath);
            hm.createLink(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    RegistryUtils.registerHandlerForRemoteLinks(registryContext, path, target, targetSubPath,
                            CurrentSession.getUser());

                    String author = CurrentSession.getUser();
                    RegistryUtils.addMountEntry(RegistryUtils.getSystemRegistry(this), registryContext, path,
                            target, targetSubPath, author);

                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, CurrentSession.getUser(),
                                LogEntry.CREATE_REMOTE_LINK, target + ";" + targetSubPath);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).createLink(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .createLink(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public void removeLink(String path) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            ResourcePath resourcePath = new ResourcePath(path);
            context.setResourcePath(resourcePath);
            registryContext.getHandlerManager().removeLink(context);

            // we will be removing the symlink handlers to remove
            Handler handlerToRemove = (Handler) context
                    .getProperty(RegistryConstants.SYMLINK_TO_REMOVE_PROPERTY_NAME);
            if (handlerToRemove != null) {
                registryContext.getHandlerManager().removeHandler(handlerToRemove,
                        HandlerLifecycleManager.TENANT_SPECIFIC_SYSTEM_HANDLER_PHASE);
            }

            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    try {
                        Collection mountCollection = (Collection) get(RegistryUtils.getAbsolutePath(registryContext,
                                RegistryConstants.LOCAL_REPOSITORY_BASE_PATH
                                        + RegistryConstants.SYSTEM_MOUNT_PATH));
                        String[] mountResources = mountCollection.getChildren();
                        Resource resource = null;
                        for (String mountResource : mountResources) {
                            String mountResName = mountResource.substring(mountResource.lastIndexOf('/') + 1);
                            String relativePath = RegistryUtils.getRelativePath(registryContext, path);
                            if (mountResName.equals(relativePath.replace("/", "-"))) {
                                resource = get(mountResource);
                                break;
                            }
                        }

                        if (resource == null) {
                            String msg = "Couldn't find the mount point to remove. ";
                            log.error(msg);
                            throw new RegistryException(msg);
                        }

                        RegistryUtils.getSystemRegistry(this).delete(resource.getPath());
                    } catch (ResourceNotFoundException ignored) {
                        // There can be situations where the mount resource is not found. In that
                        // case, we can simply ignore this exception being thrown. An example of
                        // such a situation is found in CARBON-12002.
                    }
                    if (repository.resourceExists(path)) {
                        Resource r = repository.get(path);
                        if (!Boolean.toString(true)
                                .equals(r.getProperty(RegistryConstants.REGISTRY_EXISTING_RESOURCE))) {
                            repository.delete(path);
                        }
                    }

                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, CurrentSession.getUser(), LogEntry.REMOVE_LINK,
                                null);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).removeLink(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .removeLink(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }

    }

    // check in, check out functionality

    public void restore(String path, Reader reader) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setDumpingReader(reader);
            context.setResourcePath(new ResourcePath(path));
            registryContext.getHandlerManager().restore(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    try {
                        CurrentSession.setAttribute(Repository.IS_LOGGING_ACTIVITY, context.isLoggingActivity());
                        repository.restore(path, reader);
                    } finally {
                        CurrentSession.removeAttribute(Repository.IS_LOGGING_ACTIVITY);
                    }
                    if (context.isLoggingActivity()) {
                        registryContext.getLogWriter().addLog(path, CurrentSession.getUser(), LogEntry.RESTORE,
                                null);
                    }
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).restore(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .restore(context);
                } finally {
                    rollbackTransaction();
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("total read: " + DumpReader.getTotalRead());
                log.debug("total buffered: " + DumpReader.getTotalBuffered());
                log.debug("maximum buffer size: " + DumpReader.getMaxBufferedSize());
                log.debug("total buffer read size: " + DumpReader.getTotalBufferedRead());
            }
        }
    }

    public void dump(String path, Writer writer) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setResourcePath(new ResourcePath(path));
            context.setDumpingWriter(writer);
            registryContext.getHandlerManager().dump(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    repository.dump(path, writer);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).dump(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE).dump(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }

    public String getEventingServiceURL(String path) throws RegistryException {
        if (path == null || eventingServiceURLs.size() == 0) {
            return defaultEventingServiceURL;
        }
        Set<Map.Entry<String, String>> entries = eventingServiceURLs.entrySet();
        for (Map.Entry<String, String> e : entries) {
            if (e.getValue() == null) {
                // Clean-up step
                eventingServiceURLs.remove(e.getKey());
            } else if (path.matches(e.getKey())) {
                return e.getValue();
            }
        }
        return defaultEventingServiceURL;

    }

    public void setEventingServiceURL(String path, String eventingServiceURL) throws RegistryException {
        if (path == null) {
            this.defaultEventingServiceURL = eventingServiceURL;
        } else {
            this.eventingServiceURLs.put(path, eventingServiceURL);
        }
    }

    public boolean addAspect(String name, Aspect aspect) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();
            // we are using CallerTenantId instead of tenantId to preserve the tenant information
            // even this is called from a system registry, which anyway makes tenantId always = 0,
            // but keep the callerTenantId value to it is callers real tenant id
            registryContext.addAspect(name, aspect, CurrentSession.getCallerTenantId());
            if (!context.isProcessingComplete()) {
                // transaction succeeded
                transactionSucceeded = true;
                return true;
            }
            return false;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public boolean removeAspect(String name) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();
            // we are using CallerTenantId instead of tenantId to preserve the tenant information
            // even this is called from a system registry, which anyway makes tenantId always = 0,
            // but keep the callerTenantId value to it is callers real tenant id
            registryContext.removeAspect(name, CurrentSession.getCallerTenantId());
            if (!context.isProcessingComplete()) {
                // transaction succeeded
                transactionSucceeded = true;
                return true;
            }
            return false;
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                rollbackTransaction();
            }
        }
    }

    public boolean removeVersionHistory(String path, long snapshotId) throws RegistryException {

        boolean transactionSucceeded = false;

        try {
            // start the transaction
            beginTransaction();

            versionRepository.removeVersionHistory(path, snapshotId);

            // transaction succeeded            
            transactionSucceeded = true;

        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {

                rollbackTransaction();
            }
        }

        return false;
    }

    @Override
    public void dumpLite(String path, Writer writer) throws RegistryException {
        boolean transactionSucceeded = false;
        RequestContext context = new RequestContext(this, repository, versionRepository);
        try {
            // start the transaction
            beginTransaction();

            context.setResourcePath(new ResourcePath(path));
            context.setDumpingWriter(writer);
            registryContext.getHandlerManager().dumpLite(context);
            if (!context.isSimulation()) {
                if (!context.isProcessingComplete()) {
                    repository.dumpLite(path, writer);
                }

                registryContext.getHandlerManager(HandlerLifecycleManager.COMMIT_HANDLER_PHASE).dumpLite(context);
                // transaction succeeded
                transactionSucceeded = true;
            }
        } finally {
            if (transactionSucceeded) {
                commitTransaction();
            } else {
                try {
                    registryContext.getHandlerManager(HandlerLifecycleManager.ROLLBACK_HANDLER_PHASE)
                            .dumpLite(context);
                } finally {
                    rollbackTransaction();
                }
            }
        }
    }
}