/** * Copyright (c) Codice Foundation * <p/> * This 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 any later version. * <p/> * This program 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. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package ddf.content.endpoint.rest; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import javax.activation.MimeType; import javax.activation.MimeTypeParseException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.io.IOUtils; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.impl.MetadataMap; import org.junit.Test; import junit.framework.Assert; import ddf.content.ContentFramework; import ddf.content.ContentFrameworkException; import ddf.content.data.ContentItem; import ddf.content.endpoint.rest.ContentEndpoint.CreateInfo; import ddf.content.operation.ReadRequest; import ddf.content.operation.ReadResponse; import ddf.mime.MimeTypeMapper; import ddf.mime.MimeTypeResolutionException; public class ContentEndpointCreateTest { private static final String CONTENT_DISPOSITION = "Content-Disposition"; private static final String CONTENT_TYPE = "Content-Type"; private static final String TEST_JSON = "{\r\n" + " \"properties\": {\r\n" + " \"title\": \"myTitle\",\r\n" + " \"thumbnail\": \"CA==\",\r\n" + " \"resource-uri\": \"http://example.com\",\r\n" + " \"created\": \"2012-09-01T00:09:19.368+0000\",\r\n" + " \"metadata-content-type-version\": \"myVersion\",\r\n" + " \"metadata-content-type\": \"myType\",\r\n" + " \"metadata\": \"<xml>metadata goes here ...</xml>\",\r\n" + " \"modified\": \"2012-09-01T00:09:19.368+0000\"\r\n" + " },\r\n" + " \"type\": \"Feature\",\r\n" + " \"geometry\": {\r\n" + " \"type\": \"Point\",\r\n" + " \"coordinates\": [\r\n" + " 30.0,\r\n" + " 10.0\r\n" + " ]\r\n" + " }\r\n" + "} "; @Test public void testParseAttachmentContentTypeSpecified() throws Exception { InputStream is = IOUtils.toInputStream(TEST_JSON); MetadataMap<String, String> headers = new MetadataMap<String, String>(); headers.add(CONTENT_DISPOSITION, "form-data; name=file; filename=C:\\DDF\\geojson_valid.json"); headers.add(CONTENT_TYPE, "application/json;id=geojson"); Attachment attachment = new Attachment(is, headers); ContentFramework framework = mock(ContentFramework.class); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); CreateInfo createInfo = endpoint.parseAttachment(attachment); Assert.assertNotNull(createInfo); Assert.assertEquals("application/json;id=geojson", createInfo.getContentType()); Assert.assertEquals("geojson_valid.json", createInfo.getFilename()); } /** * No Content-Type specified by client, so it should default to text/plain * and be refined by ContentEndpoint to application/json;id=geojson based on the filename's * extension of "json". * * @throws Exception */ @Test public void testParseAttachmentContentTypeNotSpecified() throws Exception { InputStream is = IOUtils.toInputStream(TEST_JSON); MetadataMap<String, String> headers = new MetadataMap<String, String>(); headers.add(ContentEndpoint.CONTENT_DISPOSITION, "form-data; name=file; filename=C:\\DDF\\geojson_valid.json"); Attachment attachment = new Attachment(is, headers); ContentFramework framework = mock(ContentFramework.class); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); CreateInfo createInfo = endpoint.parseAttachment(attachment); Assert.assertNotNull(createInfo); Assert.assertEquals("application/json;id=geojson", createInfo.getContentType()); Assert.assertEquals("geojson_valid.json", createInfo.getFilename()); } /** * Content-Type specified by client as one of the defaults (e.g., application/octet-stream) * simulating what a browser might do, and should be refined by ContentEndpoint to * application/json;id=geojson based on the filename's extension of "json". * * @throws Exception */ @Test public void testParseAttachmentContentTypeSetToBrowserDefault() throws Exception { InputStream is = IOUtils.toInputStream(TEST_JSON); MetadataMap<String, String> headers = new MetadataMap<String, String>(); headers.add(ContentEndpoint.CONTENT_DISPOSITION, "form-data; name=file; filename=C:\\DDF\\geojson_valid.json"); headers.add(CONTENT_TYPE, "application/octet-stream"); Attachment attachment = new Attachment(is, headers); ContentFramework framework = mock(ContentFramework.class); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); CreateInfo createInfo = endpoint.parseAttachment(attachment); Assert.assertNotNull(createInfo); Assert.assertEquals("application/json;id=geojson", createInfo.getContentType()); Assert.assertEquals("geojson_valid.json", createInfo.getFilename()); } /** * No filename specified by client, so ContentEndpoint generates default filename. * * @throws Exception */ @Test public void testParseAttachmentNoFilenameSpecified() throws Exception { InputStream is = IOUtils.toInputStream(TEST_JSON); MetadataMap<String, String> headers = new MetadataMap<String, String>(); headers.add(ContentEndpoint.CONTENT_DISPOSITION, "form-data; name=file"); headers.add(CONTENT_TYPE, "application/json;id=geojson"); Attachment attachment = new Attachment(is, headers); ContentFramework framework = mock(ContentFramework.class); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); CreateInfo createInfo = endpoint.parseAttachment(attachment); Assert.assertNotNull(createInfo); Assert.assertEquals("application/json;id=geojson", createInfo.getContentType()); Assert.assertEquals( ContentEndpoint.DEFAULT_FILE_NAME + "." + ContentEndpoint.DEFAULT_FILE_EXTENSION, createInfo.getFilename()); } /** * No filename or Content-Type specified by client, so ContentEndpoint sets the Content-Type * to text/plain (per CXF JAXRS default in Attachment.getContentType()) andgenerates default filename * of file.txt ("file" is default filename and ".txt" extension due to Content-Type of text/plain). * * @throws Exception */ @Test public void testParseAttachmentNoFilenameOrContentTypeSpecified() throws Exception { InputStream is = IOUtils.toInputStream(TEST_JSON); MetadataMap<String, String> headers = new MetadataMap<String, String>(); headers.add(ContentEndpoint.CONTENT_DISPOSITION, "form-data; name=file"); Attachment attachment = new Attachment(is, headers); ContentFramework framework = mock(ContentFramework.class); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); CreateInfo createInfo = endpoint.parseAttachment(attachment); Assert.assertNotNull(createInfo); // Content-Type of text/plain is the default returned from CXF JAXRS Assert.assertEquals("text/plain", createInfo.getContentType()); Assert.assertEquals(ContentEndpoint.DEFAULT_FILE_NAME + ".txt", createInfo.getFilename()); } @Test public void readValid() throws ContentFrameworkException, IOException, MimeTypeParseException, MimeTypeResolutionException { // String requestId = "testRequestId"; String content = "This is a test"; String fileName = "TestFilename.txt"; Long size = 1000L; String mimeType = "text/plain"; executeReadTest(content, fileName, size, mimeType); } @Test public void readValidNullFileNameAndMimeType() throws ContentFrameworkException, IOException, MimeTypeParseException, MimeTypeResolutionException { String content = "This is a test"; executeReadTest(content, null, null, null); } @Test(expected = ContentEndpointException.class) public void readContentEndpointExceptionExceptionExpected() throws ContentEndpointException, ContentFrameworkException, MimeTypeResolutionException { ContentFramework framework = mock(ContentFramework.class); when(framework.read(isA(ReadRequest.class))).thenThrow( new ContentEndpointException("Content Item not found.", Response.Status.NOT_FOUND)); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); endpoint.read(anyString()); } protected void executeReadTest(String content, String fileName, Long size, String mimeType) throws IOException, MimeTypeParseException, ContentFrameworkException, MimeTypeResolutionException { ContentFramework framework = mock(ContentFramework.class); ReadResponse readResponse = mock(ReadResponse.class); ContentItem contentItem = getMockGoodContentItem(content, fileName, "contentIdValue", size, mimeType); when(readResponse.getContentItem()).thenReturn(contentItem); when(framework.read(isA(ReadRequest.class))).thenReturn(readResponse); ContentEndpoint endpoint = new ContentEndpoint(framework, getMockMimeTypeMapper()); Response response = endpoint.read(anyString()); // Assertions for all valid headers returned assertThat(response.getStatus(), equalTo(200)); assertThat(IOUtils.toString((InputStream) response.getEntity()), equalTo(content)); if (fileName != null) { assertThat((String) response.getMetadata().getFirst(CONTENT_DISPOSITION), equalToIgnoringWhiteSpace("inline; filename=" + fileName)); } else { assertThat(response.getMetadata().getFirst(CONTENT_DISPOSITION), is(nullValue())); } if (mimeType != null) { assertThat((String) response.getMetadata().getFirst(HttpHeaders.CONTENT_TYPE), equalTo(mimeType)); } else { assertThat((String) response.getMetadata().getFirst(HttpHeaders.CONTENT_TYPE), equalTo(MediaType.APPLICATION_OCTET_STREAM)); } if (size != null) { assertEquals(response.getMetadata().getFirst(HttpHeaders.CONTENT_LENGTH), size); } else { assertThat(response.getMetadata().getFirst(HttpHeaders.CONTENT_LENGTH), is(nullValue())); } } protected ContentItem getMockGoodContentItem(String content, String fileName, String contentId, Long size, String mimeType) throws IOException, MimeTypeParseException { ContentItem item = mock(ContentItem.class); when(item.getInputStream()).thenReturn(new ByteArrayInputStream(content.getBytes())); when(item.getFilename()).thenReturn(fileName); when(item.getId()).thenReturn(contentId); if (size != null) { when(item.getSize()).thenReturn(size); } else { when(item.getSize()).thenThrow(new IOException("IOException")); } when(item.getMimeTypeRawData()).thenReturn(mimeType); if (mimeType != null) { when(item.getMimeType()).thenReturn(new MimeType(mimeType)); } return item; } protected MimeTypeMapper getMockMimeTypeMapper() throws MimeTypeResolutionException { MimeTypeMapper mapper = mock(MimeTypeMapper.class); when(mapper.getFileExtensionForMimeType(eq("text/plain"))).thenReturn("txt"); when(mapper.getMimeTypeForFileExtension(eq("txt"))).thenReturn("text/plain"); when(mapper.getFileExtensionForMimeType(eq("application/json"))).thenReturn("json"); when(mapper.getMimeTypeForFileExtension(eq("json"))) .thenReturn("application/json;id=geojson"); return mapper; } }