001/* 002 * The contents of this file are subject to the license and copyright 003 * detailed in the LICENSE and NOTICE files at the root of the source 004 * tree. 005 */ 006package org.fcrepo.http.api; 007 008import static javax.ws.rs.core.HttpHeaders.ALLOW; 009import static javax.ws.rs.core.HttpHeaders.LINK; 010import static org.fcrepo.http.commons.domain.RDFMediaType.JSON_LD; 011import static org.fcrepo.http.commons.domain.RDFMediaType.N3_ALT2_WITH_CHARSET; 012import static org.fcrepo.http.commons.domain.RDFMediaType.N3_WITH_CHARSET; 013import static org.fcrepo.http.commons.domain.RDFMediaType.NTRIPLES; 014import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_XML; 015import static org.fcrepo.http.commons.domain.RDFMediaType.TEXT_HTML_WITH_CHARSET; 016import static org.fcrepo.http.commons.domain.RDFMediaType.TEXT_PLAIN_WITH_CHARSET; 017import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_WITH_CHARSET; 018import static org.fcrepo.kernel.api.RdfLexicon.RDF_SOURCE; 019import static org.fcrepo.kernel.api.RdfLexicon.RESOURCE; 020import static org.slf4j.LoggerFactory.getLogger; 021 022import javax.inject.Inject; 023import javax.ws.rs.DELETE; 024import javax.ws.rs.GET; 025import javax.ws.rs.HEAD; 026import javax.ws.rs.NotFoundException; 027import javax.ws.rs.OPTIONS; 028import javax.ws.rs.POST; 029import javax.ws.rs.PUT; 030import javax.ws.rs.Path; 031import javax.ws.rs.PathParam; 032import javax.ws.rs.Produces; 033import javax.ws.rs.core.Link; 034import javax.ws.rs.core.Response; 035 036import org.fcrepo.http.commons.domain.PATCH; 037import org.fcrepo.http.commons.responses.HtmlTemplate; 038import org.fcrepo.http.commons.responses.RdfNamespacedStream; 039import org.fcrepo.kernel.api.RdfStream; 040import org.fcrepo.kernel.api.models.Binary; 041import org.fcrepo.kernel.api.services.FixityService; 042 043import org.slf4j.Logger; 044import org.springframework.context.annotation.Scope; 045 046import com.google.common.annotations.VisibleForTesting; 047 048import io.micrometer.core.annotation.Timed; 049 050/** 051 * Run a fixity check on a path 052 * 053 * @author ajs6f 054 * @since Jun 12, 2013 055 */ 056@Timed 057@Scope("request") 058@Path("/{path: .*}/fcr:fixity") 059public class FedoraFixity extends ContentExposingResource { 060 061 private static final Logger LOGGER = getLogger(FedoraFixity.class); 062 063 private static final String OPTIONS_VALUES = "OPTIONS, GET"; 064 065 @PathParam("path") protected String externalPath; 066 067 @Inject private FixityService fixityService; 068 069 /** 070 * Default JAX-RS entry point 071 */ 072 public FedoraFixity() { 073 super(); 074 } 075 076 /** 077 * Create a new FedoraNodes instance for a given path 078 * @param externalPath the external path 079 */ 080 @VisibleForTesting 081 public FedoraFixity(final String externalPath) { 082 this.externalPath = externalPath; 083 } 084 085 /** 086 * Get the results of a fixity check for a path 087 * 088 * GET /path/to/some/datastream/fcr:fixity 089 * 090 * @return datastream fixity in the given format 091 */ 092 @GET 093 @HtmlTemplate(value = "fcr:fixity") 094 @Produces({TURTLE_WITH_CHARSET + ";qs=1.0", JSON_LD + ";qs=0.8", N3_WITH_CHARSET, N3_ALT2_WITH_CHARSET, 095 RDF_XML, NTRIPLES, TEXT_PLAIN_WITH_CHARSET, TEXT_HTML_WITH_CHARSET, "*/*"}) 096 public RdfNamespacedStream getDatastreamFixity() { 097 098 if (!(resource() instanceof Binary)) { 099 throw new NotFoundException("Error: Resource at " + resource().getFedoraId().getFullIdPath() + " is not a" + 100 " binary"); 101 } 102 103 final Link.Builder resourceLink = Link.fromUri(RESOURCE.getURI()).rel("type"); 104 servletResponse.addHeader(LINK, resourceLink.build().toString()); 105 final Link.Builder rdfSourceLink = Link.fromUri(RDF_SOURCE.getURI()).rel("type"); 106 servletResponse.addHeader(LINK, rdfSourceLink.build().toString()); 107 108 final Binary binaryResource = (Binary) resource(); 109 LOGGER.info("Get fixity for '{}'", externalPath); 110 111 final RdfStream rdfStream = httpRdfService.bodyToExternalStream(getUri(binaryResource).toString(), 112 fixityService.checkFixity(binaryResource), identifierConverter()); 113 return new RdfNamespacedStream(rdfStream, namespaceRegistry.getNamespaces()); 114 } 115 116 @Override 117 protected String externalPath() { 118 return externalPath; 119 } 120 121 @OPTIONS 122 public Response options() { 123 return Response.ok().header(ALLOW, OPTIONS_VALUES).build(); 124 } 125 /* 126 * These methods are disallowed, but need to exist here or the path gets caught by the FedoraLdp path matcher. 127 */ 128 @HEAD 129 public Response get() { 130 return methodNotAllowed(); 131 } 132 @POST 133 public Response post() { 134 return methodNotAllowed(); 135 } 136 @PUT 137 public Response put() { 138 return methodNotAllowed(); 139 } 140 @PATCH 141 public Response patch() { 142 return methodNotAllowed(); 143 } 144 @DELETE 145 public Response delete() { 146 return methodNotAllowed(); 147 } 148 149 private Response methodNotAllowed() { 150 return Response.status(Response.Status.METHOD_NOT_ALLOWED).header(ALLOW, OPTIONS_VALUES).build(); 151 } 152}