From ee3a942fc7ca76d645d29ee9a41b2085d0b61e0c Mon Sep 17 00:00:00 2001 From: Jamal Kaabi-Mofrad Date: Tue, 10 May 2016 11:21:08 +0000 Subject: [PATCH] Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2) 123112 jvonka: Nodes (FileFolder) API - version options when updating/uploading (overwriting) existing content - add tests .. for now check version label only (pending future "list version history" + "get version" etc) RA-690 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126528 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/rest/api/impl/NodesImpl.java | 23 +- .../rest/api/tests/AbstractBaseApiTest.java | 31 +- .../alfresco/rest/api/tests/NodeApiTest.java | 316 ++++++++++++++++++ 3 files changed, 359 insertions(+), 11 deletions(-) diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index 8b91cbfcbf..4846205c93 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -1626,15 +1626,17 @@ public class NodesImpl implements Nodes // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) ensureVersioningEnabled(nodeRef, true, false); } - - Map versionProperties = new HashMap<>(2); - versionProperties.put(VersionModel.PROP_VERSION_TYPE, versionType); - if (reason != null) + else { - versionProperties.put(VersionModel.PROP_DESCRIPTION, reason); - } + Map versionProperties = new HashMap<>(2); + versionProperties.put(VersionModel.PROP_VERSION_TYPE, versionType); + if (reason != null) + { + versionProperties.put(VersionModel.PROP_DESCRIPTION, reason); + } - versionService.createVersion(nodeRef, versionProperties); + versionService.createVersion(nodeRef, versionProperties); + } } private void setWriterContentType(ContentWriter writer, ContentInfoWrapper contentInfo, NodeRef nodeRef, boolean guessEncodingIfNull) @@ -1754,6 +1756,11 @@ public class NodesImpl implements Nodes throw new InvalidArgumentException("Required parameters are missing"); } + if (autoRename && overwrite) + { + throw new InvalidArgumentException("Both 'overwrite' and 'autoRename' should not be true when uploading a file"); + } + try { // Map the given properties, if any. @@ -1768,8 +1775,6 @@ public class NodesImpl implements Nodes NodeRef existingFile = nodeService.getChildByName(parentNodeRef, ContentModel.ASSOC_CONTAINS, fileName); if (existingFile != null) { - // TODO throw 400 error if both autoRename and overwrite are true ? - // File already exists, decide what to do if (autoRename) { diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java index 6e3a86c498..9a49bf60eb 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java @@ -345,11 +345,22 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi protected Document createTextFile(String userId, String parentId, String fileName, String textContent) throws IOException, Exception { - return createTextFile(userId, parentId, fileName, textContent, "UTF-8", Collections.EMPTY_MAP); + return createTextFile(userId, parentId, fileName, textContent, "UTF-8", null); } protected Document createTextFile(String userId, String parentId, String fileName, String textContent, String encoding, Map props) throws IOException, Exception { + return createTextFile(userId, parentId, fileName, textContent, encoding, props, 201); + } + + protected Document createTextFile(String userId, String parentId, String fileName, String textContent, String encoding, Map props, int expectedStatus) throws IOException, Exception + { + if (props == null) + { + props = Collections.EMPTY_MAP; + + } + ByteArrayInputStream inputStream = new ByteArrayInputStream(textContent.getBytes()); File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt"); @@ -358,7 +369,23 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi .setProperties(props) .build(); - HttpResponse response = post(getNodeChildrenUrl(parentId), userId, reqBody.getBody(), null, reqBody.getContentType(), 201); + HttpResponse response = post(getNodeChildrenUrl(parentId), userId, reqBody.getBody(), null, reqBody.getContentType(), expectedStatus); + + if (response.getJsonResponse().get("error") != null) + { + return null; + } + + return RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + } + + protected Document updateTextFile(String userId, String contentId, String textContent, Map parameters) throws IOException, Exception + { + ByteArrayInputStream inputStream = new ByteArrayInputStream(textContent.getBytes()); + File txtFile = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt"); + BinaryPayload payload = new BinaryPayload(txtFile, MimetypeMap.MIMETYPE_TEXT_PLAIN); + + HttpResponse response = putBinary(getNodeContentUrl(contentId), userId, payload, null, parameters, 200); return RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); } diff --git a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java index dca0a7885e..bd711fce63 100644 --- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -2183,6 +2183,322 @@ public class NodeApiTest extends AbstractBaseApiTest assertNotNull(content, response.getResponse()); } + /** + * Test version creation when updating file binary content. + * + * TODO also relates to future v1 api to list version history, etc + * + *

PUT:

+ * {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes//content} + * + *

POST:

+ * {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes//children} + */ + @Test + public void testUpdateFileVersionCreate() throws Exception + { + String myNodeId = getMyNodeId(user1); + + Document d1 = new Document(); + d1.setName("d1.txt"); + d1.setNodeType("cm:content"); + ContentInfo ci = new ContentInfo(); + ci.setMimeType("text/plain"); + d1.setContent(ci); + + // create *empty* text file - as of now, versioning is not enabled by default + HttpResponse response = post(getNodeChildrenUrl(myNodeId), user1, toJsonAsStringNonNull(d1), 201); + Document documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + + String docId = documentResp.getId(); + assertFalse(documentResp.getAspectNames().contains("cm:versionable")); + assertNull(documentResp.getProperties()); // no properties (ie. no "cm:versionLabel") + + int cnt = 0; + + // updates - no versions + for (int i = 1; i <= 3; i++) + { + cnt++; + + // Update the empty node's content - no version created + String content = "The quick brown fox jumps over the lazy dog " + cnt; + documentResp = updateTextFile(user1, docId, content, null); + assertFalse(documentResp.getAspectNames().contains("cm:versionable")); + assertNull(documentResp.getProperties()); // no properties (ie. no "cm:versionLabel") + } + + // Update again - with version comment (note: either "comment" &/or "majorVersion" will enable versioning) + cnt++; + int majorVersion = 1; + int minorVersion = 0; + + String content = "The quick brown fox jumps over the lazy dog "+cnt; + + Map params = new HashMap<>(); + params.put("comment", "my version "+cnt); + + documentResp = updateTextFile(user1, docId, content, params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + // Update again - with another version comment + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + params = new HashMap<>(); + params.put("comment", "my version "+cnt); + + documentResp = updateTextFile(user1, docId, content, params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + minorVersion = 0; + + // Updates - major versions + for (int i = 1; i <= 3; i++) + { + cnt++; + majorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("comment", "my version "+cnt); + params.put("majorVersion", "true"); + + documentResp = updateTextFile(user1, docId, content, params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + } + + // Updates - minor versions + for (int i = 1; i <= 3; i++) + { + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("comment", "my version "+cnt); + params.put("majorVersion", "false"); + + documentResp = updateTextFile(user1, docId, content, params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + } + + // Update again - as another major version + cnt++; + majorVersion++; + minorVersion = 0; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("comment", "my version "+cnt); + params.put("majorVersion", "true"); + + documentResp = updateTextFile(user1, docId, content, params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + // Update again - as another (minor) version + // note: no version params (comment &/or majorVersion) needed since versioning is enabled on this content + + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + documentResp = updateTextFile(user1, docId, content, null); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + // Remove versionable aspect + List aspectNames = documentResp.getAspectNames(); + aspectNames.remove("cm:versionable"); + Document dUpdate = new Document(); + dUpdate.setAspectNames(aspectNames); + + response = put(URL_NODES, user1, docId, toJsonAsStringNonNull(dUpdate), null, 200); + documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + assertFalse(documentResp.getAspectNames().contains("cm:versionable")); + assertNull(documentResp.getProperties()); // no properties (ie. no "cm:versionLabel") + + // Updates - no versions + for (int i = 1; i <= 3; i++) + { + cnt++; + + // Update the empty node's content - no version created + content = "The quick brown fox jumps over the lazy dog " + cnt; + documentResp = updateTextFile(user1, docId, content, null); + assertFalse(documentResp.getAspectNames().contains("cm:versionable")); + assertNull(documentResp.getProperties()); // no properties (ie. no "cm:versionLabel") + } + + // TODO add tests to also check version comment (when we can list version history) + } + + /** + * Test version creation when uploading files (via multi-part/form-data with overwrite=true) + * + * TODO also relates to future v1 api to list version history, etc + * + *

POST:

+ * {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes//children} + */ + @Test + public void testUploadFileVersionCreate() throws Exception + { + String myNodeId = getMyNodeId(user1); + + int cnt = 1; + + int majorVersion = 1; + int minorVersion = 0; + + // Upload text file - versioning is currently auto enabled on upload (create file via multi-part/form-data) + + String contentName = "content " + System.currentTimeMillis(); + String content = "The quick brown fox jumps over the lazy dog "+cnt; + + Document documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", null); + String docId = documentResp.getId(); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + Map params = null; + + // Upload text file with same name - with overwrite=true + for (int i = 1; i <= 3; i++) + { + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog " + cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + + documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + } + + minorVersion = 0; + + // Updates - major versions + for (int i = 1; i <= 3; i++) + { + cnt++; + majorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + params.put("comment", "my version "+cnt); + params.put("majorVersion", "true"); + + documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + } + + // Updates - minor versions + for (int i = 1; i <= 3; i++) + { + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + params.put("comment", "my version "+cnt); + params.put("majorVersion", "false"); + + documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", params); + assertTrue(documentResp.getAspectNames().contains("cm:versionable")); + assertNotNull(documentResp.getProperties()); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + } + + // Update again - as another major version + cnt++; + majorVersion++; + minorVersion = 0; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + params.put("majorVersion", "true"); + + documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", params); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + // Update again - as another (minor) version + cnt++; + minorVersion++; + + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + + documentResp = createTextFile(user1, myNodeId, contentName, content, "UTF-8", params); + assertEquals(majorVersion+"."+minorVersion, documentResp.getProperties().get("cm:versionLabel")); + + + // -ve test + params = new HashMap<>(); + params.put("overwrite", "true"); + params.put("autorename", "true"); + + createTextFile(user1, myNodeId, contentName, content, "UTF-8", params, 400); + + + // Remove versionable aspect + List aspectNames = documentResp.getAspectNames(); + aspectNames.remove("cm:versionable"); + Document dUpdate = new Document(); + dUpdate.setAspectNames(aspectNames); + + HttpResponse response = put(URL_NODES, user1, docId, toJsonAsStringNonNull(dUpdate), null, 200); + documentResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + assertFalse(documentResp.getAspectNames().contains("cm:versionable")); + assertNull(documentResp.getProperties()); // no properties (ie. no "cm:versionLabel") + + + // TODO review consistency - for example, we do allow update binary content (after removing versionable) + // -ve test - do not allow overwrite (using POST upload) if the file is not versionable + + cnt++; + content = "The quick brown fox jumps over the lazy dog "+cnt; + + params = new HashMap<>(); + params.put("overwrite", "true"); + + createTextFile(user1, myNodeId, contentName, content, "UTF-8", params, 409); + + // TODO add checks for version comment (eg. when we can list version history) + } + /** * Tests download of file/content. *

GET: