You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
uri-resolver/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java

239 lines
10 KiB
Java

package org.gcube.datatransfer.resolver.services;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
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.datatransfer.resolver.ConstantsResolver;
import org.gcube.datatransfer.resolver.caches.LoadingMapOfScopeCache;
import org.gcube.datatransfer.resolver.catalogue.CatalogueRequest;
import org.gcube.datatransfer.resolver.catalogue.ItemCatalogueURLs;
import org.gcube.datatransfer.resolver.catalogue.ResourceCatalogueCodes;
import org.gcube.datatransfer.resolver.catalogue.resource.CkanCatalogueConfigurationsReader;
import org.gcube.datatransfer.resolver.catalogue.resource.GatewayCKANCatalogueReference;
import org.gcube.datatransfer.resolver.catalogue.resource.GetAllInfrastructureScopes;
import org.gcube.datatransfer.resolver.services.error.ExceptionManager;
import org.gcube.datatransfer.resolver.util.Util;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import eu.trentorise.opendata.jackan.model.CkanDataset;
/**
* The Class CatalogueResolver.
*
* @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it)
* Nov 16, 2018
*/
@Path("{entityContext:ctlg(-(o|g|p|d))?}")
public class CatalogueResolver {
private static Logger logger = LoggerFactory.getLogger(CatalogueResolver.class);
private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#CATALOGUE_Resolver";
/**
* Resolve catalogue.
*
* @param req the req
* @param entityName the entity name
* @param vreName the vre name
* @param entityContext the entity context
* @return the response
*/
@GET
@Path("/{vreName}/{entityName}")
public Response resolveCatalogue(@Context HttpServletRequest req,
@PathParam("entityName") String entityName,
@PathParam("vreName") String vreName,
@PathParam("entityContext") String entityContext) throws WebApplicationException{
logger.info(this.getClass().getSimpleName()+" GET starts...");
try {
InnerMethodName.instance.set("resolveCataloguePublicLink");
ItemCatalogueURLs itemCatalogueURLs = getItemCatalogueURLs(req, vreName, entityContext, entityName);
String itemCatalogueURL;
if(itemCatalogueURLs.isPublicItem()){
logger.info("The dataset "+itemCatalogueURLs.getItemName()+" should be a public item (not private to VRE).");
if(itemCatalogueURLs.getPublicVRECataloguePortletURL()!=null && !itemCatalogueURLs.getPublicVRECataloguePortletURL().isEmpty()) {
itemCatalogueURL = itemCatalogueURLs.getPublicVRECataloguePortletURL();
logger.info("I found the public VRE catalogue URL, so using public access to it: "+itemCatalogueURL);
}else {
itemCatalogueURL = itemCatalogueURLs.getPublicGatewayCataloguePortletURL();
logger.info("No public VRE catalogue URL found, so using public access to gateway CKAN portlet: "+itemCatalogueURL);
}
}else{
itemCatalogueURL = itemCatalogueURLs.getPrivateVRECataloguePortletURL();
logger.info("The dataset "+itemCatalogueURLs.getItemName()+" is a private item (to VRE) so using protected access to CKAN portlet: "+itemCatalogueURL);
}
return Response.seeOther(new URL(itemCatalogueURL).toURI()).build();
}catch (Exception e) {
if(!(e instanceof WebApplicationException)){
//UNEXPECTED EXCEPTION managing it as WebApplicationException
String error = "Error occurred on resolving the Catalgoue URL. Please, contact the support!";
if(e.getCause()!=null)
error+="\n\nCaused: "+e.getCause().getMessage();
throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI);
}
//ALREADY MANAGED AS WebApplicationException
logger.error("Exception:", e);
throw (WebApplicationException) e;
}
}
/**
* Post catalogue.
*
* @param req the req
* @param jsonRequest the json request
* @return the response
*/
@POST
@Path("")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public Response postCatalogue(@Context HttpServletRequest req, CatalogueRequest jsonRequest) throws WebApplicationException{
logger.info(this.getClass().getSimpleName()+" POST starts...");
try{
InnerMethodName.instance.set("postCataloguePublicLink");
logger.info("The body contains the request: "+jsonRequest.toString());
//CHECK IF INPUT SCOPE IS VALID
String scope = jsonRequest.getGcube_scope();
if(!scope.startsWith(ConstantsResolver.SCOPE_SEPARATOR)){
logger.info("Scope not start with char '{}' adding it",ConstantsResolver.SCOPE_SEPARATOR);
scope+=ConstantsResolver.SCOPE_SEPARATOR+scope;
}
String serverUrl = Util.getServerURL(req);
final String vreName = scope.substring(scope.lastIndexOf(ConstantsResolver.SCOPE_SEPARATOR)+1, scope.length());
ScopeBean fullScope = null;
//CHECK IF THE vreName has a valid scope, so it is a valid VRE
try {
fullScope = LoadingMapOfScopeCache.get(vreName);
}catch(ExecutionException e){
logger.error("Error on getting the fullscope from cache for vreName "+vreName, e);
throw ExceptionManager.wrongParameterException(req, "Error on getting full scope for the VRE name "+vreName+". Is it registered as VRE in the D4Science Infrastructure System?", this.getClass(), helpURI);
}
if(fullScope==null)
throw ExceptionManager.notFoundException(req, "The scope '"+scope+"' does not matching any scope in the infrastructure. Is it valid?", this.getClass(), helpURI);
ResourceCatalogueCodes rc = ResourceCatalogueCodes.valueOfCodeValue(jsonRequest.getEntity_context());
if(rc==null){
logger.error("Entity context is null/malformed");
throw ExceptionManager.badRequestException(req, "Entity context is null/malformed", this.getClass(), helpURI);
}
String linkURL = String.format("%s/%s/%s/%s", serverUrl, rc.getId(), vreName, jsonRequest.getEntity_name());
logger.info("Returining Catalogue URL: "+linkURL);
return Response.ok(linkURL).header("Location", linkURL).build();
}catch (Exception e) {
if(!(e instanceof WebApplicationException)){
//UNEXPECTED EXCEPTION managing it as WebApplicationException
String error = "Error occurred on resolving the Analytics URL. Please, contact the support!";
throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI);
}
//ALREADY MANAGED AS WebApplicationExceptiongetItemCatalogueURLs
logger.error("Exception:", e);
throw (WebApplicationException) e;
}
}
/**
* Gets the item catalogue UR ls.
*
* @param req the req
* @param scopeName the scope name
* @param entityContext the entity context
* @param entityName the entity name
* @return the item catalogue UR ls
* @throws Exception the exception
*/
protected static ItemCatalogueURLs getItemCatalogueURLs(HttpServletRequest req, String scopeName, String entityContext, String entityName) throws Exception{
try {
String entityContextValue = ResourceCatalogueCodes.valueOfCodeId(entityContext).getValue();
ScopeBean scopeBean = null;
try{
scopeBean = LoadingMapOfScopeCache.get(scopeName);
}catch(ExecutionException | InvalidCacheLoadException e){
logger.error("Error on getting the fullscope from cache for scopeName "+scopeName, e);
throw ExceptionManager.wrongParameterException(req, "Error on getting full scope for the scope name '"+scopeName+"'. Is it registered as a valid Scope in the D4Science Infrastructure System?", CatalogueResolver.class, helpURI);
}
String fullScope = scopeBean.toString();
logger.info("Read fullScope: "+fullScope + " for SCOPE name: "+scopeName +" from cache created by: "+GetAllInfrastructureScopes.class.getSimpleName());
if(scopeBean.is(Type.VO)) {
logger.info("It is a {} scope", Type.VO);
logger.warn("The Catalogue can't work at {} level, I'm overriding the scope to {} level", Type.VO, Type.INFRASTRUCTURE);
String[] splitScope = fullScope.split(ConstantsResolver.SCOPE_SEPARATOR);
fullScope = ConstantsResolver.SCOPE_SEPARATOR+splitScope[1]; //THIS IS THE INFRASTRUCTURE SCOPE
logger.info("Overriden the input scope {} with {} as type: {}", scopeBean.toString(), Type.INFRASTRUCTURE, fullScope);
}
ScopeProvider.instance.set(fullScope);
GatewayCKANCatalogueReference ckanCatalogueReference = CkanCatalogueConfigurationsReader.loadCatalogueEndPoints();
logger.info("For scope "+fullScope+" loaded end points: "+ckanCatalogueReference);
//IS THE PRODUCT PLUBLIC OR PRIVATE?
String datasetName = entityName;
boolean isPublicItem = false;
if(ckanCatalogueReference.getCkanURL()!=null){
try{
CkanDataset dataset = CkanCatalogueConfigurationsReader.getDataset(datasetName, ckanCatalogueReference.getCkanURL());
if(dataset!=null){
isPublicItem = true;
//ckanPorltetUrl = ckanCatalogueReference.getPublicPortletURL();
logger.info("The dataset "+datasetName+" is a public item");
}
}catch(Exception e){
logger.warn("Error on checking if dataset: "+datasetName+" is private or not", e);
isPublicItem = true;
}
}
String publicGatewayPorltetURL = String.format("%s?path=/%s/%s",ckanCatalogueReference.getPublicGatewayPortletURL(),entityContextValue, entityName);
String privateVREPortletURL = String.format("%s?path=/%s/%s",ckanCatalogueReference.getPrivateVREPortletURL(),entityContextValue, entityName);
String publicVREPortletURL = String.format("%s?path=/%s/%s",ckanCatalogueReference.getPublicVREPortletURL(),entityContextValue, entityName);
return new ItemCatalogueURLs(entityName, isPublicItem, privateVREPortletURL, publicVREPortletURL, publicGatewayPorltetURL);
}catch (Exception e) {
logger.error("Error when resolving CatalogueURL:", e);
throw e;
}
}
}