cmslockmanager.java

来自「找了很久才找到到源代码」· Java 代码 · 共 900 行 · 第 1/3 页

JAVA
900
字号
/*
 * File   : $Source: /usr/local/cvs/opencms/src/org/opencms/lock/CmsLockManager.java,v $
 * Date   : $Date: 2007-09-07 12:02:16 $
 * Version: $Revision: 1.45 $
 *
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) 2002 - 2007 Alkacon Software GmbH (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 GmbH, 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.db.CmsDbContext;
import org.opencms.db.CmsDriverManager;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.file.CmsVfsResourceNotFoundException;
import org.opencms.i18n.CmsMessageContainer;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsUUID;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * The CmsLockManager is used by the Cms application to detect 
 * the lock state of a resource.<p>
 * 
 * The lock state depends on the path of the resource, and probably 
 * locked parent folders. The result of a query to the lock manager
 * are instances of CmsLock objects.<p>
 * 
 * @author Michael Emmerich 
 * @author Thomas Weckert  
 * @author Andreas Zahner  
 * @author Michael Moossen  
 * 
 * @version $Revision: 1.45 $ 
 * 
 * @since 6.0.0 
 * 
 * @see org.opencms.file.CmsObject#getLock(CmsResource)
 * @see org.opencms.lock.CmsLock
 */
public final class CmsLockManager {

    /** The driver manager instance. */
    private CmsDriverManager m_driverManager;

    /** The flag to indicate if the locks should be written to the db. */
    private boolean m_isDirty = false;

    /** The flag to indicate if the lock manager has been started in run level 4. */
    private boolean m_runningInServlet = false;

    /**
     * Default constructor, creates a new lock manager.<p>
     * 
     * @param driverManager the driver manager instance 
     */
    public CmsLockManager(CmsDriverManager driverManager) {

        m_driverManager = driverManager;
    }

    /**
     * Adds a resource to the lock manager.<p>
     * 
     * @param dbc the current database context
     * @param resource the resource
     * @param user the user who locked the resource
     * @param project the project where the resource is locked
     * @param type the lock type
     * 
     * @throws CmsLockException if the resource is locked
     * @throws CmsException if something goes wrong
     */
    public void addResource(CmsDbContext dbc, CmsResource resource, CmsUser user, CmsProject project, CmsLockType type)
    throws CmsLockException, CmsException {

        // check the type
        if (!type.isSystem() && !type.isExclusive()) {
            // invalid type
            throw new CmsLockException(Messages.get().container(Messages.ERR_INVALID_LOCK_TYPE_1, type.toString()));
        }

        // get the current lock
        CmsLock currentLock = getLock(dbc, resource);

        // check lockability
        checkLockable(dbc, resource, user, project, type, currentLock);

        boolean needNewLock = true;
        // prevent shared locks get compromised
        if ((type.isExclusive()) && !(type.isTemporary() && currentLock.isInherited())) {
            if (!currentLock.getEditionLock().isUnlocked()) {
                needNewLock = false;
            }
        }

        CmsLock newLock = CmsLock.getNullLock();
        if (needNewLock) {
            // lock the resource
            newLock = new CmsLock(resource.getRootPath(), user.getId(), project, type);
            lockResource(newLock);
        }

        // handle collisions with exclusive locked sub-resources in case of a folder
        if (resource.isFolder() && newLock.getSystemLock().isUnlocked()) {
            String resourceName = resource.getRootPath();
            Iterator itLocks = OpenCms.getMemoryMonitor().getAllCachedLocks().iterator();
            while (itLocks.hasNext()) {
                CmsLock lock = (CmsLock)itLocks.next();
                String lockedPath = lock.getResourceName();
                if (lockedPath.startsWith(resourceName) && !lockedPath.equals(resourceName)) {
                    unlockResource(lockedPath, false);
                }
            }
        }
    }

    /**
     * Counts the exclusive locked resources in a project.<p>
     * 
     * @param project the project
     * 
     * @return the number of exclusive locked resources in the specified project
     */
    public int countExclusiveLocksInProject(CmsProject project) {

        int count = 0;
        Iterator itLocks = OpenCms.getMemoryMonitor().getAllCachedLocks().iterator();
        while (itLocks.hasNext()) {
            CmsLock lock = (CmsLock)itLocks.next();
            if (lock.getEditionLock().isInProject(project)) {
                count++;
            }
        }
        return count;
    }

    /**
     * Returns the lock state of the given resource.<p>
     * 
     * In case no lock is set, the <code>null lock</code> which can be obtained 
     * by {@link CmsLock#getNullLock()} is returned.<p>
     * 
     * @param dbc the current database context
     * @param resource the resource
     * 
     * @return the lock state of the given resource 

     * @throws CmsException if something goes wrong
     */
    public CmsLock getLock(CmsDbContext dbc, CmsResource resource) throws CmsException {

        return getLock(dbc, resource, true);
    }

    /**
     * Returns the lock state of the given resource.<p>
     * 
     * In case no lock is set, the <code>null lock</code> which can be obtained 
     * by {@link CmsLock#getNullLock()} is returned.<p>
     * 
     * @param dbc the current database context
     * @param resource the resource
     * @param includeSiblings if siblings (shared locks) should be included in the search
     * 
     * @return the lock state of the given resource 

     * @throws CmsException if something goes wrong
     */
    public CmsLock getLock(CmsDbContext dbc, CmsResource resource, boolean includeSiblings) throws CmsException {

        // resources are never locked in the online project
        // and non-existent resources are never locked
        if ((resource == null) || (dbc.currentProject().isOnlineProject())) {
            return CmsLock.getNullLock();
        }

        // check exclusive direct locks first
        CmsLock lock = getDirectLock(resource.getRootPath());
        if ((lock == null) && includeSiblings) {
            // check if siblings are exclusively locked
            List siblings = internalReadSiblings(dbc, resource);
            lock = getSiblingsLock(siblings, resource.getRootPath());
        }
        if (lock == null) {
            // if there is no parent lock, this will be the null lock as well
            lock = getParentLock(resource.getRootPath());
        }
        if (!lock.getSystemLock().isUnlocked()) {
            lock = lock.getSystemLock();
        } else {
            lock = lock.getEditionLock();
        }
        return lock;
    }

    /**
     * Returns all exclusive locked resources matching the given resource name and filter.<p>
     * 
     * @param dbc the database context
     * @param resourceName the resource name
     * @param filter the lock filter
     * 
     * @return a list of root paths
     * 
     * @throws CmsException if something goes wrong 
     */
    public List getLocks(CmsDbContext dbc, String resourceName, CmsLockFilter filter) throws CmsException {

        List locks = new ArrayList();
        Iterator itLocks = OpenCms.getMemoryMonitor().getAllCachedLocks().iterator();
        while (itLocks.hasNext()) {
            CmsLock lock = (CmsLock)itLocks.next();
            if (filter.isSharedExclusive()) {
                CmsResource resource;
                try {
                    resource = m_driverManager.readResource(dbc, lock.getResourceName(), CmsResourceFilter.ALL);
                } catch (CmsVfsResourceNotFoundException e) {
                    OpenCms.getMemoryMonitor().uncacheLock(lock.getResourceName());
                    continue;
                }
                if (resource.getSiblingCount() > 1) {
                    Iterator itSiblings = internalReadSiblings(dbc, resource).iterator();
                    while (itSiblings.hasNext()) {
                        CmsResource sibling = (CmsResource)itSiblings.next();
                        CmsLock siblingLock = internalSiblingLock(lock, sibling.getRootPath());
                        if (filter.match(resourceName, siblingLock)) {
                            locks.add(siblingLock);
                        }
                    }
                }
            }
            if (filter.match(resourceName, lock)) {
                locks.add(lock);
            }
        }
        return locks;
    }

    /**
     * Returns <code>true</code> if the given resource contains a resource that has a system lock.<p>
     * 
     * This check is required for certain operations on folders.<p> 
     * 
     * @param dbc the database context
     * @param resource the resource to check the system locks for
     * 
     * @return <code>true</code> if the given resource contains a resource that has a system lock
     * 
     * @throws CmsException if something goes wrong 
     */
    public boolean hasSystemLocks(CmsDbContext dbc, CmsResource resource) throws CmsException {

        if (resource == null) {
            return false;
        }
        Iterator itLocks = OpenCms.getMemoryMonitor().getAllCachedLocks().iterator();
        while (itLocks.hasNext()) {
            CmsLock lock = (CmsLock)itLocks.next();
            if (lock.getSystemLock().isUnlocked()) {
                // only system locks matter here
                continue;
            }
            if (lock.getResourceName().startsWith(resource.getRootPath())) {
                if (lock.getResourceName().startsWith(resource.getRootPath())) {
                    return true;
                }
                try {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?