Loading src/main/java/com/inteligr8/alfresco/acs/api/NodeBodyCreateMultipart.java 0 → 100644 +99 −0 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs.api; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; public class NodeBodyCreateMultipart extends MultipartBody { private static final ObjectMapper om = new ObjectMapper(); public static NodeBodyCreateMultipart from( NodeBodyCreate nodeBody, String filename, InputStream istream, Boolean autoRename, Boolean majorVersion, Boolean versioningEnabled) throws IOException { List<Attachment> atts = new LinkedList<>(); atts.addAll(toAttachments(nodeBody)); if (autoRename != null) atts.add(toAttachment("autoRename", String.valueOf(autoRename))); if (majorVersion != null) atts.add(toAttachment("majorVersion", String.valueOf(majorVersion))); if (versioningEnabled != null) atts.add(toAttachment("versioningEnabled", String.valueOf(versioningEnabled))); atts.add(toAttachment(filename, istream)); return new NodeBodyCreateMultipart(atts, true); } public NodeBodyCreateMultipart(List<Attachment> atts) throws IOException { super(atts); } public NodeBodyCreateMultipart(List<Attachment> atts, boolean outbound) throws IOException { super(atts, outbound); } public NodeBodyCreate getBody() throws IOException { if (!MediaType.APPLICATION_JSON_TYPE.equals(this.getRootAttachment().getContentType())) throw new IllegalStateException(); InputStream istream = this.getRootAttachment().getDataHandler().getInputStream(); try { return om.readValue(istream, NodeBodyCreate.class); } finally { istream.close(); } } public Attachment getFiledataAttachment() { return this.getAttachment("filedata"); } @SuppressWarnings("unchecked") private static List<Attachment> toAttachments(NodeBodyCreate nodeBody) throws IOException { List<Attachment> atts = new LinkedList<>(); atts.add(toAttachment("name", nodeBody.getName())); atts.add(toAttachment("nodeType", nodeBody.getNodeType())); if (nodeBody.getAspectNames() != null) atts.add(toAttachment("aspectNames", nodeBody.getAspectNames())); if (nodeBody.getProperties() != null) atts.add(toAttachment("properties", (Map<String, Object>)nodeBody.getProperties())); return atts; } private static Attachment toAttachment(String name, String value) { return new Attachment(name, new ByteArrayInputStream(value.getBytes()), new ContentDisposition("form-data; name=\"" + name + "\"")); } private static Attachment toAttachment(String name, Collection<String> c) throws JsonProcessingException { return toJsonAttachment(name, c); } private static Attachment toAttachment(String name, Map<String, Object> map) throws JsonProcessingException { return toJsonAttachment(name, map); } private static Attachment toJsonAttachment(String name, Object obj) throws JsonProcessingException { String json = om.writeValueAsString(obj); return new Attachment(name, new ByteArrayInputStream(json.getBytes()), new ContentDisposition("form-data; name=\"" + name + "\"")); } private static Attachment toAttachment(String filename, InputStream istream) { return new Attachment("filedata", istream, new ContentDisposition("form-data; name=\"filedata\"; filename=\"" + filename + "\"")); } } src/main/java/com/inteligr8/alfresco/acs/api/NodesCxfApi.java +33 −15 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs.api; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; import com.inteligr8.alfresco.acs.model.Error; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; import com.inteligr8.alfresco.acs.model.NodeEntry; import io.swagger.annotations.Api; Loading Loading @@ -45,12 +40,35 @@ public interface NodesCxfApi { @ApiResponse(code = 200, message = "Unexpected error", response = Error.class) }) public NodeEntry createNode( @PathParam("nodeId") String nodeId, @Multipart NodeBodyCreate nodeBodyCreate, @QueryParam("autoRename") Boolean autoRename, @QueryParam("majorVersion") Boolean majorVersion, @QueryParam("versioningEnabled") Boolean versioningEnabled, @QueryParam("include") List<String> include, @QueryParam("fields") List<String> fields, @Multipart(value = "filedata", required = false) Attachment attachment); MultipartBody body); /* * This better impl doesn't work * @POST @Path("/nodes/{nodeId}/children") @Consumes({ MediaType.MULTIPART_FORM_DATA }) @Produces({ MediaType.APPLICATION_JSON }) @ApiOperation(value = "Create a node", tags={ }) @ApiResponses(value = { @ApiResponse(code = 201, message = "Successful response", response = NodeEntry.class), @ApiResponse(code = 400, message = "Invalid parameter: **nodeId** is not a valid format or **nodeBodyCreate** is invalid "), @ApiResponse(code = 401, message = "Authentication failed"), @ApiResponse(code = 403, message = "Current user does not have permission to create children of **nodeId**"), @ApiResponse(code = 404, message = "**nodeId** or **renditionId** does not exist "), @ApiResponse(code = 409, message = "New name clashes with an existing node in the current parent folder"), @ApiResponse(code = 413, message = "Content exceeds individual file size limit configured for the network or system"), @ApiResponse(code = 415, message = "Content Type is not supported"), @ApiResponse(code = 422, message = "Model integrity exception including a file name containing invalid characters"), @ApiResponse(code = 507, message = "Content exceeds overall storage quota limit configured for the network or system"), @ApiResponse(code = 200, message = "Unexpected error", response = Error.class) }) public NodeEntry createNode( @PathParam("nodeId") String nodeId, @Multipart("name") String name, @Multipart("nodeType") String nodeType, @Multipart("filedata") InputStream fileStream, @Multipart("filedata") ContentDisposition disposition, @Multipart(value = "autoRename", required = false) Boolean autoRename, @Multipart(value = "majorVersion", required = false) Boolean majorVersion, @Multipart(value = "versioningEnabled", required = false) Boolean versioningEnabled); */ } src/main/java/com/inteligr8/alfresco/acs/api/NodesJerseyApi.java +5 −6 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; Loading Loading @@ -47,11 +46,11 @@ public interface NodesJerseyApi { public NodeEntry createNode( @PathParam("nodeId") String nodeId, NodeBodyCreate nodeBodyCreate, @QueryParam("autoRename") Boolean autoRename, @QueryParam("majorVersion") Boolean majorVersion, @QueryParam("versioningEnabled") Boolean versioningEnabled, @QueryParam("include") List<String> include, @QueryParam("fields") List<String> fields, @FormDataParam("autoRename") Boolean autoRename, @FormDataParam("majorVersion") Boolean majorVersion, @FormDataParam("versioningEnabled") Boolean versioningEnabled, @FormDataParam("include") List<String> include, @FormDataParam("fields") List<String> fields, @FormDataParam("filedata") InputStream filedataStream, @FormDataParam("filedata") FormDataContentDisposition filedataDisposition); Loading src/test/java/com/inteligr8/alfresco/acs/ConnectionCxfClientIT.java +33 −1 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs; import java.io.ByteArrayInputStream; import java.io.IOException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import com.inteligr8.alfresco.acs.api.NodeBodyCreateMultipart; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; import com.inteligr8.alfresco.acs.model.RequestQuery; import com.inteligr8.alfresco.acs.model.RequestQuery.LanguageEnum; import com.inteligr8.alfresco.acs.model.ResultNode; import com.inteligr8.alfresco.acs.model.ResultSetPaging; import com.inteligr8.alfresco.acs.model.SearchRequest; import com.inteligr8.rs.ClientConfiguration; @TestPropertySource(locations = {"/local.properties"}) Loading @@ -13,7 +24,7 @@ public class ConnectionCxfClientIT extends ConnectionClientIT { @Autowired @Qualifier("acs.api.cxf") private AcsPublicRestApi client; private AcsPublicRestApiCxfImpl client; @Override public AcsPublicRestApi getClient() { Loading @@ -25,4 +36,25 @@ public class ConnectionCxfClientIT extends ConnectionClientIT { return this.client.getConfig(); } @Test public void uploadFile() throws IOException { RequestQuery query = new RequestQuery(); query.setLanguage(LanguageEnum.AFTS); query.setQuery("=@cm:name:'Shared'"); SearchRequest searchRequest = new SearchRequest(); searchRequest.setQuery(query); ResultSetPaging paging = this.client.getSearchApi().search(searchRequest); ResultNode folderNode = paging.getList().getEntries().iterator().next().getEntry(); String folderNodeId = folderNode.getId(); NodeBodyCreate nodeBody = new NodeBodyCreate().nodeType("cm:content").name("TestFolder"); ByteArrayInputStream istream = new ByteArrayInputStream("This is a test".getBytes()); NodeBodyCreateMultipart body = NodeBodyCreateMultipart.from(nodeBody, "test.txt", istream, true, null, null); this.client.getNodesExtApi().createNode(folderNodeId, body); } } Loading
src/main/java/com/inteligr8/alfresco/acs/api/NodeBodyCreateMultipart.java 0 → 100644 +99 −0 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs.api; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; public class NodeBodyCreateMultipart extends MultipartBody { private static final ObjectMapper om = new ObjectMapper(); public static NodeBodyCreateMultipart from( NodeBodyCreate nodeBody, String filename, InputStream istream, Boolean autoRename, Boolean majorVersion, Boolean versioningEnabled) throws IOException { List<Attachment> atts = new LinkedList<>(); atts.addAll(toAttachments(nodeBody)); if (autoRename != null) atts.add(toAttachment("autoRename", String.valueOf(autoRename))); if (majorVersion != null) atts.add(toAttachment("majorVersion", String.valueOf(majorVersion))); if (versioningEnabled != null) atts.add(toAttachment("versioningEnabled", String.valueOf(versioningEnabled))); atts.add(toAttachment(filename, istream)); return new NodeBodyCreateMultipart(atts, true); } public NodeBodyCreateMultipart(List<Attachment> atts) throws IOException { super(atts); } public NodeBodyCreateMultipart(List<Attachment> atts, boolean outbound) throws IOException { super(atts, outbound); } public NodeBodyCreate getBody() throws IOException { if (!MediaType.APPLICATION_JSON_TYPE.equals(this.getRootAttachment().getContentType())) throw new IllegalStateException(); InputStream istream = this.getRootAttachment().getDataHandler().getInputStream(); try { return om.readValue(istream, NodeBodyCreate.class); } finally { istream.close(); } } public Attachment getFiledataAttachment() { return this.getAttachment("filedata"); } @SuppressWarnings("unchecked") private static List<Attachment> toAttachments(NodeBodyCreate nodeBody) throws IOException { List<Attachment> atts = new LinkedList<>(); atts.add(toAttachment("name", nodeBody.getName())); atts.add(toAttachment("nodeType", nodeBody.getNodeType())); if (nodeBody.getAspectNames() != null) atts.add(toAttachment("aspectNames", nodeBody.getAspectNames())); if (nodeBody.getProperties() != null) atts.add(toAttachment("properties", (Map<String, Object>)nodeBody.getProperties())); return atts; } private static Attachment toAttachment(String name, String value) { return new Attachment(name, new ByteArrayInputStream(value.getBytes()), new ContentDisposition("form-data; name=\"" + name + "\"")); } private static Attachment toAttachment(String name, Collection<String> c) throws JsonProcessingException { return toJsonAttachment(name, c); } private static Attachment toAttachment(String name, Map<String, Object> map) throws JsonProcessingException { return toJsonAttachment(name, map); } private static Attachment toJsonAttachment(String name, Object obj) throws JsonProcessingException { String json = om.writeValueAsString(obj); return new Attachment(name, new ByteArrayInputStream(json.getBytes()), new ContentDisposition("form-data; name=\"" + name + "\"")); } private static Attachment toAttachment(String filename, InputStream istream) { return new Attachment("filedata", istream, new ContentDisposition("form-data; name=\"filedata\"; filename=\"" + filename + "\"")); } }
src/main/java/com/inteligr8/alfresco/acs/api/NodesCxfApi.java +33 −15 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs.api; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; import com.inteligr8.alfresco.acs.model.Error; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; import com.inteligr8.alfresco.acs.model.NodeEntry; import io.swagger.annotations.Api; Loading Loading @@ -45,12 +40,35 @@ public interface NodesCxfApi { @ApiResponse(code = 200, message = "Unexpected error", response = Error.class) }) public NodeEntry createNode( @PathParam("nodeId") String nodeId, @Multipart NodeBodyCreate nodeBodyCreate, @QueryParam("autoRename") Boolean autoRename, @QueryParam("majorVersion") Boolean majorVersion, @QueryParam("versioningEnabled") Boolean versioningEnabled, @QueryParam("include") List<String> include, @QueryParam("fields") List<String> fields, @Multipart(value = "filedata", required = false) Attachment attachment); MultipartBody body); /* * This better impl doesn't work * @POST @Path("/nodes/{nodeId}/children") @Consumes({ MediaType.MULTIPART_FORM_DATA }) @Produces({ MediaType.APPLICATION_JSON }) @ApiOperation(value = "Create a node", tags={ }) @ApiResponses(value = { @ApiResponse(code = 201, message = "Successful response", response = NodeEntry.class), @ApiResponse(code = 400, message = "Invalid parameter: **nodeId** is not a valid format or **nodeBodyCreate** is invalid "), @ApiResponse(code = 401, message = "Authentication failed"), @ApiResponse(code = 403, message = "Current user does not have permission to create children of **nodeId**"), @ApiResponse(code = 404, message = "**nodeId** or **renditionId** does not exist "), @ApiResponse(code = 409, message = "New name clashes with an existing node in the current parent folder"), @ApiResponse(code = 413, message = "Content exceeds individual file size limit configured for the network or system"), @ApiResponse(code = 415, message = "Content Type is not supported"), @ApiResponse(code = 422, message = "Model integrity exception including a file name containing invalid characters"), @ApiResponse(code = 507, message = "Content exceeds overall storage quota limit configured for the network or system"), @ApiResponse(code = 200, message = "Unexpected error", response = Error.class) }) public NodeEntry createNode( @PathParam("nodeId") String nodeId, @Multipart("name") String name, @Multipart("nodeType") String nodeType, @Multipart("filedata") InputStream fileStream, @Multipart("filedata") ContentDisposition disposition, @Multipart(value = "autoRename", required = false) Boolean autoRename, @Multipart(value = "majorVersion", required = false) Boolean majorVersion, @Multipart(value = "versioningEnabled", required = false) Boolean versioningEnabled); */ }
src/main/java/com/inteligr8/alfresco/acs/api/NodesJerseyApi.java +5 −6 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; Loading Loading @@ -47,11 +46,11 @@ public interface NodesJerseyApi { public NodeEntry createNode( @PathParam("nodeId") String nodeId, NodeBodyCreate nodeBodyCreate, @QueryParam("autoRename") Boolean autoRename, @QueryParam("majorVersion") Boolean majorVersion, @QueryParam("versioningEnabled") Boolean versioningEnabled, @QueryParam("include") List<String> include, @QueryParam("fields") List<String> fields, @FormDataParam("autoRename") Boolean autoRename, @FormDataParam("majorVersion") Boolean majorVersion, @FormDataParam("versioningEnabled") Boolean versioningEnabled, @FormDataParam("include") List<String> include, @FormDataParam("fields") List<String> fields, @FormDataParam("filedata") InputStream filedataStream, @FormDataParam("filedata") FormDataContentDisposition filedataDisposition); Loading
src/test/java/com/inteligr8/alfresco/acs/ConnectionCxfClientIT.java +33 −1 Original line number Diff line number Diff line package com.inteligr8.alfresco.acs; import java.io.ByteArrayInputStream; import java.io.IOException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import com.inteligr8.alfresco.acs.api.NodeBodyCreateMultipart; import com.inteligr8.alfresco.acs.model.NodeBodyCreate; import com.inteligr8.alfresco.acs.model.RequestQuery; import com.inteligr8.alfresco.acs.model.RequestQuery.LanguageEnum; import com.inteligr8.alfresco.acs.model.ResultNode; import com.inteligr8.alfresco.acs.model.ResultSetPaging; import com.inteligr8.alfresco.acs.model.SearchRequest; import com.inteligr8.rs.ClientConfiguration; @TestPropertySource(locations = {"/local.properties"}) Loading @@ -13,7 +24,7 @@ public class ConnectionCxfClientIT extends ConnectionClientIT { @Autowired @Qualifier("acs.api.cxf") private AcsPublicRestApi client; private AcsPublicRestApiCxfImpl client; @Override public AcsPublicRestApi getClient() { Loading @@ -25,4 +36,25 @@ public class ConnectionCxfClientIT extends ConnectionClientIT { return this.client.getConfig(); } @Test public void uploadFile() throws IOException { RequestQuery query = new RequestQuery(); query.setLanguage(LanguageEnum.AFTS); query.setQuery("=@cm:name:'Shared'"); SearchRequest searchRequest = new SearchRequest(); searchRequest.setQuery(query); ResultSetPaging paging = this.client.getSearchApi().search(searchRequest); ResultNode folderNode = paging.getList().getEntries().iterator().next().getEntry(); String folderNodeId = folderNode.getId(); NodeBodyCreate nodeBody = new NodeBodyCreate().nodeType("cm:content").name("TestFolder"); ByteArrayInputStream istream = new ByteArrayInputStream("This is a test".getBytes()); NodeBodyCreateMultipart body = NodeBodyCreateMultipart.from(nodeBody, "test.txt", istream, true, null, null); this.client.getNodesExtApi().createNode(folderNodeId, body); } }