diff --git a/source/java/org/alfresco/rest/api/Nodes.java b/source/java/org/alfresco/rest/api/Nodes.java index ef2ce81ce8..ad34237da6 100644 --- a/source/java/org/alfresco/rest/api/Nodes.java +++ b/source/java/org/alfresco/rest/api/Nodes.java @@ -118,8 +118,7 @@ public interface Nodes // TODO update REST fwk - to optionally support "attachment" (Content-Disposition) header BinaryResource getContent(String fileNodeId, Parameters parameters); - // TODO update REST fwk - to optionally support return of json - void updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters); + Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters); /** * Uploads file content and meta-data into the repository. diff --git a/source/java/org/alfresco/rest/api/impl/NodesImpl.java b/source/java/org/alfresco/rest/api/impl/NodesImpl.java index ba8c941d15..18833ab11e 100644 --- a/source/java/org/alfresco/rest/api/impl/NodesImpl.java +++ b/source/java/org/alfresco/rest/api/impl/NodesImpl.java @@ -28,6 +28,7 @@ import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.rest.antlr.WhereClauseParser; import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.model.ContentInfo; import org.alfresco.rest.api.model.Document; import org.alfresco.rest.api.model.Folder; import org.alfresco.rest.api.model.Node; @@ -38,7 +39,6 @@ import org.alfresco.rest.framework.core.exceptions.ApiException; import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; -import org.alfresco.rest.framework.core.exceptions.NotFoundException; import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException; import org.alfresco.rest.framework.core.exceptions.RequestEntityTooLargeException; import org.alfresco.rest.framework.resource.content.BasicContentInfo; @@ -86,12 +86,9 @@ import org.apache.commons.logging.LogFactory; import org.springframework.extensions.surf.util.Content; import org.springframework.extensions.webscripts.servlet.FormData; -import java.io.BufferedInputStream; -import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.math.BigInteger; -import java.nio.charset.Charset; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; @@ -994,10 +991,20 @@ public class NodesImpl implements Nodes } } - if (isContent) { + if (isContent) + { // add empty file - ContentWriter writer = sr.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - String mimeType = sr.getMimetypeService().guessMimetype(nodeName); + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + String mimeType; + ContentInfo contentInfo = nodeInfo.getContent(); + if (contentInfo != null && contentInfo.getMimeType() != null) + { + mimeType = contentInfo.getMimeType(); + } + else + { + mimeType = mimetypeService.guessMimetype(nodeName); + } writer.setMimetype(mimeType); writer.putContent(""); } @@ -1152,34 +1159,34 @@ public class NodesImpl implements Nodes } @Override - public void updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) + public Node updateContent(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) { final NodeRef nodeRef = validateNode(fileNodeId); - if (! nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) + if (!nodeMatches(nodeRef, Collections.singleton(ContentModel.TYPE_CONTENT), null)) { - throw new InvalidArgumentException("NodeId of content is expected: "+nodeRef); + throw new InvalidArgumentException("NodeId of content is expected: " + nodeRef); } - ContentWriter writer = sr.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); String mimeType = contentInfo.getMimeType(); if (mimeType == null) { - String fileName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT); + String fileName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT); writer.guessMimetype(fileName); } else { writer.setMimetype(mimeType); } - writer.guessEncoding(); - writer.putContent(stream); - // TODO - hmm - we may wish to return json info !! - return; + return getFolderOrDocumentFullInfo(nodeRef, + getParentNodeRef(nodeRef), + nodeService.getType(nodeRef), + parameters); } @Override @@ -1382,9 +1389,8 @@ public class NodesImpl implements Nodes protected void write(NodeRef nodeRef, Content content, String fileName, boolean applyMimeType, boolean guessEncoding) { ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true); - InputStream is; String mimeType = content.getMimetype(); - // Per RA-637 requirement the mimeType provided by the client takes precedent, however, + // Per RA-637 requirement the mimeType provided by the client takes precedence, however, // if the mimeType is null, then it will be retrieved or guessed. if (mimeType == null || !applyMimeType) { @@ -1398,28 +1404,17 @@ public class NodesImpl implements Nodes mimeType = mimetypeService.guessMimetype(fileName); } } + writer.setMimetype(mimeType); + if (guessEncoding) { - is = new BufferedInputStream(content.getInputStream()); - is.mark(1024); - - writer.setEncoding(guessEncoding(is, mimeType)); - try - { - is.reset(); - } - catch (IOException e) - { - logger.error("Failed to reset input stream", e); - } + writer.guessEncoding(); } else { writer.setEncoding(content.getEncoding()); - is = content.getInputStream(); } - writer.setMimetype(mimeType); - writer.putContent(is); + writer.putContent(content.getInputStream()); } /** @@ -1441,22 +1436,6 @@ public class NodesImpl implements Nodes versionService.ensureVersioningEnabled(nodeRef, props); } - /** - * Guesses the character encoding of the given inputStream. - */ - protected String guessEncoding(InputStream in, String mimeType) - { - String encoding = "UTF-8"; - - if (in != null) - { - Charset charset = mimetypeService.getContentCharsetFinder().getCharset(in, mimeType); - encoding = charset.name(); - } - - return encoding; - } - /** * Extracts the given node metadata asynchronously. */ diff --git a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java index 58a078f71f..5f6784bb74 100644 --- a/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java +++ b/source/java/org/alfresco/rest/api/nodes/NodesEntityResource.java @@ -45,7 +45,7 @@ import java.io.InputStream; @EntityResource(name="nodes", title = "Nodes") public class NodesEntityResource implements EntityResourceAction.ReadById, EntityResourceAction.Delete, EntityResourceAction.Update, - BinaryResourceAction.Read, BinaryResourceAction.Update, InitializingBean + BinaryResourceAction.Read, BinaryResourceAction.Update, InitializingBean { private Nodes nodes; @@ -86,9 +86,9 @@ public class NodesEntityResource implements @Override @WebApiDescription(title = "Upload content", description = "Upload content") @BinaryProperties({"content"}) - public void updateProperty(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) + public Node updateProperty(String fileNodeId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters) { - nodes.updateContent(fileNodeId, contentInfo, stream, parameters); + return nodes.updateContent(fileNodeId, contentInfo, stream, parameters); } /** diff --git a/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java b/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java index 8f93c34e87..aaf07c4228 100755 --- a/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java +++ b/source/java/org/alfresco/rest/framework/resource/actions/interfaces/BinaryResourceAction.java @@ -54,7 +54,7 @@ public interface BinaryResourceAction /** * HTTP PUT - Updates a binary resource if it exists, error if not */ - public static interface Update extends ResourceAction + public static interface Update extends ResourceAction { /** @@ -65,7 +65,7 @@ public interface BinaryResourceAction * @param contentInfo Basic information about the content stream * @param params {@link Parameters} */ - public void updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params); + public E updateProperty (String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params); } } diff --git a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java index 151455783e..e11509edc0 100644 --- a/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java +++ b/source/java/org/alfresco/rest/framework/webscripts/ResourceWebScriptPut.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2005-2015 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.rest.framework.webscripts; import java.io.IOException; @@ -6,7 +25,6 @@ import java.util.Locale; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.repo.web.scripts.BufferedRequest; import org.alfresco.rest.framework.core.ResourceInspector; import org.alfresco.rest.framework.core.ResourceLocator; import org.alfresco.rest.framework.core.ResourceMetadata; @@ -171,10 +189,8 @@ public class ResourceWebScriptPut extends AbstractResourceWebScript implements P { throw new DeletedResourceException("(UPDATE) "+resource.getMetaData().getUniqueId()); } - BinaryResourceAction.Update binUpdater = (BinaryResourceAction.Update) resource.getResource(); - binUpdater.updateProperty(params.getEntityId(),params.getContentInfo(), params.getStream(), params); - //Don't pass anything to the callback - its just successful - return null; + BinaryResourceAction.Update binUpdater = (BinaryResourceAction.Update) resource.getResource(); + return binUpdater.updateProperty(params.getEntityId(), params.getContentInfo(), params.getStream(), params); default: throw new UnsupportedResourceOperationException("PUT not supported for Actions"); } 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 669fdbbb73..231bd7a674 100644 --- a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java @@ -28,6 +28,7 @@ import org.alfresco.rest.api.tests.RepoService.TestPerson; import org.alfresco.rest.api.tests.RepoService.TestSite; import org.alfresco.rest.api.tests.client.HttpResponse; import org.alfresco.rest.api.tests.client.PublicApiClient; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; import org.alfresco.rest.api.tests.client.RequestContext; import org.alfresco.service.cmr.site.SiteVisibility; @@ -140,6 +141,27 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi return response; } + protected HttpResponse putBinary(String url, int version, String runAsUser, BinaryPayload payload, String queryString, Map params, + int expectedStatus) throws Exception + { + publicApiClient.setRequestContext(new RequestContext(runAsUser)); + if (queryString != null) + { + url += queryString; + } + + HttpResponse response = publicApiClient.putBinary(getScope(), version, url, null, null, null, payload, params); + checkStatus(expectedStatus, response.getStatusCode()); + + return response; + } + + protected HttpResponse putBinary(String url, String runAsUser, BinaryPayload payload, String queryString, Map params, + int expectedStatus) throws Exception + { + return putBinary(url, 1, runAsUser, payload, queryString, params, expectedStatus); + } + protected HttpResponse delete(String url, String runAsUser, String entityId, int expectedStatus) throws Exception { publicApiClient.setRequestContext(new RequestContext(runAsUser)); 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 06af6f4c8e..71ce9deaa8 100644 --- a/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java +++ b/source/test-java/org/alfresco/rest/api/tests/NodeApiTest.java @@ -34,6 +34,7 @@ import org.alfresco.repo.model.Repository; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.rest.api.Nodes; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; import org.alfresco.rest.api.tests.client.data.ContentInfo; import org.alfresco.rest.api.tests.client.data.Document; import org.alfresco.rest.api.tests.client.data.Folder; @@ -62,6 +63,7 @@ import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteVisibility; +import org.alfresco.util.TempFileProvider; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.junit.After; @@ -69,6 +71,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.util.ResourceUtils; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -130,7 +133,7 @@ public class NodeApiTest extends AbstractBaseApiTest repositoryHelper = applicationContext.getBean("repositoryHelper", Repository.class); jacksonUtil = new JacksonUtil(applicationContext.getBean("jsonHelper", JacksonHelper.class)); permissionService = applicationContext.getBean("permissionService", PermissionService.class); - + user1 = createUser("user1" + System.currentTimeMillis()); user2 = createUser("user2" + System.currentTimeMillis()); // We just need to clean the on-premise-users, @@ -1153,6 +1156,96 @@ public class NodeApiTest extends AbstractBaseApiTest put("nodes", user1, fId, toJsonAsStringNonNull(fUpdate), null, 400); } + /** + * Tests update file content + *

PUT:

+ * {@literal :/alfresco/api/-default-/public/alfresco/versions/1/nodes//content} + */ + @Test + public void testUpdateFileWithBinaryUpload() throws Exception + { + AuthenticationUtil.setFullyAuthenticatedUser(user1); + + NodeRef myFilesNodeRef = repositoryHelper.getUserHome(personService.getPerson(user1)); + + Folder f1 = new Folder(); + f1.setName("F1"); + f1.setNodeType("cm:folder"); + + HttpResponse response = post(getChildrenUrl(myFilesNodeRef), user1, toJsonAsStringNonNull(f1), 201); + Folder folderResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Folder.class); + assertEquals(f1.getName(), folderResp.getName()); + final String f1_nodeId = folderResp.getId(); + assertNotNull(f1_nodeId); + + Document doc = new Document(); + final String docName = "testdoc"; + doc.setName(docName); + doc.setNodeType("cm:content"); + ContentInfo contentInfo = new ContentInfo(); + contentInfo.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + doc.setContent(contentInfo); + + // create an empty file within F1 folder + response = post(getChildrenUrl(f1_nodeId), user1, toJsonAsStringNonNull(doc), 201); + Document docResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + assertEquals(docName, docResp.getName()); + assertNotNull(docResp.getContent()); + assertEquals(0, docResp.getContent().getSizeInBytes().intValue()); + assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, docResp.getContent().getMimeType()); + + // Update content & Download URL + final String url = "nodes/" + docResp.getId() + "/content"; + + // Update the empty node's content + String content = "The quick brown fox jumps over the lazy dog."; + ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes()); + File file = TempFileProvider.createTempFile(inputStream, getClass().getSimpleName(), ".txt"); + BinaryPayload payload = new BinaryPayload(file, MimetypeMap.MIMETYPE_TEXT_PLAIN); + + // Try to update a folder! + putBinary("nodes/" + f1_nodeId + "/content", user1, payload, null, null, 400); + + // Try to update a non-existent file + putBinary("nodes/" + UUID.randomUUID().toString() + "/content", user1, payload, null, null, 404); + + // Update the empty file + response = putBinary(url, user1, payload, null, null, 200); + docResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class); + assertEquals(docName, docResp.getName()); + assertNull(docResp.getPath()); + assertNotNull(docResp.getContent()); + assertTrue(docResp.getContent().getSizeInBytes().intValue() > 0); + assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, docResp.getContent().getMimeType()); + + // Download the file + response = getSingle(url, user1, null, 200); + assertEquals(content, response.getResponse()); + + // Update the node's content again. Also, change the mimeType and make the response to return path! + file = getResourceFile("quick.pdf"); + payload = new BinaryPayload(file, MimetypeMap.MIMETYPE_PDF); + + response = putBinary(url + "?select=path", user1, payload, null, null, 200); + docResp = jacksonUtil.parseEntry(response.getJsonResponse(), Document.class); + assertEquals(docName, docResp.getName()); + assertNotNull(docResp.getContent()); + assertTrue(docResp.getContent().getSizeInBytes().intValue() > 0); + assertEquals(MimetypeMap.MIMETYPE_PDF, docResp.getContent().getMimeType()); + PathInfo pathInfo = docResp.getPath(); + assertNotNull(pathInfo); + assertTrue(pathInfo.getIsComplete()); + List pathElements = pathInfo.getElements(); + assertNotNull(pathElements); + assertTrue(pathElements.size() > 0); + // check the last element is F1 + assertEquals(f1.getName(), pathElements.get(pathElements.size() - 1).getName()); + + // Download the file + response = getSingle(url, user1, null, 200); + assertNotNull(content, response.getResponse()); + } + // TODO add test to create multiple folders & empty files (within same parent folder) // TODO add test for file/folder links - creating, getting, listing, deleting diff --git a/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java b/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java index 84c8dced25..640a2331b2 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/HttpResponse.java @@ -8,6 +8,7 @@ import org.apache.commons.httpclient.methods.DeleteMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -56,16 +57,21 @@ public class HttpResponse { requestType = "GET"; } - else if(method instanceof PutMethod) - { - requestType = "PUT"; - StringRequestEntity requestEntity = (StringRequestEntity)((PutMethod)method).getRequestEntity(); - if(requestEntity != null) - { - requestBody = requestEntity.getContent(); - } - } - else if(method instanceof PostMethod) + else if (method instanceof PutMethod) + { + requestType = "PUT"; + RequestEntity requestEntity = ((PutMethod) method).getRequestEntity(); + if (requestEntity instanceof StringRequestEntity) + { + StringRequestEntity stringRequestEntity = (StringRequestEntity) requestEntity; + requestBody = stringRequestEntity.getContent(); + } + else if (requestEntity != null) + { + requestBody = requestEntity.toString(); + } + } + else if(method instanceof PostMethod) { requestType = "POST"; StringRequestEntity requestEntity = (StringRequestEntity)((PostMethod)method).getRequestEntity(); diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java index ebf4de88de..75651d35ec 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiClient.java @@ -14,6 +14,7 @@ import javax.servlet.http.HttpServletResponse; import org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl; import org.alfresco.opencmis.CMISDispatcherRegistry.Binding; +import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload; import org.alfresco.rest.api.tests.client.data.Activities; import org.alfresco.rest.api.tests.client.data.Activity; import org.alfresco.rest.api.tests.client.data.CMISNode; @@ -523,7 +524,18 @@ public class PublicApiClient return response; } - + + public HttpResponse putBinary(String scope, int version, String entityCollectionName, Object entityId, String relationCollectionName, + Object relationshipEntityId, BinaryPayload payload, Map params) throws IOException + { + HttpResponse response = client.putBinary(getRequestContext(), scope, version, entityCollectionName, entityId, relationCollectionName, relationshipEntityId, + payload, params); + + logger.debug(response.toString()); + + return response; + } + public HttpResponse delete(String scope, String entityCollectionName, Object entityId, String relationCollectionName, Object relationshipEntityId) throws IOException { HttpResponse response = client.delete(getRequestContext(), scope, entityCollectionName, entityId, relationCollectionName, relationshipEntityId); diff --git a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java index 9d2d3f31d0..fda4d85bf4 100644 --- a/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java +++ b/source/test-java/org/alfresco/rest/api/tests/client/PublicApiHttpClient.java @@ -19,7 +19,12 @@ package org.alfresco.rest.api.tests.client; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.MessageFormat; @@ -48,6 +53,7 @@ import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.methods.OptionsMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.methods.TraceMethod; import org.apache.commons.logging.Log; @@ -563,6 +569,23 @@ public class PublicApiHttpClient return submitRequest(req, rq); } + public HttpResponse putBinary(final RequestContext rq, final String scope, final int version, final String entityCollectionName, + final Object entityId, final String relationCollectionName, final Object relationshipEntityId, final BinaryPayload payload, + final Map params) throws IOException + { + RestApiEndpoint endpoint = new RestApiEndpoint(rq.getNetworkId(), scope, version, entityCollectionName, entityId, relationCollectionName, + relationshipEntityId, params); + String url = endpoint.getUrl(); + + PutMethod req = new PutMethod(url); + if (payload != null) + { + BinaryRequestEntity requestEntity = new BinaryRequestEntity(payload.getFile(), payload.getMimeType(), payload.getCharset()); + req.setRequestEntity(requestEntity); + } + return submitRequest(req, rq); + } + /* * Encapsulates information relating to a rest api end point, generating and * encoding urls based on the rest api implementation class. @@ -817,4 +840,100 @@ public class PublicApiHttpClient return url; } } + + /** + * @author Jamal Kaabi-Mofrad + */ + public static class BinaryRequestEntity implements RequestEntity + { + private final File file; + private final String mimeType; + private final String charset; + + public BinaryRequestEntity(File file, String mimeType, String charset) + { + this.file = file; + this.mimeType = (mimeType == null) ? "application/octet-stream" : mimeType; + this.charset = (charset == null) ? "UTF-8" : charset; + } + + @Override + public boolean isRepeatable() + { + return true; + } + + @Override + public void writeRequest(OutputStream out) throws IOException + { + InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); + try + { + int len; + byte[] buffer = new byte[8190]; + while ((len = inputStream.read(buffer)) != -1) + { + out.write(buffer, 0, len); + } + } + finally + { + inputStream.close(); + } + } + + @Override + public long getContentLength() + { + return file.length(); + } + + @Override + public String getContentType() + { + return mimeType + "; " + charset; + } + } + + /** + * @author Jamal Kaabi-Mofrad + */ + public static class BinaryPayload + { + private File file; + private String mimeType; + private String charset; + + public BinaryPayload(File file, String mimeType, String charset) + { + this.file = file; + this.mimeType = mimeType; + this.charset = charset; + } + + public BinaryPayload(File file, String mimeType) + { + this(file, mimeType, null); + } + + public BinaryPayload(File file) + { + this(file, null, null); + } + + public File getFile() + { + return file; + } + + public String getMimeType() + { + return mimeType; + } + + public String getCharset() + { + return charset; + } + } } diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java index 3ecee3da90..588a6a1b6a 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlockEntityResource.java @@ -15,16 +15,16 @@ import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.util.TempFileProvider; @EntityResource(name="flock",title="A resource used for testing binary properties") -public class FlockEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update +public class FlockEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update { //versions/1/flock/xyz/photo PUT @Override @WebApiDescription(title = "Updates a photo") @BinaryProperties("photo") - public void updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) + public Flock updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) { - return; + return null; } //versions/1/flock/xyz/photo DELETE diff --git a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java index 3479c8f9a5..4c6f8f30d1 100755 --- a/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java +++ b/source/test-java/org/alfresco/rest/framework/tests/api/mocks3/FlocketEntityResource.java @@ -12,15 +12,15 @@ import org.alfresco.rest.framework.resource.content.BinaryResource; import org.alfresco.rest.framework.resource.parameters.Parameters; @EntityResource(name="flocket",title="A resource used for testing binary properties with lost of properties") -public class FlocketEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update +public class FlocketEntityResource implements BinaryResourceAction.Read, BinaryResourceAction.Delete, BinaryResourceAction.Update { @Override @WebApiDescription(title = "Updates a flocket") @BinaryProperties({"photo","album"}) - public void updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) + public Flocket updateProperty(String entityId, BasicContentInfo contentInfo, InputStream stream, Parameters params) { - return; + return null; } @Override