2022-06-29 09:12:36 +02:00
package org.gcube.smartgears.connector.resourceregistry.resourcemanager ;
2022-06-16 13:54:13 +02:00
import java.net.URI ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Calendar ;
import java.util.Date ;
import java.util.List ;
import java.util.Map ;
import java.util.Set ;
import java.util.UUID ;
import javax.servlet.ServletRegistration ;
2022-06-29 09:11:29 +02:00
import org.gcube.common.security.providers.SecretManagerProvider ;
import org.gcube.common.security.secrets.Secret ;
2022-06-16 13:54:13 +02:00
import org.gcube.informationsystem.model.impl.properties.HeaderImpl ;
import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl ;
import org.gcube.informationsystem.model.reference.entities.Facet ;
import org.gcube.informationsystem.model.reference.entities.Resource ;
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 ;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf ;
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException ;
import org.gcube.informationsystem.resourceregistry.api.exceptions.entities.resource.ResourceNotFoundException ;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient ;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory ;
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisher ;
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisherFactory ;
import org.gcube.informationsystem.utils.ElementMapper ;
import org.gcube.resourcemanagement.model.impl.entities.facets.AccessPointFacetImpl ;
import org.gcube.resourcemanagement.model.impl.entities.facets.EventFacetImpl ;
import org.gcube.resourcemanagement.model.impl.entities.facets.SoftwareFacetImpl ;
import org.gcube.resourcemanagement.model.impl.entities.facets.StateFacetImpl ;
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 ;
import org.gcube.resourcemanagement.model.reference.entities.facets.EventFacet ;
import org.gcube.resourcemanagement.model.reference.entities.facets.SoftwareFacet ;
import org.gcube.resourcemanagement.model.reference.entities.facets.StateFacet ;
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 ;
2022-06-29 09:12:36 +02:00
import org.gcube.smartgears.connector.resourceregistry.Constants ;
import org.gcube.smartgears.connector.resourceregistry.ContextUtility ;
2022-06-16 13:54:13 +02:00
import org.gcube.smartgears.context.application.ApplicationContext ;
2022-06-29 09:11:29 +02:00
import org.gcube.smartgears.security.AuthorizationProvider ;
2022-06-16 13:54:13 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
/ * *
* @author Luca Frosini ( ISTI - CNR )
* /
public class EServiceManager {
private static Logger logger = LoggerFactory . getLogger ( HostingNodeManager . class ) ;
private static List < String > servletExcludes = Arrays . asList ( " default " , " jsp " ) ;
private ResourceRegistryPublisher resourceRegistryPublisher ;
private EService eService ;
private ApplicationContext applicationContext ;
public EServiceManager ( ApplicationContext applicationContext ) {
this . applicationContext = applicationContext ;
this . resourceRegistryPublisher = ResourceRegistryPublisherFactory . create ( ) ;
}
public void addEServiceToCurrentContext ( ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-29 09:11:29 +02:00
Secret secret = SecretManagerProvider . instance . get ( ) ;
String context = secret . getContext ( ) ;
UUID contextUUID = ContextUtility . getContextUUID ( context ) ;
2022-06-16 13:54:13 +02:00
/* Trying to get a context which is not the current to properly invoke the addToContext without forcing the operation using addResourceToCurrentContext */
2022-06-29 09:11:29 +02:00
AuthorizationProvider authorizationProvider = applicationContext . container ( ) . configuration ( ) . authorizationProvider ( ) ;
Set < String > contexts = authorizationProvider . getContexts ( ) ;
2022-06-16 13:54:13 +02:00
boolean anotherContextSet = false ;
2022-06-29 09:11:29 +02:00
for ( String c : contexts ) {
if ( c . compareTo ( context ) ! = 0 ) {
Secret s = authorizationProvider . getSecretForContext ( c ) ;
SecretManagerProvider . instance . set ( s ) ;
2022-06-16 13:54:13 +02:00
anotherContextSet = true ;
break ;
}
}
2022-06-29 09:11:29 +02:00
UUID uuid = UUID . fromString ( applicationContext . id ( ) ) ;
2022-06-16 13:54:13 +02:00
try {
if ( anotherContextSet ) {
resourceRegistryPublisher . addResourceToContext ( EService . NAME , uuid , contextUUID , false ) ;
} else {
2022-06-29 09:11:29 +02:00
resourceRegistryPublisher . addResourceToCurrentContext ( EService . NAME , uuid , false ) ;
2022-06-16 13:54:13 +02:00
}
2022-06-29 09:11:29 +02:00
logger . info ( " {} with UUID {} successfully added to context ({}) " , EService . NAME , uuid , context ) ;
2022-06-16 13:54:13 +02:00
} catch ( Exception e ) {
2022-06-29 09:11:29 +02:00
logger . error ( " Unable to add {} with UUID {} to context ({}) " , EService . NAME , uuid , context , e ) ;
2022-06-16 13:54:13 +02:00
}
}
2022-06-29 09:11:29 +02:00
2022-06-16 13:54:13 +02:00
public void addHostingNodeToCurrentContext ( ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-29 09:11:29 +02:00
Secret secret = SecretManagerProvider . instance . get ( ) ;
String context = secret . getContext ( ) ;
UUID contextUUID = ContextUtility . getContextUUID ( context ) ;
2022-06-16 13:54:13 +02:00
/* Trying to get a context which is not the current to properly invoke the addToContext without forcing the operation using addResourceToCurrentContext */
2022-06-29 09:11:29 +02:00
AuthorizationProvider authorizationProvider = applicationContext . container ( ) . configuration ( ) . authorizationProvider ( ) ;
Set < String > contexts = authorizationProvider . getContexts ( ) ;
2022-06-16 13:54:13 +02:00
boolean anotherContextSet = false ;
2022-06-29 09:11:29 +02:00
for ( String c : contexts ) {
if ( c . compareTo ( context ) ! = 0 ) {
Secret s = authorizationProvider . getSecretForContext ( c ) ;
SecretManagerProvider . instance . set ( s ) ;
2022-06-16 13:54:13 +02:00
anotherContextSet = true ;
break ;
}
}
2022-06-29 09:11:29 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
2022-06-16 13:54:13 +02:00
try {
if ( anotherContextSet ) {
2022-06-29 09:11:29 +02:00
resourceRegistryPublisher . addToContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
2022-06-16 13:54:13 +02:00
} else {
resourceRegistryPublisher . addResourceToCurrentContext ( HostingNode . NAME , uuid , false ) ;
}
2022-06-29 09:11:29 +02:00
logger . info ( " {} with UUID {} successfully added to context ({}) " , HostingNode . NAME , uuid , context ) ;
2022-06-16 13:54:13 +02:00
} catch ( Exception e ) {
2022-06-29 09:11:29 +02:00
logger . error ( " Unable to add {} with UUID {} to context ({}) " , HostingNode . NAME , uuid , context , e ) ;
2022-06-16 13:54:13 +02:00
}
}
public void addToContext ( UUID contextUUID ) throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-29 09:11:29 +02:00
String context = ContextCache . getInstance ( ) . getContextFullNameByUUID ( contextUUID ) ;
2022-06-16 13:54:13 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
try {
resourceRegistryPublisher . addToContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
2022-06-29 09:11:29 +02:00
logger . info ( " {} with UUID {} successfully added to context ({}) " , HostingNode . NAME , uuid , context ) ;
2022-06-16 13:54:13 +02:00
} catch ( Exception e ) {
2022-06-29 09:11:29 +02:00
logger . error ( " Unable to add {} with UUID {} to context ({}) " , HostingNode . NAME , uuid , context , e ) ;
2022-06-16 13:54:13 +02:00
}
}
public void removeFromCurrentContext ( )
throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-29 09:11:29 +02:00
Secret secret = SecretManagerProvider . instance . get ( ) ;
String context = secret . getContext ( ) ;
2022-06-16 13:54:13 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
try {
resourceRegistryPublisher . removeResourceFromCurrentContext ( HostingNode . NAME , uuid , false ) ;
2022-06-29 09:11:29 +02:00
logger . info ( " {} with UUID {} successfully removed from context ({}) " , HostingNode . NAME , uuid , context ) ;
2022-06-16 13:54:13 +02:00
} catch ( Exception e ) {
2022-06-29 09:11:29 +02:00
logger . error ( " Unable to remove {} with UUID {} from context ({}) " , HostingNode . NAME , uuid , context , e ) ;
2022-06-16 13:54:13 +02:00
}
}
public void removeFromContext ( UUID contextUUID )
throws ResourceNotFoundException , ContextNotFoundException , ResourceRegistryException {
2022-06-29 09:11:29 +02:00
String context = ContextCache . getInstance ( ) . getContextFullNameByUUID ( contextUUID ) ;
2022-06-16 13:54:13 +02:00
UUID uuid = UUID . fromString ( applicationContext . container ( ) . id ( ) ) ;
try {
resourceRegistryPublisher . removeResourceFromContext ( HostingNode . NAME , uuid , contextUUID , false ) ;
2022-06-29 09:11:29 +02:00
logger . info ( " {} with UUID {} successfully removed from context ({}) " , HostingNode . NAME , uuid , context ) ;
2022-06-16 13:54:13 +02:00
} catch ( Exception e ) {
2022-06-29 09:11:29 +02:00
logger . error ( " Unable to remove {} from context ({}) " , HostingNode . NAME , uuid , context , e ) ;
2022-06-16 13:54:13 +02:00
}
}
private String getBaseAddress ( ) {
ApplicationConfiguration configuration = applicationContext . configuration ( ) ;
ContainerConfiguration container = applicationContext . container ( ) . configuration ( ) ;
String baseAddress ;
2022-06-29 09:11:29 +02:00
if ( configuration . proxable ( ) ) {
String protocol = configuration . proxyAddress ( ) . getProtocol ( ) ;
String port = configuration . proxyAddress ( ) . getPort ( ) ! = null ? " : " + configuration . proxyAddress ( ) . getPort ( ) : " " ;
2022-06-16 13:54:13 +02:00
2022-06-29 09:11:29 +02:00
baseAddress = String . format ( " %s://%s%s%s " , protocol , configuration . proxyAddress ( ) . getHostname ( ) , port ,
2022-06-16 13:54:13 +02:00
applicationContext . application ( ) . getContextPath ( ) ) ;
} else {
String protocol = container . protocol ( ) ;
int port = container . port ( ) ;
baseAddress = String . format ( " %s://%s:%d%s " , protocol , container . hostname ( ) , port ,
applicationContext . application ( ) . getContextPath ( ) ) ;
}
return baseAddress ;
}
public String getState ( ) {
return applicationContext . lifecycle ( ) . state ( ) . remoteForm ( ) . toLowerCase ( ) ;
}
private StateFacet getStateFacet ( StateFacet stateFacet , Date date ) {
if ( stateFacet = = null ) {
stateFacet = new StateFacetImpl ( ) ;
}
String state = getState ( ) ;
stateFacet . setValue ( state ) ;
stateFacet . setAdditionalProperty ( " date " , date ) ;
return stateFacet ;
}
private EventFacet getEventFacet ( Date date ) {
EventFacet eventFacet = new EventFacetImpl ( ) ;
eventFacet . setDate ( date ) ;
String state = getState ( ) ;
eventFacet . setEvent ( state ) ;
return eventFacet ;
}
private EService instantiateEService ( ) {
logger . info ( " Creating {} for {} " , EService . NAME , applicationContext . name ( ) ) ;
ApplicationConfiguration applicationConfiguration = applicationContext . configuration ( ) ;
String id = applicationContext . id ( ) ;
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 ) ;
String baseAddress = getBaseAddress ( ) ;
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 ) ;
}
}
}
Date date = Calendar . getInstance ( ) . getTime ( ) ;
StateFacet stateFacet = getStateFacet ( null , date ) ;
eService . addFacet ( stateFacet ) ;
EventFacet eventFacet = getEventFacet ( date ) ; ;
eService . addFacet ( eventFacet ) ;
return eService ;
}
public EService createEService ( ) throws ResourceRegistryException {
ResourceRegistryClient resourceRegistryClient = ResourceRegistryClientFactory . create ( ) ;
UUID eServiceUUID = UUID . fromString ( applicationContext . id ( ) ) ;
try {
ResourceRegistryClientFactory . includeContextsInInstanceHeader ( true ) ;
eService = resourceRegistryClient . getInstance ( EService . class , eServiceUUID ) ;
updateFacets ( ) ;
} catch ( NotFoundException e ) {
eService = instantiateEService ( ) ;
eService = createActivatesRelation ( eService ) . getTarget ( ) ;
} catch ( AvailableInAnotherContextException e ) {
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.
eService = createActivatesRelation ( eService ) . getTarget ( ) ;
}
updateFacets ( ) ;
} catch ( ResourceRegistryException e ) {
throw e ;
}
return eService ;
}
public EService updateFacets ( ) throws ResourceRegistryException {
logger . debug ( " Updating {} for {} " , EService . NAME , applicationContext . configuration ( ) . name ( ) ) ;
StateFacet stateFacet = null ;
EventFacet eventFacet = null ;
Date date = Calendar . getInstance ( ) . getTime ( ) ;
List < ConsistsOf < ? extends Resource , ? extends Facet > > consistsOfToRemove = new ArrayList < > ( ) ;
List < ConsistsOf < ? extends Resource , ? extends Facet > > consistsOfList = eService . getConsistsOf ( ) ;
for ( ConsistsOf < ? extends Resource , ? extends Facet > c : consistsOfList ) {
if ( c . getTarget ( ) instanceof StateFacet ) {
stateFacet = ( StateFacet ) c . getTarget ( ) ;
stateFacet = getStateFacet ( stateFacet , date ) ;
continue ;
}
if ( c . getTarget ( ) instanceof EventFacet ) {
eventFacet = ( EventFacet ) c . getTarget ( ) ;
String value = eventFacet . getEvent ( ) ;
if ( value . compareTo ( getState ( ) ) = = 0 ) {
// This facet must be updated (the date must be updated) so it must not be removed from udpate
eventFacet . setDate ( date ) ;
continue ;
} else {
// This is not the event facet to be updated
// Setting the variable to null so it will be created if the event does not already exists.
eventFacet = null ;
}
}
consistsOfToRemove . add ( c ) ;
}
// Resource Update has effect only on specified facets.
// Removing the ones that have not to be changed.
consistsOfList . removeAll ( consistsOfToRemove ) ;
if ( eventFacet = = null ) {
eventFacet = getEventFacet ( date ) ;
eService . addFacet ( eventFacet ) ;
}
try {
logger . trace ( " Updating {} for {} : {} " , EService . NAME , applicationContext . configuration ( ) . name ( ) , ElementMapper . marshal ( eService ) ) ;
} catch ( Exception e ) {
}
try {
eService = resourceRegistryPublisher . updateResource ( eService ) ;
} catch ( ResourceRegistryException e ) {
logger . error ( " Error trying to publish hosting node " , e ) ;
}
return eService ;
}
private Activates < HostingNode , EService > createActivatesRelation ( EService eService )
throws ResourceRegistryException {
HostingNode hostingNode = ( ( HostingNodeManager ) applicationContext . container ( ) . properties ( ) . lookup ( Constants . HOSTING_NODE_MANAGER_PROPERTY ) . value ( ) ) . getHostingNode ( ) ;
PropagationConstraint propagationConstraint = new PropagationConstraintImpl ( ) ;
propagationConstraint . setRemoveConstraint ( RemoveConstraint . cascade ) ;
propagationConstraint . setAddConstraint ( AddConstraint . propagate ) ;
Activates < HostingNode , EService > activates = new ActivatesImpl < > ( hostingNode , eService , propagationConstraint ) ;
try {
logger . trace ( " Going to create {} and {} for application {} : {} " , Activates . NAME , EService . NAME , applicationContext . configuration ( ) . name ( ) , ElementMapper . marshal ( activates ) ) ;
} catch ( Exception e ) {
}
try {
activates = resourceRegistryPublisher . createIsRelatedTo ( activates ) ;
hostingNode . attachResource ( activates ) ;
} catch ( NotFoundException e ) {
logger . error ( " THIS IS REALLY STRANGE. YOU SHOULD NOT BE HERE. Error while creating {}. " , activates , e ) ;
throw e ;
} catch ( ResourceRegistryException e ) {
logger . error ( " Error while creating {} " , activates , e ) ;
throw e ;
}
return activates ;
}
// public void removeEService() throws ResourceRegistryException {
// try {
// resourceRegistryPublisher.delete(eService);
// } catch (ResourceRegistryException e) {
// logger.error("Unable to delete {}. Going to set the state to {}", applicationContext.name(), getState());
// updateFacets();
// }
// }
public Map < UUID , String > getContextsUUID ( ) throws Exception {
return resourceRegistryPublisher . getResourceContexts ( eService ) ;
}
}