From 9dbe6f2c4b65c8f3cb918d19a91cac8cb7c25e50 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Wed, 19 Jun 2019 11:14:00 +0200
Subject: [PATCH] OO-3938: other way to lock Office docs, add debug logs

---
 .../doceditor/office365/Office365Service.java   |  2 +-
 .../office365/manager/Office365ServiceImpl.java | 17 +++++++++++------
 .../office365/restapi/Office365WebService.java  | 16 +++++++++++-----
 .../core/util/vfs/lock/VFSLockManagerImpl.java  |  6 ++++++
 .../vfs/manager/VFSLockManagerTest.java         |  5 +++++
 5 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/main/java/org/olat/core/commons/services/doceditor/office365/Office365Service.java b/src/main/java/org/olat/core/commons/services/doceditor/office365/Office365Service.java
index 7b2db3188f7..bc49f5fd44a 100644
--- a/src/main/java/org/olat/core/commons/services/doceditor/office365/Office365Service.java
+++ b/src/main/java/org/olat/core/commons/services/doceditor/office365/Office365Service.java
@@ -67,7 +67,7 @@ public interface Office365Service {
 
 	String getLockToken(VFSLeaf vfsLeaf);
 
-	void lock(VFSLeaf vfsLeaf, Identity identity, String lockToken);
+	boolean lock(VFSLeaf vfsLeaf, Identity identity, String lockToken);
 
 	boolean canUnlock(VFSLeaf vfsLeaf, String lockToken);
 
diff --git a/src/main/java/org/olat/core/commons/services/doceditor/office365/manager/Office365ServiceImpl.java b/src/main/java/org/olat/core/commons/services/doceditor/office365/manager/Office365ServiceImpl.java
index aecbce7ae3b..59082e5faca 100644
--- a/src/main/java/org/olat/core/commons/services/doceditor/office365/manager/Office365ServiceImpl.java
+++ b/src/main/java/org/olat/core/commons/services/doceditor/office365/manager/Office365ServiceImpl.java
@@ -57,6 +57,7 @@ import org.olat.core.util.vfs.VFSLockApplicationType;
 import org.olat.core.util.vfs.VFSLockManager;
 import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.lock.LockInfo;
+import org.olat.core.util.vfs.lock.LockResult;
 import org.olat.restapi.security.RestSecurityHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -314,16 +315,20 @@ public class Office365ServiceImpl implements Office365Service, GenericEventListe
 	}
 
 	@Override
-	public void lock(VFSLeaf vfsLeaf, Identity identity, String lockToken) {
+	public boolean lock(VFSLeaf vfsLeaf, Identity identity, String lockToken) {
 		LockInfo lock = lockManager.getLock(vfsLeaf);
 		if (lock == null) {
-			lockManager.lock(vfsLeaf, identity, VFSLockApplicationType.collaboration, LOCK_APP);
-			lock = lockManager.getLock(vfsLeaf);
-			lock.getTokens().clear(); // the generated, internal token for the identity
-			
+			LockResult lockResult = lockManager.lock(vfsLeaf, identity, VFSLockApplicationType.collaboration, LOCK_APP);
+			if(lockResult.isAcquired()) {
+				lock = lockResult.getLockInfo();
+			} else {
+				return false;
+			}
+			lock.clearTokens(); // the generated, internal token for the identity
 			refreshLock(lock);
 		}
-		lock.getTokens().add(lockToken);
+		lock.addToken(lockToken);
+		return true;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java b/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
index 21abe73313d..ff2ec473412 100644
--- a/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
+++ b/src/main/java/org/olat/core/commons/services/doceditor/office365/restapi/Office365WebService.java
@@ -224,11 +224,17 @@ public class Office365WebService {
 		
 		String currentLockToken = office365Service.getLockToken(vfsLeaf);
 		if (currentLockToken == null) {
-			office365Service.lock(vfsLeaf, access.getIdentity(), lockToken);
-			String itemVersion = String.valueOf(access.getMetadata().getRevisionNr());
-			return Response.ok()
-					.header("X-WOPI-ItemVersion", itemVersion)
-					.build();
+			if(office365Service.lock(vfsLeaf, access.getIdentity(), lockToken)) {
+				String itemVersion = String.valueOf(access.getMetadata().getRevisionNr());
+				return Response.ok()
+						.header("X-WOPI-ItemVersion", itemVersion)
+						.build();
+			} else {
+				return Response.serverError()
+						.status(Status.CONFLICT)
+						.header("X-WOPI-Lock", currentLockToken)
+						.build();
+			}
 		}
 		
 		if (lockToken.equals(currentLockToken)) {
diff --git a/src/main/java/org/olat/core/util/vfs/lock/VFSLockManagerImpl.java b/src/main/java/org/olat/core/util/vfs/lock/VFSLockManagerImpl.java
index 67d643e8417..eaf0de0f6bc 100644
--- a/src/main/java/org/olat/core/util/vfs/lock/VFSLockManagerImpl.java
+++ b/src/main/java/org/olat/core/util/vfs/lock/VFSLockManagerImpl.java
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.UUID;
 import java.util.Vector;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.commons.modules.bc.FolderModule;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.vfs.VFSMetadata;
@@ -36,6 +37,7 @@ import org.olat.core.commons.services.webdav.manager.VFSResource;
 import org.olat.core.commons.services.webdav.servlets.WebResource;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
+import org.olat.core.logging.Tracing;
 import org.olat.core.util.cache.CacheWrapper;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.vfs.LocalImpl;
@@ -49,6 +51,8 @@ import org.springframework.stereotype.Service;
 @Service("vfsLockManager")
 public class VFSLockManagerImpl implements VFSLockManager {
 	
+	private static final Logger log = Tracing.createLoggerFor(VFSLockManagerImpl.class);
+	
 	//one year is enough for a long loc
     private static final long vfsExpireAt = (System.currentTimeMillis() + (365 * 24 * 60 * 60 * 1000));
     private static final long collaborationExpireAt = (System.currentTimeMillis() + (24 * 60 * 60 * 1000));
@@ -250,6 +254,7 @@ public class VFSLockManagerImpl implements VFSLockManager {
 	private LockInfo getLockInfo(VFSItem item, VFSMetadata metadata) {
 		final File file = extractFile(item);
 		if(file == null) {
+			log.debug("Lock only real file: {}", item);
 			return null;// we only lock real files
 		}
 		
@@ -280,6 +285,7 @@ public class VFSLockManagerImpl implements VFSLockManager {
 				lock.setExpiresAt(0l);
 				lock.clearTokens();
 			} else {
+				log.debug("Not VFS Lock has expired: {}", item);
 				fileLocks.remove(file);
             	lock = null;
 			}
diff --git a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSLockManagerTest.java b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSLockManagerTest.java
index 03ee150b263..6ce90fdd8e7 100644
--- a/src/test/java/org/olat/core/commons/services/vfs/manager/VFSLockManagerTest.java
+++ b/src/test/java/org/olat/core/commons/services/vfs/manager/VFSLockManagerTest.java
@@ -32,6 +32,7 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSLockApplicationType;
 import org.olat.core.util.vfs.VFSManager;
+import org.olat.core.util.vfs.lock.LockInfo;
 import org.olat.core.util.vfs.lock.LockResult;
 import org.olat.core.util.vfs.lock.VFSLockManagerImpl;
 import org.olat.test.JunitTestHelper;
@@ -300,6 +301,8 @@ public class VFSLockManagerTest extends OlatTestCase {
 		// second user, try to lock the file
 		LockResult locked = lockManager.lock(file, otherId, VFSLockApplicationType.vfs, null);
 		Assert.assertFalse(locked.isAcquired());
+		LockInfo lock = lockManager.getLock(file);
+		Assert.assertNotNull(lock);
 		// is locked
 		boolean lockedCollaboration = lockManager.isLockedForMe(file, otherId, VFSLockApplicationType.collaboration, "oo-collaboration");
 		Assert.assertTrue(lockedCollaboration);
@@ -327,6 +330,8 @@ public class VFSLockManagerTest extends OlatTestCase {
 		// Locked it
 		LockResult locked = lockManager.lock(file, id, VFSLockApplicationType.collaboration, "oo-collaboration");
 		Assert.assertTrue(locked.isAcquired());
+		LockInfo lock = lockManager.getLock(file);
+		Assert.assertNotNull(lock);
 		
 		// Try to lock it with an other app.
 		boolean lockedOtherApp = lockManager.isLockedForMe(file, id, VFSLockApplicationType.collaboration, "other-collaboration");
-- 
GitLab