From b8eadb7533bf2a0869ca78b2814b5b7f74b71c31 Mon Sep 17 00:00:00 2001 From: Paulo Gustavo Veiga Date: Wed, 23 Mar 2022 10:56:57 -0300 Subject: [PATCH] Fix unit tests --- .../wisemapping/exceptions/LockException.java | 45 +++++---- .../wisemapping/rest/MindmapController.java | 20 ++-- .../wisemapping/rest/ValidationException.java | 36 ++++---- .../wisemapping/rest/model/RestLockInfo.java | 91 +++++++++---------- .../com/wisemapping/service/LockInfo.java | 9 ++ .../com/wisemapping/service/LockManager.java | 38 ++++---- .../wisemapping/service/LockManagerImpl.java | 5 +- .../com/wisemapping/test/rest/RestHelper.java | 2 +- .../test/rest/RestMindmapITCase.java | 11 ++- 9 files changed, 144 insertions(+), 113 deletions(-) diff --git a/wise-webapp/src/main/java/com/wisemapping/exceptions/LockException.java b/wise-webapp/src/main/java/com/wisemapping/exceptions/LockException.java index 88bd18a8..31f2c07f 100755 --- a/wise-webapp/src/main/java/com/wisemapping/exceptions/LockException.java +++ b/wise-webapp/src/main/java/com/wisemapping/exceptions/LockException.java @@ -1,32 +1,39 @@ /* -* Copyright [2022] [wisemapping] -* -* Licensed under WiseMapping Public License, Version 1.0 (the "License"). -* It is basically the Apache License, Version 2.0 (the "License") plus the -* "powered by wisemapping" text requirement on every single page; -* you may not use this file except in compliance with the License. -* You may obtain a copy of the license at -* -* http://www.wisemapping.org/license -* -* 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. -*/ + * Copyright [2022] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * 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 com.wisemapping.exceptions; +import com.wisemapping.model.Mindmap; +import com.wisemapping.model.User; +import com.wisemapping.service.LockManager; import org.jetbrains.annotations.NotNull; public class LockException - extends ClientException -{ + extends ClientException { private static final String MSG_KEY = "MINDMAP_IS_LOCKED"; + public LockException(@NotNull String message) { - super(message,Severity.INFO); + super(message, Severity.INFO); + } + + public static LockException createLockLost(@NotNull Mindmap mindmap, @NotNull User user, @NotNull LockManager manager) { + return new LockException("Lock can not be granted to " + user.getEmail() + ". The lock is assigned to " + manager.getLockInfo(mindmap)); } @NotNull diff --git a/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java b/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java index 93e7ab20..bb8bfb4c 100644 --- a/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java +++ b/wise-webapp/src/main/java/com/wisemapping/rest/MindmapController.java @@ -31,10 +31,12 @@ import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -449,19 +451,23 @@ public class MindmapController extends BaseController { mindmapService.updateCollaboration(user, collaboration.get()); } - @RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/lock", consumes = {"text/plain"}, produces = {"application/json", "application/xml"}) - @ResponseStatus(value = HttpStatus.NO_CONTENT) - public void updateMapLock(@RequestBody String value, @PathVariable int id) throws WiseMappingException { + @RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/locks/{lockid}", consumes = {"text/plain"}, produces = {"application/json", "application/xml"}) + public ResponseEntity lockMindmap(@RequestBody String value, @PathVariable int id, @PathVariable long lockid) throws WiseMappingException { final User user = Utils.getUser(); final LockManager lockManager = mindmapService.getLockManager(); final Mindmap mindmap = findMindmapById(id); - final boolean lock = Boolean.parseBoolean(value); - if (!lock) { - lockManager.unlock(mindmap, user); + ResponseEntity result = new ResponseEntity<>(null, HttpStatus.NO_CONTENT); + if (Boolean.parseBoolean(value)) { + if (!lockManager.isLocked(mindmap)) { + final LockInfo lockInfo = lockManager.lock(mindmap, user, lockid); + final RestLockInfo restLockInfo = new RestLockInfo(lockInfo, user); + result = new ResponseEntity<>(restLockInfo, HttpStatus.OK); + } } else { - throw new UnsupportedOperationException("REST lock must be implemented."); + lockManager.unlock(mindmap, user); } + return result; } @RequestMapping(method = RequestMethod.DELETE, value = "/maps/batch") diff --git a/wise-webapp/src/main/java/com/wisemapping/rest/ValidationException.java b/wise-webapp/src/main/java/com/wisemapping/rest/ValidationException.java index 84bcf896..a3962513 100644 --- a/wise-webapp/src/main/java/com/wisemapping/rest/ValidationException.java +++ b/wise-webapp/src/main/java/com/wisemapping/rest/ValidationException.java @@ -1,20 +1,20 @@ /* -* Copyright [2022] [wisemapping] -* -* Licensed under WiseMapping Public License, Version 1.0 (the "License"). -* It is basically the Apache License, Version 2.0 (the "License") plus the -* "powered by wisemapping" text requirement on every single page; -* you may not use this file except in compliance with the License. -* You may obtain a copy of the license at -* -* http://www.wisemapping.org/license -* -* 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. -*/ + * Copyright [2022] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * 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 com.wisemapping.rest; @@ -23,11 +23,11 @@ import com.wisemapping.exceptions.WiseMappingException; import org.jetbrains.annotations.NotNull; import org.springframework.validation.Errors; -public class ValidationException extends WiseMappingException{ +public class ValidationException extends WiseMappingException { private final Errors errors; public ValidationException(@NotNull Errors errors) { - super("Validation Exceptions:"+errors); + super("Validation Exceptions:" + errors); this.errors = errors; } diff --git a/wise-webapp/src/main/java/com/wisemapping/rest/model/RestLockInfo.java b/wise-webapp/src/main/java/com/wisemapping/rest/model/RestLockInfo.java index 8fe3a57b..7cb226df 100644 --- a/wise-webapp/src/main/java/com/wisemapping/rest/model/RestLockInfo.java +++ b/wise-webapp/src/main/java/com/wisemapping/rest/model/RestLockInfo.java @@ -1,20 +1,20 @@ /* -* Copyright [2022] [wisemapping] -* -* Licensed under WiseMapping Public License, Version 1.0 (the "License"). -* It is basically the Apache License, Version 2.0 (the "License") plus the -* "powered by wisemapping" text requirement on every single page; -* you may not use this file except in compliance with the License. -* You may obtain a copy of the license at -* -* http://www.wisemapping.org/license -* -* 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. -*/ + * Copyright [2022] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * 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 com.wisemapping.rest.model; @@ -22,6 +22,7 @@ package com.wisemapping.rest.model; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.wisemapping.model.Collaborator; +import com.wisemapping.model.User; import com.wisemapping.service.LockInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,48 +40,42 @@ import javax.xml.bind.annotation.XmlRootElement; @JsonIgnoreProperties(ignoreUnknown = true) public class RestLockInfo { - @NotNull - final private Collaborator user; - - @Nullable - final private LockInfo lockInfo; + private long session; + private long timestamp; + private String email; // This is required only for compliance with the JAXB serializer. - public RestLockInfo(){ + public RestLockInfo() { - this.lockInfo = null; - //noinspection ConstantConditions - this.user = null; } - public RestLockInfo(@Nullable LockInfo lockInfo, @NotNull Collaborator collaborator) { - - this.lockInfo = lockInfo; - this.user = collaborator; - } - - public boolean isLocked() { - return lockInfo != null; - } - - public void setLocked(boolean locked) { - // Ignore ... - } - - public boolean isLockedByMe() { - return isLocked() && lockInfo != null && lockInfo.getUser().identityEquality(user); - } - - public void setLockedByMe(boolean lockedForMe) { - // Ignore ... + public RestLockInfo(@Nullable LockInfo lockInfo, @NotNull User user) { + this.session = lockInfo.getSession(); + this.timestamp = lockInfo.getTimestamp(); + this.email = user.getEmail(); } public long getTimestamp() { - return lockInfo != null ? lockInfo.getTimestamp() : -1; + return this.timestamp; + } + + public long getSession() { + return this.session; + } + + public void setSession(long session) { + this.session = session; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; } public void setTimestamp(long value) { - // + this.timestamp = value; } - } diff --git a/wise-webapp/src/main/java/com/wisemapping/service/LockInfo.java b/wise-webapp/src/main/java/com/wisemapping/service/LockInfo.java index 30a24108..962230bc 100644 --- a/wise-webapp/src/main/java/com/wisemapping/service/LockInfo.java +++ b/wise-webapp/src/main/java/com/wisemapping/service/LockInfo.java @@ -74,4 +74,13 @@ public class LockInfo { this.previousTimestamp = this.timestamp; this.timestamp = mindmap.getLastModificationTime().getTimeInMillis(); } + + @Override + public String toString() { + return "LockInfo{" + + "user=" + user + + ", session=" + session + + ", timestamp=" + timestamp + + '}'; + } } diff --git a/wise-webapp/src/main/java/com/wisemapping/service/LockManager.java b/wise-webapp/src/main/java/com/wisemapping/service/LockManager.java index 3aee7a19..711bef73 100644 --- a/wise-webapp/src/main/java/com/wisemapping/service/LockManager.java +++ b/wise-webapp/src/main/java/com/wisemapping/service/LockManager.java @@ -1,20 +1,20 @@ /* -* Copyright [2022] [wisemapping] -* -* Licensed under WiseMapping Public License, Version 1.0 (the "License"). -* It is basically the Apache License, Version 2.0 (the "License") plus the -* "powered by wisemapping" text requirement on every single page; -* you may not use this file except in compliance with the License. -* You may obtain a copy of the license at -* -* http://www.wisemapping.org/license -* -* 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. -*/ + * Copyright [2022] [wisemapping] + * + * Licensed under WiseMapping Public License, Version 1.0 (the "License"). + * It is basically the Apache License, Version 2.0 (the "License") plus the + * "powered by wisemapping" text requirement on every single page; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the license at + * + * http://www.wisemapping.org/license + * + * 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 com.wisemapping.service; @@ -41,5 +41,9 @@ public interface LockManager { long generateSession(); - long verifyAndUpdateLock(@NotNull Mindmap mindmap, @NotNull User user, long session, long timestamp) throws LockException, SessionExpiredException; + @NotNull + LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws LockException; + + long verifyAndUpdateLock(@NotNull Mindmap mindmap, @NotNull User user, long session, long timestamp) throws + LockException, SessionExpiredException; } diff --git a/wise-webapp/src/main/java/com/wisemapping/service/LockManagerImpl.java b/wise-webapp/src/main/java/com/wisemapping/service/LockManagerImpl.java index 24cb5e83..c8225873 100644 --- a/wise-webapp/src/main/java/com/wisemapping/service/LockManagerImpl.java +++ b/wise-webapp/src/main/java/com/wisemapping/service/LockManagerImpl.java @@ -110,9 +110,10 @@ class LockManagerImpl implements LockManager { } @NotNull - private LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws LockException { + @Override + public LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws LockException { if (isLocked(mindmap) && !isLockedBy(mindmap, user)) { - throw new LockException("Invalid lock, this should not happen"); + throw LockException.createLockLost(mindmap, user, this); } LockInfo result = lockInfoByMapId.get(mindmap.getId()); diff --git a/wise-webapp/src/test/java/com/wisemapping/test/rest/RestHelper.java b/wise-webapp/src/test/java/com/wisemapping/test/rest/RestHelper.java index 6272540f..7430e5a4 100644 --- a/wise-webapp/src/test/java/com/wisemapping/test/rest/RestHelper.java +++ b/wise-webapp/src/test/java/com/wisemapping/test/rest/RestHelper.java @@ -21,7 +21,7 @@ public class RestHelper { public static final String COLOR = "#000000"; static HttpHeaders createHeaders(@NotNull MediaType mediaType) { - List acceptableMediaTypes = new ArrayList(); + List acceptableMediaTypes = new ArrayList<>(); acceptableMediaTypes.add(mediaType); final HttpHeaders result = new HttpHeaders(); diff --git a/wise-webapp/src/test/java/com/wisemapping/test/rest/RestMindmapITCase.java b/wise-webapp/src/test/java/com/wisemapping/test/rest/RestMindmapITCase.java index fd8b418e..b5de2537 100644 --- a/wise-webapp/src/test/java/com/wisemapping/test/rest/RestMindmapITCase.java +++ b/wise-webapp/src/test/java/com/wisemapping/test/rest/RestMindmapITCase.java @@ -23,6 +23,7 @@ import static org.testng.Assert.*; @Test public class RestMindmapITCase { + private static final int SESSION_ID = 100; private String userEmail = "admin@wisemapping.com"; private static final String ICON = "glyphicon glyphicon-tag"; @@ -217,8 +218,16 @@ public class RestMindmapITCase { mapToUpdate.setXml("this is not valid"); mapToUpdate.setProperties("{zoom:x}"); + // Create lock ... + final HttpHeaders lockHeaders = createHeaders(mediaType); + lockHeaders.setContentType(MediaType.TEXT_PLAIN); + + HttpEntity lockEntity = new HttpEntity<>("true", lockHeaders); + final ResponseEntity lockResponse = template.exchange(HOST_PORT + resourceUri + "/locks/{lockid}", HttpMethod.PUT, lockEntity, RestLockInfo.class, SESSION_ID); + final RestLockInfo lockInfo = lockResponse.getBody(); + // Update map ... - final String resourceUrl = HOST_PORT + resourceUri.toString() + "/document"; + final String resourceUrl = HOST_PORT + resourceUri.toString() + "/document?session=" + lockInfo.getSession() + "×tamp=" + lockInfo.getTimestamp(); requestHeaders.setContentType(MediaType.APPLICATION_XML); final HttpEntity updateEntity = new HttpEntity<>(mapToUpdate, requestHeaders); template.put(resourceUrl, updateEntity);