2018-10-12 16:20:46 +02:00
package org.gcube.datatransfer.resolver.services ;
2018-10-23 11:27:04 +02:00
import java.io.IOException ;
2018-10-12 16:20:46 +02:00
import java.io.InputStream ;
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-23 11:27:04 +02:00
import javax.ws.rs.HEAD ;
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-12-14 14:26:37 +01:00
import javax.ws.rs.WebApplicationException ;
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.StreamingOutput ;
2018-10-23 11:27:04 +02:00
import org.apache.commons.io.IOUtils ;
import org.apache.http.HttpStatus ;
2018-10-12 16:20:46 +02:00
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 ;
2018-11-15 16:21:31 +01:00
import org.gcube.datatransfer.resolver.ConstantsResolver ;
2018-10-23 11:27:04 +02:00
import org.gcube.datatransfer.resolver.services.error.ExceptionManager ;
2019-04-02 15:19:52 +02:00
import org.gcube.datatransfer.resolver.storage.StorageClientInstance ;
2018-11-15 15:35:54 +01:00
import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput ;
2018-10-12 16:20:46 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2018-10-19 17:55:31 +02:00
2018-12-14 14:26:37 +01:00
2018-10-19 17:55:31 +02:00
/ * *
2018-12-14 14:26:37 +01:00
* The Class StorageIDResolver .
2018-10-19 17:55:31 +02:00
*
* @author Francesco Mangiacrapa at ISTI - CNR ( francesco . mangiacrapa @isti.cnr.it )
2018-12-14 14:26:37 +01:00
* Dec 14 , 2018
2018-10-19 17:55:31 +02:00
* /
2018-12-05 16:58:44 +01:00
@Path ( " storage " )
2018-10-22 15:49:19 +02:00
public class StorageIDResolver {
2018-10-12 16:20:46 +02:00
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-22 15:49:19 +02:00
private static Logger logger = LoggerFactory . getLogger ( StorageIDResolver . 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-12-14 14:26:37 +01:00
* @param req the req
2018-10-22 12:56:04 +02:00
* @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-12-14 14:26:37 +01:00
* @throws WebApplicationException the web application exception
2018-10-19 17:55:31 +02:00
* /
@GET
2019-02-19 15:18:19 +01:00
@Path ( " /{storage-id} " )
2018-12-14 14:26:37 +01:00
public Response getStorageId ( @Context HttpServletRequest req ,
@PathParam ( STORAGE_ID ) String storageId ,
@QueryParam ( ConstantsResolver . QUERY_PARAM_FILE_NAME ) String fileName ,
@QueryParam ( ConstantsResolver . QUERY_PARAM_CONTENT_TYPE ) String contentType ,
@QueryParam ( ConstantsResolver . QUERY_PARAM_VALIDATION ) Boolean validation ) throws WebApplicationException {
2018-10-23 15:02:50 +02:00
logger . info ( this . getClass ( ) . getSimpleName ( ) + " GET starts... " ) ;
2018-12-14 14:26:37 +01:00
try {
if ( storageId = = null | | storageId . isEmpty ( ) ) {
logger . error ( STORAGE_ID + " not found " ) ;
throw ExceptionManager . badRequestException ( req , " Missing mandatory path parameter " + STORAGE_ID , StorageIDResolver . class , help ) ;
}
return resolveStorageId ( req , storageId , fileName , contentType , validation ) ;
} catch ( Exception e ) {
if ( ! ( e instanceof WebApplicationException ) ) {
//UNEXPECTED EXCEPTION managing it as WebApplicationException
String error = " Error occurred on resolving the Storage ID: " + storageId + " . Please, contact the support! " ;
if ( e . getCause ( ) ! = null )
error + = " \ n \ nCaused: " + e . getCause ( ) . getMessage ( ) ;
throw ExceptionManager . internalErrorException ( req , error , this . getClass ( ) , help ) ;
}
//ALREADY MANAGED AS WebApplicationException
logger . error ( " Exception: " , e ) ;
throw ( WebApplicationException ) e ;
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-12-14 14:26:37 +01:00
* @throws Exception the exception
2018-10-19 17:55:31 +02:00
* /
2018-12-14 14:26:37 +01:00
protected static Response resolveStorageId ( HttpServletRequest httpRequest , String storageId , String fileName , String contentType , Boolean validation ) throws Exception {
2018-10-22 12:56:04 +02:00
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 ( ) ) {
2018-10-23 11:27:04 +02:00
logger . error ( " storageId not found " ) ;
2018-12-14 14:26:37 +01:00
throw ExceptionManager . badRequestException ( httpRequest , " Missing mandatory path parameter " + STORAGE_ID , StorageIDResolver . class , help ) ;
2018-10-19 11:40:52 +02:00
}
2019-04-02 15:19:52 +02:00
StorageClientInstance scInstance = buildStorageClientInstance ( storageId ) ;
2018-10-19 17:55:31 +02:00
String toSEID = null ;
IClient iClient = null ;
2019-04-02 15:19:52 +02:00
storageId = scInstance . getStorageId ( ) ; //IT SHOULD BE CHANGED es. removing the suffix '-VLT'
logger . info ( " I'm using the storageId {} " , storageId ) ;
2018-10-19 17:55:31 +02:00
try {
2019-04-02 15:19:52 +02:00
iClient = scInstance . getStorageClient ( ) . getClient ( ) ;
2018-10-19 17:55:31 +02:00
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-12-14 14:26:37 +01:00
throw ExceptionManager . notFoundException ( httpRequest , " Storage Client Exception when getting file from storage with id: " + storageId , StorageIDResolver . class , help ) ;
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-12-14 14:26:37 +01:00
throw ExceptionManager . notFoundException ( httpRequest , " Error on decrypting the " + STORAGE_ID + " ' " + storageId + " '. Is it a valid id? " , StorageIDResolver . class , help ) ;
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 ( ) )
2019-04-02 15:19:52 +02:00
contentType = file . getMimeType ( )
/ * *
* Gets the storage client instance .
*
* @param storageId the storage id
* @return the storage client instance
* @throws Exception the exception
* / ;
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 )
2019-01-09 15:40:51 +01:00
. header ( ConstantsResolver . CONTENT_DISPOSITION , " attachment; filename= \" " + fileName + " \" " )
2018-10-19 17:55:31 +02:00
. header ( ConstantsResolver . CONTENT_LENGTH , size ) ;
2018-12-14 14:26:37 +01:00
if ( contentType ! = null )
response . header ( " Content-Type " , contentType ) ;
2018-10-12 16:20:46 +02:00
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 .
*
2018-12-14 14:26:37 +01:00
* @param req the http request
2018-10-19 17:55:31 +02:00
* @param storageId the storage id
2018-10-23 11:27:04 +02:00
* @param hproxycheck the hproxycheck
2018-10-19 17:55:31 +02:00
* @return the response
2018-12-14 14:26:37 +01:00
* @throws WebApplicationException the web application exception
2018-10-19 17:55:31 +02:00
* /
2018-10-23 11:27:04 +02:00
@HEAD
2019-02-19 15:18:19 +01:00
@Path ( " /{storage-id} " )
2018-12-14 14:26:37 +01:00
public Response httpDoHead ( @Context HttpServletRequest req ,
@PathParam ( STORAGE_ID ) String storageId ,
@QueryParam ( ConstantsResolver . HPC ) Boolean hproxycheck ) throws WebApplicationException {
2018-10-23 15:02:50 +02:00
logger . info ( this . getClass ( ) . getSimpleName ( ) + " HEAD starts... " ) ;
2018-10-19 17:55:31 +02:00
2018-12-14 14:26:37 +01:00
try {
//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 ( ) ;
}
2018-10-19 17:55:31 +02:00
2018-12-14 14:26:37 +01:00
return validationPayload ( req , storageId ) ;
} catch ( Exception e ) {
2018-10-23 11:27:04 +02:00
2018-12-14 14:26:37 +01:00
if ( ! ( e instanceof WebApplicationException ) ) {
//UNEXPECTED EXCEPTION managing it as WebApplicationException
String error = " Error occurred on resolving the Storage ID: " + storageId + " . Please, contact the support! " ;
if ( e . getCause ( ) ! = null )
error + = " \ n \ nCaused: " + e . getCause ( ) . getMessage ( ) ;
throw ExceptionManager . internalErrorException ( req , error , this . getClass ( ) , help ) ;
}
//ALREADY MANAGED AS WebApplicationException
logger . error ( " Exception: " , e ) ;
throw ( WebApplicationException ) e ;
}
}
2018-10-19 17:55:31 +02:00
/ * *
* Validation payload .
*
2018-10-23 11:27:04 +02:00
* @param httpRequest the http request
2018-10-19 17:55:31 +02:00
* @param storageId the storage id
* @return the response
2018-12-14 14:26:37 +01:00
* @throws Exception the exception
2018-10-19 17:55:31 +02:00
* /
2018-12-14 14:26:37 +01:00
protected Response validationPayload ( HttpServletRequest httpRequest , String storageId ) throws Exception {
2018-10-19 17:55:31 +02:00
2018-10-23 11:27:04 +02:00
//Checking mandatory parameter storageId
2018-10-19 17:55:31 +02:00
if ( storageId = = null | | storageId . isEmpty ( ) ) {
logger . warn ( " storageId not found " ) ;
2018-12-14 14:26:37 +01:00
throw ExceptionManager . badRequestException ( httpRequest , " Storage Client Exception when getting file from storage with id: " + storageId , this . getClass ( ) , help ) ;
2018-10-19 17:55:31 +02:00
}
2019-04-02 15:19:52 +02:00
StorageClientInstance client = buildStorageClientInstance ( storageId ) ;
2018-10-19 17:55:31 +02:00
String toSEID = null ;
IClient iClient = null ;
2019-04-02 15:19:52 +02:00
storageId = client . getStorageId ( ) ; //IT SHOULD BE CHANGED es. removing the suffix '-VLT'
logger . info ( " I'm using the storageId {} " , storageId ) ;
2018-10-19 17:55:31 +02:00
try {
2019-04-02 15:19:52 +02:00
iClient = client . getStorageClient ( ) . getClient ( ) ;
2018-10-19 17:55:31 +02:00
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 ) ;
2018-12-14 14:26:37 +01:00
throw ExceptionManager . internalErrorException ( httpRequest , " Storage Client Exception when getting file from storage with id: " + storageId , StorageIDResolver . class , help ) ;
2018-10-19 17:55:31 +02:00
}
2018-10-23 11:27:04 +02:00
if ( toSEID = = null | | toSEID . isEmpty ( ) ) {
logger . error ( " Decrypted id for storageId: " + storageId + " is null or empty! " ) ;
2018-12-14 14:26:37 +01:00
throw ExceptionManager . notFoundException ( httpRequest , " Error on decrypting the " + STORAGE_ID + " ' " + storageId + " '. Is it a valid id? " , StorageIDResolver . class , help ) ;
2018-10-19 17:55:31 +02:00
}
2018-10-23 11:27:04 +02:00
2018-10-19 17:55:31 +02:00
//Building the response
InputStream streamToWrite = iClient . get ( ) . RFileAsInputStream ( toSEID ) ; //input stream
byte [ ] bytes = new byte [ 1 ] ; //1B
int c ;
2018-10-23 11:27:04 +02:00
ResponseBuilder response = null ;
2018-10-19 17:55:31 +02:00
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 ) ;
2018-10-23 11:27:04 +02:00
response = Response . status ( HttpStatus . SC_OK ) ;
2018-10-19 17:55:31 +02:00
} else
2018-12-14 14:26:37 +01:00
throw ExceptionManager . notFoundException ( httpRequest , " The file with id: " + storageId + " is missing in the storage " , StorageIDResolver . class , help ) ;
2018-10-19 17:55:31 +02:00
}
2018-10-23 11:27:04 +02:00
catch ( IOException e2 ) {
logger . error ( " Error on validating the file: " , e2 ) ;
2018-12-14 14:26:37 +01:00
throw ExceptionManager . internalErrorException ( httpRequest , " Error on validating the file with id: " + storageId , StorageIDResolver . class , help ) ;
2018-10-19 17:55:31 +02:00
}
2018-10-23 11:27:04 +02:00
if ( response = = null )
2018-12-14 14:26:37 +01:00
throw ExceptionManager . internalErrorException ( httpRequest , " Error on validating the file with id: " + storageId , StorageIDResolver . class , help ) ;
2018-10-23 11:27:04 +02:00
return response . build ( ) ;
}
2018-10-19 17:55:31 +02:00
2019-04-02 15:19:52 +02:00
2018-10-19 17:55:31 +02:00
/ * *
2019-04-02 15:19:52 +02:00
* Builds the storage client instance .
2018-10-19 17:55:31 +02:00
*
* @param storageId the storage id
* @return the storage client instance
2018-12-14 14:26:37 +01:00
* @throws Exception the exception
2018-10-19 17:55:31 +02:00
* /
2019-04-02 15:19:52 +02:00
protected static StorageClientInstance buildStorageClientInstance ( String storageId ) throws Exception {
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 )
2018-10-22 15:49:19 +02:00
client = new StorageClient ( StorageIDResolver . class . getName ( ) , StorageIDResolver . class . getSimpleName ( ) , STORAGEID_RESOLVER , AccessType . PUBLIC ) ;
2018-10-19 17:55:31 +02:00
else
2018-10-22 15:49:19 +02:00
client = new StorageClient ( StorageIDResolver . class . getName ( ) , StorageIDResolver . class . getSimpleName ( ) , STORAGEID_RESOLVER , AccessType . PUBLIC , memory ) ;
2018-10-19 17:55:31 +02:00
2019-04-02 15:19:52 +02:00
return new StorageClientInstance ( client , memory , storageId ) ;
2018-10-19 17:55:31 +02:00
}
2018-10-23 11:27:04 +02:00
2018-10-12 16:20:46 +02:00
}