package org.gcube.datatransfer.resolver.services; import java.io.IOException; import java.io.InputStream; import javax.annotation.Nullable; import javax.servlet.ServletException; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; import org.gcube.contentmanagement.blobstorage.resource.MyFile; import org.gcube.contentmanagement.blobstorage.service.IClient; import org.gcube.contentmanager.storageclient.wrapper.AccessType; import org.gcube.contentmanager.storageclient.wrapper.MemoryType; import org.gcube.contentmanager.storageclient.wrapper.StorageClient; import org.gcube.datatransfer.resolver.SingleFileStreamingOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class StorageManager. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * @author Lucio Lelii * * Oct 19, 2018 */ @Path("/") public class StorageManager { /** * */ protected static final String STORAGEID_RESOLVER = "storageid-resolver"; private static final String HPROXYCHECK = "hproxycheck"; private static final String CONTENT_TYPE = "contentType"; private static final String FILE_NAME = "fileName"; private static final String SMP_ID = "smp-id"; private static final String SMP_URI = "smp-uri"; private static final String STORAGE_ID = "storage-id"; protected static final String VALIDATION = "validation"; private static Logger logger = LoggerFactory.getLogger(StorageManager.class); /** * Gets the smpid. * * @param smpURI the smp id * @param fileName the file name * @param contentType the content type * @param validation the validation * @return the smpid */ /*@GET @Path("smp") public Response getSMPURI(@QueryParam(SMP_URI) @Nullable String smpURI, @QueryParam(FILE_NAME) String fileName, @QueryParam(CONTENT_TYPE) String contentType, @QueryParam(VALIDATION) Boolean validation){ logger.info("resolve smp-id called"); //Checking mandatory parameter smpId if(smpURI==null || smpURI.isEmpty()){ logger.error(SMP_URI+" not found"); return Response.status(Status.BAD_REQUEST).entity(Entity.text("Missing mandatory parameter "+SMP_URI)).build(); } logger.warn("Sono qui getSMPURI"); return getStorageId(smpURI, fileName, contentType, validation); }*/ /** * Gets the smpid. * * @param smpId the smp id * @param fileName the file name * @param contentType the content type * @param validation the validation * @return the smpid */ @GET @Path("id") public Response getSMPID(@QueryParam(SMP_ID) @Nullable String smpId, @QueryParam(FILE_NAME) String fileName, @QueryParam(CONTENT_TYPE) String contentType, @QueryParam(VALIDATION) Boolean validation){ logger.info("resolve smp-id called"); //Checking mandatory parameter smpId if(smpId==null || smpId.isEmpty()){ logger.error(SMP_ID+" not found"); return Response.status(400).entity(Entity.text("Missing mandatory parameter "+SMP_ID)).build(); } logger.warn("Sono qui getSMPID"); return getStorageId(smpId, fileName, contentType, validation); } /** * Gets the storage id. * * @param storageId the storage id * @param fileName the file name * @param contentType the content type * @param validation the validation * @return the storage id */ @GET @Path("{storage-id:(?!id)[^/?$]*}") public Response getStorageId(@PathParam(STORAGE_ID) String storageId, @QueryParam(FILE_NAME) String fileName, @QueryParam(CONTENT_TYPE) String contentType, @QueryParam(VALIDATION) Boolean validation) { logger.info("resolve Storage Id called"); logger.info("storage-id: "+storageId+", fileName: "+fileName+", contentType: "+contentType+", validation: "+validation); //Checking to STORAGE-ID Resolver if (storageId == null || storageId.isEmpty()) { logger.warn("storageId not found"); throw new WebApplicationException("Missing mandatory parameter "+STORAGE_ID, Status.BAD_REQUEST); } if(validation!=null && validation) return validationPayload(storageId); StorageClient client = getStorageClientInstance(storageId); String toSEID = null; IClient iClient = null; try{ iClient = client.getClient(); toSEID = iClient.getId(storageId); //to Storage Encrypted ID logger.debug("Decoded ID"+" = "+ toSEID); }catch(Exception e){ logger.error("Storage Client Exception when getting file from storage: ", e); throw new WebApplicationException("Storage Client Exception when getting file from storage with id: "+storageId, Status.INTERNAL_SERVER_ERROR); } if(toSEID==null){ String error = "Decrypted id is null, thrown exception!"; throw new WebApplicationException(error, Status.BAD_REQUEST); } long size = iClient.getSize().RFileById(toSEID); try{ MyFile file = iClient.getMetaFile().RFile(toSEID); logger.debug("MetaFile retrieved from storage? "+ (file!=null)); fileName= file.getName(); //Reading the contentType from Storage Metadata only if the passed contentType is null if(contentType==null || contentType.isEmpty()) contentType = file.getMimeType(); }catch (Exception e) { logger.warn("Error when getting file metadata from storage, printing this warning and trying to continue..", e); } fileName = fileName==null || fileName.isEmpty()?ConstantsResolver.DEFAULT_FILENAME_FROM_STORAGE_MANAGER:fileName; logger.info("filename retrieved is {}",fileName); contentType = contentType==null || contentType.isEmpty()?ConstantsResolver.DEFAULT_CONTENTTYPE_UNKNOWN_UNKNOWN:contentType; logger.info("contentType used is {}",contentType); //Building the response InputStream streamToWrite=iClient.get().RFileAsInputStream(toSEID); //input stream StreamingOutput so = new SingleFileStreamingOutput(streamToWrite); ResponseBuilder response = Response .ok(so) .header(ConstantsResolver.CONTENT_DISPOSITION,"attachment; filename = \""+fileName+"\"") .header(ConstantsResolver.CONTENT_LENGTH, size); if (contentType!= null) response.header("Content-Type",contentType); return response.build(); } /** * Http do head. * * @param storageId the storage id * @param hproxycheck the hproxycheck * @return the response * @throws ServletException the servlet exception * @throws IOException Signals that an I/O exception has occurred. */ @HEAD @Path("{storage-id}") public Response httpDoHead(@PathParam(STORAGE_ID) String storageId, @QueryParam(HPROXYCHECK) Boolean hproxycheck) throws ServletException, IOException { logger.info("doHead working.."); //THIS IS FOR HPROXY CHECK if(hproxycheck==null || hproxycheck){ logger.trace("returning status 200 for Hproxy check"); ResponseBuilder response = Response.status(HttpStatus.SC_OK); return response.build(); } return validationPayload(storageId); } /** * Validation payload. * * @param storageId the storage id * @return the response */ protected Response validationPayload(String storageId){ //Checking to STORAGE-ID Resolver if (storageId == null || storageId.isEmpty()) { logger.warn("storageId not found"); throw new WebApplicationException("Missing mandatory parameter "+STORAGE_ID, Status.BAD_REQUEST); } StorageClient client = getStorageClientInstance(storageId); String toSEID = null; IClient iClient = null; try{ iClient = client.getClient(); toSEID = iClient.getId(storageId); //to Storage Encrypted ID logger.debug("Decoded ID"+" = "+ toSEID); }catch(Exception e){ logger.error("Storage Client Exception when getting file from storage: ", e); throw new WebApplicationException("Storage Client Exception when getting file from storage with id: "+storageId, Status.INTERNAL_SERVER_ERROR); } if(toSEID==null){ String error = "Decrypted storageId is null, thrown exception!"; throw new WebApplicationException(error, Status.BAD_REQUEST); } //Building the response InputStream streamToWrite=iClient.get().RFileAsInputStream(toSEID); //input stream byte[] bytes = new byte[1]; //1B int c; try { c = streamToWrite.read(bytes); logger.info(c+" byte read from InputStream"); if(c>0){ logger.info("at least 1 byte read, returning status 200"); IOUtils.closeQuietly(streamToWrite); ResponseBuilder response = Response.status(HttpStatus.SC_OK); return response.build(); }else throw new WebApplicationException("The file with id: "+storageId+" is missing in the storage", Status.NOT_FOUND); } catch (IOException e) { logger.error("Error on validating the file: ",e); throw new WebApplicationException("Error on validating the file with id: "+storageId, Status.INTERNAL_SERVER_ERROR); } } /** * Gets the storage client instance. * * @param storageId the storage id * @return the storage client instance */ protected StorageClient getStorageClientInstance(String storageId){ MemoryType memory=null; if(storageId.endsWith(org.gcube.contentmanagement.blobstorage.transport.backend.util.Costants.VOLATILE_URL_IDENTIFICATOR)){ memory=MemoryType.VOLATILE; storageId=storageId.replace(org.gcube.contentmanagement.blobstorage.transport.backend.util.Costants.VOLATILE_URL_IDENTIFICATOR, ""); } StorageClient client; if(memory==null) client=new StorageClient(StorageManager.class.getName(), StorageManager.class.getSimpleName(), STORAGEID_RESOLVER, AccessType.PUBLIC); else client=new StorageClient(StorageManager.class.getName(), StorageManager.class.getSimpleName(), STORAGEID_RESOLVER, AccessType.PUBLIC, memory); return client; } }