Package org.apache.jackrabbit.oak.jcr.lock

Source Code of org.apache.jackrabbit.oak.jcr.lock.LockManagerImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.jcr.lock;

import java.util.Set;

import javax.annotation.Nonnull;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.lock.LockManager;

import org.apache.jackrabbit.oak.api.Tree.Status;
import org.apache.jackrabbit.oak.jcr.session.SessionContext;
import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
import org.apache.jackrabbit.oak.jcr.session.operation.SessionOperation;

/**
* Simple lock manager implementation that just keeps track of a set of lock
* tokens and delegates all locking operations back to the {@link Session}
* and {@link Node} implementations.
*/
public class LockManagerImpl implements LockManager {

    private final SessionContext sessionContext;

    private final SessionDelegate delegate;

    public LockManagerImpl(SessionContext sessionContext) {
        this.sessionContext = sessionContext;
        this.delegate = sessionContext.getSessionDelegate();
    }

    @Override @Nonnull
    public String[] getLockTokens() throws RepositoryException {
        return perform(new SessionOperation<String[]>() {
            @Override @Nonnull
            public String[] perform() {
                Set<String> tokens = sessionContext.getOpenScopedLocks();
                return tokens.toArray(new String[tokens.size()]);
            }
        });
    }

    @Override
    public void addLockToken(final String lockToken)
            throws RepositoryException {
        try {
            perform(new LockOperation<String>(sessionContext, lockToken) {
                @Override
                protected String perform(NodeDelegate node)
                        throws LockException {
                    if (node.holdsLock(false)) {
                        String token = node.getPath();
                        sessionContext.getOpenScopedLocks().add(token);
                        return null;
                    } else {
                        throw new LockException(
                                "Invalid lock token: " + lockToken);
                    }
                }
            });
        } catch (IllegalArgumentException e) { // TODO: better exception
            throw new LockException("Invalid lock token: " + lockToken);
        }
    }

    @Override
    public void removeLockToken(final String lockToken)
            throws RepositoryException {
        if (!perform(new SessionOperation<Boolean>() {
            @Override @Nonnull
            public Boolean perform() {
                // TODO: name mapping?
                return sessionContext.getOpenScopedLocks().remove(lockToken);
            }
        })) {
            throw new LockException(
                    "Lock token " + lockToken + " is not held by this session");
        }
    }

    @Override
    public boolean isLocked(String absPath) throws RepositoryException {
        return perform(new LockOperation<Boolean>(sessionContext, absPath) {
            @Override
            protected Boolean perform(NodeDelegate node) {
                return node.isLocked();
            }
        });
    }

    @Override
    public boolean holdsLock(String absPath) throws RepositoryException {
        return perform(new LockOperation<Boolean>(sessionContext, absPath) {
            @Override
            protected Boolean perform(NodeDelegate node) {
                return node.holdsLock(false);
            }
        });
    }

    @Override @Nonnull
    public Lock getLock(String absPath) throws RepositoryException {
        NodeDelegate lock = perform(
                new LockOperation<NodeDelegate>(sessionContext, absPath) {
                    @Override
                    protected NodeDelegate perform(NodeDelegate node) {
                        return node.getLock();
                    }
                });
        if (lock != null) {
            return new LockImpl(sessionContext, lock);
        } else {
            throw new LockException("Node " + absPath + " is not locked");
        }
    }

    @Override @Nonnull
    public Lock lock(
            String absPath, final boolean isDeep, final boolean isSessionScoped,
            long timeoutHint, String ownerInfo) throws RepositoryException {
        return new LockImpl(sessionContext, perform(
                new LockOperation<NodeDelegate>(sessionContext, absPath) {
                    @Override
                    protected NodeDelegate perform(NodeDelegate node)
                            throws RepositoryException {
                        if (node.getStatus() != Status.EXISTING) {
                            throw new InvalidItemStateException(
                                    "Unable to lock a node with pending changes");
                        }
                        node.lock(isDeep);
                        String path = node.getPath();
                        if (isSessionScoped) {
                            sessionContext.getSessionScopedLocks().add(path);
                        } else {
                            sessionContext.getOpenScopedLocks().add(path);
                        }
                        session.refresh(true);
                        return node;
                    }
                }));
    }

    @Override
    public void unlock(String absPath) throws RepositoryException {
        perform(new LockOperation<Void>(sessionContext, absPath) {
            @Override
            protected Void perform(NodeDelegate node)
                    throws RepositoryException {
                String path = node.getPath();
                if (sessionContext.getSessionScopedLocks().contains(path)
                        || sessionContext.getOpenScopedLocks().contains(path)) {
                    node.unlock();
                    sessionContext.getSessionScopedLocks().remove(path);
                    sessionContext.getOpenScopedLocks().remove(path);
                    session.refresh(true);
                    return null;
                } else {
                    throw new LockException("Not an owner of the lock " + path);
                }
            }
        });
    }

    private <T> T perform(SessionOperation<T> operation)
            throws RepositoryException {
        return delegate.perform(operation);
    }

}
TOP

Related Classes of org.apache.jackrabbit.oak.jcr.lock.LockManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.