Skip to content

Commit

Permalink
Updated REST API for user provided checksums during add DS
Browse files Browse the repository at this point in the history
  • Loading branch information
Vincent Nguyen committed Mar 7, 2013
1 parent a438fd5 commit 53858f8
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 15 deletions.
Expand Up @@ -46,6 +46,7 @@
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.fcrepo.AbstractResource;
import org.fcrepo.Datastream;
import org.fcrepo.ExceptionHandlers.InvalidChecksumException;
import org.fcrepo.jaxb.responses.management.DatastreamHistory;
import org.fcrepo.jaxb.responses.management.DatastreamProfile;
import org.fcrepo.jaxb.responses.access.ObjectDatastreams;
Expand Down Expand Up @@ -171,7 +172,7 @@ public MultipartBody getDatastreamsContents(@PathParam("pid")
}

/**
* Create a new datastream
* Create a new datastream with user provided checksum for validation
*
* @param pid
* persistent identifier of the digital object
Expand All @@ -188,7 +189,9 @@ public MultipartBody getDatastreamsContents(@PathParam("pid")
@POST
@Path("/{dsid}")
public Response addDatastream(@PathParam("pid")
final String pid, @PathParam("dsid")
final String pid, @QueryParam("checksumType")
final String checksumType, @QueryParam("checksum")
final String checksum, @PathParam("dsid")
final String dsid, @HeaderParam("Content-Type")
MediaType contentType, InputStream requestBodyStream)
throws RepositoryException, IOException {
Expand All @@ -202,16 +205,43 @@ public Response addDatastream(@PathParam("pid")
if (!session.nodeExists(dspath)) {
return created(
addDatastreamNode(pid, dspath, contentType,
requestBodyStream, session)).build();
requestBodyStream, session, checksumType, checksum)).build();
} else {
session.getNode(dspath).remove();
session.save();
return created(
addDatastreamNode(pid, dspath, contentType,
requestBodyStream, session)).build();
requestBodyStream, session, checksumType, checksum)).build();
}

}

/**
* Create a new datastream
*
* @param pid
* persistent identifier of the digital object
* @param dsid
* datastream identifier
* @param contentType
* Content-Type header
* @param requestBodyStream
* Binary blob
* @return 201 Created
* @throws RepositoryException
* @throws IOException
*/
@POST
@Path("/{dsid}")
public Response addDatastream(@PathParam("pid")
final String pid, @PathParam("dsid")
final String dsid, @HeaderParam("Content-Type")
MediaType contentType, InputStream requestBodyStream)
throws RepositoryException, IOException {

return addDatastream(pid, null, null, dsid, contentType, requestBodyStream);

}

/**
* Modify an existing datastream's content
Expand Down Expand Up @@ -243,21 +273,21 @@ public Response modifyDatastream(@PathParam("pid")

return created(
addDatastreamNode(pid, dspath, contentType, requestBodyStream,
session)).build();
session, null, null)).build();

}

private URI addDatastreamNode(final String pid, final String dsPath,
final MediaType contentType, final InputStream requestBodyStream,
final Session session) throws RepositoryException, IOException {
final Session session, String checksumType, String checksum) throws RepositoryException, IOException {

Long oldObjectSize =
getObjectSize(session.getNode(getObjectJcrNodePath(pid)));
logger.debug("Attempting to add datastream node at path: " + dsPath);
try {
boolean created = session.nodeExists(dsPath);
createDatastreamNode(session, dsPath, contentType.toString(),
requestBodyStream);
requestBodyStream, checksumType, checksum);
session.save();
if (created) {
/*
Expand All @@ -271,10 +301,14 @@ private URI addDatastreamNode(final String pid, final String dsPath,
// now we save again to persist the repo size
session.save();
}
logger.debug("Finished adding datastream node at path: " + dsPath);
} catch (InvalidChecksumException e) {
logger.error("Checksum Mismatch Exception");
logger.debug("No datastream has been added");
session.logout();
} finally {
session.logout();
}
logger.debug("Finished adding datastream node at path: " + dsPath);
return uriInfo.getAbsolutePath();
}

Expand Down
23 changes: 18 additions & 5 deletions fcrepo-kernel/src/main/java/org/fcrepo/Datastream.java
Expand Up @@ -21,6 +21,7 @@
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.VersionException;

import org.fcrepo.ExceptionHandlers.InvalidChecksumException;
import org.fcrepo.utils.ContentDigest;
import org.modeshape.jcr.api.Binary;
import org.modeshape.jcr.api.JcrTools;
Expand Down Expand Up @@ -72,7 +73,7 @@ public InputStream getContent() throws RepositoryException {
* @param content
* @throws RepositoryException
*/
public void setContent(InputStream content) throws RepositoryException {
public void setContent(InputStream content, String checksumType, String checksum) throws RepositoryException, InvalidChecksumException {
final Node contentNode =
findOrCreateChild(node, JCR_CONTENT, NT_RESOURCE);

Expand Down Expand Up @@ -109,18 +110,30 @@ public void setContent(InputStream content) throws RepositoryException {
* develop later.
*/
Property dataProperty = contentNode.setProperty(JCR_DATA, binary);

String dsChecksum = binary.getHexHash();
if(checksum != null && !checksum.equals("")){
if(!checksum.equals(binary.getHexHash())) {
logger.debug("Failed checksum test");
throw new InvalidChecksumException("Checksum Mismatch of " + dsChecksum + " and " + checksum);
}
}

contentNode.setProperty(CONTENT_SIZE, dataProperty.getLength());
contentNode.setProperty(DIGEST_VALUE, binary.getHexHash());
contentNode.setProperty(DIGEST_VALUE, dsChecksum);
contentNode.setProperty(DIGEST_ALGORITHM, "SHA-1");

logger.debug("Created data property at path: " + dataProperty.getPath());

}

public void setContent(InputStream content) throws RepositoryException, InvalidChecksumException {
setContent(content, null, null);
}

public void setContent(InputStream content, String mimeType)
throws RepositoryException {
setContent(content);
public void setContent(InputStream content, String mimeType, String checksumType, String checksum)
throws RepositoryException, InvalidChecksumException {
setContent(content, checksumType, checksum);
node.setProperty("fedora:contentType", mimeType);
}

Expand Down
@@ -0,0 +1,11 @@
package org.fcrepo.ExceptionHandlers;

import javax.jcr.RepositoryException;

public class InvalidChecksumException
extends RepositoryException {

public InvalidChecksumException(String message) {
super(message);
}
}
Expand Up @@ -22,6 +22,7 @@
import javax.jcr.Session;

import org.fcrepo.Datastream;
import org.fcrepo.ExceptionHandlers.InvalidChecksumException;
import org.modeshape.jcr.api.JcrTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -47,11 +48,20 @@ public class DatastreamService {
public static Node createDatastreamNode(final Session session,
final String dsPath, final String contentType,
final InputStream requestBodyStream) throws RepositoryException,
IOException {
IOException, InvalidChecksumException {

return createDatastreamNode(session, dsPath, contentType, requestBodyStream, null, null);
}

public static Node createDatastreamNode(final Session session,
final String dsPath, final String contentType,
final InputStream requestBodyStream,
String checksumType, String checksum) throws RepositoryException,
IOException, InvalidChecksumException {

final Node ds = jcrTools.findOrCreateNode(session, dsPath, NT_FILE);
ds.addMixin(FEDORA_DATASTREAM);
new Datastream(ds).setContent(requestBodyStream,contentType);
new Datastream(ds).setContent(requestBodyStream, contentType, checksumType, checksum);
ds.addMixin(FEDORA_OWNED);
ds.setProperty(FEDORA_OWNERID, session.getUserID());

Expand Down
20 changes: 20 additions & 0 deletions fcrepo-kernel/src/test/java/org/fcrepo/DatastreamTest.java
Expand Up @@ -124,4 +124,24 @@ public void testModifyDatastreamContentDigestAndLength() throws IOException, Rep

assertEquals("0123456789", contentString);
}

@Test
public void testDatastreamContentWithChecksum() throws IOException, RepositoryException {
Session session = repo.login();
createObjectNode(session, "testObject");
createDatastreamNode(session,
"/objects/testObject/testDatastreamNode4",
"application/octet-stream", new ByteArrayInputStream(
"asdf".getBytes()), "SHA-1", "3da541559918a808c2402bba5012f6c60b27661c");

session.save();

final Datastream ds = getDatastream("testObject", "testDatastreamNode4");
assertEquals("urn:sha1:3da541559918a808c2402bba5012f6c60b27661c", ds
.getContentDigest().toString());

String contentString = IOUtils.toString(ds.getContent(), "ASCII");

assertEquals("asdf", contentString);
}
}

0 comments on commit 53858f8

Please sign in to comment.