/******************************************************************************* * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2019) * * contact.vitam@culture.gouv.fr * * This software is a computer program whose purpose is to implement a digital archiving back-office system managing * high volumetry securely and efficiently. * * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as * circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". * * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the * successive licensors have only limited liability. * * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or * developing or reproducing the software by the user in light of its specific status of free software, that may mean * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data * to be ensured and, more generally, to use and operate it in the same conditions as regards security. * * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you * accept its terms. *******************************************************************************/ package fr.gouv.vitam.workspace.rest; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Collections; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.Suspended; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import fr.gouv.vitam.common.CommonMediaType; import fr.gouv.vitam.common.GlobalDataRest; import fr.gouv.vitam.common.ParametersChecker; import fr.gouv.vitam.common.digest.DigestType; import fr.gouv.vitam.common.json.JsonHandler; import fr.gouv.vitam.common.logging.VitamLogger; import fr.gouv.vitam.common.logging.VitamLoggerFactory; import fr.gouv.vitam.common.server.application.AsyncInputStreamHelper; import fr.gouv.vitam.common.server.application.VitamHttpHeader; import fr.gouv.vitam.common.server.application.resources.ApplicationStatusResource; import fr.gouv.vitam.common.storage.StorageConfiguration; import fr.gouv.vitam.common.storage.api.ContentAddressableStorage; import fr.gouv.vitam.common.storage.builder.StoreContextBuilder; import fr.gouv.vitam.common.storage.constants.ErrorMessage; import fr.gouv.vitam.common.stream.StreamUtils; import fr.gouv.vitam.common.thread.VitamThreadPoolExecutor; import fr.gouv.vitam.workspace.api.exception.ContentAddressableStorageAlreadyExistException; import fr.gouv.vitam.workspace.api.exception.ContentAddressableStorageCompressedFileException; import fr.gouv.vitam.workspace.api.exception.ContentAddressableStorageException; import fr.gouv.vitam.workspace.api.exception.ContentAddressableStorageNotFoundException; import fr.gouv.vitam.workspace.api.exception.ContentAddressableStorageServerException; import fr.gouv.vitam.workspace.api.model.ContainerInformation; import fr.gouv.vitam.workspace.common.RequestResponseError; import fr.gouv.vitam.workspace.common.VitamError; /** * The Workspace Resource. */ @Path("/workspace/v1") @javax.ws.rs.ApplicationPath("webresources") public class WorkspaceResource extends ApplicationStatusResource { private static final VitamLogger LOGGER = VitamLoggerFactory.getInstance(WorkspaceResource.class); private static final String FOLDER_NAME = "folderName"; private static final String OBJECT_NAME = "objectName"; private static final String CONTAINER_NAME = "containerName"; private final ContentAddressableStorage workspace; /** * Constructor used to configure a workspace * * @param configuration the storage config */ public WorkspaceResource(StorageConfiguration configuration) { workspace = StoreContextBuilder.newStoreContext(configuration); LOGGER.info("init Workspace Resource server"); } /** * creates a container into the workspace * * @param containerName as path param * @return Response */ @Path("/containers/{containerName}") @POST @Produces(MediaType.APPLICATION_JSON) public Response createContainer(@PathParam(CONTAINER_NAME) String containerName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName); workspace.createContainer(containerName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageAlreadyExistException e) { LOGGER.error(ErrorMessage.CONTAINER_ALREADY_EXIST.getMessage() + containerName + " => " + e.getMessage()); return Response.status(Status.CONFLICT).entity(containerName).build(); } catch (ContentAddressableStorageServerException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.CREATED).entity(containerName).build(); } /** * deletes a container in the workspace * * @param containerName path param of container name * @param recursive true if the container should be deleted recursively * @return Response */ @Path("/containers/{containerName}") @DELETE @Produces(MediaType.APPLICATION_JSON) public Response deleteContainer(@PathParam(CONTAINER_NAME) String containerName, @HeaderParam(GlobalDataRest.X_RECURSIVE) boolean recursive) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName); workspace.deleteContainer(containerName, recursive); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.CONTAINER_NOT_FOUND.getMessage() + containerName + " => " + e.getMessage()); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.NO_CONTENT).entity(containerName).build(); } /** * checks if a container exists in the workspace * * @param containerName path param for container name * @return Response */ @Path("/containers/{containerName}") @HEAD @Produces(MediaType.APPLICATION_JSON) public Response isExistingContainer(@PathParam(CONTAINER_NAME) String containerName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName); final boolean exists = workspace.isExistingContainer(containerName); if (exists) { return Response.status(Status.OK).entity(containerName).build(); } else { return Response.status(Status.NOT_FOUND).build(); } } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } } /** * Count the number of binary files in the container * * @param containerName path param for container name * @return Response containing the number of objects in "objectNumber" */ @Path("/containers/{containerName}/count") @GET @Produces(MediaType.APPLICATION_JSON) public Response countObjects(@PathParam(CONTAINER_NAME) String containerName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName); final long objectNumber = workspace.countObjects(containerName); // TODO should use a common model object, but since it should be common with driver, where ? final ObjectNode result = JsonHandler.createObjectNode(); result.put("objectNumber", objectNumber); return Response.status(Status.OK).entity(result).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException exc) { LOGGER.error(ErrorMessage.CONTAINER_NOT_FOUND.getMessage() + containerName, exc); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } } /** * Get container information like capacity * * @param containerName the container name * @return a Json with usableSpace and usedSpace information */ @Path("/container/{containerName}") @GET @Produces(MediaType.APPLICATION_JSON) public Response getContainerInformation(@PathParam(CONTAINER_NAME) String containerName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName); final ContainerInformation containerInformation = workspace.getContainerInformation(containerName); return Response.status(Status.OK).entity(containerInformation).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException exc) { LOGGER.error(ErrorMessage.CONTAINER_NOT_FOUND.getMessage() + containerName, exc); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } } /** * creates a folder into a container * * @param containerName path param of container name * @param folderName path param of folder * @return Response */ @Path("/containers/{containerName}/folders/{folderName:.*}") @POST @Produces(MediaType.APPLICATION_JSON) public Response createFolder(@PathParam(CONTAINER_NAME) String containerName, @PathParam(FOLDER_NAME) String folderName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, folderName); workspace.createFolder(containerName, folderName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageAlreadyExistException e) { LOGGER.error(ErrorMessage.FOLDER_ALREADY_EXIST.getMessage() + containerName + "/" + folderName, e); return Response.status(Status.CONFLICT).entity(containerName + "/" + folderName).build(); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.FOLDER_NOT_FOUND.getMessage() + containerName + "/" + folderName, e); return Response.status(Status.NOT_FOUND).entity(containerName + "/" + folderName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.CREATED).entity(containerName + "/" + folderName).build(); } /** * deletes a folder in a container * * @param containerName path param for container name * @param folderName path param for folder name * @return Response */ @Path("/containers/{containerName}/folders/{folderName:.*}") @DELETE @Produces(MediaType.APPLICATION_JSON) public Response deleteFolder(@PathParam(CONTAINER_NAME) String containerName, @PathParam(FOLDER_NAME) String folderName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, folderName); workspace.deleteFolder(containerName, folderName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.FOLDER_NOT_FOUND.getMessage() + containerName + "/" + folderName, e); return Response.status(Status.NOT_FOUND).entity(containerName + "/" + folderName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.NO_CONTENT).entity(containerName + "/" + folderName).build(); } /** * checks if a folder exists in a container * * @param containerName path param for container name * @param folderName path param for folder name * @return Response */ @Path("/containers/{containerName}/folders/{folderName:.*}") @HEAD @Produces(MediaType.APPLICATION_JSON) public Response isExistingFolder(@PathParam(CONTAINER_NAME) String containerName, @PathParam(FOLDER_NAME) String folderName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, folderName); final boolean exists = workspace.isExistingFolder(containerName, folderName); if (exists) { return Response.status(Status.OK).entity(containerName + "/" + folderName).build(); } else { return Response.status(Status.NOT_FOUND).build(); } } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } } /** * uncompress a sip into the workspace * * @param stream data input stream * @param containerName name of container * @param folderName name of folder * @param archiveType * @return Response */ @Path("/containers/{containerName}/folders/{folderName:.*}") @PUT @Consumes({CommonMediaType.ZIP, CommonMediaType.GZIP, CommonMediaType.TAR, CommonMediaType.BZIP2}) @Produces(MediaType.APPLICATION_JSON) public Response uncompressObject(InputStream stream, @PathParam(CONTAINER_NAME) String containerName, @PathParam(FOLDER_NAME) String folderName, @HeaderParam(HttpHeaders.CONTENT_TYPE) String archiveType) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_FOLDER_NAMES_ARE_A_MANDATORY_PARAMETER.getMessage(), containerName, folderName); try { workspace.uncompressObject(containerName, folderName, archiveType, stream); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.CONTAINER_NOT_FOUND.getMessage() + containerName, e); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageAlreadyExistException e) { LOGGER.error(ErrorMessage.CONTAINER_ALREADY_EXIST.getMessage() + containerName, e); return Response.status(Status.CONFLICT).entity(containerName).build(); } catch (final ContentAddressableStorageCompressedFileException e) { LOGGER.error(e); final Status status = Status.BAD_REQUEST; // TODO P0 : For now it is generic code "0000" since vitam error code have not been defined return Response.status(status) .entity(new RequestResponseError().setError( new VitamError(status.getStatusCode()) .setContext("WORKSPACE") .setState("vitam_code") .setMessage(status.getReasonPhrase()) .setDescription(status.getReasonPhrase()))) .build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.CREATED).entity(containerName).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } finally { StreamUtils.closeSilently(stream); } } /** * gets the list of object from folder * * @param containerName name of container * @param folderName name of folder * @return Response */ @Path("/containers/{containerName}/folders/{folderName:.*}") @GET @Produces(MediaType.APPLICATION_JSON) public Response getUriDigitalObjectListByFolder(@PathParam(CONTAINER_NAME) String containerName, @PathParam(FOLDER_NAME) String folderName) { List<URI> uriList = null; try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_FOLDER_NAMES_ARE_A_MANDATORY_PARAMETER.getMessage(), containerName, folderName); uriList = workspace.getListUriDigitalObjectFromFolder(containerName, folderName); } catch (final ContentAddressableStorageNotFoundException eNotFoundException) { LOGGER.error(ErrorMessage.FOLDER_NOT_FOUND.getMessage() + containerName + "/" + folderName, eNotFoundException); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException eAddressableStorageException) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), eAddressableStorageException); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(Collections.<URI>emptyList()).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } if (uriList == null || uriList.isEmpty()) { return Response.status(Status.NO_CONTENT).entity(Collections.<URI>emptyList()).build(); } return Response.status(Status.OK).entity(uriList).build(); } /** * puts an object into a container * * @param stream data input stream * @param objectName name of data object * @param containerName name of container * @return Response */ @Path("/containers/{containerName}/objects/{objectName:.*}") @POST @Consumes(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.APPLICATION_JSON) public Response putObject(InputStream stream, @PathParam(CONTAINER_NAME) String containerName, @PathParam(OBJECT_NAME) String objectName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, objectName); workspace.putObject(containerName, objectName, stream); return Response.status(Status.CREATED).entity(containerName + "/" + objectName).build(); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.OBJECT_NOT_FOUND.getMessage() + containerName, e); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } finally { StreamUtils.closeSilently(stream); } } /** * Deletes an objects in a container * * * @param containerName container name * @param objectName object name * @return Response */ @Path("/containers/{containerName}/objects/{objectName:.*}") @DELETE @Produces(MediaType.APPLICATION_JSON) public Response deleteObject(@PathParam(CONTAINER_NAME) String containerName, @PathParam(OBJECT_NAME) String objectName) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, objectName); workspace.deleteObject(containerName, objectName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.OBJECT_NOT_FOUND.getMessage() + containerName, e); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.NO_CONTENT).entity(containerName).build(); } /** * gets an objects from a container in the workspace * * @param containerName name of container * @param objectName name of object * @param asyncResponse response async * @throws IOException when there is an error of get object */ @Path("/containers/{containerName}/objects/{objectName:.*}") @GET @Produces(MediaType.APPLICATION_OCTET_STREAM) public void getObject(@PathParam(CONTAINER_NAME) String containerName, @PathParam(OBJECT_NAME) String objectName, @Suspended final AsyncResponse asyncResponse) { VitamThreadPoolExecutor.getDefaultExecutor().execute(new Runnable() { @Override public void run() { getObjectAsync(containerName, objectName, asyncResponse); } }); } /** * gets an objects from a container in the workspace * * @param containerName name of container * @param objectName name of object * @return Response * @throws IOException when there is an error of get object */ @Path("/containers/{containerName}/objects/{objectName:.*}") @GET @Produces(MediaType.APPLICATION_JSON) public Response getObjectInformation(@PathParam(CONTAINER_NAME) String containerName, @PathParam(OBJECT_NAME) String objectName) throws IOException { JsonNode jsonResultNode; try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, objectName); jsonResultNode = workspace.getObjectInformation(containerName, objectName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.OBJECT_NOT_FOUND.getMessage() + containerName, e); return Response.status(Status.NOT_FOUND).entity(containerName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } return Response.status(Status.OK).entity(jsonResultNode).build(); } /** * checks if a object exists in an container or compute object Digest * * @param containerName name of container * @param objectName name of object * @param algo path parameter of algo * @return Response */ @Path("/containers/{containerName}/objects/{objectName:.*}") @HEAD @Produces(MediaType.APPLICATION_JSON) public Response computeObjectDigest(@PathParam(CONTAINER_NAME) String containerName, @PathParam(OBJECT_NAME) String objectName, @HeaderParam(GlobalDataRest.X_DIGEST_ALGORITHM) String algo) { try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_OBJECT_NAMES_ARE_A_MANDATORY_PARAMETER.getMessage(), containerName, objectName); } catch (final IllegalArgumentException e) { LOGGER.error(e); return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } if (algo != null) { LOGGER.debug(GlobalDataRest.X_DIGEST_ALGORITHM + " : " + algo); String messageDigest = null; try { messageDigest = workspace.computeObjectDigest(containerName, objectName, DigestType.fromValue(algo)); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.OBJECT_NOT_FOUND.getMessage() + containerName, e); return Response.status(Status.NOT_FOUND) .header(GlobalDataRest.X_DIGEST_ALGORITHM, algo) .entity(containerName + "/" + objectName).build(); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR) .header(GlobalDataRest.X_DIGEST_ALGORITHM, algo) .entity(containerName + "/" + objectName).build(); } return Response.status(Status.OK) .header(GlobalDataRest.X_DIGEST_ALGORITHM, algo) .header(GlobalDataRest.X_DIGEST, messageDigest).build(); } else { try { boolean exists = workspace.isExistingObject(containerName, objectName); if (exists) { return Response.status(Status.OK).entity(containerName + "/" + objectName).build(); } else { return Response.status(Status.NOT_FOUND).build(); } } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); return Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build(); } } } private void getObjectAsync(String containerName, String objectName, AsyncResponse asyncResponse) { AsyncInputStreamHelper helper = null; try { ParametersChecker.checkParameter(ErrorMessage.CONTAINER_NAME_IS_A_MANDATORY_PARAMETER.getMessage(), containerName, objectName); Response response = workspace.getObject(containerName, objectName); helper = new AsyncInputStreamHelper(asyncResponse, (InputStream) response.getEntity()); final ResponseBuilder responseBuilder = Response.status(Status.OK).type(MediaType.APPLICATION_OCTET_STREAM) .header(VitamHttpHeader.X_CONTENT_LENGTH.getName(), response.getHeaderString(VitamHttpHeader.X_CONTENT_LENGTH.getName())); helper.writeResponse(responseBuilder); } catch (final IllegalArgumentException e) { LOGGER.error(e); AsyncInputStreamHelper.asyncResponseResume(asyncResponse, Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build()); } catch (final ContentAddressableStorageNotFoundException e) { LOGGER.error(ErrorMessage.OBJECT_NOT_FOUND.getMessage() + containerName, e); AsyncInputStreamHelper.asyncResponseResume(asyncResponse, Response.status(Status.NOT_FOUND).entity(containerName).build()); } catch (final ContentAddressableStorageException e) { LOGGER.error(ErrorMessage.INTERNAL_SERVER_ERROR.getMessage(), e); AsyncInputStreamHelper.asyncResponseResume(asyncResponse, Response.status(Status.INTERNAL_SERVER_ERROR).entity(containerName).build()); } } }