/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.jersey.media.multipart.internal;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.Collections;
import java.util.Set;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import org.glassfish.jersey.media.multipart.BodyPart;
import org.glassfish.jersey.media.multipart.BodyPartEntity;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* Unit tests for {@link org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide} (in the client) and
* {@link org.glassfish.jersey.media.multipart.internal.MultiPartWriter} (in the server)
.*/
public class MultiPartReaderWriterTest extends MultiPartJerseyTest {
private static Path TMP_DIRECTORY;
private static String ORIGINAL_TMP_DIRECTORY;
@Before
public void setUp() throws Exception {
super.setUp();
ORIGINAL_TMP_DIRECTORY = System.getProperty("java.io.tmpdir");
TMP_DIRECTORY = Files.createTempDirectory(MultiPartReaderWriterTest.class.getName());
System.setProperty("java.io.tmpdir", TMP_DIRECTORY.toString());
}
@After
public void tearDown() throws Exception {
super.tearDown();
try {
Files.delete(TMP_DIRECTORY);
} finally {
System.setProperty("java.io.tmpdir", ORIGINAL_TMP_DIRECTORY);
}
}
@Override
protected Set<Class<?>> getResourceClasses() {
return Collections.<Class<?>>singleton(MultiPartResource.class);
}
@Test
public void testZero() {
final WebTarget target = target().path("multipart").path("zero");
final String result = target.request("text/plain").get(String.class);
assertEquals("Hello, world\r\n", result);
}
@Test
public void testOne() {
final WebTarget target = target().path("multipart/one");
try {
final MultiPart result = target.request("multipart/mixed").get(MultiPart.class);
checkMediaType(new MediaType("multipart", "mixed"), result.getMediaType());
assertEquals(1, result.getBodyParts().size());
final BodyPart part = result.getBodyParts().get(0);
checkMediaType(new MediaType("text", "plain"), part.getMediaType());
checkEntity("This is the only segment", (BodyPartEntity) part.getEntity());
result.getParameterizedHeaders();
result.cleanup();
} catch (final IOException | ParseException e) {
e.printStackTrace(System.out);
fail("Caught exception: " + e);
}
}
@Test
public void testETag() {
final WebTarget target = target().path("multipart/etag");
try {
final MultiPart result = target.request("multipart/mixed").get(MultiPart.class);
checkMediaType(new MediaType("multipart", "mixed"), result.getMediaType());
assertEquals(1, result.getBodyParts().size());
final BodyPart part = result.getBodyParts().get(0);
checkMediaType(new MediaType("text", "plain"), part.getMediaType());
checkEntity("This is the only segment", (BodyPartEntity) part.getEntity());
assertEquals("\"value\"", part.getHeaders().getFirst("ETag"));
result.getParameterizedHeaders();
result.cleanup();
} catch (final IOException | ParseException e) {
e.printStackTrace(System.out);
fail("Caught exception: " + e);
}
}
@Test
public void testTwo() {
final WebTarget target = target().path("multipart/two");
try {
final MultiPart result = target.request("multipart/mixed").get(MultiPart.class);
checkMediaType(new MediaType("multipart", "mixed"), result.getMediaType());
assertEquals(2, result.getBodyParts().size());
final BodyPart part1 = result.getBodyParts().get(0);
checkMediaType(new MediaType("text", "plain"), part1.getMediaType());
checkEntity("This is the first segment", (BodyPartEntity) part1.getEntity());
final BodyPart part2 = result.getBodyParts().get(1);
checkMediaType(new MediaType("text", "xml"), part2.getMediaType());
checkEntity("<outer><inner>value</inner></outer>", (BodyPartEntity) part2.getEntity());
result.getParameterizedHeaders();
result.cleanup();
} catch (final IOException | ParseException e) {
e.printStackTrace(System.out);
fail("Caught exception: " + e);
}
}
@Test
public void testThree() {
final WebTarget target = target().path("multipart/three");
try {
final MultiPart result = target.request("multipart/mixed").get(MultiPart.class);
checkMediaType(new MediaType("multipart", "mixed"), result.getMediaType());
assertEquals(2, result.getBodyParts().size());
final BodyPart part1 = result.getBodyParts().get(0);
checkMediaType(new MediaType("text", "plain"), part1.getMediaType());
checkEntity("This is the first segment", (BodyPartEntity) part1.getEntity());
final BodyPart part2 = result.getBodyParts().get(1);
checkMediaType(new MediaType("x-application", "x-format"), part2.getMediaType());
final MultiPartBean entity = part2.getEntityAs(MultiPartBean.class);
assertEquals("myname", entity.getName());
assertEquals("myvalue", entity.getValue());
result.getParameterizedHeaders();
result.cleanup();
} catch (final IOException | ParseException e) {
e.printStackTrace(System.out);
fail("Caught exception: " + e);
}
}
@Test
public void testFour() {
final WebTarget target = target().path("multipart/four");
final MultiPartBean bean = new MultiPartBean("myname", "myvalue");
final MultiPart entity = new MultiPart()
.bodyPart("This is the first segment", new MediaType("text", "plain"))
.bodyPart(bean, new MediaType("x-application", "x-format"));
final String response = target.request("text/plain").put(Entity.entity(entity, "multipart/mixed"), String.class);
if (!response.startsWith("SUCCESS:")) {
fail("Response is '" + response + "'");
}
}
@Test
public void testFourBiz() {
final WebTarget target = target().path("multipart/four");
final MultiPartBean bean = new MultiPartBean("myname", "myvalue");
final MultiPart entity = new MultiPart()
.bodyPart("This is the first segment", new MediaType("text", "plain"))
.bodyPart(bean, new MediaType("x-application", "x-format"));
final String response = target.request("text/plain").header("Content-Type", "multipart/mixed")
.put(Entity.entity(entity, "multipart/mixed"), String.class);
if (!response.startsWith("SUCCESS:")) {
fail("Response is '" + response + "'");
}
}
/**
* Test sending a completely empty MultiPart.
*/
@Test(expected = ProcessingException.class)
public void testSix() {
target()
.path("multipart/six")
.request("text/plain")
.post(Entity.entity(new MultiPart(), "multipart/mixed"), String.class);
fail("Should have thrown an exception about zero body parts");
}
/**
* Zero length body part.
*/
@Test
public void testTen() {
final WebTarget target = target().path("multipart/ten");
final MultiPartBean bean = new MultiPartBean("myname", "myvalue");
final MultiPart entity = new MultiPart()
.bodyPart(bean, new MediaType("x-application", "x-format"))
.bodyPart("", MediaType.APPLICATION_OCTET_STREAM_TYPE);
final String response = target.request("text/plain").put(Entity.entity(entity, "multipart/mixed"), String.class);
if (!response.startsWith("SUCCESS:")) {
fail("Response is '" + response + "'");
}
}
/**
* Echo back various sized body part entities, and check size/content
*/
@Test
public void testEleven() throws Exception {
final String seed = "0123456789ABCDEF";
checkEleven(seed, 0);
checkEleven(seed, 1);
checkEleven(seed, 10);
checkEleven(seed, 100);
checkEleven(seed, 1000);
checkEleven(seed, 10000);
checkEleven(seed, 100000);
}
/**
* Echo back the multipart that was sent.
*/
@Test
public void testTwelve() throws Exception {
final WebTarget target = target().path("multipart/twelve");
final MultiPart entity = new MultiPart().bodyPart("CONTENT", MediaType.TEXT_PLAIN_TYPE);
final MultiPart response = target.request("multipart/mixed")
.put(Entity.entity(entity, "multipart/mixed"), MultiPart.class);
final String actual = response.getBodyParts().get(0).getEntityAs(String.class);
assertEquals("CONTENT", actual);
response.cleanup();
}
/**
* Call clean up explicitly.
*/
@Test
public void testThirteen() {
final WebTarget target = target().path("multipart/thirteen");
final MultiPart entity = new MultiPart()
.bodyPart("CONTENT", MediaType.TEXT_PLAIN_TYPE);
final String response = target.request("multipart/mixed").put(Entity.entity(entity, "multipart/mixed"), String.class);
assertEquals("cleanup", response);
}
/**
* Test for JERSEY-2515 - Jersey should not leave any temporary files after verifying that it is possible
* to create files in java.io.tmpdir.
*/
@Test
@SuppressWarnings("ConstantConditions")
public void shouldNotBeAnyTemporaryFiles() {
// Make sure the MBR is initialized on the client-side as well.
target().request().get();
assertEquals(0, TMP_DIRECTORY.toFile().listFiles().length);
}
private void checkEntity(final String expected, final BodyPartEntity entity) throws IOException {
// Convert the raw bytes into a String
final InputStreamReader sr = new InputStreamReader(entity.getInputStream());
final StringWriter sw = new StringWriter();
while (true) {
final int ch = sr.read();
if (ch < 0) {
break;
}
sw.append((char) ch);
}
// Perform the comparison
assertEquals(expected, sw.toString());
}
private void checkEleven(final String seed, final int multiplier) throws Exception {
final StringBuilder sb = new StringBuilder(seed.length() * multiplier);
for (int i = 0; i < multiplier; i++) {
sb.append(seed);
}
final String expected = sb.toString();
final WebTarget target = target().path("multipart/eleven");
final MultiPart entity = new MultiPart().bodyPart(expected, MediaType.TEXT_PLAIN_TYPE);
final MultiPart response = target.request("multipart/mixed")
.put(Entity.entity(entity, "multipart/mixed"), MultiPart.class);
final String actual = response.getBodyParts().get(0).getEntityAs(String.class);
assertEquals("Length for multiplier " + multiplier, expected.length(), actual.length());
assertEquals("Content for multiplier " + multiplier, expected, actual);
response.cleanup();
}
private void checkMediaType(final MediaType expected, final MediaType actual) {
assertEquals("Expected MediaType=" + expected, expected.getType(), actual.getType());
assertEquals("Expected MediaType=" + expected, expected.getSubtype(), actual.getSubtype());
}
}