2018-12-05 16:58:44 +01:00
/ * *
*
* /
package org.gcube.datatransfer.resolver.services ;
import java.io.ByteArrayOutputStream ;
import java.io.File ;
import java.io.IOException ;
import java.io.UnsupportedEncodingException ;
import java.net.URLEncoder ;
import java.nio.file.Files ;
2018-12-07 11:28:37 +01:00
import java.text.SimpleDateFormat ;
2018-12-05 16:58:44 +01:00
import java.util.ArrayList ;
2018-12-07 11:28:37 +01:00
import java.util.Date ;
2018-12-05 16:58:44 +01:00
import java.util.List ;
import java.util.Map ;
import javax.servlet.http.HttpServletRequest ;
import javax.ws.rs.Consumes ;
import javax.ws.rs.POST ;
import javax.ws.rs.Path ;
import javax.ws.rs.Produces ;
import javax.ws.rs.core.Context ;
import javax.ws.rs.core.MediaType ;
import javax.ws.rs.core.Response ;
import javax.xml.bind.JAXBException ;
2018-12-07 10:41:18 +01:00
import org.gcube.common.authorization.library.provider.SecurityTokenProvider ;
2018-12-05 16:58:44 +01:00
import org.gcube.common.scope.api.ScopeProvider ;
import org.gcube.common.scope.impl.ScopeBean ;
import org.gcube.common.scope.impl.ScopeBean.Type ;
import org.gcube.data.analysis.dminvocation.ActionType ;
import org.gcube.data.analysis.dminvocation.DataMinerInvocationManager ;
import org.gcube.data.analysis.dminvocation.model.DataMinerInputParams ;
import org.gcube.data.analysis.dminvocation.model.DataMinerInvocation ;
import org.gcube.data.analysis.dminvocation.model.DataMinerParam ;
import org.gcube.data.analysis.dminvocation.model.DataMinerParameters ;
import org.gcube.datatransfer.resolver.dataminer.DataMinerRequest ;
2018-12-07 10:41:18 +01:00
import org.gcube.datatransfer.resolver.requesthandler.TokenSetter ;
2018-12-05 16:58:44 +01:00
import org.gcube.datatransfer.resolver.services.error.ExceptionManager ;
import org.gcube.datatransfer.resolver.util.Util ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
/ * *
* The Class DataMinerResolver .
*
* @author Francesco Mangiacrapa francesco . mangiacrapa @isti.cnr.it
* Nov 28 , 2018
* /
@Path ( " /analytics " )
public class AnalyticsCreateResolver {
2018-12-07 10:41:18 +01:00
/ * *
2018-12-07 11:28:37 +01:00
*
2018-12-07 10:41:18 +01:00
* /
private static final String DATAMINER_INVOCATION_MODEL = " dim " ;
2018-12-05 16:58:44 +01:00
/ * *
*
* /
private static final String UTF_8 = " UTF-8 " ;
private static Logger logger = LoggerFactory . getLogger ( AnalyticsCreateResolver . class ) ;
2018-12-07 10:41:18 +01:00
private static String helpURI = " https://wiki.gcube-system.org/gcube/URI_Resolver#Analitycs_Resolver " ;
2018-12-05 16:58:44 +01:00
2018-12-07 12:39:02 +01:00
private static SimpleDateFormat dateFormat = new SimpleDateFormat ( " yyyy-MM-dd_HH:mm:ss.SSS " ) ;
2018-12-07 11:28:37 +01:00
2018-12-05 16:58:44 +01:00
/ * *
* Post catalogue .
*
* @param req the req
* @param jsonRequest the json request
* @return the response
* /
@POST
@Path ( " /create " )
@Consumes ( MediaType . APPLICATION_JSON )
@Produces ( MediaType . TEXT_PLAIN )
public Response postCatalogue ( @Context HttpServletRequest req , DataMinerRequest jsonRequest ) {
logger . info ( this . getClass ( ) . getSimpleName ( ) + " POST starts... " ) ;
logger . info ( " The body contains the request: " + jsonRequest . toString ( ) ) ;
2018-12-07 10:41:18 +01:00
//SIMULATING SMART GEAR BEHAVIOUR - VALIDATING TOKEN
/ * String contextToken = req . getParameter ( " gcube-token " ) ;
if ( contextToken = = null | | contextToken . isEmpty ( ) ) {
contextToken = req . getHeader ( " gcube-token " ) ;
logger . info ( " Read context token from HTTP header... " ) ;
}
if ( contextToken = = null | | contextToken . isEmpty ( ) ) {
logger . error ( " Context Token not passed " ) ;
ExceptionManager . throwUnauthorizedException ( req , " You are not authorized. You must pass a gcube-token of VRE " , this . getClass ( ) , helpURI ) ;
}
String scope = " " ;
try {
AuthorizationEntry entry = authorizationService ( ) . get ( contextToken ) ;
scope = entry . getContext ( ) ;
}
catch ( Exception e1 ) {
logger . error ( " Unresolved token: " + contextToken , e1 ) ;
ExceptionManager . throwUnauthorizedException ( req , " Your token " + contextToken + " seems not valid, it is unscoped. Have you passed a valid token of VRE? " , this . getClass ( ) , helpURI ) ;
}
String appToken = req . getServletContext ( ) . getInitParameter ( TokenSetter . ROOT_APP_TOKEN ) ;
if ( contextToken . compareTo ( appToken ) = = 0 ) {
logger . error ( " Token not passed, SecurityTokenProvider contains the root app token: " + appToken . substring ( 0 , 10 ) + " ... " ) ;
ExceptionManager . throwUnauthorizedException ( req , " You are not authorized. You must pass a token of VRE " , this . getClass ( ) , helpURI ) ;
}
//TOKEN AND SCOPE SHOULD BE VALID SETTINGS THEM
SecurityTokenProvider . instance . set ( contextToken ) ;
ScopeProvider . instance . set ( scope ) ;
//END SIMULATING SMART GEAR BEHAVIOUR - VALIDATING TOKEN
* /
String contextToken = SecurityTokenProvider . instance . get ( ) ;
2018-12-05 16:58:44 +01:00
String scope = ScopeProvider . instance . get ( ) ;
2018-12-07 10:41:18 +01:00
logger . info ( " SecurityTokenProvider contextToken: " + contextToken ) ;
logger . info ( " ScopeProvider scope: " + scope ) ;
String appToken = req . getServletContext ( ) . getInitParameter ( TokenSetter . ROOT_APP_TOKEN ) ;
if ( contextToken . compareTo ( appToken ) = = 0 ) {
logger . error ( " Token not passed, SecurityTokenProvider contains the root app token: " + appToken . substring ( 0 , 10 ) + " ... " ) ;
ExceptionManager . throwUnauthorizedException ( req , " You are not authorized. You must pass a token of VRE " , this . getClass ( ) , helpURI ) ;
}
2018-12-05 16:58:44 +01:00
String operatorID = jsonRequest . getOperatorId ( ) ;
if ( scope = = null | | scope . isEmpty ( ) ) {
logger . error ( " The parameter 'scope' not found or empty in the JSON object " ) ;
ExceptionManager . throwBadRequestException ( req , " Mandatory body parameter 'scope' not found or empty in the JSON object " , this . getClass ( ) , helpURI ) ;
}
if ( operatorID = = null | | operatorID . isEmpty ( ) ) {
logger . error ( " The parameter 'operatorId' not found or empty in the JSON object " ) ;
ExceptionManager . throwBadRequestException ( req , " Mandatory body parameter 'operatorId' not found or empty in the JSON object " , this . getClass ( ) , helpURI ) ;
}
ScopeBean scopeBean = new ScopeBean ( scope ) ;
String publicLinkToDMInvFile = " " ;
if ( scopeBean . is ( Type . VRE ) ) {
String vreName = scopeBean . name ( ) ;
try {
String dataminerResolverURL = String . format ( " %s/%s " , Util . getServerURL ( req ) , " dataminer/get " ) ;
//Creating DM invocation file
DataMinerInvocation dmInvocation = new DataMinerInvocation ( ) ;
dmInvocation . setOperatorId ( operatorID ) ;
dmInvocation . setActionType ( ActionType . RUN ) ;
DataMinerInputParams inputParams = new DataMinerInputParams ( ) ;
List < DataMinerParam > listParam = new ArrayList < DataMinerParam > ( ) ;
Map < String , String > parameters = jsonRequest . getParameters ( ) ;
for ( String param : parameters . keySet ( ) ) {
listParam . add ( new DataMinerParam ( param , parameters . get ( param ) ) ) ;
}
inputParams . setListParam ( listParam ) ;
dmInvocation . setParameters ( new DataMinerParameters ( inputParams , null ) ) ;
File tempInvocationFile = null ;
try {
ByteArrayOutputStream xmlByteArray = DataMinerInvocationManager . marshaling ( dmInvocation , org . gcube . data . analysis . dminvocation . MediaType . ApplicationXML ) ;
2018-12-07 11:28:37 +01:00
String uniqueName = createDMInvocationFileName ( jsonRequest . getOperatorId ( ) ) ;
tempInvocationFile = createTempFile ( uniqueName , " .xml " , xmlByteArray . toByteArray ( ) ) ;
2018-12-05 16:58:44 +01:00
//CREATE THE FILE ON STORAGE HUB
}
catch ( IOException | JAXBException e ) {
logger . error ( " Error on creating you request with " + dmInvocation + " " , e ) ;
ExceptionManager . throwBadRequestException ( req , " Error on creating you request with " + dmInvocation , this . getClass ( ) , helpURI ) ;
} finally {
//DELETING THE TEMP FILE
2018-12-07 10:41:18 +01:00
if ( tempInvocationFile ! = null & & tempInvocationFile . exists ( ) )
tempInvocationFile . delete ( ) ;
2018-12-05 16:58:44 +01:00
}
2018-12-07 10:41:18 +01:00
String dataMinerURL = String . format ( " %s/%s?%s=%s " , dataminerResolverURL , vreName , DATAMINER_INVOCATION_MODEL , URLEncoder . encode ( publicLinkToDMInvFile , UTF_8 ) ) ;
2018-12-05 16:58:44 +01:00
logger . info ( " Returning Analytics URL: " + dataMinerURL ) ;
return Response . ok ( dataMinerURL ) . header ( " Location " , dataMinerURL ) . build ( ) ;
}
catch ( UnsupportedEncodingException e ) {
logger . error ( " Encoding error for " + publicLinkToDMInvFile + " " , e ) ;
ExceptionManager . throwBadRequestException ( req , " Error on encoding the public link " + publicLinkToDMInvFile , this . getClass ( ) , helpURI ) ;
}
return null ;
} else {
logger . error ( " The input scope " + scope + " is not a VRE " ) ;
ExceptionManager . throwBadRequestException ( req , " Working in the " + scope + " scope that is not a VRE. Use a token of VRE " , this . getClass ( ) , helpURI ) ;
}
return null ;
}
2018-12-07 11:28:37 +01:00
2018-12-05 16:58:44 +01:00
/ * *
* Creates the temp file .
*
* @param fileName the file name
* @param extension the extension
* @param data the data
* @return the file
* @throws IOException Signals that an I / O exception has occurred .
* /
private static File createTempFile ( String fileName , String extension , byte [ ] data ) throws IOException {
// Since Java 1.7 Files and Path API simplify operations on files
java . nio . file . Path path = Files . createTempFile ( fileName , extension ) ;
File file = path . toFile ( ) ;
// writing sample data
Files . write ( path , data ) ;
logger . info ( " Created the temfile: " + file . getAbsolutePath ( ) ) ;
return file ;
}
2018-12-07 11:28:37 +01:00
/ * *
* Creates the dm invocation file name .
*
* @param operatorId the operator id
* @return the string
* /
private static String createDMInvocationFileName ( String operatorId ) {
String fileName = " dim " ;
int index = operatorId . lastIndexOf ( " . " ) ;
if ( index > 0 & & index < operatorId . length ( ) ) {
fileName + = " - " + operatorId . substring ( index + 1 , operatorId . length ( ) ) ;
}
String currentTimestamp = dateFormat . format ( new Date ( ) ) ;
fileName + = " - " + currentTimestamp ;
return fileName ;
}
2018-12-05 16:58:44 +01:00
}