package org.gcube.smartgears.handler.resourceregistry.resourcemanager; import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.UUID; import javax.servlet.ServletRegistration; import org.gcube.informationsystem.model.impl.properties.HeaderImpl; import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl; import org.gcube.informationsystem.model.impl.relations.ConsistsOfImpl; 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.exceptions.AlreadyPresentException; 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.context.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException; import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisher; import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisherFactory; import org.gcube.resourcemanagement.model.impl.entities.facets.AccessPointFacetImpl; import org.gcube.resourcemanagement.model.impl.entities.facets.ServiceStateFacetImpl; import org.gcube.resourcemanagement.model.impl.entities.facets.SoftwareFacetImpl; 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.ServiceStateFacet; import org.gcube.resourcemanagement.model.reference.entities.facets.SoftwareFacet; 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; import org.gcube.smartgears.handler.resourceregistry.Constants; import org.gcube.smartgears.handler.resourceregistry.ContextUtility; import org.gcube.smartgears.handler.resourceregistry.EServiceHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EServiceManager { private static Logger logger = LoggerFactory.getLogger(HostingNodeManager.class); private static List servletExcludes = Arrays.asList("default", "jsp"); private ResourceRegistryPublisher resourceRegistryPublisher; private Activates activates; private EService eService; public EServiceManager() { this.resourceRegistryPublisher = ResourceRegistryPublisherFactory.create(); } public EService geteService() { return eService; } public void addToContext(ApplicationContext applicationContext) throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { HostingNode hostingNode = applicationContext.container().properties().lookup(Constants.HOSTING_NODE_MANAGER_PROPERTY) .value(HostingNodeManager.class).getHostingNode(); boolean added = resourceRegistryPublisher.addResourceToCurrentContext(hostingNode); if (added) { logger.info("{} successfully added to current context ({})", eService, ContextUtility.getCurrentContextName()); } else { logger.error("Unable to add {} to current context ({})", eService, ContextUtility.getCurrentContextName()); } } public void removeFromContext() throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { boolean removed = false; removed = resourceRegistryPublisher.removeResourceFromCurrentContext(eService); if (removed) { logger.info("{} successfully removed from current context ({})", eService, ContextUtility.getCurrentContextName()); } else { logger.error("Unable to remove {} from current context ({})", eService, ContextUtility.getCurrentContextName()); } } private String getBaseAddress(ApplicationContext context) { ApplicationConfiguration configuration = context.configuration(); ContainerConfiguration container = context.container().configuration(); 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, context.application().getContextPath()); } else { String protocol = container.protocol(); int port = container.port(); baseAddress = String.format("%s://%s:%d%s", protocol, container.hostname(), port, context.application().getContextPath()); } return baseAddress; } public String getState(ApplicationContext applicationContext) { return applicationContext.lifecycle().state().remoteForm().toLowerCase(); } private EService instantiateEService(ApplicationContext applicationContext) { 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 isIdentifiedBy = new IsIdentifiedByImpl( eService, softwareFacet); eService.addFacet(isIdentifiedBy); String baseAddress = getBaseAddress(applicationContext); 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); } } } ServiceStateFacet serviceStateFacet = new ServiceStateFacetImpl(); serviceStateFacet.setValue(getState(applicationContext)); eService.addFacet(serviceStateFacet); return eService; } public EService createEService(ApplicationContext applicationContext) throws ResourceRegistryException { try { eService = instantiateEService(applicationContext); activates = createActivatesRelation(applicationContext, eService); //eService = resourceRegistryPublisher.createResource(eService); } catch (AvailableInAnotherContextException | AlreadyPresentException e) { // resourceRegistryPublisher.delete(eService); // eService = resourceRegistryPublisher.createResource(eService); resourceRegistryPublisher.delete(activates); activates = createActivatesRelation(applicationContext, eService); } return eService; } public void updateServiceStateFacet(ApplicationContext applicationContext) throws ResourceRegistryException { String state = getState(applicationContext); ServiceStateFacet serviceStateFacet = null; List serviceStateFacets = eService.getFacets(ServiceStateFacet.class); if (serviceStateFacets != null && serviceStateFacets.size() >= 1) { serviceStateFacet = serviceStateFacets.get(0); serviceStateFacet.setValue(state); serviceStateFacet = resourceRegistryPublisher.updateFacet(serviceStateFacet); for (int i = 1; i < serviceStateFacets.size(); i++) { try { logger.warn("You should not be here. There are more than one {}. Anyway deleting it : {}", ServiceStateFacet.class.getSimpleName(), serviceStateFacets.get(i)); resourceRegistryPublisher.deleteFacet(serviceStateFacets.get(i)); } catch (Exception e) { logger.warn("Unable to delete {} which should not exists : {}", ServiceStateFacet.class.getSimpleName(), serviceStateFacets.get(i)); } } } else { serviceStateFacet = new ServiceStateFacetImpl(); serviceStateFacet.setValue(state); serviceStateFacet = resourceRegistryPublisher.createFacet(serviceStateFacet); ConsistsOf consistsOf = new ConsistsOfImpl( eService, serviceStateFacet, null); consistsOf = resourceRegistryPublisher.createConsistsOf(consistsOf); } // Newly created ServiceStateFacet must be added to all context ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(EServiceHandler.class.getClassLoader()); Set startTokens = applicationContext.configuration().startTokens(); for (String token : startTokens) { ContextUtility.setContextFromToken(token); addToContext(applicationContext); } } catch (ResourceRegistryException e) { throw e; } finally { ContextUtility.resetContex(); Thread.currentThread().setContextClassLoader(contextCL); } } private Activates createActivatesRelation(ApplicationContext applicationContext, EService eService) throws ResourceRegistryException { HostingNode hostingNode = applicationContext.container().properties().lookup(Constants.HOSTING_NODE_MANAGER_PROPERTY) .value(HostingNodeManager.class).getHostingNode(); PropagationConstraint propagationConstraint = new PropagationConstraintImpl(); propagationConstraint.setRemoveConstraint(RemoveConstraint.cascade); propagationConstraint.setAddConstraint(AddConstraint.propagate); Activates activates = new ActivatesImpl<>(hostingNode, eService, propagationConstraint); try { activates = resourceRegistryPublisher.createIsRelatedTo(activates); } catch (NotFoundException e) { logger.error("THIS IS REALLY STRANGE. YOU SHOULD NE BE HERE. Error while creating {}.", activates, e); throw e; } catch (ResourceRegistryException e) { logger.error("Error while creating {}", activates, e); throw e; } hostingNode.attachResource(activates); return activates; } public void removeEService(ApplicationContext applicationContext) throws ResourceRegistryException { try { resourceRegistryPublisher.delete(eService); } catch (ResourceRegistryException e) { logger.error("Unable to delete {}. Going to set the state to {}", applicationContext.name(), getState(applicationContext)); updateServiceStateFacet(applicationContext); } } }