⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 txlockmanagerimpl.java

📁 jsr170接口的java实现。是个apache的开源项目。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * 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.webdav.jcr.transaction;import org.apache.jackrabbit.util.Text;import org.apache.jackrabbit.webdav.DavConstants;import org.apache.jackrabbit.webdav.DavException;import org.apache.jackrabbit.webdav.DavResource;import org.apache.jackrabbit.webdav.DavResourceLocator;import org.apache.jackrabbit.webdav.DavServletResponse;import org.apache.jackrabbit.webdav.WebdavResponse;import org.apache.jackrabbit.webdav.jcr.JcrDavException;import org.apache.jackrabbit.webdav.jcr.JcrDavSession;import org.apache.jackrabbit.webdav.lock.ActiveLock;import org.apache.jackrabbit.webdav.lock.LockInfo;import org.apache.jackrabbit.webdav.lock.LockManager;import org.apache.jackrabbit.webdav.lock.Scope;import org.apache.jackrabbit.webdav.lock.Type;import org.apache.jackrabbit.webdav.transaction.TransactionConstants;import org.apache.jackrabbit.webdav.transaction.TransactionInfo;import org.apache.jackrabbit.webdav.transaction.TransactionResource;import org.apache.jackrabbit.webdav.transaction.TxActiveLock;import org.apache.jackrabbit.webdav.transaction.TxLockManager;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.jcr.Item;import javax.jcr.PathNotFoundException;import javax.jcr.RepositoryException;import javax.jcr.Session;import javax.transaction.xa.XAException;import javax.transaction.xa.XAResource;import javax.transaction.xa.Xid;import java.util.HashMap;import java.util.Iterator;import java.util.IdentityHashMap;import java.util.Map;/** * <code>TxLockManagerImpl</code> manages locks with locktype * '{@link TransactionConstants#TRANSACTION dcr:transaction}'. * <p/> */ //todo: removing all expired locks //todo: 'local' and 'global' are not accurate terms in the given context > replace /*todo: the usage of the 'global' transaction is not according to the JTA specification,   which explicitely requires any transaction present on a servlet to be completed before   the service method returns. Starting/completing transactions on the session object,   which is possible with the jackrabbit implementation is a hack.*/ /*todo: review of this transaction part is therefore required. Is there a use-case   for those 'global' transactions at all...*/public class TxLockManagerImpl implements TxLockManager {    private static Logger log = LoggerFactory.getLogger(TxLockManagerImpl.class);    private TransactionMap map = new TransactionMap();    private Map listeners = new IdentityHashMap();    /**     * Create a new lock.     *     * @param lockInfo as present in the request body.     * @param resource     * @return the lock     * @throws DavException             if the lock could not be obtained.     * @throws IllegalArgumentException if the resource is <code>null</code> or     *                                  does not implement {@link TransactionResource} interface.     * @see LockManager#createLock(org.apache.jackrabbit.webdav.lock.LockInfo, org.apache.jackrabbit.webdav.DavResource)     */    public ActiveLock createLock(LockInfo lockInfo, DavResource resource)            throws DavException {        if (resource == null || !(resource instanceof TransactionResource)) {            throw new IllegalArgumentException("Invalid resource");        }        return createLock(lockInfo, (TransactionResource) resource);    }    /**     * Create a new lock.     *     * @param lockInfo     * @param resource     * @return the lock     * @throws DavException if the request lock has the wrong lock type or if     *                      the lock could not be obtained for any reason.     */    private synchronized ActiveLock createLock(LockInfo lockInfo, TransactionResource resource)            throws DavException {        if (!lockInfo.isDeep() || !TransactionConstants.TRANSACTION.equals(lockInfo.getType())) {            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);        }        ActiveLock existing = getLock(lockInfo.getType(), lockInfo.getScope(), resource);        if (existing != null) {            throw new DavException(DavServletResponse.SC_LOCKED);        }        // TODO: check for locks on member resources is required as well for lock is always deep!        Transaction tx = createTransaction(resource.getLocator(), lockInfo);        tx.start(resource);        // keep references to this lock        addReferences(tx, getMap(resource), resource);        return tx.getLock();    }    /**     * Build the transaction object associated by the lock.     *     * @param locator     * @param lockInfo     * @return     */    private Transaction createTransaction(DavResourceLocator locator, LockInfo lockInfo) {        if (TransactionConstants.GLOBAL.equals(lockInfo.getScope())) {            return new GlobalTransaction(locator, new TxActiveLock(lockInfo));        } else {            return new LocalTransaction(locator, new TxActiveLock(lockInfo));        }    }    /**     * Refresh the lock indentified by the given lock token.     *     * @param lockInfo     * @param lockToken     * @param resource     * @return the lock     * @throws DavException     * @throws IllegalArgumentException if the resource is <code>null</code> or     *                                  does not implement {@link TransactionResource} interface.     * @see LockManager#refreshLock(org.apache.jackrabbit.webdav.lock.LockInfo, String, org.apache.jackrabbit.webdav.DavResource)     */    public ActiveLock refreshLock(LockInfo lockInfo, String lockToken,                                  DavResource resource) throws DavException {        if (resource == null || !(resource instanceof TransactionResource)) {            throw new IllegalArgumentException("Invalid resource");        }        return refreshLock(lockInfo, lockToken, (TransactionResource) resource);    }    /**     * Reset the timeout of the lock identified by the given lock token.     *     * @param lockInfo     * @param lockToken     * @param resource     * @return     * @throws DavException if the lockdid not exist or is expired.     */    private synchronized ActiveLock refreshLock(LockInfo lockInfo, String lockToken,                                                TransactionResource resource) throws DavException {        TransactionMap responsibleMap = getMap(resource);        Transaction tx = responsibleMap.get(lockToken);        if (tx == null) {            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No valid transaction lock found for resource '" + resource.getResourcePath() + "'");        } else if (tx.getLock().isExpired()) {            removeExpired(tx, responsibleMap, resource);            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired.");        } else {            tx.getLock().setTimeout(lockInfo.getTimeout());        }        return tx.getLock();    }    /**     * Throws UnsupportedOperationException.     *     * @param lockToken     * @param resource     * @throws DavException     * @see LockManager#releaseLock(String, org.apache.jackrabbit.webdav.DavResource)     */    public void releaseLock(String lockToken, DavResource resource)            throws DavException {        throw new UnsupportedOperationException("A transaction lock can only be release with a TransactionInfo object and a lock token.");    }    /**     * Release the lock identified by the given lock token.     *     * @param lockInfo     * @param lockToken     * @param resource     * @throws DavException     */    public synchronized void releaseLock(TransactionInfo lockInfo, String lockToken,                                         TransactionResource resource) throws DavException {        if (resource == null) {            throw new IllegalArgumentException("Resource must not be null.");        }        TransactionMap responsibleMap = getMap(resource);        Transaction tx = responsibleMap.get(lockToken);        if (tx == null) {            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No transaction lock found for resource '" + resource.getResourcePath() + "'");        } else if (tx.getLock().isExpired()) {            removeExpired(tx, responsibleMap, resource);            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction lock for resource '" + resource.getResourcePath() + "' was already expired.");        } else {            if (lockInfo.isCommit()) {                TransactionListener[] txListeners;                synchronized (listeners) {                    txListeners = (TransactionListener[]) listeners.values().toArray(new TransactionListener[0]);                }                for (int i = 0; i < txListeners.length; i++) {                    txListeners[i].beforeCommit(resource, lockToken);                }                DavException ex = null;                try {                    tx.commit(resource);                } catch (DavException e) {                    ex = e;                }                for (int i = 0; i < txListeners.length; i++) {                    txListeners[i].afterCommit(resource, lockToken, ex == null);                }                if (ex != null) {                    throw ex;                }            } else {                tx.rollback(resource);            }            removeReferences(tx, responsibleMap, resource);        }    }    /**     * Always returns null     *     * @param type     * @param scope     * @param resource     * @return null     * @see #getLock(Type, Scope, TransactionResource)     * @see LockManager#getLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope, org.apache.jackrabbit.webdav.DavResource)     */    public ActiveLock getLock(Type type, Scope scope, DavResource resource) {        return null;    }    /**     * Returns true if the given lock token belongs to a lock that applies to     * the given resource, false otherwise. The token may either be retrieved     * from the {@link DavConstants#HEADER_LOCK_TOKEN Lock-Token header} or     * from the {@link TransactionConstants#HEADER_TRANSACTIONID TransactionId header}.     *     * @param token     * @param resource     * @return     * @see LockManager#hasLock(String token, DavResource resource)     */    public boolean hasLock(String token, DavResource resource) {        return getLock(token, null, resource) != null;    }    /**     * Return the lock applied to the given resource or <code>null</code>     *     * @param type     * @param scope     * @param resource     * @return lock applied to the given resource or <code>null</code>     * @see LockManager#getLock(Type, Scope, DavResource)     *      todo: is it correct to return one that specific lock, the current session is token-holder of?     */    public ActiveLock getLock(Type type, Scope scope, TransactionResource resource) {        ActiveLock lock = null;        if (TransactionConstants.TRANSACTION.equals(type)) {            String[] sessionTokens = resource.getSession().getLockTokens();            int i = 0;            while (lock == null && i < sessionTokens.length) {                String lockToken = sessionTokens[i];                lock = getLock(lockToken, scope, resource);                i++;            }        }        return lock;    }    //-----------------------------< listener support >-------------------------    /**     * Adds a transaction listener to this <code>TxLockManager</code>.     * @param listener the listener to add.     */    public void addTransactionListener(TransactionListener listener) {        synchronized (listeners) {            listeners.put(listener, listener);        }    }    /**     * Removes a transaction listener from this <code>TxLockManager</code>.     * @param listener the listener to remove.     */    public void removeTransactionListener(TransactionListener listener) {        synchronized (listeners) {            listeners.remove(listener);        }    }    /**     * @param lockToken     * @param resource     * @return     */    private ActiveLock getLock(String lockToken, Scope scope, DavResource resource) {        if (!(resource instanceof TransactionResource)) {            log.warn("TransactionResource expected");            return null;        }        ActiveLock lock = null;        Transaction tx = null;        TransactionMap m = map;        // check if main-map contains that txId        if (m.containsKey(lockToken)) {            tx = m.get(lockToken);        } else {            // look through all the nested tx-maps (i.e. global txs) for the given txId            Iterator it = m.values().iterator();            while (it.hasNext() && tx == null) {                Transaction txMap = (Transaction) it.next();                if (!txMap.isLocal()) {                    m = ((TransactionMap) txMap);                    if (m.containsKey(lockToken)) {                        tx = ((TransactionMap) txMap).get(lockToken);                    }                }            }        }        if (tx != null) {            if (tx.getLock().isExpired()) {                removeExpired(tx, m, (TransactionResource) resource);            } else if (tx.appliesToResource(resource) && (scope == null || tx.getLock().getScope().equals(scope))) {                lock = tx.getLock();            }        }        return lock;    }    /**     * Return the map that may contain a transaction lock for the given resource.     * In case the resource provides a transactionId, the map must be a     * repository transaction that is identified by the given id and which in     * turn can act as map.     *     * @param resource     * @return responsible map.     * @throws DavException if no map could be retrieved.     */    private TransactionMap getMap(TransactionResource resource)            throws DavException {        String txKey = resource.getTransactionId();        if (txKey == null) {

⌨️ 快捷键说明

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