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.commons.exceptionhandlers; 007 008import org.fcrepo.config.FedoraPropsConfig; 009import org.fcrepo.http.commons.api.rdf.HttpIdentifierConverter; 010import org.fcrepo.http.commons.domain.RDFMediaType; 011import org.fcrepo.http.commons.responses.ConcurrentExceptionResponse; 012import org.fcrepo.kernel.api.exception.ConcurrentUpdateException; 013import org.slf4j.Logger; 014 015import javax.inject.Inject; 016import javax.ws.rs.core.Context; 017import javax.ws.rs.core.Response; 018import javax.ws.rs.core.UriInfo; 019import javax.ws.rs.ext.ExceptionMapper; 020import javax.ws.rs.ext.Provider; 021 022import static javax.ws.rs.core.Response.status; 023import static org.fcrepo.http.commons.session.TransactionConstants.TX_PREFIX; 024import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_ID_PREFIX; 025import static org.slf4j.LoggerFactory.getLogger; 026 027/** 028 * @author pwinckles 029 */ 030@Provider 031public class ConcurrentUpdateExceptionMapper implements 032 ExceptionMapper<ConcurrentUpdateException>, ExceptionDebugLogging { 033 034 private static final Logger LOGGER = getLogger(ConcurrentUpdateExceptionMapper.class); 035 036 @Inject 037 private FedoraPropsConfig config; 038 039 @Context 040 private UriInfo uriInfo; 041 042 @Override 043 public Response toResponse(final ConcurrentUpdateException e) { 044 debugException(this, e, LOGGER); 045 final var response = new ConcurrentExceptionResponse(e.getResponseMessage()); 046 047 // create external links for the transaction ids 048 if (config.includeTransactionOnConflict()) { 049 final var identifierConverter = new HttpIdentifierConverter(uriInfo.getBaseUriBuilder() 050 .clone().path("/{path: .*}")); 051 final var existingId = FEDORA_ID_PREFIX + "/" + TX_PREFIX + e.getExistingTransactionId(); 052 final var conflictingId = FEDORA_ID_PREFIX + "/" + TX_PREFIX + e.getConflictingTransactionId(); 053 response.setExistingTransactionId(identifierConverter.toExternalId(existingId)); 054 response.setConflictingTransactionId(identifierConverter.toExternalId(conflictingId)); 055 } 056 057 return status(Response.Status.CONFLICT) 058 .entity(response) 059 .type(RDFMediaType.APPLICATION_JSON_TYPE).build(); 060 } 061 062}