package org.gcube.datatransfer.resolver.services; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; 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.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.gcube.datatransfer.resolver.services.exceptions.BadRequestException; import org.gcube.datatransfer.resolver.services.exceptions.InternalServerException; import org.gcube.datatransfer.resolver.services.exceptions.WrongParameterException; 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 StorageIDResolver { /** * */ protected static final String STORAGEID_RESOLVER = "storageid-resolver"; private static final String STORAGE_ID = "storage-id"; private static Logger logger = LoggerFactory.getLogger(StorageIDResolver.class); private static String help = "https://wiki.gcube-system.org/gcube/URI_Resolver#STORAGE-ID_Resolver"; /** * Gets the storage id. * * @param httpRequest the http request * @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:(?!index)[^/?$]*}") //@Path("{storage-id}") public Response getStorageId(@Context HttpServletRequest httpRequest, @PathParam(STORAGE_ID) String storageId, @QueryParam(ConstantsResolver.FILE_NAME) String fileName, @QueryParam(ConstantsResolver.CONTENT_TYPE) String contentType, @QueryParam(ConstantsResolver.VALIDATION) Boolean validation) { logger.info("resolve Storage-Id called"); //Checking mandatory parameter storageId if(storageId==null || storageId.isEmpty()){ logger.error(STORAGE_ID+" not found"); try { throw new BadRequestException(httpRequest, Status.NOT_ACCEPTABLE, "Missing mandatory path parameter "+STORAGE_ID, StorageIDResolver.class, new URI(help)); } catch (URISyntaxException e) { //silent } } return resolveStorageId(httpRequest, storageId, fileName, contentType, validation); } /** * Resolve storage id. * * @param httpRequest the http request * @param storageId the storage id * @param fileName the file name * @param contentType the content type * @param validation the validation * @return the response */ protected static Response resolveStorageId(HttpServletRequest httpRequest, String storageId, String fileName, String contentType, Boolean validation) { logger.info("storage-id: "+storageId+", fileName: "+fileName+", contentType: "+contentType+", validation: "+validation); //Checking mandatory parameter storageId if (storageId == null || storageId.isEmpty()) { logger.warn("storageId not found"); try { throw new BadRequestException(httpRequest, Status.NOT_ACCEPTABLE, "Missing mandatory path parameter "+STORAGE_ID, StorageIDResolver.class, new URI(help)); } catch (URISyntaxException e) { //silent } } /* 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.info("Decoded ID"+" = "+ toSEID); }catch(Exception e){ logger.error("Storage Client Exception when getting file from storage: ", e); try { throw new InternalServerException(httpRequest, Status.INTERNAL_SERVER_ERROR, "Storage Client Exception when getting file from storage with id: "+storageId, StorageIDResolver.class, new URI(help)); } catch (URISyntaxException e1) { //silent } } if(toSEID==null || toSEID.isEmpty()){ logger.error("Decrypted id for storageId: "+storageId +" is null or empty!"); try { throw new WrongParameterException(httpRequest, Status.BAD_REQUEST, "Error on decrypting the "+STORAGE_ID+ " '"+storageId+"'. Is it a valid id?", StorageIDResolver.class, new URI(help)); } catch (URISyntaxException e) { //silent } } long size = iClient.getSize().RFileById(toSEID); try{ MyFile file = iClient.getMetaFile().RFile(toSEID); logger.debug("MetaFile retrieved from storage? "+ (file!=null)); //Reading the fileName from Storage Metadata only if the passed fileName is null if(fileName==null || fileName.isEmpty()) 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 * @return the response */ /*@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 static 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(StorageIDResolver.class.getName(), StorageIDResolver.class.getSimpleName(), STORAGEID_RESOLVER, AccessType.PUBLIC); else client=new StorageClient(StorageIDResolver.class.getName(), StorageIDResolver.class.getSimpleName(), STORAGEID_RESOLVER, AccessType.PUBLIC, memory); return client; } }