org.opencms.lock.CmsLockUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.opencms.lock.CmsLockUtil.java

Source

/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.lock;

import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.gwt.Messages;
import org.opencms.lock.CmsLockActionRecord.LockChange;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.util.CmsFileUtil;

import java.io.Closeable;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;

import com.google.common.collect.Maps;

/**
 * Locking utility class.<p>
 */
public final class CmsLockUtil {

    /** Helper to handle the lock reports together with the files. */
    public static final class LockedFile {

        /** The cms object used for locking, unlocking and encoding determination. */
        private CmsObject m_cms;
        /** The file that was read. */
        private CmsFile m_file;
        /** The lock action record from locking the file. */
        private CmsLockActionRecord m_lockRecord;
        /** Flag, indicating if the file was newly created. */
        private boolean m_new;

        /** Private constructor.
         * @param cms the cms user context.
         * @param resource the resource to lock and read.
         * @throws CmsException thrown if locking fails.
         */
        private LockedFile(CmsObject cms, CmsResource resource) throws CmsException {
            m_lockRecord = CmsLockUtil.ensureLock(cms, resource);
            m_file = cms.readFile(resource);
            m_new = false;
            m_cms = cms;
        }

        /**
         * Lock and read a file.
         * @param cms the cms user context.
         * @param resource the resource to lock and read.
         * @return the read file with the lock action record.
         * @throws CmsException thrown if locking fails
         */
        public static LockedFile lockResource(CmsObject cms, CmsResource resource) throws CmsException {

            return new LockedFile(cms, resource);
        }

        /**
         * Returns the encoding used for the file.
         *
         * @see CmsFileUtil#getEncoding(CmsObject, CmsResource)
         *
         * @return the encoding used for the file.
         */
        public String getEncoding() {

            return CmsFileUtil.getEncoding(m_cms, m_file);

        }

        /** Returns the file.
         * @return the file.
         */
        public CmsFile getFile() {

            return m_file;
        }

        /** Returns the lock action record.
         * @return the lock action record.
         */
        public CmsLockActionRecord getLockActionRecord() {

            return m_lockRecord;
        }

        /**
         * Returns a flag, indicating if the file is newly created.
         * @return flag, indicating if the file is newly created.
         */
        public boolean isCreated() {

            return m_new;
        }

        /**
         * Set the flag, indicating if the file was newly created.
         * @param isNew flag, indicating if the file was newly created.
         */
        public void setCreated(boolean isNew) {

            m_new = isNew;

        }

        public boolean unlock() throws CmsException {

            if (!m_lockRecord.getChange().equals(LockChange.unchanged) || m_new) {
                m_cms.unlockResource(m_file);
                return true;
            } else {
                return false;
            }
        }

    }

    /** Logger instance for this class. */
    private static final Log LOG = CmsLog.getLog(CmsLockUtil.class);

    /**
     * Hidden constructor.
     */
    private CmsLockUtil() {
        // Hide constructor for util class
    }

    /**
     * Static helper method to lock a resource.<p>
     *
     * @param cms the CMS context to use
     * @param resource the resource to lock
     * @return the action that was taken
     *
     * @throws CmsException if something goes wrong
     */
    public static CmsLockActionRecord ensureLock(CmsObject cms, CmsResource resource) throws CmsException {

        LockChange change = LockChange.unchanged;
        List<CmsResource> blockingResources = cms.getBlockingLockedResources(resource);
        if ((blockingResources != null) && !blockingResources.isEmpty()) {
            throw new CmsException(Messages.get().container(Messages.ERR_RESOURCE_HAS_BLOCKING_LOCKED_CHILDREN_1,
                    cms.getSitePath(resource)));
        }
        CmsUser user = cms.getRequestContext().getCurrentUser();
        CmsLock lock = cms.getLock(resource);
        if (!lock.isOwnedBy(user)) {
            cms.lockResourceTemporary(resource);
            change = LockChange.locked;
            lock = cms.getLock(resource);
        } else if (!lock.isOwnedInProjectBy(user, cms.getRequestContext().getCurrentProject())) {
            cms.changeLock(resource);
            change = LockChange.changed;
            lock = cms.getLock(resource);
        }
        return new CmsLockActionRecord(lock, change);
    }

    /**
     * Utility method for locking and unlocking a set of resources conveniently with the try-with syntax
     * from Java 1.7.<p>
     *
     * This method locks a set of resources and returns a Closeable instance that will unlock the locked resources
     * when its close() method is called.
     *
     * @param cms the CMS context
     * @param resources the resources to lock
     *
     * @return the Closeable used to unlock the resources
     * @throws Exception if something goes wrong
     */
    public static Closeable withLockedResources(final CmsObject cms, CmsResource... resources) throws Exception {

        final Map<CmsResource, CmsLockActionRecord> lockMap = Maps.newHashMap();
        Closeable result = new Closeable() {

            @SuppressWarnings("synthetic-access")
            public void close() {

                for (Map.Entry<CmsResource, CmsLockActionRecord> entry : lockMap.entrySet()) {
                    if (entry.getValue().getChange() == LockChange.locked) {
                        CmsResource resourceToUnlock = entry.getKey();
                        // the resource may have been moved, so we read it again to get the correct path
                        try {
                            resourceToUnlock = cms.readResource(entry.getKey().getStructureId(),
                                    CmsResourceFilter.ALL);
                        } catch (CmsException e) {
                            LOG.error(e.getLocalizedMessage(), e);
                        }
                        try {
                            cms.unlockResource(resourceToUnlock);
                        } catch (CmsException e) {
                            LOG.warn(e.getLocalizedMessage(), e);
                        }
                    }

                }
            }
        };
        try {
            for (CmsResource resource : resources) {
                CmsLockActionRecord record = ensureLock(cms, resource);
                lockMap.put(resource, record);
            }
        } catch (CmsException e) {
            result.close();
            throw e;
        }
        return result;
    }

}