diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/ConstantsResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/ConstantsResolver.java new file mode 100644 index 0000000..687d4f4 --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/services/ConstantsResolver.java @@ -0,0 +1,22 @@ +/** + * + */ +package org.gcube.datatransfer.resolver.services; + + +/** + * The Class ConstantsResolver. + * + * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) + * Oct 19, 2018 + */ +public class ConstantsResolver { + + public static final String CONTENT_DISPOSITION = "content-disposition"; + public static final String DEFAULT_CONTENTTYPE_UNKNOWN_UNKNOWN = "unknown/unknown"; + public static final String DEFAULT_FILENAME_FROM_STORAGE_MANAGER = "fromStorageManager"; + public static final String CONTENT_LENGTH = "Content-Length"; + + protected static final String HPC = "hproxycheck"; //for hproxycheck + +} diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StorageManager.java b/src/main/java/org/gcube/datatransfer/resolver/services/StorageManager.java index 1b66c18..e945db9 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StorageManager.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StorageManager.java @@ -1,58 +1,147 @@ 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)?}|{storage-id}") - public Response getFile(@PathParam("storage-id") String storageId, @QueryParam("smp-id") String smpId, @QueryParam("fileName") String fileName, @QueryParam("contentType") String contentType, @QueryParam("validation") String validation) { + @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); - logger.info("smp-id: "+smpId); - logger.info("fileName: "+fileName); - logger.info("contentType: "+contentType); + logger.info("storage-id: "+storageId+", fileName: "+fileName+", contentType: "+contentType+", validation: "+validation); //Checking to STORAGE-ID Resolver - boolean storageIdFound = true; if (storageId == null || storageId.isEmpty()) { logger.warn("storageId not found"); - storageIdFound = false; + throw new WebApplicationException("Missing mandatory parameter "+STORAGE_ID, Status.BAD_REQUEST); } - //If storageId not found, Checking to SMP-ID Resolver - if(!storageIdFound){ - if(smpId==null || smpId.isEmpty()){ - logger.warn("smp-id not found"); - throw new WebApplicationException("Missing mandatory parameter 'smp-id' or 'storage-id'", Status.BAD_REQUEST); - } - } + if(validation!=null && validation) + return validationPayload(storageId); - StorageClient client = new StorageClient("DataTransfer", "UriResolver", "storageid-resolver", AccessType.PUBLIC); - IClient iClient = client.getClient(); - String toSEID = iClient.getId(storageId); //to Storage Encrypted ID - logger.debug("Decoded ID"+" = "+ toSEID); + 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!"; @@ -63,31 +152,139 @@ public class StorageManager { try{ - MyFile file = client.getClient().getMetaFile().RFile(toSEID); + 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) + 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()?"download":fileName; + 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("content-disposition","attachment; filename = \""+fileName+"\"") - .header("Content-Length", size); + .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; + } + }