diff --git a/pom.xml b/pom.xml index f273296..9273de3 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,9 @@ 8 8 lines,vars,source + + 2.35 + 3.4.7 @@ -54,6 +57,18 @@ jackson-module-jaxb-annotations 2.12.2 + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} + true + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey.version} + true + diff --git a/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestCxfApi.java b/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestCxfApi.java new file mode 100644 index 0000000..0dea71d --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestCxfApi.java @@ -0,0 +1,18 @@ +package com.inteligr8.alfresco.activiti; + +import com.inteligr8.alfresco.activiti.api.AppDefinitionsCxfApi; + +/** + * This interface appends Apache CXF implementation specific methods to the + * JAX-RS API of the APS Public ReST API. This is due to a lack of multi-part + * in the JAX-RS specification. + * + * @author brian@inteligr8.com + */ +public interface ApsPublicRestCxfApi extends ApsPublicRestApi { + + default AppDefinitionsCxfApi getAppDefinitionsCxfApi() { + return this.getApi(AppDefinitionsCxfApi.class); + } + +} diff --git a/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestJerseyApi.java b/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestJerseyApi.java new file mode 100644 index 0000000..eb922ee --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/ApsPublicRestJerseyApi.java @@ -0,0 +1,18 @@ +package com.inteligr8.alfresco.activiti; + +import com.inteligr8.alfresco.activiti.api.AppDefinitionsJerseyApi; + +/** + * This interface appends Jersey implementation specific methods to the JAX-RS + * API of the APS Public ReST API. This is due to a lack of multi-part in the + * JAX-RS specification. + * + * @author brian@inteligr8.com + */ +public interface ApsPublicRestJerseyApi extends ApsPublicRestApi { + + default AppDefinitionsJerseyApi getAppDefinitionsJerseyApi() { + return this.getApi(AppDefinitionsJerseyApi.class); + } + +} diff --git a/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsCxfApi.java b/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsCxfApi.java new file mode 100644 index 0000000..0d20916 --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsCxfApi.java @@ -0,0 +1,51 @@ + +package com.inteligr8.alfresco.activiti.api; + +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 com.inteligr8.alfresco.activiti.model.AppDefinitionRepresentation; +import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation; +import com.inteligr8.alfresco.activiti.model.FileMultipartCxf; + +@Path("/api/enterprise/app-definitions") +public interface AppDefinitionsCxfApi { + + @POST + @Path("import") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionRepresentation import_( + FileMultipartCxf body, + @QueryParam("renewIdmEntries") Boolean renewIdmEntries); + + @POST + @Path("{modelId}/import") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionRepresentation import_( + @PathParam("modelId") Long appId, + FileMultipartCxf body, + @QueryParam("renewIdmEntries") Boolean renewIdmEntries); + + @POST + @Path("publish-app") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionUpdateResultRepresentation publishApp( + FileMultipartCxf body); + + @POST + @Path("{modelId}/publish-app") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionUpdateResultRepresentation publishApp( + @PathParam("modelId") Long appId, + FileMultipartCxf body); + +} diff --git a/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsJerseyApi.java b/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsJerseyApi.java new file mode 100644 index 0000000..866ce7d --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/api/AppDefinitionsJerseyApi.java @@ -0,0 +1,51 @@ + +package com.inteligr8.alfresco.activiti.api; + +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 com.inteligr8.alfresco.activiti.model.AppDefinitionRepresentation; +import com.inteligr8.alfresco.activiti.model.AppDefinitionUpdateResultRepresentation; +import com.inteligr8.alfresco.activiti.model.FileMultipartJersey; + +@Path("/api/enterprise/app-definitions") +public interface AppDefinitionsJerseyApi { + + @POST + @Path("import") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionRepresentation importApp( + FileMultipartJersey file, + @QueryParam("renewIdmEntries") Boolean renewIdmEntries); + + @POST + @Path("{modelId}/import") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionRepresentation importApp( + @PathParam("modelId") Long appId, + FileMultipartJersey file, + @QueryParam("renewIdmEntries") Boolean renewIdmEntries); + + @POST + @Path("publish-app") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionUpdateResultRepresentation publishApp( + FileMultipartJersey file); + + @POST + @Path("{modelId}/publish-app") + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + AppDefinitionUpdateResultRepresentation publishApp( + @PathParam("modelId") Long appId, + FileMultipartJersey file); + +} diff --git a/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartCxf.java b/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartCxf.java new file mode 100644 index 0000000..ce84a6d --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartCxf.java @@ -0,0 +1,38 @@ +package com.inteligr8.alfresco.activiti.model; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; + +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; +import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; + +public class FileMultipartCxf extends MultipartBody { + + public static FileMultipartCxf from(String filename, InputStream istream) throws IOException { + return new FileMultipartCxf(Arrays.asList(toAttachment(filename, istream))); + } + + public FileMultipartCxf(List atts) throws IOException { + super(atts); + } + + public FileMultipartCxf(List atts, boolean outbound) { + super(atts, outbound); + } + + public Attachment getFileAttachment() { + return this.getAttachment("file"); + } + + private static Attachment toAttachment(String filename, InputStream istream) { + if (filename == null) { + return new Attachment("file", istream, new ContentDisposition("form-data; name=\"file\"")); + } else { + return new Attachment("file", istream, new ContentDisposition("form-data; name=\"file\"; filename=\"" + filename + "\"")); + } + } + +} diff --git a/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartJersey.java b/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartJersey.java new file mode 100644 index 0000000..99160c5 --- /dev/null +++ b/src/main/java/com/inteligr8/alfresco/activiti/model/FileMultipartJersey.java @@ -0,0 +1,38 @@ +package com.inteligr8.alfresco.activiti.model; + +import java.io.InputStream; +import java.text.ParseException; + +import org.glassfish.jersey.media.multipart.BodyPart; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataMultiPart; + +public class FileMultipartJersey extends FormDataMultiPart { + + public static FileMultipartJersey from(String filename, InputStream istream) throws ParseException { + FileMultipartJersey multipart = new FileMultipartJersey(); + multipart.bodyPart(toBodyPart(filename, istream)); + return multipart; + } + + private FileMultipartJersey() { + } + + public FormDataBodyPart getFileAttachment() { + return this.getField("file"); + } + + private static BodyPart toBodyPart(String filename, InputStream istream) throws ParseException { + if (filename == null) { + return new FormDataBodyPart() + .contentDisposition(new FormDataContentDisposition("form-data; name=\"file\"")) + .entity(istream); + } else { + return new FormDataBodyPart() + .contentDisposition(new FormDataContentDisposition("form-data; name=\"file\"; filename=\"" + filename + "\"")) + .entity(istream); + } + } + +}