/** * */ 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; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; 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; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; 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; import org.gcube.datatransfer.resolver.requesthandler.TokenSetter; 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 { /** * */ private static final String DATAMINER_INVOCATION_MODEL = "dim"; /** * */ private static final String UTF_8 = "UTF-8"; private static Logger logger = LoggerFactory.getLogger(AnalyticsCreateResolver.class); private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#Analitycs_Resolver"; /** * 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()); //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(); String scope = ScopeProvider.instance.get(); 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); } 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 listParam = new ArrayList(); Map 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); tempInvocationFile = createTempFile("dataminer-invocation"+UUID.randomUUID(), ".xml", xmlByteArray.toByteArray()); //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 if(tempInvocationFile!=null && tempInvocationFile.exists()) tempInvocationFile.delete(); } String dataMinerURL = String.format("%s/%s?%s=%s", dataminerResolverURL, vreName, DATAMINER_INVOCATION_MODEL, URLEncoder.encode(publicLinkToDMInvFile, UTF_8)); 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; } /** * 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; } }