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}