📄 txlockmanagerimpl.java
字号:
return map; } else { if (!map.containsKey(txKey)) { throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Transaction map '" + map + " does not contain a transaction with TransactionId '" + txKey + "'."); } Transaction tx = map.get(txKey); if (tx.isLocal()) { throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "TransactionId '" + txKey + "' points to a local transaction, that cannot act as transaction map"); } else if (tx.getLock() != null && tx.getLock().isExpired()) { removeExpired(tx, map, resource); throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to retrieve an expired global transaction."); } // tx is a global transaction that acts as map as well. return (TransactionMap) tx; } } /** * Rollbacks the specified transaction and releases the lock. This includes * the removal of all references. * * @param tx * @param responsibleMap * @param resource */ private static void removeExpired(Transaction tx, TransactionMap responsibleMap, TransactionResource resource) { log.debug("Removing expired transaction lock " + tx); try { tx.rollback(resource); removeReferences(tx, responsibleMap, resource); } catch (DavException e) { log.error("Error while removing expired transaction lock: " + e.getMessage()); } } /** * Create the required references to the new transaction specified by tx. * * @param tx * @param responsibleMap * @param resource * @throws DavException */ private static void addReferences(Transaction tx, TransactionMap responsibleMap, TransactionResource resource) throws DavException { log.debug("Adding transactionId '" + tx.getId() + "' as session lock token."); resource.getSession().addLockToken(tx.getId()); responsibleMap.put(tx.getId(), tx); resource.getSession().addReference(tx.getId()); } /** * Remove all references to the specified transaction. * * @param tx * @param responsibleMap * @param resource */ private static void removeReferences(Transaction tx, TransactionMap responsibleMap, TransactionResource resource) { log.debug("Removing transactionId '" + tx.getId() + "' from session lock tokens."); resource.getSession().removeLockToken(tx.getId()); responsibleMap.remove(tx.getId()); resource.getSession().removeReference(tx.getId()); } /** * @param resource * @return JCR session */ private static Session getRepositorySession(TransactionResource resource) throws DavException { return JcrDavSession.getRepositorySession(resource.getSession()); } //------------------------------------------< inner classes, interfaces >--- /** * Internal <code>Transaction</code> interface */ private interface Transaction { TxActiveLock getLock(); /** * @return the id of this transaction. */ String getId(); /** * @return path of the lock holding resource */ String getResourcePath(); /** * @param resource * @return true if the lock defined by this transaction applies to the * given resource, either due to the resource holding that lock or due * to a deep lock hold by any ancestor resource. */ boolean appliesToResource(DavResource resource); /** * @return true if this transaction is used to allow for transient changes * on the underlying repository, that may be persisted with the final * UNLOCK request only. */ boolean isLocal(); /** * Start this transaction. * * @param resource * @throws DavException if an error occurs. */ void start(TransactionResource resource) throws DavException; /** * Commit this transaction * * @param resource * @throws DavException if an error occurs. */ void commit(TransactionResource resource) throws DavException; /** * Rollback this transaction. * * @param resource * @throws DavException if an error occurs. */ void rollback(TransactionResource resource) throws DavException; } /** * Abstract transaction covering functionally to both implementations. */ private abstract static class AbstractTransaction extends TransactionMap implements Transaction { private final DavResourceLocator locator; private final TxActiveLock lock; private AbstractTransaction(DavResourceLocator locator, TxActiveLock lock) { this.locator = locator; this.lock = lock; } /** * @see #getLock() */ public TxActiveLock getLock() { return lock; } /** * @see #getId() */ public String getId() { return lock.getToken(); } /** * @see #getResourcePath() */ public String getResourcePath() { return locator.getResourcePath(); } /** * @see #appliesToResource(DavResource) */ public boolean appliesToResource(DavResource resource) { if (locator.isSameWorkspace(resource.getLocator())) { String lockResourcePath = getResourcePath(); String resPath = resource.getResourcePath(); while (!"".equals(resPath)) { if (lockResourcePath.equals(resPath)) { return true; } resPath = Text.getRelativeParent(resPath, 1); } } return false; } } /** * */ private final static class LocalTransaction extends AbstractTransaction { private LocalTransaction(DavResourceLocator locator, TxActiveLock lock) { super(locator, lock); } public boolean isLocal() { return true; } public void start(TransactionResource resource) throws DavException { try { // make sure, the given resource represents an existing repository item if (!getRepositorySession(resource).itemExists(resource.getLocator().getRepositoryPath())) { throw new DavException(DavServletResponse.SC_CONFLICT, "Unable to start local transaction: no repository item present at " + getResourcePath()); } } catch (RepositoryException e) { log.error("Unexpected error: " + e.getMessage()); throw new JcrDavException(e); } } public void commit(TransactionResource resource) throws DavException { try { getItem(resource).save(); } catch (RepositoryException e) { throw new JcrDavException(e); } } public void rollback(TransactionResource resource) throws DavException { try { getItem(resource).refresh(false); } catch (RepositoryException e) { throw new JcrDavException(e); } } private Item getItem(TransactionResource resource) throws PathNotFoundException, RepositoryException, DavException { String itemPath = resource.getLocator().getRepositoryPath(); return getRepositorySession(resource).getItem(itemPath); } public Transaction put(String key, Transaction value) throws DavException { throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest a new transaction into a local one."); } } /** * */ private static class GlobalTransaction extends AbstractTransaction { private Xid xid; private GlobalTransaction(DavResourceLocator locator, TxActiveLock lock) { super(locator, lock); xid = new XidImpl(lock.getToken()); } public boolean isLocal() { return false; } public void start(TransactionResource resource) throws DavException { XAResource xaRes = getXAResource(resource); try { xaRes.setTransactionTimeout((int) getLock().getTimeout() / 1000); xaRes.start(xid, XAResource.TMNOFLAGS); } catch (XAException e) { throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); } } public void commit(TransactionResource resource) throws DavException { XAResource xaRes = getXAResource(resource); try { xaRes.commit(xid, false); removeLocalTxReferences(resource); } catch (XAException e) { throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); } } public void rollback(TransactionResource resource) throws DavException { XAResource xaRes = getXAResource(resource); try { xaRes.rollback(xid); removeLocalTxReferences(resource); } catch (XAException e) { throw new DavException(DavServletResponse.SC_FORBIDDEN, e.getMessage()); } } private XAResource getXAResource(TransactionResource resource) throws DavException { /* // commented, since server should be jackrabbit independant Session session = resource.getSession().getRepositorySession(); if (session instanceof XASession) { return ((XASession)session).getXAResource(); } else { throw new DavException(DavServletResponse.SC_FORBIDDEN); } */ throw new DavException(DavServletResponse.SC_FORBIDDEN); } private void removeLocalTxReferences(TransactionResource resource) { Iterator it = values().iterator(); while (it.hasNext()) { Transaction tx = (Transaction) it.next(); removeReferences(tx, this, resource); } } public Transaction put(String key, Transaction value) throws DavException { if (!(value instanceof LocalTransaction)) { throw new DavException(WebdavResponse.SC_PRECONDITION_FAILED, "Attempt to nest global transaction into a global one."); } return (Transaction) super.put(key, value); } } /** * */ private static class TransactionMap extends HashMap { public Transaction get(String key) { Transaction tx = null; if (containsKey(key)) { tx = (Transaction) super.get(key); } return tx; } public Transaction put(String key, Transaction value) throws DavException { // any global an local transactions allowed. return (Transaction) super.put(key, value); } } /** * Private class implementing Xid interface. */ private static class XidImpl implements Xid { private final String id; /** * Create a new Xid * * @param id */ private XidImpl(String id) { this.id = id; } /** * @return 1 * @see javax.transaction.xa.Xid#getFormatId() */ public int getFormatId() { // todo: define reasonable format id return 1; } /** * @return an empty byte array. * @see javax.transaction.xa.Xid#getBranchQualifier() */ public byte[] getBranchQualifier() { return new byte[0]; } /** * @return id as byte array * @see javax.transaction.xa.Xid#getGlobalTransactionId() */ public byte[] getGlobalTransactionId() { return id.getBytes(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -