Skip to content

Commit

Permalink
Use premis hasOriginalName (and hasSize) predicates on fedora:binary
Browse files Browse the repository at this point in the history
resources

Expose the premis:hasOriginalName propertyfrom the HTTP API using
the Content-Disposition ("filename") header for both fcr:content
and a POST with a binary payload.

Expose originalFileName throughout the kernel's Datastream API.

Fixes https://www.pivotaltracker.com/story/show/61500736
  • Loading branch information
cbeer committed Dec 2, 2013
1 parent ceae23e commit eb99d16
Show file tree
Hide file tree
Showing 22 changed files with 261 additions and 71 deletions.
Expand Up @@ -29,6 +29,7 @@
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

Expand All @@ -52,6 +53,7 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import com.sun.jersey.core.header.ContentDisposition;
import org.fcrepo.http.commons.AbstractResource;
import org.fcrepo.http.commons.api.rdf.HttpGraphSubjects;
import org.fcrepo.http.commons.domain.Range;
Expand Down Expand Up @@ -95,11 +97,12 @@ public class FedoraContent extends AbstractResource {
public Response create(@PathParam("path")
final List<PathSegment> pathList,
@HeaderParam("Slug") final String slug,
@HeaderParam("Content-Disposition") final String contentDisposition,
@QueryParam("checksum") final String checksum,
@HeaderParam("Content-Type") final MediaType requestContentType,
final InputStream requestBodyStream)
throws IOException, InvalidChecksumException,
RepositoryException, URISyntaxException {
RepositoryException, URISyntaxException, ParseException {
final MediaType contentType =
requestContentType != null ? requestContentType
: APPLICATION_OCTET_STREAM_TYPE;
Expand Down Expand Up @@ -140,9 +143,19 @@ public Response create(@PathParam("path")
checksumURI = null;
}

final String originalFileName;

if (contentDisposition != null) {
final ContentDisposition disposition = new ContentDisposition(contentDisposition);
originalFileName = disposition.getFileName();
} else {
originalFileName = null;
}


final Node datastreamNode =
datastreamService.createDatastreamNode(session, newDatastreamPath,
contentType.toString(), requestBodyStream,
contentType.toString(), originalFileName, requestBodyStream,
checksumURI);

final HttpGraphSubjects subjects =
Expand Down Expand Up @@ -176,10 +189,12 @@ public Response create(@PathParam("path")
@Timed
public Response modifyContent(@PathParam("path") final List<PathSegment> pathList,
@QueryParam("checksum") final String checksum,
@HeaderParam("Content-Disposition") final String contentDisposition,
@HeaderParam("Content-Type") final MediaType requestContentType,
final InputStream requestBodyStream,
@Context final Request request) throws RepositoryException,
IOException, InvalidChecksumException, URISyntaxException {
@Context final Request request)
throws RepositoryException, IOException, InvalidChecksumException, URISyntaxException, ParseException {

try {
final String path = toPath(pathList);
final MediaType contentType =
Expand Down Expand Up @@ -215,10 +230,18 @@ public Response modifyContent(@PathParam("path") final List<PathSegment> pathLis
checksumURI = null;
}

final String originalFileName;

if (contentDisposition != null) {
final ContentDisposition disposition = new ContentDisposition(contentDisposition);
originalFileName = disposition.getFileName();
} else {
originalFileName = null;
}

final Node datastreamNode =
datastreamService.createDatastreamNode(session, path,
contentType.toString(), requestBodyStream, checksumURI);
contentType.toString(), originalFileName, requestBodyStream, checksumURI);

final boolean isNew = datastreamNode.isNew();
session.save();
Expand Down
Expand Up @@ -132,7 +132,7 @@ public Response modifyDatastreams(@PathParam("path")
src = (InputStream) obj;
}
datastreamService.createDatastreamNode(session, dsPath, part
.getMediaType().toString(), src);
.getMediaType().toString(), null, src);
pathsChanged.add(dsPath);
}

Expand Down
16 changes: 13 additions & 3 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraNodes.java
Expand Up @@ -83,6 +83,7 @@
import javax.ws.rs.core.UriInfo;

import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.sun.jersey.core.header.ContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.commons.io.IOUtils;
import org.apache.jena.riot.Lang;
Expand Down Expand Up @@ -377,6 +378,7 @@ public Response createObject(@PathParam("path")
final String mixin,
@QueryParam("checksum")
final String checksum,
@HeaderParam("Content-Disposition") final String contentDisposition,
@HeaderParam("Content-Type")
final MediaType requestContentType,
@HeaderParam("Slug")
Expand Down Expand Up @@ -483,9 +485,17 @@ public Response createObject(@PathParam("path")
result.replaceProperties(subjects, inputModel);
} else if (result instanceof Datastream) {

final String originalFileName;

if (contentDisposition != null) {
final ContentDisposition disposition = new ContentDisposition(contentDisposition);
originalFileName = disposition.getFileName();
} else {
originalFileName = null;
}

datastreamService.createDatastreamNode(session,
newObjectPath, contentTypeString,
requestBodyStream, checksumURI);
newObjectPath, contentTypeString, originalFileName, requestBodyStream, checksumURI);

}
}
Expand Down Expand Up @@ -532,7 +542,7 @@ public Response createObjectFromFormPost(
@FormDataParam("file") final InputStream file
) throws Exception {

return createObject(pathList, mixin, null, null, slug, uriInfo, file);
return createObject(pathList, mixin, null, null, null, slug, uriInfo, file);

}

Expand Down
Expand Up @@ -39,6 +39,7 @@
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.Date;

import javax.jcr.Node;
Expand Down Expand Up @@ -105,7 +106,7 @@ public void setUp() throws Exception {

@Test
public void testPutContent() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException {
InvalidChecksumException, URISyntaxException, ParseException {
final String pid = "FedoraDatastreamsTest1";
final String dsId = "testDS";
final String dsContent = "asdf";
Expand All @@ -117,21 +118,21 @@ public void testPutContent() throws RepositoryException, IOException,
when(mockNodeService.exists(mockSession, dsPath)).thenReturn(false);
when(
mockDatastreams.createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), any(InputStream.class), eq((URI)null)))
eq(dsPath), anyString(), eq("xyz"), any(InputStream.class), eq((URI)null)))
.thenReturn(mockNode);
when(mockDatastreams.exists(mockSession, dsPath)).thenReturn(true);
final Response actual =
testObj.modifyContent(createPathList(pid, dsId), null, null,
testObj.modifyContent(createPathList(pid, dsId), null, "inline; filename=\"xyz\"", null,
dsContentStream, null);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), any(InputStream.class), eq((URI)null));
eq(dsPath), anyString(), eq("xyz"), any(InputStream.class), eq((URI)null));
verify(mockSession).save();
}

@Test
public void testCreateContent() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException {
InvalidChecksumException, URISyntaxException, ParseException {
final String pid = "FedoraDatastreamsTest1";
final String dsId = "xyz";
final String dsContent = "asdf";
Expand All @@ -143,24 +144,24 @@ public void testCreateContent() throws RepositoryException, IOException,
when(mockNodeService.exists(mockSession, dsPath)).thenReturn(false);
when(
mockDatastreams.createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), any(InputStream.class),
eq(dsPath), anyString(), eq((String)null), any(InputStream.class),
eq((URI) null))).thenReturn(mockNode);
when(mockDatastreams.exists(mockSession, dsPath)).thenReturn(true);
final Response actual =
testObj.create(createPathList(pid, dsId), null, null, TEXT_PLAIN_TYPE,
testObj.create(createPathList(pid, dsId), null, null, null, TEXT_PLAIN_TYPE,
dsContentStream);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(mockSession, dsPath,
"text/plain", dsContentStream, null);
"text/plain", null, dsContentStream, null);
verify(mockSession).save();
}

@Test
public void testCreateContentAtMintedPath() throws RepositoryException,
IOException,
InvalidChecksumException,
URISyntaxException,
NoSuchFieldException {
IOException,
InvalidChecksumException,
URISyntaxException,
NoSuchFieldException, ParseException {
final String pid = "FedoraDatastreamsTest1";
final String dsContent = "asdf";
final String dsPath = "/" + pid;
Expand All @@ -173,15 +174,15 @@ public void testCreateContentAtMintedPath() throws RepositoryException,
when(mockContentNode.getPath()).thenReturn(dsPath + "xyz/jcr:content");
when(
mockDatastreams.createDatastreamNode(any(Session.class), eq("/"
+ pid + "/xyz"), anyString(), any(InputStream.class),
+ pid + "/xyz"), anyString(), eq((String)null), any(InputStream.class),
eq((URI) null))).thenReturn(mockNode);
when(mockDatastreams.exists(mockSession, dsPath)).thenReturn(true);
final Response actual =
testObj.create(createPathList(pid), null, null, TEXT_PLAIN_TYPE,
testObj.create(createPathList(pid), null, null, null, TEXT_PLAIN_TYPE,
dsContentStream);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(mockSession,
"/" + pid + "/xyz", "text/plain", dsContentStream, null);
"/" + pid + "/xyz", "text/plain", null, dsContentStream, null);
verify(mockSession).save();
}

Expand All @@ -191,7 +192,7 @@ public void testCreateContentWithSlug() throws RepositoryException,
IOException,
InvalidChecksumException,
URISyntaxException,
NoSuchFieldException {
NoSuchFieldException, ParseException {
final String pid = "FedoraDatastreamsTest1";
final String dsid = "slug";
final String dsContent = "asdf";
Expand All @@ -204,21 +205,21 @@ public void testCreateContentWithSlug() throws RepositoryException,
when(mockContentNode.getPath()).thenReturn(dsPath + "slug/jcr:content");
when(
mockDatastreams.createDatastreamNode(any(Session.class), eq("/"
+ pid + "/slug"), anyString(), any(InputStream.class),
+ pid + "/slug"), anyString(), eq((String)null), any(InputStream.class),
eq((URI) null))).thenReturn(mockNode);
when(mockDatastreams.exists(mockSession, dsPath)).thenReturn(true);
final Response actual =
testObj.create(createPathList(pid), dsid, null, TEXT_PLAIN_TYPE,
testObj.create(createPathList(pid), dsid, null, null, TEXT_PLAIN_TYPE,
dsContentStream);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(mockSession,
"/" + pid + "/slug", "text/plain", dsContentStream, null);
"/" + pid + "/slug", "text/plain", null, dsContentStream, null);
verify(mockSession).save();
}

@Test
public void testModifyContent() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException {
InvalidChecksumException, URISyntaxException, ParseException {
final String pid = "FedoraDatastreamsTest1";
final String dsId = "testDS";
final String dsContent = "asdf";
Expand All @@ -235,15 +236,15 @@ public void testModifyContent() throws RepositoryException, IOException,
any(EntityTag.class))).thenReturn(null);
when(
mockDatastreams.createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), any(InputStream.class), eq(checksum)))
eq(dsPath), anyString(), eq((String)null), any(InputStream.class), eq(checksum)))
.thenReturn(mockNode);
when(mockDatastreams.exists(mockSession, dsPath)).thenReturn(true);
final Response actual =
testObj.modifyContent(createPathList(pid, dsId), "urn:sha1:some-checksum", null,
testObj.modifyContent(createPathList(pid, dsId), "urn:sha1:some-checksum", null, null,
dsContentStream, mockRequest);
assertEquals(NO_CONTENT.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), any(InputStream.class), eq(checksum));
eq(dsPath), anyString(), eq((String)null), any(InputStream.class), eq(checksum));
verify(mockSession).save();
}

Expand Down
Expand Up @@ -138,10 +138,10 @@ public void testModifyDatastreams() throws RepositoryException,
dsId2), multipart);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams).createDatastreamNode(any(Session.class),
eq("/" + pid + "/" + dsId1), anyString(),
eq("/" + pid + "/" + dsId1), anyString(), eq((String)null),
any(InputStream.class));
verify(mockDatastreams).createDatastreamNode(any(Session.class),
eq("/" + pid + "/" + dsId2), anyString(),
eq("/" + pid + "/" + dsId2), anyString(), eq((String)null),
any(InputStream.class));
verify(mockSession).save();
}
Expand Down

0 comments on commit eb99d16

Please sign in to comment.