Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
make sure we send the right Location header back when POSTing binary …
…content to create a new node
  • Loading branch information
cbeer committed Aug 2, 2013
1 parent eca8521 commit d9f5b5e
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 13 deletions.
95 changes: 84 additions & 11 deletions fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java
Expand Up @@ -16,6 +16,9 @@

package org.fcrepo.api;

import static com.sun.jersey.api.Responses.clientError;
import static com.sun.jersey.api.Responses.notAcceptable;
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.noContent;
Expand Down Expand Up @@ -47,6 +50,7 @@
import java.util.Date;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -75,14 +79,17 @@
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import org.apache.commons.io.IOUtils;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.WebContent;
import org.fcrepo.AbstractResource;
import org.fcrepo.Datastream;
import org.fcrepo.FedoraResource;
import org.fcrepo.api.rdf.HttpGraphSubjects;
import org.fcrepo.exception.InvalidChecksumException;
import org.fcrepo.http.PATCH;
import org.fcrepo.session.InjectedSession;
import org.fcrepo.utils.FedoraJcrTypes;
import org.modeshape.jcr.api.JcrConstants;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -374,7 +381,6 @@ public Response createOrReplaceObjectRdf(
public Response createObject(@PathParam("path")
final List<PathSegment> pathList,
@QueryParam("mixin")
@DefaultValue(FedoraJcrTypes.FEDORA_OBJECT)
final String mixin,
@QueryParam("checksum")
final String checksum,
Expand Down Expand Up @@ -422,20 +428,87 @@ public Response createObject(@PathParam("path")

final HttpGraphSubjects subjects = new HttpGraphSubjects(session, FedoraNodes.class, uriInfo);

final FedoraResource resource =
createObjectOrDatastreamFromRequestContent(session,
newObjectPath,
mixin,
subjects,
requestBodyStream,
requestContentType,
checksumURI);
final String objectType;

if (mixin != null) {
objectType = mixin;
} else {
if (requestContentType != null) {
final String s = requestContentType.toString();
if (s.equals(WebContent.contentTypeSPARQLUpdate) || contentTypeToLang(s) != null) {
objectType = FedoraJcrTypes.FEDORA_OBJECT;
} else {
objectType = FedoraJcrTypes.FEDORA_DATASTREAM;
}
} else {
objectType = FedoraJcrTypes.FEDORA_OBJECT;
}
}

final FedoraResource result;

switch (objectType) {
case FedoraJcrTypes.FEDORA_OBJECT:
result = objectService.createObject(session, newObjectPath);
break;
case FedoraJcrTypes.FEDORA_DATASTREAM:
result = datastreamService.createDatastream(session, newObjectPath);
break;
default:
throw new WebApplicationException(clientError().entity("Unknown object type " + objectType).build());
}

if (requestBodyStream != null) {

final MediaType contentType =
requestContentType != null ? requestContentType
: APPLICATION_OCTET_STREAM_TYPE;

final String contentTypeString = contentType.toString();

if (contentTypeString.equals(WebContent.contentTypeSPARQLUpdate)) {
result.updatePropertiesDataset(subjects, IOUtils.toString(requestBodyStream));
} else if (contentTypeToLang(contentTypeString) != null) {

final Lang lang = contentTypeToLang(contentTypeString);

if (lang == null) {
throw new WebApplicationException(notAcceptable().entity("Invalid Content type " + contentType).build());
}

final String format = lang.getName()
.toUpperCase();

final Model inputModel = ModelFactory.createDefaultModel()
.read(requestBodyStream,
subjects.getGraphSubject(result.getNode()).toString(),
format);

result.replacePropertiesDataset(subjects, inputModel);
} else if (result instanceof Datastream) {

final Node node =
datastreamService.createDatastreamNode(session, newObjectPath,
contentTypeString, requestBodyStream,
checksumURI);


}
}

session.save();

logger.debug("Finished creating {} with path: {}", mixin, newObjectPath);

final URI location = new URI(subjects.getGraphSubject(resource.getNode())
.getURI());
final URI location;
if (result.hasContent()) {
location = new URI(subjects.getGraphSubject(result.getNode().getNode(JcrConstants.JCR_CONTENT))
.getURI());
} else {
location = new URI(subjects.getGraphSubject(result.getNode())
.getURI());
}

return created(location).entity(newObjectPath).build();

} finally {
Expand Down
Expand Up @@ -60,6 +60,7 @@
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.sparql.util.Context;
import org.apache.commons.io.IOUtils;
import org.fcrepo.Datastream;
import org.fcrepo.FedoraObject;
import org.fcrepo.FedoraResource;
import org.fcrepo.exception.InvalidChecksumException;
Expand Down Expand Up @@ -222,10 +223,13 @@ public void testCreateDatastream() throws RepositoryException, IOException,
mockDatastreams.createDatastreamNode(any(Session.class),
eq(dsPath), anyString(), eq(dsContentStream),
any(URI.class))).thenReturn(mockNode);
Datastream mockDatastream = mock(Datastream.class);
when(mockDatastream.getNode()).thenReturn(mockNode);
when(mockDatastreams.createDatastream(mockSession, dsPath)).thenReturn(mockDatastream);
when(mockNode.getPath()).thenReturn(dsPath);
final Response actual =
testObj.createObject(createPathList(pid, dsId),
FEDORA_DATASTREAM, null, null, null, getUriInfoImpl(),
FEDORA_DATASTREAM, null, MediaType.APPLICATION_OCTET_STREAM_TYPE, null, getUriInfoImpl(),
dsContentStream);
assertEquals(CREATED.getStatusCode(), actual.getStatus());
verify(mockDatastreams)
Expand Down
Expand Up @@ -184,6 +184,27 @@ public void testIngestWithSlug() throws Exception {
getStatus(new HttpGet(location)));
}

@Test
public void testIngestWithBinary() throws Exception {
final HttpPost method = postObjMethod("");
method.addHeader("Content-Type", "application/octet-stream");
BasicHttpEntity entity = new BasicHttpEntity();
entity.setContent(new ByteArrayInputStream("xyz".getBytes()));
method.setEntity(entity);
final HttpResponse response = client.execute(method);
final String content = EntityUtils.toString(response.getEntity());
final int status = response.getStatusLine().getStatusCode();
assertEquals("Didn't get a CREATED response! Got content:\n" + content,
CREATED.getStatusCode(), status);
assertTrue("Response wasn't a PID", compile("[a-z]+").matcher(content)
.find());
final String location = response.getFirstHeader("Location").getValue();
assertNotEquals(serverAddress + "/objects", location);
assertTrue(location.endsWith("fcr:content"));
assertEquals("Object wasn't created!", OK.getStatusCode(),
getStatus(new HttpGet(location)));
}

@Test
public void testDeleteObject() throws Exception {
assertEquals(CREATED.getStatusCode(),
Expand Down
Expand Up @@ -85,6 +85,16 @@ public class DatastreamService extends RepositoryService {

private static final Logger logger = getLogger(DatastreamService.class);

/**
* Create a stub datastream without content
* @param session
* @param dsPath
* @return
* @throws RepositoryException
*/
public Datastream createDatastream(final Session session, final String dsPath) throws RepositoryException {
return new Datastream(session, dsPath);
}
/**
* Create a new Datastream node in the JCR store
*
Expand Down Expand Up @@ -124,7 +134,7 @@ public Node createDatastreamNode(final Session session,
final InputStream requestBodyStream, final URI checksum)
throws RepositoryException, IOException, InvalidChecksumException {

final Datastream ds = new Datastream(session, dsPath);
final Datastream ds = createDatastream(session, dsPath);
ds.setContent(requestBodyStream, contentType, checksum,
getStoragePolicyDecisionPoint());
return ds.getNode();
Expand Down

0 comments on commit d9f5b5e

Please sign in to comment.