diff --git a/source/java/org/alfresco/repo/webdav/LockMethod.java b/source/java/org/alfresco/repo/webdav/LockMethod.java
index 6e67240046..505b707873 100644
--- a/source/java/org/alfresco/repo/webdav/LockMethod.java
+++ b/source/java/org/alfresco/repo/webdav/LockMethod.java
@@ -459,6 +459,7 @@ public class LockMethod extends WebDAVMethod
{
// Update the expiry for the lock
lockInfo.setTimeoutSeconds(getLockTimeout());
+ getDAVLockService().lock(lockNode.getNodeRef(), lockInfo);
}
}
diff --git a/source/java/org/alfresco/repo/webdav/PropFindMethod.java b/source/java/org/alfresco/repo/webdav/PropFindMethod.java
index 181dc007bf..cf50979bb7 100644
--- a/source/java/org/alfresco/repo/webdav/PropFindMethod.java
+++ b/source/java/org/alfresco/repo/webdav/PropFindMethod.java
@@ -922,7 +922,7 @@ public class PropFindMethod extends WebDAVMethod
{
// Output the lock status response
LockInfo lockInfo = getNodeLockInfo(nodeInfo);
- if (lockInfo.isLocked())
+ if (lockInfo.isLocked() && !lockInfo.isExpired())
{
generateLockDiscoveryXML(xml, nodeInfo, lockInfo);
}
diff --git a/source/test-java/org/alfresco/RemoteApi01TestSuite.java b/source/test-java/org/alfresco/RemoteApi01TestSuite.java
index 96430a8dc2..9f2619ae52 100644
--- a/source/test-java/org/alfresco/RemoteApi01TestSuite.java
+++ b/source/test-java/org/alfresco/RemoteApi01TestSuite.java
@@ -71,6 +71,7 @@ public class RemoteApi01TestSuite extends TestSuite
{
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.webdav.MoveMethodTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.webdav.UnlockMethodTest.class));
+ suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.webdav.LockMethodTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.webdav.WebDAVHelperIntegrationTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.webdav.WebDAVMethodTest.class));
suite.addTestSuite(org.alfresco.repo.webservice.CMLUtilTest.class);
diff --git a/source/test-java/org/alfresco/repo/webdav/LockMethodTest.java b/source/test-java/org/alfresco/repo/webdav/LockMethodTest.java
new file mode 100644
index 0000000000..8e24812cbb
--- /dev/null
+++ b/source/test-java/org/alfresco/repo/webdav/LockMethodTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.webdav;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.Serializable;
+import java.util.Collections;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.security.authentication.AuthenticationComponent;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.security.MutableAuthenticationService;
+import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.GUID;
+import org.alfresco.util.TestWithUserUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+/**
+ * Tests for the {@link LockMethod} class.
+ *
+ * @author pavel.yurkevich
+ */
+public class LockMethodTest
+{
+ private LockMethod lockMethod;
+ private PropFindMethod propFindMethod;
+
+ private ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext(new String[]
+ {
+ "classpath:alfresco/application-context.xml", "classpath:alfresco/web-scripts-application-context.xml",
+ "classpath:alfresco/remote-api-context.xml"
+ });
+
+ /**
+ * Services used by the tests
+ */
+ private WebDAVHelper davHelper;
+ private TransactionService transactionService;
+ private AuthenticationComponent authenticationComponent;
+ private NodeService nodeService;
+ private MutableAuthenticationService authenticationService;
+ private PermissionService permissionService;
+ private ContentService contentService;
+ private FileFolderService fileFolderService;
+
+ /**
+ * Types and properties used by the tests
+ */
+ private static final String CONTENT_1 = "This is some content";
+ private static final String TEST_STORE_IDENTIFIER = "test_store-" + System.currentTimeMillis();
+ private static final String TEST_FILE_NAME = "file";
+
+ /**
+ * Data used by the tests
+ */
+ private StoreRef storeRef;
+ private NodeRef rootNodeRef;
+ private NodeRef folderNodeRef;
+ private NodeRef fileNodeRef;
+
+ /**
+ * User details
+ */
+ private String userName;
+ private static final String PWD = "password";
+
+ @Before
+ public void setUp() throws Exception
+ {
+ lockMethod = new LockMethod();
+ propFindMethod = new PropFindMethod();
+
+ this.transactionService = (TransactionService) applicationContext.getBean("TransactionService");
+ this.davHelper = (WebDAVHelper) applicationContext.getBean("webDAVHelper");
+ this.authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
+ this.nodeService = (NodeService) applicationContext.getBean("NodeService");
+ this.authenticationService = (MutableAuthenticationService) applicationContext.getBean("authenticationService");
+ this.permissionService = (PermissionService) applicationContext.getBean("permissionService");
+ this.contentService = (ContentService) applicationContext.getBean("contentService");
+ this.fileFolderService = (FileFolderService) applicationContext.getBean("fileFolderService");
+
+ this.authenticationComponent.setSystemUserAsCurrentUser();
+
+ RetryingTransactionCallback createTestFileCallback = new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ // Create the store and get the root node reference
+ storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, TEST_STORE_IDENTIFIER);
+ if (!nodeService.exists(storeRef))
+ {
+ storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, TEST_STORE_IDENTIFIER);
+ }
+ rootNodeRef = nodeService.getRootNode(storeRef);
+
+ // Create and authenticate the user
+ userName = "webdavLockTest" + GUID.generate();
+ TestWithUserUtils.createUser(userName, PWD, rootNodeRef, nodeService, authenticationService);
+ permissionService.setPermission(rootNodeRef, userName, PermissionService.ALL_PERMISSIONS, true);
+ TestWithUserUtils.authenticateUser(userName, PWD, rootNodeRef, authenticationService);
+
+ // create test file in test folder
+ folderNodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("test"), ContentModel.TYPE_FOLDER,
+ Collections. singletonMap(ContentModel.PROP_NAME, "folder")).getChildRef();
+ fileNodeRef = nodeService.createNode(folderNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName("test"), ContentModel.TYPE_CONTENT,
+ Collections. singletonMap(ContentModel.PROP_NAME, TEST_FILE_NAME)).getChildRef();
+ ContentWriter contentWriter = contentService.getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
+ contentWriter.setMimetype("text/plain");
+ contentWriter.setEncoding("UTF-8");
+ contentWriter.putContent(CONTENT_1);
+
+ return null;
+ }
+
+ };
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(createTestFileCallback);
+ }
+
+ @After
+ public void tearDown()
+ {
+ lockMethod = null;
+ propFindMethod = null;
+
+ // clear context for current user
+ this.authenticationComponent.clearCurrentSecurityContext();
+
+ // delete test store as system user
+ this.authenticationComponent.setSystemUserAsCurrentUser();
+ RetryingTransactionCallback deleteStoreCallback = new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ if (nodeService.exists(storeRef))
+ {
+ nodeService.deleteStore(storeRef);
+ }
+ return null;
+ }
+ };
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(deleteStoreCallback);
+ }
+
+ @Test
+ public void testRefreshLock() throws Exception
+ {
+ MockHttpServletRequest lockRequest = new MockHttpServletRequest();
+ lockRequest.addHeader(WebDAV.HEADER_TIMEOUT, WebDAV.SECOND + 5);
+ lockRequest.setRequestURI("/" + TEST_FILE_NAME);
+
+ String content = "" +
+ "" +
+ "" + userName + "";
+
+ lockRequest.setContent(content.getBytes("UTF-8"));
+
+ lockMethod.setDetails(lockRequest, new MockHttpServletResponse(), davHelper, folderNodeRef);
+ lockMethod.parseRequestHeaders();
+ lockMethod.parseRequestBody();
+
+ RetryingTransactionCallback lockExecuteImplCallBack = new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ lockMethod.executeImpl();
+ return null;
+ }
+ };
+
+ // lock node for 5 seconds
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(lockExecuteImplCallBack);
+
+ RetryingTransactionCallback getNodeLockInfoCallBack = new RetryingTransactionCallback()
+ {
+ @Override
+ public LockInfo execute() throws Throwable
+ {
+ return lockMethod.getNodeLockInfo(fileFolderService.getFileInfo(fileNodeRef));
+ }
+ };
+
+ // get lock info
+ LockInfo lockInfo = this.transactionService.getRetryingTransactionHelper().doInTransaction(getNodeLockInfoCallBack);
+
+ assertNotNull(lockInfo);
+
+ // wait for 1 second
+ Thread.sleep(1000);
+
+ String lockToken = fileNodeRef.getId() + WebDAV.LOCK_TOKEN_SEPERATOR + this.userName;
+ String lockHeaderValue = "(<" + WebDAV.OPAQUE_LOCK_TOKEN + lockToken + ">)";
+ lockRequest.addHeader(WebDAV.HEADER_IF, lockHeaderValue);
+
+ lockMethod.parseRequestHeaders();
+
+ // update lock for another 5 seconds
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(lockExecuteImplCallBack);
+
+ // get updated lock info
+ LockInfo updatedLockInfo = this.transactionService.getRetryingTransactionHelper().doInTransaction(getNodeLockInfoCallBack);
+
+ assertNotNull(updatedLockInfo);
+
+ assertEquals("Lock owner should not change after lock refresh.", lockInfo.getOwner(), updatedLockInfo.getOwner());
+ assertEquals("Lock token should not change after lock refresh.", lockInfo.getExclusiveLockToken(), updatedLockInfo.getExclusiveLockToken());
+
+ assertFalse("Expires was not updated.", lockInfo.getExpires().equals(updatedLockInfo.getExpires()));
+ assertTrue("Expires was updated incorrectly.", lockInfo.getExpires().before(updatedLockInfo.getExpires()));
+
+ // prepare propfind method
+ MockHttpServletRequest propFindRequest = new MockHttpServletRequest();
+ propFindRequest.setRequestURI("/" + TEST_FILE_NAME);
+ propFindRequest.addHeader(WebDAV.HEADER_DEPTH, "1");
+ content = "" +
+ "";
+
+ propFindRequest.setContent(content.getBytes("UTF-8"));
+
+ MockHttpServletResponse propfindResponse = new MockHttpServletResponse();
+ propFindMethod.setDetails(propFindRequest, propfindResponse, davHelper, folderNodeRef);
+
+ propFindMethod.parseRequestHeaders();
+ propFindMethod.parseRequestBody();
+
+ RetryingTransactionCallback propfindExecuteImplCallBack = new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ propFindMethod.executeImpl();
+ return null;
+ }
+ };
+
+ // make propfind method call for locked resource
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(propfindExecuteImplCallBack);
+
+ String response = propfindResponse.getContentAsString();
+
+ assertFalse("Propfind response should contain lock informarion.", response.indexOf("lockdiscovery") == -1);
+
+ // wait for lock expiration
+ Thread.sleep(6000);
+
+ propfindResponse = new MockHttpServletResponse();
+ propFindMethod.setDetails(propFindRequest, propfindResponse, davHelper, folderNodeRef);
+
+ // make another propfind call on resource with expired lock
+ this.transactionService.getRetryingTransactionHelper().doInTransaction(propfindExecuteImplCallBack);
+ response = propfindResponse.getContentAsString();
+
+ // check that lock information is not there for expired lock
+ assertTrue("Propfind response should not conatain information about expired lock", response.indexOf("lockdiscovery") == -1);
+ }
+}