Skip to content

Commit

Permalink
LDP#Post
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Sep 25, 2014
1 parent b3b0e63 commit 307d238
Showing 1 changed file with 143 additions and 0 deletions.
143 changes: 143 additions & 0 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraLdp.java
Expand Up @@ -74,8 +74,10 @@
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.NotSupportedException;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
Expand All @@ -100,6 +102,7 @@
import static com.google.common.collect.Iterators.concat;
import static com.google.common.collect.Iterators.transform;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static javax.ws.rs.core.MediaType.APPLICATION_XHTML_XML;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
Expand Down Expand Up @@ -574,6 +577,108 @@ public Response updateSparql(@ContentLocation final InputStream requestBodyStrea
}


/**
* Creates a new object.
*
* application/octet-stream;qs=1001 is a workaround for JERSEY-2636, to ensure
* requests without a Content-Type get routed here.
*
* @return 201
*/
@POST
@Consumes({MediaType.APPLICATION_OCTET_STREAM + ";qs=1001", MediaType.WILDCARD})
@Timed
public Response createObject(@QueryParam("mixin") final String mixin,
@QueryParam("checksum") final String checksum,
@HeaderParam("Content-Disposition") final ContentDisposition contentDisposition,
@HeaderParam("Content-Type") final MediaType requestContentType,
@HeaderParam("Slug") final String slug,
@ContentLocation final InputStream requestBodyStream)
throws ParseException, IOException,
InvalidChecksumException, URISyntaxException {

if (!(resource() instanceof FedoraObject)) {
throw new ClientErrorException("Object cannot have child nodes", CONFLICT);
}

final MediaType contentType = getSimpleContentType(requestContentType);

final String contentTypeString = contentType.toString();

final String newObjectPath = mintNewPid(path, slug);

LOGGER.debug("Attempting to ingest with path: {}", newObjectPath);

try {

final MediaType effectiveContentType
= requestBodyStream == null || requestContentType == null ? null : contentType;
final FedoraResource result = createFedoraResource(mixin,
effectiveContentType,
newObjectPath, contentDisposition);

final Response.ResponseBuilder response;
final URI location = getUri(result);

if (requestBodyStream == null || requestContentType == null) {
LOGGER.trace("No request body detected");
} else {
LOGGER.trace("Received createObject with a request body and content type \"{}\"", contentTypeString);

if (contentTypeString.equals(contentTypeSPARQLUpdate)) {
LOGGER.trace("Found SPARQL-Update content, applying..");
result.updatePropertiesDataset(translator(), IOUtils.toString(requestBodyStream));
} else if (isRdfContentType(contentTypeString)) {
LOGGER.trace("Found a RDF syntax, attempting to replace triples");

final Lang lang = contentTypeToLang(contentTypeString);

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

final Model inputModel =
createDefaultModel().read(requestBodyStream, getUri(result).toString(), format);

result.replaceProperties(translator(), inputModel,
getTriples(result, PropertiesRdfContext.class));
} else if (result instanceof FedoraBinary) {
LOGGER.trace("Created a datastream and have a binary payload.");

final URI checksumURI = checksumURI(checksum);
final String originalFileName = contentDisposition != null ? contentDisposition.getFileName() : "";

((FedoraBinary)result).setContent(requestBodyStream,
contentTypeString,
checksumURI,
originalFileName,
datastreamService.getStoragePolicyDecisionPoint());

}
}

if (result.isNew()) {
response = created(location).entity(location.toString());
} else {
response = noContent();
}

try {
session.save();
versionService.nodeUpdated(result.getNode());
} catch (final RepositoryException e) {
throw new RepositoryRuntimeException(e);
}

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

addCacheControlHeaders(servletResponse, result, session);

return response.build();

} finally {
session.logout();
}
}

private void addResourceHttpHeaders(final FedoraResource resource) {

if (resource instanceof Datastream) {
Expand Down Expand Up @@ -772,4 +877,42 @@ private static String getMessage(final Statement stmt) {
}
return null;
}

private String mintNewPid(final String base, final String slug) {
String pid;
final String newObjectPath;

assertPathExists(base);

if (slug != null && !slug.isEmpty()) {
pid = slug;
} else {
pid = pidMinter.mintPid();
}
// reverse translate the proffered or created identifier
LOGGER.trace("Using external identifier {} to create new resource.", pid);
LOGGER.trace("Using prefixed external identifier {} to create new resource.", uriInfo.getBaseUri() + "/"
+ pid);
pid = translator().getPathFromSubject(createResource(uriInfo.getBaseUri() + "/" + pid));
// remove leading slash left over from translation
pid = pid.substring(1, pid.length());
LOGGER.trace("Using internal identifier {} to create new resource.", pid);
newObjectPath = base + "/" + pid;

assertPathMissing(newObjectPath);
return newObjectPath;
}

private void assertPathMissing(final String path) {
if (nodeService.exists(session, path)) {
throw new ClientErrorException(path + " is an existing resource!", CONFLICT);
}
}

private void assertPathExists(final String path) {
if (!nodeService.exists(session, path)) {
throw new NotFoundException();
}
}

}

0 comments on commit 307d238

Please sign in to comment.