You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2005/09/07 16:18:37 UTC
svn commit: r279325 - in /incubator/jackrabbit/trunk/core/src:
java/org/apache/jackrabbit/core/ java/org/apache/jackrabbit/core/lock/
test/org/apache/jackrabbit/test/api/lock/
Author: dpfister
Date: Wed Sep 7 07:18:06 2005
New Revision: 279325
URL: http://svn.apache.org/viewcvs?rev=279325&view=rev
Log:
Fixed JCR-155 and JCR-207
Modified:
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/NodeImpl.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/PathMap.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
incubator/jackrabbit/trunk/core/src/test/org/apache/jackrabbit/test/api/lock/LockTest.java
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=279325&r1=279324&r2=279325&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Wed Sep 7 07:18:06 2005
@@ -119,7 +119,7 @@
builder.addLast(elements[i]);
}
Path parentPath = builder.getPath();
- cache(state, parentPath);
+ cache((NodeState) state, parentPath);
} catch (MalformedPathException mpe) {
log.warn("Failed to build path of " + state.getId(), mpe);
}
@@ -159,7 +159,7 @@
if (state.isNode()) {
try {
- cache(state, builder.getPath());
+ cache((NodeState) state, builder.getPath());
} catch (MalformedPathException mpe) {
log.warn("Failed to build path of " + state.getId());
}
@@ -271,6 +271,42 @@
* {@inheritDoc}
*/
public void stateModified(ItemState modified) {
+ stateModified((NodeState) modified);
+ }
+
+ /**
+ * Evict moved or renamed items from the cache.
+ */
+ private void stateModified(NodeState modified) {
+ synchronized (cacheMonitor) {
+ LRUEntry entry = (LRUEntry) idCache.get(modified.getId());
+ if (entry == null) {
+ // Item not cached, ignore
+ return;
+ }
+
+ PathMap.Element element = entry.getElement();
+
+ Iterator iter = element.getChildren();
+ while (iter.hasNext()) {
+ PathMap.Element child = (PathMap.Element) iter.next();
+ NodeState.ChildNodeEntry cne = modified.getChildNodeEntry(
+ child.getName(), child.getIndex() + 1);
+ if (cne == null) {
+ // Item does not exist, remove
+ child.remove();
+ evict(child);
+ return;
+ }
+
+ LRUEntry childEntry = (LRUEntry) child.get();
+ if (childEntry != null && !cne.getUUID().equals(childEntry.getUUID())) {
+ // Different child item, remove
+ child.remove();
+ evict(child);
+ }
+ }
+ }
}
/**
@@ -430,11 +466,11 @@
* Cache an item in the hierarchy given its id and path. Adds a listener
* for this item state to get notified about changes.
*
- * @param state item state, may be <code>null</code>
+ * @param state node state
* @param path path to item
*/
- private void cache(ItemState state, Path path) {
- ItemId id = state.getId();
+ private void cache(NodeState state, Path path) {
+ NodeId id = (NodeId) state.getId();
synchronized (cacheMonitor) {
if (idCache.get(id) != null) {
@@ -602,9 +638,9 @@
private LRUEntry next;
/**
- * Item id
+ * Node id
*/
- private final ItemId id;
+ private final NodeId id;
/**
* Element in path map
@@ -614,9 +650,9 @@
/**
* Create a new instance of this class
*
- * @param id item id
+ * @param id node id
*/
- public LRUEntry(ItemId id, PathMap.Element element) {
+ public LRUEntry(NodeId id, PathMap.Element element) {
this.id = id;
this.element = element;
@@ -683,12 +719,21 @@
}
/**
- * Return item ID
+ * Return node ID
*
- * @return item ID
+ * @return node ID
*/
- public ItemId getId() {
+ public NodeId getId() {
return id;
+ }
+
+ /**
+ * Return node UUID.
+ *
+ * @return node UUID
+ */
+ public String getUUID() {
+ return id.getUUID();
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/NodeImpl.java?rev=279325&r1=279324&r2=279325&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/NodeImpl.java Wed Sep 7 07:18:06 2005
@@ -3746,6 +3746,10 @@
// check state of this instance
sanityCheck();
+ if (isNew()) {
+ throw new LockException("Node not locked: " + safeGetJCRPath());
+ }
+
LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager();
return lockMgr.getLock(this);
}
@@ -3780,8 +3784,8 @@
// check state of this instance
sanityCheck();
- if (!isNodeType(MIX_LOCKABLE)) {
- // a node that is not lockable never holds a lock
+ if (!isNodeType(MIX_LOCKABLE) || isNew()) {
+ // a node that is new or not lockable never holds a lock
return false;
}
@@ -3796,6 +3800,10 @@
// check state of this instance
sanityCheck();
+ if (isNew()) {
+ return false;
+ }
+
LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager();
return lockMgr.isLocked(this);
}
@@ -3822,6 +3830,11 @@
* @throws RepositoryException if some other error occurs
*/
protected void checkLock() throws LockException, RepositoryException {
+ if (isNew()) {
+ // a new node must not be checked
+ return;
+ }
+
LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager();
lockMgr.checkLock(this);
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/PathMap.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/PathMap.java?rev=279325&r1=279324&r2=279325&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/PathMap.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/PathMap.java Wed Sep 7 07:18:06 2005
@@ -479,6 +479,28 @@
public int getChildrenCount() {
return childrenCount;
}
+
+ /**
+ * Return an iterator over all of this element's children. Every
+ * element returned by this iterator is of type {@link #Element}.
+ */
+ public Iterator getChildren() {
+ ArrayList result = new ArrayList();
+
+ if (children != null) {
+ Iterator iter = children.values().iterator();
+ while (iter.hasNext()) {
+ ArrayList list = (ArrayList) iter.next();
+ for (int i = 0; i < list.size(); i++) {
+ Element element = (Element) list.get(i);
+ if (element != null) {
+ result.add(element);
+ }
+ }
+ }
+ }
+ return result.iterator();
+ }
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=279325&r1=279324&r2=279325&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Wed Sep 7 07:18:06 2005
@@ -22,6 +22,7 @@
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.PathMap;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.observation.EventImpl;
import org.apache.jackrabbit.core.observation.SynchronousEventListener;
import org.apache.jackrabbit.core.value.InternalValue;
@@ -34,6 +35,8 @@
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.AccessDeniedException;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.observation.Event;
@@ -160,7 +163,7 @@
NodeId id = new NodeId(lockToken.uuid);
NodeImpl node = (NodeImpl) session.getItemManager().getItem(id);
- Path path = node.getPrimaryPath();
+ Path path = getPath(node.getId());
LockInfo info = new LockInfo(this, lockToken, false,
node.getProperty(Constants.JCR_LOCKISDEEP).getBoolean(),
@@ -230,7 +233,7 @@
synchronized (contentMonitor) {
synchronized (lockMap) {
// check whether node is already locked
- Path path = node.getPrimaryPath();
+ Path path = getPath(node.getId());
PathMap.Element element = lockMap.map(path, false);
LockInfo other = (LockInfo) element.get();
@@ -287,7 +290,7 @@
// get node's path and remove child in path map
NodeImpl node = (NodeImpl) session.getItemManager().getItem(
new NodeId(info.getUUID()));
- Path path = node.getPrimaryPath();
+ Path path = getPath(node.getId());
synchronized (lockMap) {
PathMap.Element element = lockMap.map(path, true);
@@ -334,7 +337,7 @@
throws LockException, RepositoryException {
synchronized (lockMap) {
- Path path = node.getPrimaryPath();
+ Path path = getPath(node.getId());
PathMap.Element element = lockMap.map(path, false);
LockInfo info = (LockInfo) element.get();
@@ -365,9 +368,7 @@
synchronized (contentMonitor) {
synchronized (lockMap) {
// check whether node is locked by this session
- Path path = node.getPrimaryPath();
-
- PathMap.Element element = lockMap.map(path, true);
+ PathMap.Element element = lockMap.map(getPath(node.getId()), true);
if (element == null) {
throw new LockException("Node not locked: " + node.safeGetJCRPath());
}
@@ -397,7 +398,7 @@
*/
public boolean holdsLock(NodeImpl node) throws RepositoryException {
synchronized (lockMap) {
- PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
+ PathMap.Element element = lockMap.map(getPath(node.getId()), true);
if (element == null) {
return false;
}
@@ -409,9 +410,9 @@
* {@inheritDoc}
*/
public boolean isLocked(NodeImpl node) throws RepositoryException {
- Path path = node.getPrimaryPath();
-
synchronized (lockMap) {
+ Path path = getPath(node.getId());
+
PathMap.Element element = lockMap.map(path, false);
LockInfo info = (LockInfo) element.get();
if (info == null) {
@@ -431,7 +432,7 @@
public void checkLock(NodeImpl node)
throws LockException, RepositoryException {
- checkLock(node.getPrimaryPath(), node.getSession());
+ checkLock(getPath(node.getId()), node.getSession());
}
/**
@@ -458,7 +459,7 @@
try {
LockToken lockToken = LockToken.parse(lt);
- NodeImpl node = (NodeImpl) session.getItemManager().
+ NodeImpl node = (NodeImpl) this.session.getItemManager().
getItem(new NodeId(lockToken.uuid));
PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
if (element != null) {
@@ -487,7 +488,7 @@
try {
LockToken lockToken = LockToken.parse(lt);
- NodeImpl node = (NodeImpl) session.getItemManager().
+ NodeImpl node = (NodeImpl) this.session.getItemManager().
getItem(new NodeId(lockToken.uuid));
PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
if (element != null) {
@@ -509,6 +510,18 @@
}
}
+ /**
+ * Return the path of an item given its id. This method will lookup the
+ * item inside the system session and will therefore not find transiently
+ * created but not yet saved items
+ */
+ private Path getPath(ItemId id)
+ throws ItemNotFoundException, AccessDeniedException,
+ RepositoryException {
+
+ return session.getHierarchyManager().getPath(id);
+ }
+
//----------------------------------------------< SynchronousEventListener >
/**
Modified: incubator/jackrabbit/trunk/core/src/test/org/apache/jackrabbit/test/api/lock/LockTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/test/org/apache/jackrabbit/test/api/lock/LockTest.java?rev=279325&r1=279324&r2=279325&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/test/org/apache/jackrabbit/test/api/lock/LockTest.java (original)
+++ incubator/jackrabbit/trunk/core/src/test/org/apache/jackrabbit/test/api/lock/LockTest.java Wed Sep 7 07:18:06 2005
@@ -609,6 +609,39 @@
}
/**
+ * Tests if move preserves lock state (JIRA issue JCR-207). A node that has
+ * been locked must still appear locked when it has been moved or renamed,
+ * regardless whether the changes have already been made persistent.
+ */
+ public void testMoveLocked() throws Exception {
+ Session session = testRootNode.getSession();
+
+ // create two nodes, parent and child
+ Node testNode1 = testRootNode.addNode(nodeName1);
+ testNode1.addMixin(mixLockable);
+ Node testNode2 = testNode1.addNode(nodeName2);
+ testNode2.addMixin(mixLockable);
+ testRootNode.save();
+
+ // lock child node
+ testNode2.lock(false, true);
+
+ // assert: child node locked
+ assertTrue("Child node locked", testNode2.isLocked());
+
+ // move child node up
+ String newPath = testRootNode.getPath() + "/" + testNode2.getName();
+ session.move(testNode2.getPath(), newPath);
+
+ // assert: child node locked, before save
+ assertTrue("Child node locked before save", testNode2.isLocked());
+ session.save();
+
+ // assert: child node locked, after save
+ assertTrue("Child node locked after save", testNode2.isLocked());
+ }
+
+ /**
* Return a flag indicating whether the indicated session contains
* a specific lock token
*/