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
      */