Skip to content

Commit

Permalink
Ldp#PUT
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Sep 25, 2014
1 parent 5f9ee08 commit b3b0e63
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 17 deletions.
142 changes: 140 additions & 2 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraLdp.java
Expand Up @@ -42,6 +42,7 @@
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.FedoraObject;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.impl.DatastreamImpl;
import org.fcrepo.kernel.impl.FedoraObjectImpl;
Expand All @@ -66,16 +67,20 @@
import javax.jcr.Session;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.NotSupportedException;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
Expand All @@ -88,6 +93,7 @@
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;

Expand All @@ -98,8 +104,12 @@
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN_TYPE;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.CONFLICT;
import static javax.ws.rs.core.Response.Status.PARTIAL_CONTENT;
import static javax.ws.rs.core.Response.Status.REQUESTED_RANGE_NOT_SATISFIABLE;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.status;
Expand All @@ -114,6 +124,8 @@
import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_XML;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_X;
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_DATASTREAM;
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_OBJECT;
import static org.fcrepo.kernel.RdfLexicon.LDP_NAMESPACE;
import static org.fcrepo.kernel.rdf.GraphProperties.PROBLEMS_MODEL_NAME;
import static org.slf4j.LoggerFactory.getLogger;
Expand Down Expand Up @@ -421,6 +433,90 @@ public Response deleteObject() {
}
}


/**
* Create a resource at a specified path, or replace triples with provided RDF.
* @param requestContentType
* @param requestBodyStream
* @return 204
*/
@PUT
@Consumes
@Timed
public Response createOrReplaceObjectRdf(@HeaderParam("Content-Type") final MediaType requestContentType,
@ContentLocation final InputStream requestBodyStream,
@QueryParam("checksum") final String checksum,
@HeaderParam("Content-Disposition") final ContentDisposition contentDisposition)
throws URISyntaxException, InvalidChecksumException, ParseException {

try {

final FedoraResource resource;
final Response.ResponseBuilder response;


final MediaType contentType = getSimpleContentType(requestContentType);

if (nodeService.exists(session, path)) {
resource = resource();
response = noContent();
} else {
final MediaType effectiveContentType
= requestBodyStream == null || requestContentType == null ? null : contentType;
resource = createFedoraResource(null, effectiveContentType, path, contentDisposition);

final URI location = getUri(resource);

response = created(location).entity(location.toString());
}

evaluateRequestPreconditions(request, servletResponse, resource, session);

if (requestContentType != null && requestBodyStream != null) {

if (resource instanceof FedoraObject) {
final Lang format = contentTypeToLang(contentType.toString());

if (format == null || contentType.equals(TEXT_PLAIN_TYPE)) {
throw new NotSupportedException();
}

final Model inputModel = createDefaultModel()
.read(requestBodyStream, getUri(resource).toString(), format.getName().toUpperCase());

resource.replaceProperties(translator(), inputModel,
getTriples(resource, PropertiesRdfContext.class));
} else if (resource instanceof FedoraBinary) {
final URI checksumURI = checksumURI(checksum);
final String originalFileName
= contentDisposition != null ? contentDisposition.getFileName() : null;

((FedoraBinary) resource).setContent(requestBodyStream,
requestContentType.toString(),
checksumURI,
originalFileName,
datastreamService.getStoragePolicyDecisionPoint());
}

} else if (!resource.isNew()) {
throw new ClientErrorException("No RDF provided and the resource already exists!", CONFLICT);
}

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

addCacheControlHeaders(servletResponse, resource, session);

return response.build();
} finally {
session.logout();
}
}

/**
* Update an object using SPARQL-UPDATE
*
Expand All @@ -433,8 +529,6 @@ public Response deleteObject() {
@Timed
public Response updateSparql(@ContentLocation final InputStream requestBodyStream) throws IOException {

LOGGER.debug("Attempting to update path: {}", path);

if (resource() instanceof FedoraBinary) {
throw new BadRequestException(resource() + " is not a valid object to receive a PATCH");
}
Expand Down Expand Up @@ -571,6 +665,50 @@ private FedoraResource resource() {
return resource;
}


private String getRequestedObjectType(final String mixin,
final MediaType requestContentType,
final ContentDisposition contentDisposition) {
String objectType = FEDORA_OBJECT;

if (mixin != null) {
objectType = mixin;
} else {
if (requestContentType != null) {
final String s = requestContentType.toString();
if (!s.equals(contentTypeSPARQLUpdate) && !isRdfContentType(s)) {
objectType = FEDORA_DATASTREAM;
}
}

if (contentDisposition != null && contentDisposition.getType().equals("attachment")) {
objectType = FEDORA_DATASTREAM;
}
}
return objectType;
}

private FedoraResource createFedoraResource(final String requestMixin,
final MediaType requestContentType,
final String path,
final ContentDisposition contentDisposition) {
final String objectType = getRequestedObjectType(requestMixin, requestContentType, contentDisposition);

final FedoraResource result;

switch (objectType) {
case FEDORA_OBJECT:
result = objectService.findOrCreateObject(session, path);
break;
case FEDORA_DATASTREAM:
result = datastreamService.findOrCreateDatastream(session, path).getBinary();
break;
default:
throw new ClientErrorException("Unknown object type " + objectType, BAD_REQUEST);
}
return result;
}

private HttpIdentifierTranslator translator() {
if (identifierTranslator == null) {
identifierTranslator = new HttpIdentifierTranslator(session, this.getClass(), uriInfo);
Expand Down

0 comments on commit b3b0e63

Please sign in to comment.