diff --git a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs31/ee/multipart/MultipartSupportIT.java b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs31/ee/multipart/MultipartSupportIT.java index 49d00ab7..8f7c334a 100644 --- a/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs31/ee/multipart/MultipartSupportIT.java +++ b/jaxrs-tck/src/main/java/ee/jakarta/tck/ws/rs/jaxrs31/ee/multipart/MultipartSupportIT.java @@ -76,351 +76,351 @@ @ExtendWith(ArquillianExtension.class) @RunAsClient public class MultipartSupportIT { - private static final long serialVersionUID = 31L; - - private static final String LS = System.lineSeparator(); - static InputStream xmlFile() { - String xml = - "" + LS + - " " + LS + - " " + LS + - " " + LS + - " " + LS + - " " + LS + - " " + LS + - ""; - return new ByteArrayInputStream(xml.getBytes()); - } - - - @BeforeEach - void logStartTest(TestInfo testInfo) { - TestUtil.logMsg("STARTING TEST : "+testInfo.getDisplayName()); - } - - @AfterEach - void logFinishTest(TestInfo testInfo) { - TestUtil.logMsg("FINISHED TEST : "+testInfo.getDisplayName()); - } - - @Deployment - public static WebArchive deployment() { - return ShrinkWrap.create(WebArchive.class, MultipartSupportIT.class.getSimpleName() + ".war") - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); - } - - @ArquillianResource - private URI uri; - - /** - * Verify sending a List of {@link EntityPart} and receiving a List sent back from the resource method containing - * the same parts plus an additional part added by thye resource method containing extra headers. - * - * @throws Exception if an error occurs in the test - */ - @Test - public void basicTest() throws Exception { - try (Client client = ClientBuilder.newClient()) { - final List multipart = List.of( - EntityPart.withName("octet-stream") - .content("test string".getBytes(StandardCharsets.UTF_8)) - .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .build(), - EntityPart.withName("file") - .content("test file", xmlFile()) - .mediaType(MediaType.APPLICATION_XML) - .build() - ); - try ( - Response response = client.target(createCombinedUri(uri, "test/basicTest")) - .request(MediaType.MULTIPART_FORM_DATA_TYPE) - .post(Entity.entity(new GenericEntity<>(multipart) { - }, MediaType.MULTIPART_FORM_DATA))) { - Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); - final List entityParts = response.readEntity(new GenericType<>() { - }); - if (entityParts.size() != 3) { - final String msg = "Expected 3 entries, received " + - entityParts.size() + - '.' + - System.lineSeparator() + - getMessage(entityParts); - Assertions.fail(msg); - } - EntityPart part = find(entityParts, "received-string"); - Assertions.assertNotNull(part, getMessage(entityParts)); - Assertions.assertEquals("test string", part.getContent(String.class)); - - part = find(entityParts, "received-file"); - Assertions.assertNotNull(part, getMessage(entityParts)); - Assertions.assertTrue(part.getContent(String.class).contains("value6")); - - part = find(entityParts, "added-input-stream"); - Assertions.assertNotNull(part, getMessage(entityParts)); - Assertions.assertEquals("Add part on return.", part.getContent(String.class)); - - // Check headers. Should be 4: Content-Disposition, Content-Type, and the 2 headers - // that were added. - if ((part.getHeaders() == null) || (part.getHeaders().size() != 4)) { - final String msg = "Expected 4 headers, received " + - part.getHeaders().size(); - Assertions.fail(msg); - } - Assertions.assertEquals("[Test1]", part.getHeaders().get("Header1").get(0)); - Assertions.assertEquals("[Test2]", part.getHeaders().get("Header2").get(0)); - } - } - } - - /** - * Verify that invoking a resource method with a single EntityPart can be injected in different formats; - * {@link String}, {@link EntityPart} and {@link InputStream} with the same content for each. - * - * @throws Exception if an error occurs in the test - */ - @Test - public void singleFormParamTest() throws Exception { - try (Client client = ClientBuilder.newClient()) { - final List multipart = List.of( - EntityPart.withName("test-string") - .content("test single part") - .mediaType(MediaType.TEXT_PLAIN_TYPE) - .build()); - try ( - Response response = client.target(createCombinedUri(uri, "test//single-form-param")) - .request(MediaType.MULTIPART_FORM_DATA_TYPE) - .post(Entity.entity(new GenericEntity<>(multipart) { - }, MediaType.MULTIPART_FORM_DATA))) { - Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); - final List entityParts = response.readEntity(new GenericType<>() { - }); - if (entityParts.size() != 3) { - final String msg = "Expected 3 entries, received " + - entityParts.size() + - '.' + - System.lineSeparator() + - getMessage(entityParts); - Assertions.fail(msg); - } - verifyEntityPart(entityParts, "received-entity-part", "test single part"); - verifyEntityPart(entityParts, "received-string", "test single part"); - verifyEntityPart(entityParts, "received-input-stream", "test single part"); - } - } - } - - - /** - * Verify sending a {@link List} containing three {@link EntityPart}, each injected as a different type. - *

- * The returned result will be {@code multipart/form-data} content with a new name and the content for each - * injected field. - *

- * - * @throws Exception if an error occurs in the test - */ - @Test - public void multiFormParamTest() throws Exception { - try (Client client = ClientBuilder.newClient()) { - final List multipart = List.of( - EntityPart.withName("entity-part") - .content("test entity part") - .mediaType(MediaType.TEXT_PLAIN_TYPE) - .build(), - EntityPart.withName("string-part") - .content("test string") - .mediaType(MediaType.TEXT_PLAIN_TYPE) - .build(), - EntityPart.withName("input-stream-part") - .content("test input stream".getBytes(StandardCharsets.UTF_8)) - .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .build()); - try ( - Response response = client.target(createCombinedUri(uri, "test/multi-form-param")) - .request(MediaType.MULTIPART_FORM_DATA_TYPE) - .post(Entity.entity(new GenericEntity<>(multipart) { - }, MediaType.MULTIPART_FORM_DATA))) { - Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); - final List entityParts = response.readEntity(new GenericType<>() { - }); - if (entityParts.size() != 3) { - final String msg = "Expected 3 entries, received " + - entityParts.size() + - '.' + - System.lineSeparator() + - getMessage(entityParts); - Assertions.fail(msg); - } - verifyEntityPart(entityParts, "received-entity-part", "test entity part"); - verifyEntityPart(entityParts, "received-string", "test string"); - verifyEntityPart(entityParts, "received-input-stream", "test input stream"); - } - } - } - - private static void verifyEntityPart(final List parts, final String name, final String text) - throws IOException { - final EntityPart part = find(parts, name); - Assertions.assertNotNull(part, - String.format("Failed to find entity part %s in: %s", name, getMessage(parts))); - Assertions.assertEquals(text, part.getContent(String.class)); - } - - private static String getMessage(final List parts) throws IOException { - final StringBuilder msg = new StringBuilder(); - final Iterator iter = parts.iterator(); - while (iter.hasNext()) { - final EntityPart part = iter.next(); - msg.append('[') - .append(part.getName()) - .append("={") - .append("headers=") - .append(part.getHeaders()) - .append(", mediaType=") - .append(part.getMediaType()) - .append(", body=") - .append(toString(part.getContent())) - .append('}'); - if (iter.hasNext()) { - msg.append("], "); - } else { - msg.append(']'); - } - } - return msg.toString(); - } - - private static String toString(final InputStream in) throws IOException { - // try-with-resources fails here due to a bug in the - //noinspection TryFinallyCanBeTryWithResources - try { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] buffer = new byte[32]; - int len; - while ((len = in.read(buffer)) > 0) { - out.write(buffer, 0, len); - } - return out.toString(StandardCharsets.UTF_8); - } finally { - in.close(); - } - } - - private static EntityPart find(final Collection parts, final String name) { - for (EntityPart part : parts) { - if (name.equals(part.getName())) { - return part; - } - } - return null; - } - - private static URI createCombinedUri(final URI uri, final String path) throws URISyntaxException { - if (path == null || path.isEmpty()) { - return uri; - } - String uriString = uri.toString(); - - TestUtil.logMsg("Initial uri string: " + uriString); - - final StringBuilder builder = new StringBuilder(uriString); - if (builder.charAt(builder.length() - 1) == '/') { - if (path.charAt(0) == '/') { - builder.append(path.substring(1)); - } else { - builder.append(path); - } - } else if (path.charAt(0) == '/') { - builder.append(path.substring(1)); - } else { - builder.append('/').append(path); - } - - String builderString = builder.toString(); - TestUtil.logMsg("Combined uri string: " + builderString); - - return new URI(builderString); - } - - @ApplicationPath("/") - public static class MultipartTestApplication extends Application { - } - - @Path("/test") - public static class TestResource { - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces(MediaType.MULTIPART_FORM_DATA) - @Path("/basicTest") - public Response basicTest(final List parts) throws IOException { - final List multipart = List.of( - EntityPart.withName("received-string") - .content(find(parts,"octet-stream").getContent(byte[].class)) - .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .build(), - EntityPart.withName("received-file") - .content(find(parts,"file")) - .mediaType(MediaType.APPLICATION_XML) - .build(), - EntityPart.withName("added-input-stream") - .content(new ByteArrayInputStream("Add part on return.".getBytes())) - .mediaType("text/asciidoc") - .header("Header1","Test1") - .header("Header2","Test2") - .build()); - return Response.ok(new GenericEntity<>(multipart) { - }, MediaType.MULTIPART_FORM_DATA).build(); - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces(MediaType.MULTIPART_FORM_DATA) - @Path("/single-form-param") - public List singleParamTest(@FormParam("test-string") final String string, - @FormParam("test-string") final EntityPart entityPart, - @FormParam("test-string") final InputStream in) throws IOException { - return List.of( - EntityPart.withName("received-entity-part") - .content(entityPart.getContent(String.class)) - .mediaType(entityPart.getMediaType()) - .fileName(entityPart.getFileName().orElse(null)) - .build(), - EntityPart.withName("received-input-stream") - .content(MultipartSupportIT.toString(in).getBytes(StandardCharsets.UTF_8)) - .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .build(), - EntityPart.withName("received-string") - .content(string) - .mediaType(MediaType.TEXT_PLAIN_TYPE) - .build()); - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces(MediaType.MULTIPART_FORM_DATA) - @Path("/multi-form-param") - public Response multipleFormParamTest(@FormParam("string-part") final String string, - @FormParam("entity-part") final EntityPart entityPart, - @FormParam("input-stream-part") final InputStream in) throws IOException { - final List multipart = List.of( - EntityPart.withName("received-entity-part") - .content(entityPart.getContent(String.class)) - .mediaType(entityPart.getMediaType()) - .fileName(entityPart.getFileName().orElse(null)) - .build(), - EntityPart.withName("received-input-stream") - .content(MultipartSupportIT.toString(in).getBytes(StandardCharsets.UTF_8)) - .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) - .build(), - EntityPart.withName("received-string") - .content(string) - .mediaType(MediaType.TEXT_PLAIN_TYPE) - .build()); - return Response.ok(new GenericEntity<>(multipart) { - }, MediaType.MULTIPART_FORM_DATA).build(); - } - - } + private static final long serialVersionUID = 31L; + + private static final String LS = System.lineSeparator(); + static InputStream xmlFile() { + String xml = + "" + LS + + " " + LS + + " " + LS + + " " + LS + + " " + LS + + " " + LS + + " " + LS + + ""; + return new ByteArrayInputStream(xml.getBytes()); + } + + + @BeforeEach + void logStartTest(TestInfo testInfo) { + TestUtil.logMsg("STARTING TEST : "+testInfo.getDisplayName()); + } + + @AfterEach + void logFinishTest(TestInfo testInfo) { + TestUtil.logMsg("FINISHED TEST : "+testInfo.getDisplayName()); + } + + @Deployment + public static WebArchive deployment() { + return ShrinkWrap.create(WebArchive.class, MultipartSupportIT.class.getSimpleName() + ".war") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @ArquillianResource + private URI uri; + + /** + * Verify sending a List of {@link EntityPart} and receiving a List sent back from the resource method containing + * the same parts plus an additional part added by thye resource method containing extra headers. + * + * @throws Exception if an error occurs in the test + */ + @Test + public void basicTest() throws Exception { + try (Client client = ClientBuilder.newClient()) { + final List multipart = List.of( + EntityPart.withName("octet-stream") + .content("test string".getBytes(StandardCharsets.UTF_8)) + .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .build(), + EntityPart.withName("file") + .content("test file", xmlFile()) + .mediaType(MediaType.APPLICATION_XML) + .build() + ); + try ( + Response response = client.target(createCombinedUri(uri, "test/basicTest")) + .request(MediaType.MULTIPART_FORM_DATA_TYPE) + .post(Entity.entity(new GenericEntity<>(multipart) { + }, MediaType.MULTIPART_FORM_DATA))) { + Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); + final List entityParts = response.readEntity(new GenericType<>() { + }); + if (entityParts.size() != 3) { + final String msg = "Expected 3 entries, received " + + entityParts.size() + + '.' + + System.lineSeparator() + + getMessage(entityParts); + Assertions.fail(msg); + } + EntityPart part = find(entityParts, "received-string"); + Assertions.assertNotNull(part, getMessage(entityParts)); + Assertions.assertEquals("test string", part.getContent(String.class)); + + part = find(entityParts, "received-file"); + Assertions.assertNotNull(part, getMessage(entityParts)); + Assertions.assertTrue(part.getContent(String.class).contains("value6")); + + part = find(entityParts, "added-input-stream"); + Assertions.assertNotNull(part, getMessage(entityParts)); + Assertions.assertEquals("Add part on return.", part.getContent(String.class)); + + // Check headers. Should be 4: Content-Disposition, Content-Type, and the 2 headers + // that were added. + if ((part.getHeaders() == null) || (part.getHeaders().size() != 4)) { + final String msg = "Expected 4 headers, received " + + part.getHeaders().size(); + Assertions.fail(msg); + } + Assertions.assertEquals("[Test1]", part.getHeaders().get("Header1").get(0)); + Assertions.assertEquals("[Test2]", part.getHeaders().get("Header2").get(0)); + } + } + } + + /** + * Verify that invoking a resource method with a single EntityPart can be injected in different formats; + * {@link String}, {@link EntityPart} and {@link InputStream} with the same content for each. + * + * @throws Exception if an error occurs in the test + */ + @Test + public void singleFormParamTest() throws Exception { + try (Client client = ClientBuilder.newClient()) { + final List multipart = List.of( + EntityPart.withName("test-string") + .content("test single part") + .mediaType(MediaType.TEXT_PLAIN_TYPE) + .build()); + try ( + Response response = client.target(createCombinedUri(uri, "test//single-form-param")) + .request(MediaType.MULTIPART_FORM_DATA_TYPE) + .post(Entity.entity(new GenericEntity<>(multipart) { + }, MediaType.MULTIPART_FORM_DATA))) { + Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); + final List entityParts = response.readEntity(new GenericType<>() { + }); + if (entityParts.size() != 3) { + final String msg = "Expected 3 entries, received " + + entityParts.size() + + '.' + + System.lineSeparator() + + getMessage(entityParts); + Assertions.fail(msg); + } + verifyEntityPart(entityParts, "received-entity-part", "test single part"); + verifyEntityPart(entityParts, "received-string", "test single part"); + verifyEntityPart(entityParts, "received-input-stream", "test single part"); + } + } + } + + + /** + * Verify sending a {@link List} containing three {@link EntityPart}, each injected as a different type. + *

+ * The returned result will be {@code multipart/form-data} content with a new name and the content for each + * injected field. + *

+ * + * @throws Exception if an error occurs in the test + */ + @Test + public void multiFormParamTest() throws Exception { + try (Client client = ClientBuilder.newClient()) { + final List multipart = List.of( + EntityPart.withName("entity-part") + .content("test entity part") + .mediaType(MediaType.TEXT_PLAIN_TYPE) + .build(), + EntityPart.withName("string-part") + .content("test string") + .mediaType(MediaType.TEXT_PLAIN_TYPE) + .build(), + EntityPart.withName("input-stream-part") + .content("test input stream".getBytes(StandardCharsets.UTF_8)) + .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .build()); + try ( + Response response = client.target(createCombinedUri(uri, "test/multi-form-param")) + .request(MediaType.MULTIPART_FORM_DATA_TYPE) + .post(Entity.entity(new GenericEntity<>(multipart) { + }, MediaType.MULTIPART_FORM_DATA))) { + Assertions.assertEquals(Response.Status.OK, response.getStatusInfo()); + final List entityParts = response.readEntity(new GenericType<>() { + }); + if (entityParts.size() != 3) { + final String msg = "Expected 3 entries, received " + + entityParts.size() + + '.' + + System.lineSeparator() + + getMessage(entityParts); + Assertions.fail(msg); + } + verifyEntityPart(entityParts, "received-entity-part", "test entity part"); + verifyEntityPart(entityParts, "received-string", "test string"); + verifyEntityPart(entityParts, "received-input-stream", "test input stream"); + } + } + } + + private static void verifyEntityPart(final List parts, final String name, final String text) + throws IOException { + final EntityPart part = find(parts, name); + Assertions.assertNotNull(part, + String.format("Failed to find entity part %s in: %s", name, getMessage(parts))); + Assertions.assertEquals(text, part.getContent(String.class)); + } + + private static String getMessage(final List parts) throws IOException { + final StringBuilder msg = new StringBuilder(); + final Iterator iter = parts.iterator(); + while (iter.hasNext()) { + final EntityPart part = iter.next(); + msg.append('[') + .append(part.getName()) + .append("={") + .append("headers=") + .append(part.getHeaders()) + .append(", mediaType=") + .append(part.getMediaType()) + .append(", body=") + .append(toString(part.getContent())) + .append('}'); + if (iter.hasNext()) { + msg.append("], "); + } else { + msg.append(']'); + } + } + return msg.toString(); + } + + private static String toString(final InputStream in) throws IOException { + // try-with-resources fails here due to a bug in the + //noinspection TryFinallyCanBeTryWithResources + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[32]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + return out.toString(StandardCharsets.UTF_8); + } finally { + in.close(); + } + } + + private static EntityPart find(final Collection parts, final String name) { + for (EntityPart part : parts) { + if (name.equals(part.getName())) { + return part; + } + } + return null; + } + + private static URI createCombinedUri(final URI uri, final String path) throws URISyntaxException { + if (path == null || path.isEmpty()) { + return uri; + } + String uriString = uri.toString(); + + TestUtil.logMsg("Initial uri string: " + uriString); + + final StringBuilder builder = new StringBuilder(uriString); + if (builder.charAt(builder.length() - 1) == '/') { + if (path.charAt(0) == '/') { + builder.append(path.substring(1)); + } else { + builder.append(path); + } + } else if (path.charAt(0) == '/') { + builder.append(path.substring(1)); + } else { + builder.append('/').append(path); + } + + String builderString = builder.toString(); + TestUtil.logMsg("Combined uri string: " + builderString); + + return new URI(builderString); + } + + @ApplicationPath("/") + public static class MultipartTestApplication extends Application { + } + + @Path("/test") + public static class TestResource { + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.MULTIPART_FORM_DATA) + @Path("/basicTest") + public Response basicTest(final List parts) throws IOException { + final List multipart = List.of( + EntityPart.withName("received-string") + .content(find(parts,"octet-stream").getContent(byte[].class)) + .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .build(), + EntityPart.withName("received-file") + .content(find(parts,"file")) + .mediaType(MediaType.APPLICATION_XML) + .build(), + EntityPart.withName("added-input-stream") + .content(new ByteArrayInputStream("Add part on return.".getBytes())) + .mediaType("text/asciidoc") + .header("Header1","Test1") + .header("Header2","Test2") + .build()); + return Response.ok(new GenericEntity<>(multipart) { + }, MediaType.MULTIPART_FORM_DATA).build(); + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.MULTIPART_FORM_DATA) + @Path("/single-form-param") + public List singleParamTest(@FormParam("test-string") final String string, + @FormParam("test-string") final EntityPart entityPart, + @FormParam("test-string") final InputStream in) throws IOException { + return List.of( + EntityPart.withName("received-entity-part") + .content(entityPart.getContent(String.class)) + .mediaType(entityPart.getMediaType()) + .fileName(entityPart.getFileName().orElse(null)) + .build(), + EntityPart.withName("received-input-stream") + .content(MultipartSupportIT.toString(in).getBytes(StandardCharsets.UTF_8)) + .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .build(), + EntityPart.withName("received-string") + .content(string) + .mediaType(MediaType.TEXT_PLAIN_TYPE) + .build()); + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.MULTIPART_FORM_DATA) + @Path("/multi-form-param") + public Response multipleFormParamTest(@FormParam("string-part") final String string, + @FormParam("entity-part") final EntityPart entityPart, + @FormParam("input-stream-part") final InputStream in) throws IOException { + final List multipart = List.of( + EntityPart.withName("received-entity-part") + .content(entityPart.getContent(String.class)) + .mediaType(entityPart.getMediaType()) + .fileName(entityPart.getFileName().orElse(null)) + .build(), + EntityPart.withName("received-input-stream") + .content(MultipartSupportIT.toString(in).getBytes(StandardCharsets.UTF_8)) + .mediaType(MediaType.APPLICATION_OCTET_STREAM_TYPE) + .build(), + EntityPart.withName("received-string") + .content(string) + .mediaType(MediaType.TEXT_PLAIN_TYPE) + .build()); + return Response.ok(new GenericEntity<>(multipart) { + }, MediaType.MULTIPART_FORM_DATA).build(); + } + + } } \ No newline at end of file