All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fcrepo.http.api.FedoraTombstones Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree.
 */
package org.fcrepo.http.api;

import com.google.common.annotations.VisibleForTesting;
import io.micrometer.core.annotation.Timed;

import org.fcrepo.kernel.api.exception.PathNotFoundException;
import org.fcrepo.kernel.api.exception.PathNotFoundRuntimeException;
import org.fcrepo.kernel.api.identifiers.FedoraId;
import org.fcrepo.kernel.api.models.FedoraResource;
import org.fcrepo.kernel.api.models.Tombstone;
import org.fcrepo.kernel.api.services.PurgeResourceService;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;

import javax.inject.Inject;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
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;
import javax.ws.rs.core.Response;

import static javax.ws.rs.core.Response.noContent;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * CRUD operations on Fedora tombstones
 *
 * @author cbeer
 */
@Timed
@Scope("request")
@Path("/{path: .*}/fcr:tombstone")
public class FedoraTombstones extends ContentExposingResource {

    private static final Logger LOGGER = getLogger(FedoraTombstones.class);

    @PathParam("path") protected String externalPath;

    @Inject
    private PurgeResourceService purgeResourceService;

    /**
     * Default JAX-RS entry point
     */
    public FedoraTombstones() {
        super();
    }

    /**
     * Create a new FedoraTombstones instance for a given path
     * @param externalPath the external path
     */
    @VisibleForTesting
    public FedoraTombstones(final String externalPath) {
        this.externalPath = externalPath;
    }

    /**
     * Delete a tombstone resource (freeing the original resource to be reused)
     * @return the free resource
     */
    @DELETE
    public Response delete() {
        final FedoraResource resource = resource();
        if (!(resource instanceof Tombstone)) {
            // If the resource is not deleted there is no tombstone.
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        final Tombstone tombstone = (Tombstone) resource;
        final var deletedResource = tombstone.getDeletedObject();
        if (deletedResource.getArchivalGroupId().isPresent()) {
            return Response.status(Response.Status.METHOD_NOT_ALLOWED).allow().build();
        }

        try {
            LOGGER.info("Delete tombstone: {}", resource.getFedoraId());
            doInDbTxWithRetry(() -> {
                purgeResourceService.perform(transaction(), tombstone.getDeletedObject(), getUserPrincipal());
                transaction().commitIfShortLived();
            });
            return noContent().build();
        } finally {
            transaction().releaseResourceLocksIfShortLived();
        }
    }

    /*
     * These methods are disallowed, but need to exist here or the path gets caught by the FedoraLdp path matcher.
     */
    @GET
    public Response get() {
        return methodNotAllowed();
    }

    @POST
    public Response post() {
        return methodNotAllowed();
    }
    @PUT
    public Response put() {
        return methodNotAllowed();
    }

    @OPTIONS
    public Response options() {
        final var resource = resource();
        if (!(resource instanceof Tombstone)) {
            // If the resource is not deleted there is no tombstone.
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        final var response = Response.ok().allow();
        final Tombstone tombstone = (Tombstone) resource;
        final var deletedResource = tombstone.getDeletedObject();
        if (deletedResource.getArchivalGroupId().isEmpty()) {
            response.allow("DELETE");
        }

        return response.build();
    }

    @Override
    protected FedoraResource resource() {
        final FedoraId resourceId = identifierConverter().pathToInternalId(externalPath);
        try {
            return getFedoraResource(transaction(), resourceId);
        } catch (final PathNotFoundException e) {
            throw new PathNotFoundRuntimeException(e.getMessage(), e);
        }
    }

    @Override
    protected String externalPath() {
        return null;
    }

    private Response methodNotAllowed() {
        final var response = Response.status(Response.Status.METHOD_NOT_ALLOWED).allow();
        final var resource = resource();
        if (resource instanceof Tombstone) {
            final var deleted = ((Tombstone) resource).getDeletedObject();
            if (deleted.getArchivalGroupId().isEmpty()) {
                response.allow("DELETE");
            }
        }

        return response.build();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy