2018-10-12 16:20:46 +02:00
package org.gcube.datatransfer.resolver.services ;
2020-06-18 15:48:47 +02:00
import java.net.URI ;
2018-10-12 16:20:46 +02:00
import java.net.URL ;
2020-06-18 15:48:47 +02:00
import java.util.HashMap ;
import java.util.Map ;
2018-11-09 12:05:53 +01:00
import java.util.concurrent.ExecutionException ;
2018-10-12 16:20:46 +02:00
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 ;
2018-12-14 12:28:59 +01:00
import javax.ws.rs.WebApplicationException ;
2018-10-12 16:20:46 +02:00
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 ;
2019-05-16 12:54:20 +02:00
import org.gcube.common.scope.impl.ScopeBean ;
import org.gcube.common.scope.impl.ScopeBean.Type ;
2020-04-06 16:11:55 +02:00
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET ;
2019-05-16 14:56:48 +02:00
import org.gcube.datatransfer.resolver.ConstantsResolver ;
2020-06-18 15:48:47 +02:00
import org.gcube.datatransfer.resolver.caches.LoadingMapOfDetachedVRE ;
2019-05-21 16:27:58 +02:00
import org.gcube.datatransfer.resolver.caches.LoadingMapOfScopeCache ;
2018-10-12 16:20:46 +02:00
import org.gcube.datatransfer.resolver.catalogue.CatalogueRequest ;
2018-11-26 12:56:51 +01:00
import org.gcube.datatransfer.resolver.catalogue.ItemCatalogueURLs ;
2018-11-15 12:18:03 +01:00
import org.gcube.datatransfer.resolver.catalogue.ResourceCatalogueCodes ;
2020-06-18 15:48:47 +02:00
import org.gcube.datatransfer.resolver.catalogue.resource.CatalogueStaticConfigurations ;
2018-10-12 16:20:46 +02:00
import org.gcube.datatransfer.resolver.catalogue.resource.CkanCatalogueConfigurationsReader ;
import org.gcube.datatransfer.resolver.catalogue.resource.GatewayCKANCatalogueReference ;
2019-05-16 12:54:20 +02:00
import org.gcube.datatransfer.resolver.catalogue.resource.GetAllInfrastructureScopes ;
2018-11-09 12:05:53 +01:00
import org.gcube.datatransfer.resolver.services.error.ExceptionManager ;
2018-11-30 12:51:17 +01:00
import org.gcube.datatransfer.resolver.util.Util ;
2020-06-18 15:48:47 +02:00
import org.gcube.infrastructure.detachedres.detachedreslibrary.shared.re.VRE ;
2018-10-24 10:09:09 +02:00
import org.gcube.smartgears.utils.InnerMethodName ;
2018-10-12 16:20:46 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2018-12-17 15:52:31 +01:00
import com.google.common.cache.CacheLoader.InvalidCacheLoadException ;
2018-10-12 16:20:46 +02:00
import eu.trentorise.opendata.jackan.model.CkanDataset ;
2018-11-23 15:45:33 +01:00
/ * *
* The Class CatalogueResolver .
*
* @author Francesco Mangiacrapa at ISTI - CNR ( francesco . mangiacrapa @isti.cnr.it )
* Nov 16 , 2018
* /
2019-02-19 15:18:19 +01:00
@Path ( " {entityContext:ctlg(-(o|g|p|d))?} " )
2018-10-23 14:58:46 +02:00
public class CatalogueResolver {
2018-10-12 16:20:46 +02:00
2019-05-16 14:56:48 +02:00
2018-10-23 14:58:46 +02:00
private static Logger logger = LoggerFactory . getLogger ( CatalogueResolver . class ) ;
2018-11-09 12:05:53 +01:00
private static String helpURI = " https://wiki.gcube-system.org/gcube/URI_Resolver#CATALOGUE_Resolver " ;
2020-06-18 15:48:47 +02:00
private static enum SCOPE_STATUS { ACTIVE , DETACHED }
2018-10-12 16:20:46 +02:00
2018-11-23 15:45:33 +01:00
/ * *
* Resolve catalogue .
*
* @param req the req
* @param entityName the entity name
* @param vreName the vre name
* @param entityContext the entity context
* @return the response
* /
2018-10-12 16:20:46 +02:00
@GET
2019-02-19 15:18:19 +01:00
@Path ( " /{vreName}/{entityName} " )
2018-12-14 12:28:59 +01:00
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... " ) ;
2018-10-12 16:20:46 +02:00
try {
2018-12-14 12:28:59 +01:00
InnerMethodName . instance . set ( " resolveCataloguePublicLink " ) ;
2018-12-17 11:48:18 +01:00
ItemCatalogueURLs itemCatalogueURLs = getItemCatalogueURLs ( req , vreName , entityContext , entityName ) ;
2018-11-26 12:56:51 +01:00
String itemCatalogueURL ;
if ( itemCatalogueURLs . isPublicItem ( ) ) {
2019-11-14 10:53:11 +01:00
logger . info ( " The dataset " + itemCatalogueURLs . getItemName ( ) + " was detected as public item (not private to VRE) " ) ;
2019-11-12 18:18:22 +01:00
if ( itemCatalogueURLs . getPublicVRECataloguePortletURL ( ) ! = null & & ! itemCatalogueURLs . getPublicVRECataloguePortletURL ( ) . isEmpty ( ) ) {
itemCatalogueURL = itemCatalogueURLs . getPublicVRECataloguePortletURL ( ) ;
2019-11-13 11:48:55 +01:00
logger . info ( " I found the public VRE catalogue URL, so using public access to it: " + itemCatalogueURL ) ;
2019-11-12 18:18:22 +01:00
} else {
itemCatalogueURL = itemCatalogueURLs . getPublicGatewayCataloguePortletURL ( ) ;
logger . info ( " No public VRE catalogue URL found, so using public access to gateway CKAN portlet: " + itemCatalogueURL ) ;
}
2018-11-26 12:56:51 +01:00
} else {
2019-11-12 18:18:22 +01:00
itemCatalogueURL = itemCatalogueURLs . getPrivateVRECataloguePortletURL ( ) ;
2019-11-13 11:48:55 +01:00
logger . info ( " The dataset " + itemCatalogueURLs . getItemName ( ) + " is a private item (to VRE) so using protected access to CKAN portlet: " + itemCatalogueURL ) ;
2018-11-26 12:56:51 +01:00
}
2018-11-23 15:45:33 +01:00
return Response . seeOther ( new URL ( itemCatalogueURL ) . toURI ( ) ) . build ( ) ;
2018-10-12 16:20:46 +02:00
} catch ( Exception e ) {
2018-12-14 12:28:59 +01:00
if ( ! ( e instanceof WebApplicationException ) ) {
//UNEXPECTED EXCEPTION managing it as WebApplicationException
2018-12-14 14:26:37 +01:00
String error = " Error occurred on resolving the Catalgoue URL. Please, contact the support! " ;
if ( e . getCause ( ) ! = null )
error + = " \ n \ nCaused: " + e . getCause ( ) . getMessage ( ) ;
2018-12-14 12:28:59 +01:00
throw ExceptionManager . internalErrorException ( req , error , this . getClass ( ) , helpURI ) ;
}
//ALREADY MANAGED AS WebApplicationException
logger . error ( " Exception: " , e ) ;
throw ( WebApplicationException ) e ;
2018-10-12 16:20:46 +02:00
}
}
2021-06-04 15:09:06 +02:00
2018-11-23 15:45:33 +01:00
/ * *
* Post catalogue .
*
* @param req the req
* @param jsonRequest the json request
* @return the response
* /
2018-10-12 16:20:46 +02:00
@POST
2019-02-19 15:18:19 +01:00
@Path ( " " )
2018-10-12 16:20:46 +02:00
@Consumes ( MediaType . APPLICATION_JSON )
@Produces ( MediaType . TEXT_PLAIN )
2018-12-14 12:28:59 +01:00
public Response postCatalogue ( @Context HttpServletRequest req , CatalogueRequest jsonRequest ) throws WebApplicationException {
logger . info ( this . getClass ( ) . getSimpleName ( ) + " POST starts... " ) ;
2018-10-12 16:20:46 +02:00
2018-12-14 12:28:59 +01:00
try {
2018-10-12 16:20:46 +02:00
2018-12-14 12:28:59 +01:00
InnerMethodName . instance . set ( " postCataloguePublicLink " ) ;
logger . info ( " The body contains the request: " + jsonRequest . toString ( ) ) ;
2018-11-09 12:05:53 +01:00
2018-12-14 12:28:59 +01:00
//CHECK IF INPUT SCOPE IS VALID
String scope = jsonRequest . getGcube_scope ( ) ;
2019-05-16 14:56:48 +02:00
if ( ! scope . startsWith ( ConstantsResolver . SCOPE_SEPARATOR ) ) {
logger . info ( " Scope not start with char '{}' adding it " , ConstantsResolver . SCOPE_SEPARATOR ) ;
scope + = ConstantsResolver . SCOPE_SEPARATOR + scope ;
2018-12-14 12:28:59 +01:00
}
2018-10-12 16:20:46 +02:00
2018-12-14 12:28:59 +01:00
String serverUrl = Util . getServerURL ( req ) ;
2018-10-12 16:20:46 +02:00
2019-05-16 14:56:48 +02:00
final String vreName = scope . substring ( scope . lastIndexOf ( ConstantsResolver . SCOPE_SEPARATOR ) + 1 , scope . length ( ) ) ;
2019-05-16 12:54:20 +02:00
ScopeBean fullScope = null ;
2018-12-17 11:48:18 +01:00
2018-12-14 12:28:59 +01:00
//CHECK IF THE vreName has a valid scope, so it is a valid VRE
try {
2019-05-16 12:54:20 +02:00
fullScope = LoadingMapOfScopeCache . get ( vreName ) ;
2018-12-17 11:48:18 +01:00
} 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 ) ;
2018-12-14 12:28:59 +01:00
}
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 ) ;
}
2019-11-12 18:18:22 +01:00
//ALREADY MANAGED AS WebApplicationExceptiongetItemCatalogueURLs
2018-12-14 12:28:59 +01:00
logger . error ( " Exception: " , e ) ;
throw ( WebApplicationException ) e ;
}
2018-11-23 15:45:33 +01:00
}
2018-10-12 16:20:46 +02:00
2018-11-23 15:45:33 +01:00
/ * *
2019-05-16 12:54:20 +02:00
* Gets the item catalogue UR ls .
2018-11-23 15:45:33 +01:00
*
2018-12-17 11:48:18 +01:00
* @param req the req
2019-05-16 12:54:20 +02:00
* @param scopeName the scope name
2018-11-23 15:45:33 +01:00
* @param entityContext the entity context
* @param entityName the entity name
2019-05-16 12:54:20 +02:00
* @return the item catalogue UR ls
2018-11-23 15:45:33 +01:00
* @throws Exception the exception
* /
2019-05-16 12:54:20 +02:00
protected static ItemCatalogueURLs getItemCatalogueURLs ( HttpServletRequest req , String scopeName , String entityContext , String entityName ) throws Exception {
2018-11-23 15:45:33 +01:00
try {
String entityContextValue = ResourceCatalogueCodes . valueOfCodeId ( entityContext ) . getValue ( ) ;
2019-05-16 12:54:20 +02:00
ScopeBean scopeBean = null ;
2020-06-18 15:48:47 +02:00
SCOPE_STATUS scopeStatus = SCOPE_STATUS . ACTIVE ;
VRE vreDetached = null ;
2018-12-17 11:48:18 +01:00
try {
2019-05-16 12:54:20 +02:00
scopeBean = LoadingMapOfScopeCache . get ( scopeName ) ;
2018-12-17 15:52:31 +01:00
} catch ( ExecutionException | InvalidCacheLoadException e ) {
2020-06-18 15:48:47 +02:00
logger . error ( " Error on getting the fullscope from cache for scopeName {}. Tryng to load it from DetachedRE " , scopeName ) ;
boolean isScopeDetached = false ;
try {
vreDetached = LoadingMapOfDetachedVRE . get ( scopeName ) ;
scopeBean = new ScopeBean ( vreDetached . getScope ( ) ) ;
scopeStatus = SCOPE_STATUS . DETACHED ;
logger . info ( " I loaded a valid VRE obj for scope name {} " , scopeName ) ;
isScopeDetached = true ;
} catch ( Exception e1 ) {
logger . warn ( " I was not able to load a detached VRE for vreName {}. Going to error for wrong scope " , scopeName ) ;
}
//If is not a cas of scope detached, going to error for wrong scope
if ( ! isScopeDetached ) {
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 ) ;
}
2019-05-16 12:54:20 +02:00
}
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 ) ;
2019-05-16 14:56:48 +02:00
String [ ] splitScope = fullScope . split ( ConstantsResolver . SCOPE_SEPARATOR ) ;
fullScope = ConstantsResolver . SCOPE_SEPARATOR + splitScope [ 1 ] ; //THIS IS THE INFRASTRUCTURE SCOPE
2019-05-16 15:02:15 +02:00
logger . info ( " Overriden the input scope {} with {} as type: {} " , scopeBean . toString ( ) , Type . INFRASTRUCTURE , fullScope ) ;
2018-12-17 11:48:18 +01:00
}
2018-11-23 15:45:33 +01:00
ScopeProvider . instance . set ( fullScope ) ;
2020-06-18 15:48:47 +02:00
GatewayCKANCatalogueReference ckanCatalogueReference = null ;
logger . info ( " Managing scope status: {} " , scopeStatus ) ;
switch ( scopeStatus ) {
case DETACHED :
String privatePortletURL = vreDetached . getCatalogPortletURL ( ) ;
//The private portlet URL
Map < ACCESS_LEVEL_TO_CATALOGUE_PORTLET , String > mapAccessURLToCatalogue = new HashMap < ACCESS_LEVEL_TO_CATALOGUE_PORTLET , String > ( 3 ) ;
mapAccessURLToCatalogue . put ( ACCESS_LEVEL_TO_CATALOGUE_PORTLET . PRIVATE_VRE , privatePortletURL ) ;
//Building the gateway catalogue public URL from private VRE Portlet URL
URI toURL = new URI ( privatePortletURL ) ;
String publicURL = privatePortletURL . startsWith ( " https:// " ) ? " https:// " + toURL . getHost ( ) : " http:// " + toURL . getHost ( ) ;
//It returns the string "catalogue"
CatalogueStaticConfigurations staticConf = new CatalogueStaticConfigurations ( ) ;
//Replacing for example "ckan-bb" with "[PREFIXES-TO-CATALOGUE-URL]-bb" (e.g catalogue-bb)
String relativeURLWithCatalogueName = staticConf . buildRelativeURLToPublicCatalogueGateway ( vreDetached . getCatalogUrl ( ) ) ;
String toGatewayPortletURL = String . format ( " %s/%s " , publicURL , relativeURLWithCatalogueName ) ;
mapAccessURLToCatalogue . put ( ACCESS_LEVEL_TO_CATALOGUE_PORTLET . PUBLIC_GATEWAY , toGatewayPortletURL ) ;
ckanCatalogueReference = new GatewayCKANCatalogueReference ( fullScope , vreDetached . getCatalogUrl ( ) , mapAccessURLToCatalogue ) ;
break ;
case ACTIVE :
default :
ckanCatalogueReference = CkanCatalogueConfigurationsReader . loadCatalogueEndPoints ( ) ;
break ;
}
2018-11-23 15:45:33 +01:00
2020-06-18 15:48:47 +02:00
2018-11-23 15:45:33 +01:00
logger . info ( " For scope " + fullScope + " loaded end points: " + ckanCatalogueReference ) ;
//IS THE PRODUCT PLUBLIC OR PRIVATE?
String datasetName = entityName ;
2018-11-26 12:56:51 +01:00
boolean isPublicItem = false ;
2018-11-23 15:45:33 +01:00
if ( ckanCatalogueReference . getCkanURL ( ) ! = null ) {
try {
CkanDataset dataset = CkanCatalogueConfigurationsReader . getDataset ( datasetName , ckanCatalogueReference . getCkanURL ( ) ) ;
if ( dataset ! = null ) {
2018-11-26 12:56:51 +01:00
isPublicItem = true ;
//ckanPorltetUrl = ckanCatalogueReference.getPublicPortletURL();
logger . info ( " The dataset " + datasetName + " is a public item " ) ;
2018-11-23 15:45:33 +01:00
}
} catch ( Exception e ) {
logger . warn ( " Error on checking if dataset: " + datasetName + " is private or not " , e ) ;
2018-11-26 12:56:51 +01:00
isPublicItem = true ;
2018-10-12 16:20:46 +02:00
}
2018-11-23 15:45:33 +01:00
}
2018-10-12 16:20:46 +02:00
2020-04-06 16:11:55 +02:00
String publicGatewayPorltetURL = String . format ( " %s?path=/%s/%s " ,
ckanCatalogueReference . getCatalogueURL ( ACCESS_LEVEL_TO_CATALOGUE_PORTLET . PUBLIC_GATEWAY ) ,
entityContextValue ,
entityName ) ;
String privateVREPortletURL = String . format ( " %s?path=/%s/%s " ,
ckanCatalogueReference . getCatalogueURL ( ACCESS_LEVEL_TO_CATALOGUE_PORTLET . PRIVATE_VRE ) ,
entityContextValue ,
entityName ) ;
2019-11-14 10:41:08 +01:00
//Checking if the public VRE portlet URL is available (so it was read from GR)
String publicVREPortletURL = null ;
2020-04-06 16:11:55 +02:00
String toCheckPublicVREPortletURL = ckanCatalogueReference . getCatalogueURL ( ACCESS_LEVEL_TO_CATALOGUE_PORTLET . PUBLIC_VRE ) ;
if ( toCheckPublicVREPortletURL ! = null & & ! toCheckPublicVREPortletURL . isEmpty ( ) ) {
2019-11-14 10:41:08 +01:00
//here the catalogue is available/deployed as public at VRE level
2020-04-06 16:11:55 +02:00
publicVREPortletURL = String . format ( " %s?path=/%s/%s " ,
toCheckPublicVREPortletURL ,
entityContextValue ,
entityName ) ;
2019-11-14 10:41:08 +01:00
}
2019-11-13 11:27:17 +01:00
return new ItemCatalogueURLs ( entityName , isPublicItem , privateVREPortletURL , publicVREPortletURL , publicGatewayPorltetURL ) ;
2018-11-23 15:45:33 +01:00
} catch ( Exception e ) {
2018-12-14 12:28:59 +01:00
logger . error ( " Error when resolving CatalogueURL: " , e ) ;
2018-11-23 15:45:33 +01:00
throw e ;
}
2018-10-12 16:20:46 +02:00
}
}