diff --git a/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java b/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java index d55bd12d7c..4c2a97d068 100644 --- a/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java +++ b/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java @@ -230,27 +230,8 @@ public Response createObject(@PathParam("path") path + " is an existing resource").build(); } - if (FedoraJcrTypes.FEDORA_OBJECT.equals(mixin)) { - final FedoraObject result = - objectService.createObject(session, path); - - if (requestBodyStream != null && - requestContentType != null && - requestContentType.toString().equals( - WebContent.contentTypeSPARQLUpdate)) { - result.updateGraph(IOUtils.toString(requestBodyStream)); - } + createObjectOrDatastreamFromRequestContent(session, path, mixin, requestBodyStream, requestContentType, checksumType, checksum); - } - if (FedoraJcrTypes.FEDORA_DATASTREAM.equals(mixin)) { - final MediaType contentType = - requestContentType != null ? requestContentType - : APPLICATION_OCTET_STREAM_TYPE; - - datastreamService.createDatastreamNode(session, path, - contentType.toString(), requestBodyStream, - checksumType, checksum); - } session.save(); logger.debug("Finished creating {} with path: {}", mixin, path); return created(uriInfo.getRequestUri()).entity(path).build(); diff --git a/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraUnnamedObjects.java b/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraUnnamedObjects.java index 9f4cd416b5..85d6f651d0 100644 --- a/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraUnnamedObjects.java +++ b/fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraUnnamedObjects.java @@ -1,26 +1,31 @@ package org.fcrepo.api; +import static javax.ws.rs.core.Response.created; import static org.slf4j.LoggerFactory.getLogger; import java.io.IOException; +import java.io.InputStream; import java.util.List; import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Response; +import org.apache.http.HttpStatus; import org.fcrepo.AbstractResource; import org.fcrepo.exception.InvalidChecksumException; import org.fcrepo.utils.FedoraJcrTypes; import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.google.common.collect.ImmutableList; @Component @@ -29,48 +34,39 @@ public class FedoraUnnamedObjects extends AbstractResource { private static final Logger logger = getLogger(FedoraUnnamedObjects.class); - @Autowired - FedoraDatastreams datastreamsResource; - - @Autowired - FedoraNodes objectsResource; - /** * Create an anonymous object with a newly minted name * @param pathList * @return 201 */ @POST - public Response ingestAndMint(@PathParam("path") - final List pathList) throws RepositoryException { - logger.debug("Creating a new unnamed object"); + public Response ingestAndMint(@PathParam("path") final List pathList, + @QueryParam("mixin") @DefaultValue(FedoraJcrTypes.FEDORA_OBJECT) String mixin, + @QueryParam("checksumType") final String checksumType, + @QueryParam("checksum") final String checksum, + @HeaderParam("Content-Type") final MediaType requestContentType, + final InputStream requestBodyStream) throws RepositoryException, IOException, InvalidChecksumException { final String pid = pidMinter.mintPid(); - PathSegment path = new PathSegment() { - @Override - public String getPath() { - return pid; - } + String path = toPath(pathList) + "/" + pid; + + logger.debug("Attempting to ingest with path: {}", path); - @Override - public MultivaluedMap getMatrixParameters() { - return null; + final Session session = getAuthenticatedSession(); + + try { + if (nodeService.exists(session, path)) { + return Response.status(HttpStatus.SC_CONFLICT).entity(path + " is an existing resource").build(); } - }; + createObjectOrDatastreamFromRequestContent(session, path, mixin, requestBodyStream, requestContentType, checksumType, checksum); - ImmutableList.Builder segments = ImmutableList.builder(); - segments.addAll(pathList); - segments.add(path); + session.save(); + logger.debug("Finished creating {} with path: {}", mixin, path); + return created(uriInfo.getRequestUri()).entity(path).build(); - try { - return objectsResource.createObject( - segments.build(), - FedoraJcrTypes.FEDORA_OBJECT, null, null, null, null); - } catch (IOException e) { - throw new RepositoryException(e.getMessage(), e); - } catch (InvalidChecksumException e) { - throw new RepositoryException(e.getMessage(), e); + } finally { + session.logout(); } } diff --git a/fcrepo-http-api/src/main/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjects.java b/fcrepo-http-api/src/main/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjects.java new file mode 100644 index 0000000000..02edf41d50 --- /dev/null +++ b/fcrepo-http-api/src/main/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjects.java @@ -0,0 +1,65 @@ +package org.fcrepo.api.repository; + +import org.apache.http.HttpStatus; +import org.fcrepo.AbstractResource; +import org.fcrepo.exception.InvalidChecksumException; +import org.fcrepo.utils.FedoraJcrTypes; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.io.InputStream; + +import static javax.ws.rs.core.Response.created; +import static org.slf4j.LoggerFactory.getLogger; + +@Component +@Path("/rest/fcr:new") +public class FedoraRepositoryUnnamedObjects extends AbstractResource { + + private static final Logger logger = getLogger(FedoraRepositoryUnnamedObjects.class); + + /** + * Create an anonymous object with a newly minted name + * @return 201 + */ + @POST + public Response ingestAndMint( + @QueryParam("mixin") @DefaultValue(FedoraJcrTypes.FEDORA_OBJECT) String mixin, + @QueryParam("checksumType") final String checksumType, + @QueryParam("checksum") final String checksum, + @HeaderParam("Content-Type") final MediaType requestContentType, + final InputStream requestBodyStream) throws RepositoryException, IOException, InvalidChecksumException { + final String pid = pidMinter.mintPid(); + + String path = "/" + pid; + + logger.debug("Attempting to ingest with path: {}", path); + + final Session session = getAuthenticatedSession(); + + try { + if (nodeService.exists(session, path)) { + return Response.status(HttpStatus.SC_CONFLICT).entity(path + " is an existing resource").build(); + } + + createObjectOrDatastreamFromRequestContent(session, path, mixin, requestBodyStream, requestContentType, checksumType, checksum); + + session.save(); + logger.debug("Finished creating {} with path: {}", mixin, path); + return created(uriInfo.getRequestUri()).entity(path).build(); + + } finally { + session.logout(); + } + } +} diff --git a/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraNodesTest.java b/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraNodesTest.java index 86d1111ffc..f322b42ca8 100644 --- a/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraNodesTest.java +++ b/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraNodesTest.java @@ -122,6 +122,7 @@ public void testCreateObject() throws RepositoryException, IOException, assertNotNull(actual); assertEquals(Status.CREATED.getStatusCode(), actual.getStatus()); assertTrue(actual.getEntity().toString().endsWith(pid)); + verify(mockNodes).exists(mockSession, path); verify(mockObjects).createObject(mockSession, path); verify(mockSession).save(); } diff --git a/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraUnnamedObjectsTest.java b/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraUnnamedObjectsTest.java index 37f6b51a35..c3f2a8a7e9 100644 --- a/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraUnnamedObjectsTest.java +++ b/fcrepo-http-api/src/test/java/org/fcrepo/api/FedoraUnnamedObjectsTest.java @@ -2,55 +2,47 @@ package org.fcrepo.api; import static org.fcrepo.test.util.PathSegmentImpl.createPathList; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.IOException; -import java.io.InputStream; -import java.security.Principal; -import java.util.List; import javax.jcr.LoginException; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.core.Response; import org.fcrepo.exception.InvalidChecksumException; import org.fcrepo.identifiers.UUIDPidMinter; +import org.fcrepo.services.NodeService; +import org.fcrepo.services.ObjectService; +import org.fcrepo.test.util.TestHelpers; import org.fcrepo.utils.FedoraJcrTypes; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.modeshape.jcr.api.Repository; public class FedoraUnnamedObjectsTest { FedoraUnnamedObjects testObj; - FedoraNodes mockObjects; - - Repository mockRepo; - Session mockSession; - SecurityContext mockSecurityContext; - - HttpServletRequest mockServletRequest; - - Principal mockPrincipal; - - String mockUser = "testuser"; + ObjectService mockObjects; + NodeService mockNodeService; @Before - public void setUp() throws LoginException, RepositoryException { - mockObjects = mock(FedoraNodes.class); + public void setUp() throws RepositoryException { + mockObjects = mock(ObjectService.class); + mockNodeService = mock(NodeService.class); testObj = new FedoraUnnamedObjects(); - testObj.objectsResource = mockObjects; + mockSession = TestHelpers.mockSession(testObj); + testObj.setNodeService(mockNodeService); + testObj.setObjectService(mockObjects); } @After @@ -58,18 +50,23 @@ public void tearDown() { } - @SuppressWarnings("unchecked") @Test public void testIngestAndMint() throws RepositoryException, IOException, InvalidChecksumException { final UUIDPidMinter mockMint = mock(UUIDPidMinter.class); testObj.setPidMinter(mockMint); - testObj.ingestAndMint(createPathList("objects", "fcr:new")); - verify(mockMint).mintPid(); - verify(mockObjects).createObject(any(List.class), - eq(FedoraJcrTypes.FEDORA_OBJECT), isNull(String.class), - isNull(String.class), isNull(MediaType.class), - isNull(InputStream.class)); + when(mockMint.mintPid()).thenReturn("uuid-123"); + + final Response actual = + testObj.ingestAndMint(createPathList("objects"), + FedoraJcrTypes.FEDORA_OBJECT, null, null, null, null); + assertNotNull(actual); + assertEquals(Response.Status.CREATED.getStatusCode(), actual.getStatus()); + assertTrue(actual.getEntity().toString().endsWith("uuid-123")); + verify(mockObjects).createObject(mockSession, "/objects/uuid-123"); + verify(mockNodeService).exists(mockSession, "/objects/uuid-123"); + verify(mockSession).save(); + } } diff --git a/fcrepo-http-api/src/test/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjectsTest.java b/fcrepo-http-api/src/test/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjectsTest.java new file mode 100644 index 0000000000..7a97265677 --- /dev/null +++ b/fcrepo-http-api/src/test/java/org/fcrepo/api/repository/FedoraRepositoryUnnamedObjectsTest.java @@ -0,0 +1,68 @@ +package org.fcrepo.api.repository; + +import org.fcrepo.api.FedoraUnnamedObjects; +import org.fcrepo.exception.InvalidChecksumException; +import org.fcrepo.identifiers.UUIDPidMinter; +import org.fcrepo.services.NodeService; +import org.fcrepo.services.ObjectService; +import org.fcrepo.test.util.TestHelpers; +import org.fcrepo.utils.FedoraJcrTypes; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.ws.rs.core.Response; +import java.io.IOException; + +import static org.fcrepo.test.util.PathSegmentImpl.createPathList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class FedoraRepositoryUnnamedObjectsTest { + + FedoraRepositoryUnnamedObjects testObj; + + Session mockSession; + + ObjectService mockObjects; + NodeService mockNodeService; + + @Before + public void setUp() throws RepositoryException { + mockObjects = mock(ObjectService.class); + mockNodeService = mock(NodeService.class); + testObj = new FedoraRepositoryUnnamedObjects(); + mockSession = TestHelpers.mockSession(testObj); + testObj.setNodeService(mockNodeService); + testObj.setObjectService(mockObjects); + } + + @After + public void tearDown() { + + } + + @Test + public void testIngestAndMint() throws RepositoryException, IOException, + InvalidChecksumException { + final UUIDPidMinter mockMint = mock(UUIDPidMinter.class); + testObj.setPidMinter(mockMint); + when(mockMint.mintPid()).thenReturn("uuid-123"); + + final Response actual = + testObj.ingestAndMint(FedoraJcrTypes.FEDORA_OBJECT, null, null, null, null); + assertNotNull(actual); + assertEquals(Response.Status.CREATED.getStatusCode(), actual.getStatus()); + assertTrue(actual.getEntity().toString().endsWith("uuid-123")); + verify(mockObjects).createObject(mockSession, "/uuid-123"); + verify(mockNodeService).exists(mockSession, "/uuid-123"); + verify(mockSession).save(); + + } +} diff --git a/fcrepo-http-api/src/test/java/org/fcrepo/integration/api/FedoraUnnamedObjectsIT.java b/fcrepo-http-api/src/test/java/org/fcrepo/integration/api/FedoraUnnamedObjectsIT.java index d555f91042..161e50e5e5 100644 --- a/fcrepo-http-api/src/test/java/org/fcrepo/integration/api/FedoraUnnamedObjectsIT.java +++ b/fcrepo-http-api/src/test/java/org/fcrepo/integration/api/FedoraUnnamedObjectsIT.java @@ -26,5 +26,21 @@ public void testIngestWithNew() throws Exception { .find()); assertTrue("new object did not mint a PID", !content.endsWith("/fcr:new")); } + + @Test + public void testRepositoryLevelIngestWithNew() throws Exception { + final HttpPost method = new HttpPost(serverAddress + "fcr:new"); + + final HttpResponse response = client.execute(method); + final String content = EntityUtils.toString(response.getEntity()); + int status = response.getStatusLine().getStatusCode(); + if (201 != status) { + logger.error(content); + } + assertEquals(201, status); + assertTrue("Response wasn't a PID", compile("[a-z]+").matcher(content) + .find()); + assertTrue("new object did not mint a PID", !content.endsWith("/fcr:new")); + } } diff --git a/fcrepo-http-commons/src/main/java/org/fcrepo/AbstractResource.java b/fcrepo-http-commons/src/main/java/org/fcrepo/AbstractResource.java index 459b2fbcfe..c0eb4cb0ec 100644 --- a/fcrepo-http-commons/src/main/java/org/fcrepo/AbstractResource.java +++ b/fcrepo-http-commons/src/main/java/org/fcrepo/AbstractResource.java @@ -1,9 +1,12 @@ package org.fcrepo; +import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE; import static javax.ws.rs.core.Response.noContent; import static org.slf4j.LoggerFactory.getLogger; +import java.io.IOException; +import java.io.InputStream; import java.util.List; import javax.annotation.PostConstruct; @@ -12,17 +15,22 @@ import javax.jcr.Session; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; +import org.apache.commons.io.IOUtils; +import org.apache.jena.riot.WebContent; +import org.fcrepo.exception.InvalidChecksumException; import org.fcrepo.identifiers.PidMinter; import org.fcrepo.services.DatastreamService; import org.fcrepo.services.NodeService; import org.fcrepo.services.ObjectService; import org.fcrepo.session.AuthenticatedSessionProvider; import org.fcrepo.session.SessionFactory; +import org.fcrepo.utils.FedoraJcrTypes; import org.fcrepo.utils.NamespaceTools; import org.modeshape.jcr.api.JcrTools; import org.slf4j.Logger; @@ -107,6 +115,32 @@ protected AuthenticatedSessionProvider getAuthenticatedSessionProvider() { return sessions.getSessionProvider(securityContext, servletRequest); } + protected FedoraResource createObjectOrDatastreamFromRequestContent(final Session session, final String path, final String mixin, final InputStream requestBodyStream, final MediaType requestContentType, final String checksumType, final String checksum) throws RepositoryException, InvalidChecksumException, IOException { + + final FedoraResource result; + + if (FedoraJcrTypes.FEDORA_OBJECT.equals(mixin)){ + result = objectService.createObject(session, path); + + if(requestBodyStream != null && requestContentType != null && requestContentType.toString().equals(WebContent.contentTypeSPARQLUpdate)) { + result.updateGraph(IOUtils.toString(requestBodyStream)); + } + + } else if (FedoraJcrTypes.FEDORA_DATASTREAM.equals(mixin)){ + final MediaType contentType = + requestContentType != null ? requestContentType + : APPLICATION_OCTET_STREAM_TYPE; + + final Node node = datastreamService.createDatastreamNode(session, path, contentType + .toString(), requestBodyStream, checksumType, checksum); + result = new Datastream(node); + } else { + result = null; + } + + return result; + } + protected synchronized Response deleteResource(final Node resource) throws RepositoryException {