You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2012/01/19 20:14:23 UTC

svn commit: r1233544 - in /jackrabbit/trunk/jackrabbit-jcr-server/src: main/java/org/apache/jackrabbit/webdav/jcr/ main/java/org/apache/jackrabbit/webdav/jcr/lock/ test/java/org/apache/jackrabbit/webdav/jcr/

Author: reschke
Date: Thu Jan 19 19:14:22 2012
New Revision: 1233544

URL: http://svn.apache.org/viewvc?rev=1233544&view=rev
Log:
JCR-3209: introduce a JCR<->DAV lock token mapper

Added:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java?rev=1233544&r1=1233543&r2=1233544&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/JcrDavSession.java Thu Jan 19 19:14:22 2012
@@ -20,9 +20,11 @@ import org.apache.jackrabbit.webdav.DavE
 import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import java.util.HashSet;
 
@@ -97,7 +99,14 @@ public abstract class JcrDavSession impl
      * @see DavSession#addLockToken(String)
      */
     public void addLockToken(String token) {
-        session.addLockToken(getJCRLockToken(token));
+        if (!LockTokenMapper.isForSessionScopedLock(token)) {
+            try {
+                session.getWorkspace().getLockManager().addLockToken(LockTokenMapper.getJcrLockToken(token));
+            }
+            catch (RepositoryException ex) {
+                log.debug("trying to add lock token " + token + " to session", ex);
+            }
+        }
         lockTokens.add(token);
     }
 
@@ -116,16 +125,14 @@ public abstract class JcrDavSession impl
      * @see DavSession#removeLockToken(String)
      */
     public void removeLockToken(String token) {
-        session.removeLockToken(getJCRLockToken(token));
-        lockTokens.remove(token);
-    }
-
-    //------------------------------------------------------------< private >---
-    private static String getJCRLockToken(String token) {
-        if (token.startsWith(DavConstants.OPAQUE_LOCK_TOKEN_PREFIX)) {
-            return token.substring(DavConstants.OPAQUE_LOCK_TOKEN_PREFIX.length());
-        } else {
-            return token;
+        if (!LockTokenMapper.isForSessionScopedLock(token)) {
+            try {
+                session.getWorkspace().getLockManager().removeLockToken(LockTokenMapper.getJcrLockToken(token));
+            }
+            catch (RepositoryException ex) {
+                log.debug("trying to remove lock token " + token + " to session", ex);
+            }
         }
+        lockTokens.remove(token);
     }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java?rev=1233544&r1=1233543&r2=1233544&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java Thu Jan 19 19:14:22 2012
@@ -93,20 +93,14 @@ public class JcrActiveLock extends Abstr
      * @see ActiveLock#getToken()
      */
     public String getToken() {
-        String token = lock.getLockToken();
-        if (token == null && lock.isSessionScoped()
-                && lock.isLockOwningSession()) {
-            // special handling for session scoped locks that are owned by the
-            // current session but never expose their token with jsr 283.
-            try {
-                token = lock.getNode().getIdentifier();
-            } catch (RepositoryException e) {
-                // should never get here
-                log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token.",e.getMessage());
-            }
+        try {
+            return LockTokenMapper.getDavLocktoken(lock);
+        } catch (RepositoryException e) {
+            // should never get here
+            log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token.",
+                    e.getMessage());
+            return null;
         }
-        // default behaviour: just return the token exposed by the lock.
-        return token;
     }
 
     /**

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java?rev=1233544&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java Thu Jan 19 19:14:22 2012
@@ -0,0 +1,74 @@
+/*
+ * 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.lock;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.Lock;
+
+import org.apache.jackrabbit.util.Text;
+
+/**
+ * Maps between WebDAV lock tokens and JCR lock tokens.
+ * <p>
+ * The following notations are used:
+ * 
+ * <pre>
+ * opaquelocktoken:SESSIONSCOPED:<em>NODEIDENTIFIER</em>
+ * opaquelocktoken:OPENSCOPED:<em>JCRLOCKTOKEN</em>
+ * </pre>
+ * 
+ * The first format is used if the JCR lock does not reveal a lock token, such
+ * as when it is a session-scoped lock (where SESSIONSCOPED is a constant UUID
+ * defined below, and NODEIDENTIFIER is the suitably escaped JCR Node
+ * identifier).
+ * <p>
+ * The second format is used for open-scoped locks (where OPENSCOPED is another
+ * constant UUID defined below, and JCRLOCKTOKEN is the suitably escaped JCR
+ * lock token).
+ */
+public class LockTokenMapper {
+
+    private static final String OL = "opaquelocktoken:";
+
+    private static final String SESSIONSCOPED = "4403ef44-4124-11e1-b965-00059a3c7a00";
+    private static final String OPENSCOPED = "dccce564-412e-11e1-b969-00059a3c7a00";
+
+    private static final String SESSPREFIX = OL + SESSIONSCOPED + ":";
+    private static final String OPENPREFIX = OL + OPENSCOPED + ":";
+
+    public static String getDavLocktoken(Lock lock) throws RepositoryException {
+        String jcrLockToken = lock.getLockToken();
+
+        if (jcrLockToken == null) {
+            return SESSPREFIX + Text.escape(lock.getNode().getIdentifier());
+        } else {
+            return OPENPREFIX + Text.escape(jcrLockToken);
+        }
+    }
+
+    public static String getJcrLockToken(String token) throws RepositoryException {
+        if (token.startsWith(OPENPREFIX)) {
+            return Text.unescape(token.substring(OPENPREFIX.length()));
+        } else {
+            throw new RepositoryException("not a token for an open-scoped JCR lock: " + token);
+        }
+    }
+
+    public static boolean isForSessionScopedLock(String token) {
+        return token.startsWith(SESSPREFIX);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/LockTokenMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java?rev=1233544&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java Thu Jan 19 19:14:22 2012
@@ -0,0 +1,107 @@
+/*
+ * 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;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.Lock;
+import javax.jcr.lock.LockException;
+
+import org.apache.jackrabbit.webdav.jcr.lock.LockTokenMapper;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>LockTokenMappingTest</code>...
+ */
+public class LockTokenMappingTest extends TestCase {
+
+    // test lock with a lock token similar to the ones assigned by Jackrabbit
+    public void testOpenScopedJcr() throws RepositoryException, URISyntaxException {
+        testRoundtrip(UUID.randomUUID().toString() + "-X");
+    }
+
+    // test a fancy lock string
+    public void testOpenScopedFancy() throws RepositoryException, URISyntaxException {
+        testRoundtrip("\n\u00c4 \u20ac");
+    }
+
+    private void testRoundtrip(String token) throws RepositoryException, URISyntaxException {
+
+        Lock l = new TestLock(token);
+        String davtoken = LockTokenMapper.getDavLocktoken(l);
+
+        // valid URI?
+        URI u = new URI(davtoken);
+        assertTrue("lock token must be absolute URI", u.isAbsolute());
+        assertEquals("lock token URI must be all-ASCII", u.toASCIIString(), u.toString());
+
+        String jcrtoken = LockTokenMapper.getJcrLockToken(davtoken);
+        assertEquals(jcrtoken, l.getLockToken());
+    }
+
+    /**
+     * Minimal Lock impl for tests above
+     */
+    private static class TestLock implements Lock {
+
+        private final String token;
+
+        public TestLock(String token) {
+            this.token = token;
+        }
+
+        public String getLockOwner() {
+            return null;
+        }
+
+        public boolean isDeep() {
+            return false;
+        }
+
+        public Node getNode() {
+            return null;
+        }
+
+        public String getLockToken() {
+            return token;
+        }
+
+        public long getSecondsRemaining() throws RepositoryException {
+            return 0;
+        }
+
+        public boolean isLive() throws RepositoryException {
+            return false;
+        }
+
+        public boolean isSessionScoped() {
+            return false;
+        }
+
+        public boolean isLockOwningSession() {
+            return false;
+        }
+
+        public void refresh() throws LockException, RepositoryException {
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/LockTokenMappingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native