2018-10-12 16:20:46 +02:00
package org.gcube.datatransfer.resolver.services ;
import java.io.InputStream ;
2018-10-22 15:39:51 +02:00
import java.net.URI ;
import java.net.URISyntaxException ;
2018-10-12 16:20:46 +02:00
2018-10-22 12:56:04 +02:00
import javax.servlet.http.HttpServletRequest ;
2018-10-18 18:24:49 +02:00
import javax.ws.rs.GET ;
2018-10-12 16:20:46 +02:00
import javax.ws.rs.Path ;
import javax.ws.rs.PathParam ;
2018-10-19 11:40:52 +02:00
import javax.ws.rs.QueryParam ;
2018-10-22 12:56:04 +02:00
import javax.ws.rs.core.Context ;
2018-10-12 16:20:46 +02:00
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 ;
2018-10-19 17:55:31 +02:00
import org.gcube.contentmanager.storageclient.wrapper.MemoryType ;
2018-10-12 16:20:46 +02:00
import org.gcube.contentmanager.storageclient.wrapper.StorageClient ;
import org.gcube.datatransfer.resolver.SingleFileStreamingOutput ;
2018-10-22 12:56:04 +02:00
import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException ;
import org.gcube.datatransfer.resolver.services.exceptions.InternalServerException ;
import org.gcube.datatransfer.resolver.services.exceptions.WrongParameterException ;
2018-10-12 16:20:46 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2018-10-19 17:55:31 +02:00
/ * *
* The Class StorageManager .
*
* @author Francesco Mangiacrapa at ISTI - CNR ( francesco . mangiacrapa @isti.cnr.it )
* @author Lucio Lelii
*
* Oct 19 , 2018
* /
2018-10-18 18:24:49 +02:00
@Path ( " / " )
2018-10-12 16:20:46 +02:00
public class StorageManager {
2018-10-19 17:55:31 +02:00
/ * *
*
* /
protected static final String STORAGEID_RESOLVER = " storageid-resolver " ;
private static final String STORAGE_ID = " storage-id " ;
2018-10-12 16:20:46 +02:00
private static Logger logger = LoggerFactory . getLogger ( StorageManager . class ) ;
2018-10-19 11:40:52 +02:00
2018-10-22 15:39:51 +02:00
private static String help = " https://wiki.gcube-system.org/gcube/URI_Resolver#STORAGE-ID_Resolver " ;
2018-10-19 17:55:31 +02:00
/ * *
2018-10-22 12:56:04 +02:00
* Gets the storage id .
2018-10-19 17:55:31 +02:00
*
2018-10-22 12:56:04 +02:00
* @param httpRequest the http request
* @param storageId the storage id
2018-10-19 17:55:31 +02:00
* @param fileName the file name
* @param contentType the content type
* @param validation the validation
2018-10-22 12:56:04 +02:00
* @return the storage id
2018-10-19 17:55:31 +02:00
* /
@GET
2018-10-22 12:56:04 +02:00
@Path ( " {storage-id:(?!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 " ) ;
2018-10-22 15:39:51 +02:00
try {
throw new BadRequestException ( httpRequest , Status . NOT_ACCEPTABLE , " Missing mandatory path parameter " + STORAGE_ID , StorageManager . class , new URI ( help ) ) ;
}
catch ( URISyntaxException e ) {
//silent
}
2018-10-19 17:55:31 +02:00
}
2018-10-22 12:56:04 +02:00
return resolveStorageId ( httpRequest , storageId , fileName , contentType , validation ) ;
2018-10-19 17:55:31 +02:00
}
/ * *
2018-10-22 12:56:04 +02:00
* Resolve storage id .
2018-10-19 17:55:31 +02:00
*
2018-10-22 12:56:04 +02:00
* @param httpRequest the http request
2018-10-19 17:55:31 +02:00
* @param storageId the storage id
* @param fileName the file name
* @param contentType the content type
* @param validation the validation
2018-10-22 12:56:04 +02:00
* @return the response
2018-10-19 17:55:31 +02:00
* /
2018-10-22 12:56:04 +02:00
protected static Response resolveStorageId ( HttpServletRequest httpRequest , String storageId , String fileName , String contentType , Boolean validation ) {
2018-10-19 17:55:31 +02:00
logger . info ( " storage-id: " + storageId + " , fileName: " + fileName + " , contentType: " + contentType + " , validation: " + validation ) ;
2018-10-19 11:40:52 +02:00
2018-10-22 12:56:04 +02:00
//Checking mandatory parameter storageId
2018-10-19 11:40:52 +02:00
if ( storageId = = null | | storageId . isEmpty ( ) ) {
logger . warn ( " storageId not found " ) ;
2018-10-22 15:39:51 +02:00
try {
throw new BadRequestException ( httpRequest , Status . NOT_ACCEPTABLE , " Missing mandatory path parameter " + STORAGE_ID , StorageManager . class , new URI ( help ) ) ;
}
catch ( URISyntaxException e ) {
//silent
}
2018-10-19 11:40:52 +02:00
}
2018-10-19 18:11:19 +02:00
/ *
2018-10-19 17:55:31 +02:00
if ( validation ! = null & & validation )
return validationPayload ( storageId ) ;
2018-10-19 18:11:19 +02:00
* /
2018-10-19 11:40:52 +02:00
2018-10-19 17:55:31 +02:00
StorageClient client = getStorageClientInstance ( storageId ) ;
String toSEID = null ;
IClient iClient = null ;
try {
iClient = client . getClient ( ) ;
toSEID = iClient . getId ( storageId ) ; //to Storage Encrypted ID
2018-10-22 14:55:41 +02:00
logger . info ( " Decoded ID " + " = " + toSEID ) ;
2018-10-19 17:55:31 +02:00
} catch ( Exception e ) {
logger . error ( " Storage Client Exception when getting file from storage: " , e ) ;
2018-10-22 15:39:51 +02:00
try {
throw new InternalServerException ( httpRequest , Status . INTERNAL_SERVER_ERROR , " Storage Client Exception when getting file from storage with id: " + storageId , StorageManager . class , new URI ( help ) ) ;
}
catch ( URISyntaxException e1 ) {
//silent
}
2018-10-19 17:55:31 +02:00
}
2018-10-12 16:20:46 +02:00
2018-10-22 14:55:41 +02:00
if ( toSEID = = null | | toSEID . isEmpty ( ) ) {
logger . error ( " Decrypted id for storageId: " + storageId + " is null or empty! " ) ;
2018-10-22 15:39:51 +02:00
try {
throw new WrongParameterException ( httpRequest , Status . BAD_REQUEST , " Error on decrypting the " + STORAGE_ID + " ' " + storageId + " '. Is it a valid id? " , StorageManager . class , new URI ( help ) ) ;
}
catch ( URISyntaxException e ) {
//silent
}
2018-10-12 16:20:46 +02:00
}
2018-10-19 11:40:52 +02:00
2018-10-12 16:20:46 +02:00
long size = iClient . getSize ( ) . RFileById ( toSEID ) ;
2018-10-19 11:40:52 +02:00
2018-10-12 16:20:46 +02:00
try {
2018-10-19 11:40:52 +02:00
2018-10-19 17:55:31 +02:00
MyFile file = iClient . getMetaFile ( ) . RFile ( toSEID ) ;
2018-10-12 16:20:46 +02:00
logger . debug ( " MetaFile retrieved from storage? " + ( file ! = null ) ) ;
2018-10-19 18:11:19 +02:00
//Reading the fileName from Storage Metadata only if the passed fileName is null
if ( fileName = = null | | fileName . isEmpty ( ) )
fileName = file . getName ( ) ;
2018-10-19 11:40:52 +02:00
//Reading the contentType from Storage Metadata only if the passed contentType is null
2018-10-19 17:55:31 +02:00
if ( contentType = = null | | contentType . isEmpty ( ) )
2018-10-19 11:40:52 +02:00
contentType = file . getMimeType ( ) ;
2018-10-12 16:20:46 +02:00
} catch ( Exception e ) {
logger . warn ( " Error when getting file metadata from storage, printing this warning and trying to continue.. " , e ) ;
}
2018-10-19 11:40:52 +02:00
2018-10-19 17:55:31 +02:00
fileName = fileName = = null | | fileName . isEmpty ( ) ? ConstantsResolver . DEFAULT_FILENAME_FROM_STORAGE_MANAGER : fileName ;
2018-10-18 18:24:49 +02:00
logger . info ( " filename retrieved is {} " , fileName ) ;
2018-10-19 11:40:52 +02:00
2018-10-19 17:55:31 +02:00
contentType = contentType = = null | | contentType . isEmpty ( ) ? ConstantsResolver . DEFAULT_CONTENTTYPE_UNKNOWN_UNKNOWN : contentType ;
logger . info ( " contentType used is {} " , contentType ) ;
2018-10-19 11:40:52 +02:00
//Building the response
2018-10-12 16:20:46 +02:00
InputStream streamToWrite = iClient . get ( ) . RFileAsInputStream ( toSEID ) ; //input stream
StreamingOutput so = new SingleFileStreamingOutput ( streamToWrite ) ;
2018-10-19 17:55:31 +02:00
2018-10-12 16:20:46 +02:00
ResponseBuilder response = Response
. ok ( so )
2018-10-19 17:55:31 +02:00
. header ( ConstantsResolver . CONTENT_DISPOSITION , " attachment; filename = \" " + fileName + " \" " )
. header ( ConstantsResolver . CONTENT_LENGTH , size ) ;
2018-10-12 16:20:46 +02:00
if ( contentType ! = null ) response . header ( " Content-Type " , contentType ) ;
return response . build ( ) ;
2018-10-22 12:56:04 +02:00
2018-10-12 16:20:46 +02:00
}
2018-10-19 11:40:52 +02:00
2018-10-19 17:55:31 +02:00
/ * *
* Http do head .
*
* @param storageId the storage id
* @return the response
* /
2018-10-19 18:11:19 +02:00
/ * @HEAD
2018-10-19 17:55:31 +02:00
@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 ) ;
2018-10-19 18:11:19 +02:00
} * /
2018-10-19 17:55:31 +02:00
/ * *
* Validation payload .
*
* @param storageId the storage id
* @return the response
* /
2018-10-19 18:11:19 +02:00
/ * protected Response validationPayload ( String storageId ) {
2018-10-19 17:55:31 +02:00
//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 ) ;
}
2018-10-19 18:11:19 +02:00
} * /
2018-10-19 17:55:31 +02:00
/ * *
* Gets the storage client instance .
*
* @param storageId the storage id
* @return the storage client instance
* /
2018-10-22 12:56:04 +02:00
protected static StorageClient getStorageClientInstance ( String storageId ) {
2018-10-19 17:55:31 +02:00
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 ;
}
2018-10-12 16:20:46 +02:00
}