2020-10-20 16:25:30 +02:00
package org.gcube.smartgears.handler.resourceregistry.resourcemanager ;
import java.net.URI ;
import java.util.Arrays ;
2022-05-24 12:20:55 +02:00
import java.util.Calendar ;
import java.util.Date ;
2020-10-20 16:25:30 +02:00
import java.util.List ;
2021-10-28 11:21:14 +02:00
import java.util.Map ;
2022-06-09 16:07:22 +02:00
import java.util.Set ;
2020-10-20 16:25:30 +02:00
import java.util.UUID ;
import javax.servlet.ServletRegistration ;
2022-06-09 16:07:22 +02:00
import org.gcube.common.authorization.library.provider.SecurityTokenProvider ;
2020-10-20 16:25:30 +02:00
import org.gcube.informationsystem.model.impl.properties.HeaderImpl ;
import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl ;
import org.gcube.informationsystem.model.reference.properties.Header ;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint ;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint ;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint ;
2020-11-10 15:52:46 +01:00
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache ;
2020-10-20 16:25:30 +02:00
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException ;
2022-02-01 16:47:02 +01:00
import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException ;
2021-10-25 11:00:27 +02:00
import org.gcube.informationsystem.resourceregistry.api.exceptions.entities.resource.ResourceNotFoundException ;
2020-10-22 12:10:37 +02:00
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient ;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory ;
2020-10-20 16:25:30 +02:00
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisher ;
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisherFactory ;
import org.gcube.resourcemanagement.model.impl.entities.facets.AccessPointFacetImpl ;
2022-05-24 12:20:55 +02:00
import org.gcube.resourcemanagement.model.impl.entities.facets.EventFacetImpl ;
2020-10-20 16:25:30 +02:00
import org.gcube.resourcemanagement.model.impl.entities.facets.SoftwareFacetImpl ;
2020-12-21 23:10:14 +01:00
import org.gcube.resourcemanagement.model.impl.entities.facets.StateFacetImpl ;
2020-10-20 16:25:30 +02:00
import org.gcube.resourcemanagement.model.impl.entities.resources.EServiceImpl ;
import org.gcube.resourcemanagement.model.impl.properties.ValueSchemaImpl ;
import org.gcube.resourcemanagement.model.impl.relations.consistsof.IsIdentifiedByImpl ;
import org.gcube.resourcemanagement.model.impl.relations.isrelatedto.ActivatesImpl ;
import org.gcube.resourcemanagement.model.reference.entities.facets.AccessPointFacet ;
2022-05-24 12:20:55 +02:00
import org.gcube.resourcemanagement.model.reference.entities.facets.EventFacet ;
2020-10-20 16:25:30 +02:00
import org.gcube.resourcemanagement.model.reference.entities.facets.SoftwareFacet ;
2020-12-21 23:10:14 +01:00
import org.gcube.resourcemanagement.model.reference.entities.facets.StateFacet ;
2020-10-20 16:25:30 +02:00
import org.gcube.resourcemanagement.model.reference.entities.resources.EService ;
import org.gcube.resourcemanagement.model.reference.entities.resources.HostingNode ;
import org.gcube.resourcemanagement.model.reference.properties.ValueSchema ;
import org.gcube.resourcemanagement.model.reference.relations.consistsof.IsIdentifiedBy ;
import org.gcube.resourcemanagement.model.reference.relations.isrelatedto.Activates ;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration ;
import org.gcube.smartgears.configuration.container.ContainerConfiguration ;
import org.gcube.smartgears.context.application.ApplicationContext ;
2022-06-09 16:30:59 +02:00
import org.gcube.smartgears.handler.resourceregistry.Constants ;
2022-05-24 11:13:39 +02:00
import org.gcube.smartgears.handler.resourceregistry.ContextUtility ;
2020-10-20 16:25:30 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2020-10-26 11:48:26 +01:00
/ * *
2022-02-07 11:39:51 +01:00
* @author Luca Frosini ( ISTI - CNR )
2020-10-26 11:48:26 +01:00
* /
2020-10-20 16:25:30 +02:00
public class EServiceManager {
2022-05-24 11:13:39 +02:00
private static Logger logger = LoggerFactory . getLogger ( HostingNodeManager . class ) ;
2020-10-22 12:10:37 +02:00
2020-10-20 16:25:30 +02:00
private static List < String > servletExcludes = Arrays . asList ( " default " , " jsp " ) ;
2020-10-22 12:10:37 +02:00
2020-10-20 16:25:30 +02:00
private ResourceRegistryPublisher resourceRegistryPublisher ;
2020-10-22 12:10:37 +02:00
2020-10-26 11:48:26 +01:00
// private Activates<HostingNode, EService> activates;
2020-10-20 16:25:30 +02:00
private EService eService ;
2020-12-21 23:10:14 +01:00
private StateFacet stateFacet ;
2020-10-22 12:10:37 +02:00
2020-10-23 10:34:38 +02:00
private ApplicationContext applicationContext ;
public EServiceManager ( ApplicationContext applicationContext ) {
this . applicationContext = applicationContext ;
2020-10-20 16:25:30 +02:00
this . resourceRegistryPublisher = ResourceRegistryPublisherFactory . create ( ) ;
}
2020-10-22 12:10:37 +02:00
2020-10-23 10:34:38 +02:00
public EService getEService ( ) {
2020-10-20 16:25:30 +02:00
return eService ;
}
2020-10-22 12:10:37 +02:00
2022-05-24 12:20:55 +02:00
public void addEServiceToCurrentContext ( ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-09 16:07:22 +02:00
String currentToken = SecurityTokenProvider . instance . get ( ) ;
UUID contextUUID = ContextUtility . getContextUUID ( currentToken ) ;
/* Trying to get a context which is not the current to properly invoke the addToContext without forcing the operation using addResourceToCurrentContext */
boolean anotherContextSet = false ;
Set < String > startTokens = applicationContext . configuration ( ) . startTokens ( ) ;
for ( String token : startTokens ) {
UUID anotherContextUUID = ContextUtility . getContextUUID ( token ) ;
if ( anotherContextUUID . compareTo ( contextUUID ) ! = 0 ) {
ContextUtility . setContextFromToken ( token ) ;
anotherContextSet = true ;
break ;
}
}
2022-05-24 12:20:55 +02:00
UUID uuid = UUID . fromString ( applicationContext . id ( ) ) ;
try {
2022-06-09 16:07:22 +02:00
if ( anotherContextSet ) {
resourceRegistryPublisher . addResourceToContext ( EService . NAME , uuid , contextUUID , false ) ;
} else {
resourceRegistryPublisher . addResourceToCurrentContext ( HostingNode . NAME , uuid , false ) ;
}
2022-05-24 12:20:55 +02:00
logger . info ( " {} with UUID {} successfully added to current context ({}) " , EService . NAME , uuid , ContextUtility . getCurrentContextName ( ) ) ;
} catch ( Exception e ) {
logger . error ( " Unable to add {} with UUID {} to current context ({}) " , EService . NAME , uuid , ContextUtility . getCurrentContextName ( ) , e ) ;
2022-06-09 16:07:22 +02:00
} finally {
ContextUtility . setContextFromToken ( currentToken ) ;
2022-05-24 12:20:55 +02:00
}
}
2022-06-09 16:07:22 +02:00
public void addHostingNodeToCurrentContext ( ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
String currentToken = SecurityTokenProvider . instance . get ( ) ;
UUID contextUUID = ContextUtility . getContextUUID ( currentToken ) ;
/* Trying to get a context which is not the current to properly invoke the addToContext without forcing the operation using addResourceToCurrentContext */
boolean anotherContextSet = false ;
Set < String > startTokens = applicationContext . configuration ( ) . startTokens ( ) ;
for ( String token : startTokens ) {
UUID anotherContextUUID = ContextUtility . getContextUUID ( token ) ;
if ( anotherContextUUID . compareTo ( contextUUID ) ! = 0 ) {
ContextUtility . setContextFromToken ( token ) ;
anotherContextSet = true ;
break ;
}
}
2022-05-24 12:20:55 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
2021-07-07 10:20:32 +02:00
try {
2022-06-09 16:07:22 +02:00
if ( anotherContextSet ) {
resourceRegistryPublisher . addResourceToContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
} else {
resourceRegistryPublisher . addResourceToCurrentContext ( HostingNode . NAME , uuid , false ) ;
}
2022-05-24 12:20:55 +02:00
logger . info ( " {} with UUID {} successfully added to current context ({}) " , HostingNode . NAME , uuid , ContextUtility . getCurrentContextName ( ) ) ;
2021-07-07 10:20:32 +02:00
} catch ( Exception e ) {
2022-05-24 12:20:55 +02:00
logger . error ( " Unable to add {} with UUID {} to current context ({}) " , HostingNode . NAME , uuid , ContextUtility . getCurrentContextName ( ) , e ) ;
2022-06-09 16:07:22 +02:00
} finally {
ContextUtility . setContextFromToken ( currentToken ) ;
2020-10-20 16:25:30 +02:00
}
}
2022-06-08 17:42:47 +02:00
public void addToContext ( UUID contextUUID ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
try {
resourceRegistryPublisher . addToContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
logger . info ( " {} with UUID {} successfully added to current context ({}) " , HostingNode . NAME , uuid , ContextUtility . getCurrentContextName ( ) ) ;
} catch ( Exception e ) {
logger . error ( " Unable to add {} with UUID {} to current context ({}) " , HostingNode . NAME , uuid , ContextUtility . getCurrentContextName ( ) , e ) ;
}
}
2020-10-22 12:10:37 +02:00
2022-06-09 16:07:22 +02:00
public void removeFromCurrentContext ( )
2020-10-22 12:10:37 +02:00
throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-05-24 12:20:55 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
2021-07-07 10:20:32 +02:00
try {
2022-05-24 12:20:55 +02:00
resourceRegistryPublisher . removeResourceFromCurrentContext ( HostingNode . NAME , uuid , false ) ;
logger . info ( " {} with UUID {} successfully removed from current context ({}) " , HostingNode . NAME , uuid ,
2022-05-24 11:13:39 +02:00
ContextUtility . getCurrentContextName ( ) ) ;
2021-07-07 10:20:32 +02:00
} catch ( Exception e ) {
2022-05-24 12:20:55 +02:00
logger . error ( " Unable to remove {} with UUID {} from current context ({}) " , HostingNode . NAME , uuid , ContextUtility . getCurrentContextName ( ) , e ) ;
2020-10-20 16:25:30 +02:00
}
}
2021-07-07 10:20:32 +02:00
2020-11-11 14:19:58 +01:00
public void removeFromContext ( UUID contextUUID )
throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
String contextFullName = ContextCache . getInstance ( ) . getContextFullNameByUUID ( contextUUID ) ;
2022-05-24 12:20:55 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
2021-07-07 10:20:32 +02:00
try {
2022-05-24 12:20:55 +02:00
resourceRegistryPublisher . removeResourceFromContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
logger . info ( " {} with UUID {} successfully removed from context ({}) " , HostingNode . NAME , uuid , contextFullName ) ;
2021-07-07 10:20:32 +02:00
} catch ( Exception e ) {
2022-05-24 12:20:55 +02:00
logger . error ( " Unable to remove {} from current context ({}) " , HostingNode . NAME , uuid , contextFullName , e ) ;
2020-11-11 14:19:58 +01:00
}
}
2020-10-20 16:25:30 +02:00
2020-10-23 10:34:38 +02:00
private String getBaseAddress ( ) {
ApplicationConfiguration configuration = applicationContext . configuration ( ) ;
ContainerConfiguration container = applicationContext . container ( ) . configuration ( ) ;
2020-10-20 16:25:30 +02:00
String baseAddress ;
if ( configuration . proxied ( ) ) {
String protocol = configuration . proxyAddress ( ) . protocol ( ) ;
String port = configuration . proxyAddress ( ) . port ( ) ! = null ? " : " + configuration . proxyAddress ( ) . port ( ) : " " ;
baseAddress = String . format ( " %s://%s%s%s " , protocol , configuration . proxyAddress ( ) . hostname ( ) , port ,
2020-10-23 10:34:38 +02:00
applicationContext . application ( ) . getContextPath ( ) ) ;
2020-10-20 16:25:30 +02:00
} else {
String protocol = container . protocol ( ) ;
int port = container . port ( ) ;
baseAddress = String . format ( " %s://%s:%d%s " , protocol , container . hostname ( ) , port ,
2020-10-23 10:34:38 +02:00
applicationContext . application ( ) . getContextPath ( ) ) ;
2020-10-20 16:25:30 +02:00
}
return baseAddress ;
}
2020-10-23 10:34:38 +02:00
public String getState ( ) {
2020-10-20 16:25:30 +02:00
return applicationContext . lifecycle ( ) . state ( ) . remoteForm ( ) . toLowerCase ( ) ;
}
2020-10-22 12:10:37 +02:00
2020-10-23 10:34:38 +02:00
private EService instantiateEService ( ) {
2020-10-20 16:25:30 +02:00
logger . info ( " Creating {} for {} " , EService . NAME , applicationContext . name ( ) ) ;
ApplicationConfiguration applicationConfiguration = applicationContext . configuration ( ) ;
String id = applicationContext . id ( ) ;
2020-10-22 12:10:37 +02:00
2020-10-20 16:25:30 +02:00
UUID uuid = UUID . fromString ( id ) ;
EService eService = new EServiceImpl ( ) ;
Header header = new HeaderImpl ( uuid ) ;
eService . setHeader ( header ) ;
SoftwareFacet softwareFacet = new SoftwareFacetImpl ( ) ;
softwareFacet . setDescription ( applicationConfiguration . description ( ) ) ;
softwareFacet . setGroup ( applicationConfiguration . serviceClass ( ) ) ;
softwareFacet . setName ( applicationConfiguration . name ( ) ) ;
softwareFacet . setVersion ( applicationConfiguration . version ( ) ) ;
IsIdentifiedBy < EService , SoftwareFacet > isIdentifiedBy = new IsIdentifiedByImpl < EService , SoftwareFacet > (
eService , softwareFacet ) ;
eService . addFacet ( isIdentifiedBy ) ;
2020-10-23 10:34:38 +02:00
String baseAddress = getBaseAddress ( ) ;
2020-10-20 16:25:30 +02:00
for ( ServletRegistration servlet : applicationContext . application ( ) . getServletRegistrations ( ) . values ( ) ) {
if ( ! servletExcludes . contains ( servlet . getName ( ) ) ) {
for ( String mapping : servlet . getMappings ( ) ) {
String address = baseAddress
+ ( mapping . endsWith ( " * " ) ? mapping . substring ( 0 , mapping . length ( ) - 2 ) : mapping ) ;
AccessPointFacet accessPointFacet = new AccessPointFacetImpl ( ) ;
accessPointFacet . setEntryName ( servlet . getName ( ) ) ;
accessPointFacet . setEndpoint ( URI . create ( address ) ) ;
ValueSchema valueSchema = new ValueSchemaImpl ( ) ;
valueSchema . setValue ( " gcube-token " ) ;
accessPointFacet . setAuthorization ( valueSchema ) ;
eService . addFacet ( accessPointFacet ) ;
}
}
}
2022-05-24 12:20:55 +02:00
Date date = Calendar . getInstance ( ) . getTime ( ) ;
2020-12-21 23:10:14 +01:00
stateFacet = new StateFacetImpl ( ) ;
2020-10-23 10:34:38 +02:00
String state = getState ( ) ;
2020-12-21 23:10:14 +01:00
stateFacet . setValue ( state ) ;
2022-05-24 12:20:55 +02:00
stateFacet . setAdditionalProperty ( " date " , date ) ;
2022-06-09 16:30:59 +02:00
eService . addFacet ( stateFacet ) ;
2022-05-24 12:20:55 +02:00
EventFacet eventFacet = new EventFacetImpl ( ) ;
eventFacet . setEvent ( state ) ;
eventFacet . setDate ( date ) ;
eService . addFacet ( eventFacet ) ;
2020-10-20 16:25:30 +02:00
return eService ;
}
2021-07-07 10:20:32 +02:00
2020-10-23 10:34:38 +02:00
public EService createEService ( ) throws ResourceRegistryException {
2020-10-26 11:48:26 +01:00
ResourceRegistryClient resourceRegistryClient = ResourceRegistryClientFactory . create ( ) ;
UUID eServiceUUID = UUID . fromString ( applicationContext . id ( ) ) ;
2020-10-20 16:25:30 +02:00
try {
2020-11-10 15:52:46 +01:00
ResourceRegistryClientFactory . includeContextsInInstanceHeader ( true ) ;
2020-10-26 11:48:26 +01:00
eService = resourceRegistryClient . getInstance ( EService . class , eServiceUUID ) ;
2020-12-21 23:10:14 +01:00
stateFacet = eService . getFacets ( StateFacet . class ) . get ( 0 ) ;
2022-05-24 12:20:55 +02:00
updateServiceStateFacet ( ) ;
2020-10-26 11:48:26 +01:00
} catch ( NotFoundException e ) {
eService = instantiateEService ( ) ;
createActivatesRelation ( eService ) ;
} catch ( AvailableInAnotherContextException e ) {
2022-06-09 16:07:22 +02:00
addHostingNodeToCurrentContext ( ) ;
try {
eService = resourceRegistryClient . getInstance ( EService . class , eServiceUUID ) ;
} catch ( AvailableInAnotherContextException ex ) {
addEServiceToCurrentContext ( ) ;
eService = resourceRegistryClient . getInstance ( EService . class , eServiceUUID ) ;
// addToContext() is executed on HostingNode.
// If the EService is still not available we need to create activates
// relation because does not exists otherwise the EService should
// already be in the context due to propagation constraint.
createActivatesRelation ( eService ) ;
}
stateFacet = eService . getFacets ( StateFacet . class ) . get ( 0 ) ;
updateServiceStateFacet ( ) ;
2020-10-26 11:48:26 +01:00
} catch ( ResourceRegistryException e ) {
throw e ;
2020-10-20 16:25:30 +02:00
}
return eService ;
}
2020-10-23 10:34:38 +02:00
public void updateServiceStateFacet ( ) throws ResourceRegistryException {
2022-05-24 12:20:55 +02:00
Date date = Calendar . getInstance ( ) . getTime ( ) ;
2020-10-23 10:34:38 +02:00
String state = getState ( ) ;
2020-12-21 23:10:14 +01:00
stateFacet . setValue ( state ) ;
2022-05-24 12:20:55 +02:00
boolean found = false ;
List < EventFacet > eventFacets = eService . getFacets ( EventFacet . class ) ;
for ( EventFacet eventFacet : eventFacets ) {
if ( eventFacet . getEvent ( ) . compareTo ( state ) = = 0 ) {
found = true ;
eventFacet . setDate ( date ) ;
break ;
}
}
if ( ! found ) {
EventFacet eventFacet = new EventFacetImpl ( ) ;
eventFacet . setDate ( date ) ;
eventFacet . setEvent ( state ) ;
eService . addFacet ( eventFacet ) ;
}
eService = resourceRegistryPublisher . updateResource ( eService ) ;
2020-10-22 12:10:37 +02:00
}
2020-10-20 16:25:30 +02:00
2020-10-23 10:34:38 +02:00
private Activates < HostingNode , EService > createActivatesRelation ( EService eService )
throws ResourceRegistryException {
2020-10-20 16:25:30 +02:00
2022-06-09 16:30:59 +02:00
HostingNode hostingNode = ( ( HostingNodeManager ) applicationContext . container ( ) . properties ( ) . lookup ( Constants . HOSTING_NODE_MANAGER_PROPERTY ) . value ( ) ) . getHostingNode ( ) ;
2020-10-20 16:25:30 +02:00
PropagationConstraint propagationConstraint = new PropagationConstraintImpl ( ) ;
propagationConstraint . setRemoveConstraint ( RemoveConstraint . cascade ) ;
propagationConstraint . setAddConstraint ( AddConstraint . propagate ) ;
Activates < HostingNode , EService > activates = new ActivatesImpl < > ( hostingNode , eService , propagationConstraint ) ;
try {
activates = resourceRegistryPublisher . createIsRelatedTo ( activates ) ;
2022-06-09 16:30:59 +02:00
hostingNode . attachResource ( activates ) ;
2020-10-20 16:25:30 +02:00
} catch ( NotFoundException e ) {
2022-06-09 16:07:22 +02:00
logger . error ( " THIS IS REALLY STRANGE. YOU SHOULD NOT BE HERE. Error while creating {}. " , activates , e ) ;
2020-10-20 16:25:30 +02:00
throw e ;
} catch ( ResourceRegistryException e ) {
logger . error ( " Error while creating {} " , activates , e ) ;
throw e ;
}
return activates ;
}
2020-10-22 12:10:37 +02:00
2020-10-23 10:34:38 +02:00
public void removeEService ( ) throws ResourceRegistryException {
2020-10-20 16:25:30 +02:00
try {
resourceRegistryPublisher . delete ( eService ) ;
} catch ( ResourceRegistryException e ) {
2020-10-23 10:34:38 +02:00
logger . error ( " Unable to delete {}. Going to set the state to {} " , applicationContext . name ( ) , getState ( ) ) ;
updateServiceStateFacet ( ) ;
2020-10-20 16:25:30 +02:00
}
}
2021-07-07 10:20:32 +02:00
2021-10-28 11:21:14 +02:00
public Map < UUID , String > getContextsUUID ( ) throws Exception {
2020-11-11 14:19:58 +01:00
return resourceRegistryPublisher . getResourceContexts ( eService ) ;
}
2020-10-20 16:25:30 +02:00
}