diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..953de0b
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..4b4674f
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+
+
+ resource-registry-handlers
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ec4300d
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1380fb4
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,81 @@
+
+ 4.0.0
+ org.gcube.smartgears.handlers
+ resource-registry-handlers
+ 1.0.0-SNAPSHOT
+ Resource Registry Handler
+
+
+
+
+ org.gcube.distribution
+ gcube-bom
+ LATEST
+ pom
+ import
+
+
+ org.gcube.distribution
+ maven-smartgears-bom
+ LATEST
+ pom
+ import
+
+
+
+
+
+
+ org.gcube.information-system
+ resource-registry-publisher
+
+
+
+ org.gcube.information-system
+ resource-registry-client
+
+
+
+ org.gcube.core
+ common-events
+
+
+
+ org.gcube.core
+ common-smartgears
+
+
+
+ org.gcube.information-system
+ information-system-model
+
+
+
+ org.gcube.information-system
+ gcube-resources
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+ provided
+
+
+
+
+
+ ${artifactId}
+
+
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.7
+ 1.7
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java
new file mode 100644
index 0000000..83a6d37
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java
@@ -0,0 +1,34 @@
+package org.gcube.smartgears.handler.resourceregistry;
+
+import org.gcube.informationsystem.model.entity.resource.EService;
+import org.gcube.informationsystem.model.entity.resource.HostingNode;
+
+/**
+ * Library-wide constants.
+ *
+ *
+ * @author Fabio Simeoni
+ *
+ */
+public class Constants {
+
+
+ public static final String HOSTING_NODE_PROPERTY = HostingNode.NAME;
+
+
+ /**
+ * The configuration name of {@link EServiceManager} and {@link HostingNodeManager}.
+ */
+ public static final String RESOURCE_MANAGEMENT = "resource-management";
+
+
+
+ /**
+ * The name of the context property that contains the EService Resource.
+ */
+ public static final String ESERVICE_PROPERTY = EService.NAME;
+
+ public static final long default_container_publication_frequency_in_seconds = 60;
+
+ public static final int application_republish_frequency_in_minutes = 20;
+}
diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java
new file mode 100644
index 0000000..2b61f99
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java
@@ -0,0 +1,593 @@
+package org.gcube.smartgears.handler.resourceregistry;
+
+import static org.gcube.common.events.Observes.Kind.resilient;
+import static org.gcube.smartgears.handler.resourceregistry.Constants.ESERVICE_PROPERTY;
+import static org.gcube.smartgears.handler.resourceregistry.Constants.RESOURCE_MANAGEMENT;
+import static org.gcube.smartgears.handlers.ProfileEvents.addToContext;
+import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext;
+import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.activation;
+import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.failure;
+import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.stop;
+import static org.gcube.smartgears.utils.Utils.rethrowUnchecked;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletRegistration;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
+import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.events.Observes;
+import org.gcube.common.scope.api.ScopeProvider;
+import org.gcube.informationsystem.impl.embedded.HeaderImpl;
+import org.gcube.informationsystem.impl.embedded.PropagationConstraintImpl;
+import org.gcube.informationsystem.impl.embedded.ValueSchemaImpl;
+import org.gcube.informationsystem.impl.entity.facet.AccessPointFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.ServiceStateFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.SoftwareFacetImpl;
+import org.gcube.informationsystem.impl.entity.resource.EServiceImpl;
+import org.gcube.informationsystem.impl.relation.ConsistsOfImpl;
+import org.gcube.informationsystem.impl.relation.IsIdentifiedByImpl;
+import org.gcube.informationsystem.impl.relation.isrelatedto.HostsImpl;
+import org.gcube.informationsystem.model.embedded.Header;
+import org.gcube.informationsystem.model.embedded.PropagationConstraint;
+import org.gcube.informationsystem.model.embedded.PropagationConstraint.AddConstraint;
+import org.gcube.informationsystem.model.embedded.PropagationConstraint.RemoveConstraint;
+import org.gcube.informationsystem.model.embedded.ValueSchema;
+import org.gcube.informationsystem.model.entity.Facet;
+import org.gcube.informationsystem.model.entity.Resource;
+import org.gcube.informationsystem.model.entity.facet.AccessPointFacet;
+import org.gcube.informationsystem.model.entity.facet.ServiceStateFacet;
+import org.gcube.informationsystem.model.entity.facet.SoftwareFacet;
+import org.gcube.informationsystem.model.entity.resource.EService;
+import org.gcube.informationsystem.model.entity.resource.HostingNode;
+import org.gcube.informationsystem.model.relation.ConsistsOf;
+import org.gcube.informationsystem.model.relation.IsIdentifiedBy;
+import org.gcube.informationsystem.model.relation.IsRelatedTo;
+import org.gcube.informationsystem.model.relation.isrelatedto.Hosts;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceAlreadyPresentException;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException;
+import org.gcube.informationsystem.resourceregistry.client.proxy.Direction;
+import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClient;
+import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClientFactory;
+import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisher;
+import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisherFactory;
+import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
+import org.gcube.smartgears.configuration.container.ContainerConfiguration;
+import org.gcube.smartgears.context.Property;
+import org.gcube.smartgears.context.application.ApplicationContext;
+import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent;
+import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
+import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
+import org.gcube.smartgears.lifecycle.application.ApplicationState;
+import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
+import org.gcube.smartgears.provider.ProviderFactory;
+import org.gcube.smartgears.utils.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the {@link EService} {@link Resource} of the application.
+ *
+ * The manager:
+ *
+ * -
+ * creates the {@link EService} {@link Resource} and the facets it
+ * {@link ConsistsOf} when the application starts for the first time;
+ * -
+ * update the {@link ServiceStateFacet} when the application becomes active, and
+ * at any lifecycle change thereafter;
+ *
+ *
+ *
+ * @author Luca Frosini
+ */
+@XmlRootElement(name = RESOURCE_MANAGEMENT)
+public class EServiceManager extends ApplicationLifecycleHandler {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(EServiceManager.class);
+
+ private ApplicationContext applicationContext;
+ private AuthorizationProxy authorizationProxy;
+ private ScheduledFuture> periodicUpdates;
+
+ private static List servletExcludes = Arrays.asList("default","jsp");
+
+ public EServiceManager() {
+ super();
+ this.authorizationProxy = ProviderFactory.provider()
+ .authorizationProxy();
+ }
+
+ private void setContextFromToken(String token) {
+ if (token == null || token.compareTo("") == 0) {
+ SecurityTokenProvider.instance.reset();
+ ScopeProvider.instance.reset();
+ } else {
+ SecurityTokenProvider.instance.set(token);
+ String scope = getCurrentContextName(token);
+ ScopeProvider.instance.set(scope);
+ }
+
+ }
+
+ @Override
+ public void onStart(ApplicationLifecycleEvent.Start e) {
+ this.applicationContext = e.context();
+ EService eService = instantiateEService();
+ eService = publishEservice(eService);
+ registerObservers();
+ schedulePeriodicUpdates();
+ }
+
+ private void share(EService eService) {
+ logger.trace("sharing EService for {}", applicationContext.name());
+ applicationContext.properties().add(
+ new Property(ESERVICE_PROPERTY, eService));
+ }
+
+ // helpers
+ private void registerObservers() {
+
+ applicationContext.events().subscribe(new Object() {
+
+ @Observes({ activation, stop, failure })
+ void onChanged(ApplicationLifecycle lc) {
+ String state = lc.state().remoteForm().toLowerCase();
+ logger.debug("Moving app {} to {}", applicationContext.name(),
+ state);
+ EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class);
+ createOrUpdateServiceStateFacet(eService, state);
+ }
+
+ @Observes(value = addToContext)
+ void addTo(String token) {
+ EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class);
+ addToContext(eService, token);
+ }
+
+ @Observes(value = removeFromContext)
+ void removeFrom(String token) {
+ EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class);
+ removeFromContext(eService, token);
+ }
+ });
+ }
+
+ private void schedulePeriodicUpdates() {
+
+ // register to cancel updates
+ applicationContext.events().subscribe(
+
+ new Object() {
+
+ // we register it in response to lifecycle events so that we can
+ // stop and resume along with application
+ @Observes(value = { activation }, kind = resilient)
+ synchronized void restartPeriodicUpdates(
+ final ApplicationLifecycle lc) {
+
+ // already running
+ if (periodicUpdates != null) {
+ return;
+ }
+
+ if (lc.state() == ApplicationState.active) {
+ logger.info(
+ "scheduling periodic updates of application {} EService",
+ applicationContext.name());
+ } else {
+ logger.info(
+ "resuming periodic updates of application {} EService",
+ applicationContext.name());
+ }
+
+ final Runnable updateTask = new Runnable() {
+ public void run() {
+ EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class);
+ try {
+ String state = lc.state().remoteForm()
+ .toLowerCase();
+ createOrUpdateServiceStateFacet(eService, state);
+ } catch (Exception e) {
+ logger.error(
+ "cannot complete periodic update of EService",
+ e);
+ }
+ }
+ };
+
+ periodicUpdates = Utils.scheduledServicePool
+ .scheduleAtFixedRate(
+ updateTask,
+ Constants.application_republish_frequency_in_minutes,
+ Constants.application_republish_frequency_in_minutes,
+ TimeUnit.MINUTES);
+
+ }
+
+ @Observes(value = { stop, failure }, kind = resilient)
+ synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) {
+
+ if (periodicUpdates != null) {
+ logger.trace(
+ "stopping periodic updates of application {} EService",
+ applicationContext.name());
+
+ try {
+ periodicUpdates.cancel(true);
+ periodicUpdates = null;
+ } catch (Exception e) {
+ logger.warn(
+ "could not stop periodic updates of application {} EService",
+ applicationContext.name(), e);
+ }
+ }
+ }
+
+ });
+
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private void createHostsRelation(EService eService,
+ ResourceRegistryPublisher resourceRegistryPublisher) {
+ HostingNode hostingNode = applicationContext.container().properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class);
+
+ if (hostingNode != null) {
+
+ ResourceRegistryClient resourceRegistryClient = ResourceRegistryClientFactory.create();
+
+ Hosts hosts = null;
+
+ try {
+ List resources = resourceRegistryClient.getInstancesFromEntity(Hosts.NAME, false, hostingNode.getHeader().getUUID(), Direction.out);
+ for(Resource resource : resources){
+ if(resource instanceof HostingNode && resource.getHeader().getUUID().compareTo(hostingNode.getHeader().getUUID())==0){
+ List> isRelatedToList = resource.getIsRelatedTo();
+ for (IsRelatedTo extends Resource, ? extends Resource> isRelatedTo : isRelatedToList) {
+ if (isRelatedTo instanceof Hosts) {
+ if (isRelatedTo.getTarget().getHeader().getUUID()
+ .compareTo(eService.getHeader().getUUID()) == 0) {
+ hosts = (Hosts) isRelatedTo;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ }catch (Exception e) {
+ logger.error("Error while trying to retrieve Hosts relation", e);
+ }
+
+ if (hosts == null) {
+
+ PropagationConstraint propagationConstraint = new PropagationConstraintImpl();
+ propagationConstraint
+ .setRemoveConstraint(RemoveConstraint.cascade);
+ propagationConstraint
+ .setAddConstraint(AddConstraint.propagate);
+
+ hosts = new HostsImpl<>(hostingNode, eService,
+ propagationConstraint);
+
+ try {
+ hosts = resourceRegistryPublisher.createIsRelatedTo(
+ Hosts.class, hosts);
+ } catch (ResourceNotFoundException e) {
+ logger.error("THIS IS REALLY STRANGE. YOU SHOULD NE BE HERE. Error while creating {}.", hosts, e);
+ } catch (ResourceRegistryException e) {
+ logger.error("Error while creating {}", hosts, e);
+ }
+ }
+ }
+ }
+
+ private EService createEServiceAndHosts(
+ ResourceRegistryPublisher resourceRegistryPublisher,
+ EService eService) throws ResourceRegistryException {
+ try {
+ eService = resourceRegistryPublisher.createResource(EService.class,
+ eService);
+ } catch (ResourceAlreadyPresentException e) {
+ ResourceRegistryClient registryClient = ResourceRegistryClientFactory
+ .create();
+ eService = registryClient.getInstance(EService.class, eService
+ .getHeader().getUUID());
+ }
+
+ try {
+ createHostsRelation(eService, resourceRegistryPublisher);
+ } catch (Exception ex) {
+ logger.error(
+ "Unable to Create {} relation from {} to {} ({} : {})",
+ Hosts.NAME, HostingNode.NAME, EService.NAME,
+ applicationContext.name(), eService.getHeader().getUUID(),
+ ex);
+ }
+
+ return eService;
+ }
+
+ private EService publishEservice(EService eService) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ EServiceManager.class.getClassLoader());
+
+ boolean create = true;
+
+ Set startTokens = applicationContext.configuration()
+ .startTokens();
+ for (String token : startTokens) {
+ setContextFromToken(token);
+
+ try {
+ ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory
+ .create();
+ if (create) {
+
+ eService = createEServiceAndHosts(
+ resourceRegistryPublisher, eService);
+
+ create = false;
+
+ } else {
+ boolean added = resourceRegistryPublisher
+ .addResourceToContext(eService);
+
+ if (added) {
+ logger.info(
+ "{} successfully added to current context ({})",
+ eService, getCurrentContextName(token));
+ share(eService);
+ } else {
+ logger.error(
+ "Unable to add {} to current context ({})",
+ eService, getCurrentContextName(token));
+ }
+ }
+
+ share(eService);
+
+ } catch (ResourceRegistryException e) {
+ logger.error("Unable to add {} to current context ({})",
+ eService, getCurrentContextName(token), e);
+ }
+
+ }
+
+ } catch (Exception e) {
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+
+ return eService;
+
+ }
+
+ private String getCurrentContextName(String token) {
+ try {
+ return this.authorizationProxy.get(token).getContext();
+ } catch (Exception e) {
+ logger.error("Error retrieving token {}, it should never happen",
+ token);
+ return null;
+ }
+ }
+
+ private void removeFromContext(EService eService, String token) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ EServiceManager.class.getClassLoader());
+ setContextFromToken(token);
+
+ boolean removed = false;
+
+ ResourceRegistryPublisher resourceRegistryPublisher =
+ ResourceRegistryPublisherFactory.create();
+ removed = resourceRegistryPublisher
+ .removeResourceFromContext(eService);
+
+ if (removed) {
+ logger.info(
+ "{} successfully removed from current context ({})",
+ eService, getCurrentContextName(token));
+ share(eService);
+ } else {
+ logger.error("Unable to remove {} from current context ({})",
+ eService, getCurrentContextName(token));
+ }
+
+ share(eService);
+
+ } catch (Exception e) {
+ logger.error("Unable to remove {} from current context ({})",
+ eService, getCurrentContextName(token), e);
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ }
+
+ private void addToContext(EService eService, String token) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ EServiceManager.class.getClassLoader());
+ setContextFromToken(token);
+
+ ResourceRegistryPublisher resourceRegistryPublisher =
+ ResourceRegistryPublisherFactory.create();
+ boolean added = resourceRegistryPublisher
+ .addResourceToContext(eService);
+
+ if (added) {
+ logger.info("{} successfully added to current context ({})",
+ eService, getCurrentContextName(token));
+ share(eService);
+ } else {
+ logger.error("Unable to add {} to current context ({})",
+ eService, getCurrentContextName(token));
+ }
+
+ share(eService);
+
+ } catch (Exception e) {
+ logger.error("Unable to add {} to current context ({})", eService,
+ getCurrentContextName(token), e);
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ }
+
+ private void createOrUpdateServiceStateFacet(EService eService, String state) {
+
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+
+ if (previousToken == null) {
+ setContextFromToken((String) applicationContext.configuration()
+ .startTokens().toArray()[0]);
+ }
+ Thread.currentThread().setContextClassLoader(
+ EServiceManager.class.getClassLoader());
+
+ ServiceStateFacet serviceStateFacet = null;
+
+ List> consistsOfList = eService
+ .getConsistsOf();
+ for (ConsistsOf extends Resource, ? extends Facet> c : consistsOfList) {
+ if (c.getTarget() instanceof ServiceStateFacet) {
+ serviceStateFacet = (ServiceStateFacet) c.getTarget();
+ break;
+ }
+ }
+
+ ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory
+ .create();
+ try {
+ serviceStateFacet.setValue(state);
+ serviceStateFacet = resourceRegistryPublisher.updateFacet(
+ ServiceStateFacet.class, serviceStateFacet);
+
+ } catch (Exception e) {
+ try {
+ ConsistsOf consistsOf = new ConsistsOfImpl(
+ eService, serviceStateFacet, null);
+ @SuppressWarnings("unchecked")
+ ConsistsOf createdConsistsOf = resourceRegistryPublisher.createConsistsOf(ConsistsOf.class, consistsOf);
+
+ eService.addFacet(createdConsistsOf);
+ } catch (Exception ex) {
+ eService = createEServiceAndHosts(
+ resourceRegistryPublisher, eService);
+ }
+ }
+
+ share(eService);
+
+ } catch (Exception e) {
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+
+ }
+
+ private EService instantiateEService() {
+ logger.info("Creating EService for {}", applicationContext.name());
+
+ ApplicationConfiguration applicationConfiguration = applicationContext
+ .configuration();
+
+ UUID uuid = UUID.fromString(this.applicationContext.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, null);
+ eService.addFacet(isIdentifiedBy);
+
+ ApplicationConfiguration configuration = applicationContext.configuration();
+ ContainerConfiguration container = applicationContext.container().configuration();
+
+ String baseAddress;
+ if (configuration.proxied()){
+ String protocol = container.proxyAddress().secure()? "https://": "http://";
+ int port = container.proxyAddress().port();
+ baseAddress=String.format("%s%s:%d%s", protocol , container.proxyAddress().hostname(), port,applicationContext.application().getContextPath());
+ } else {
+ String protocol = configuration.secure()? "https://": "http://";
+ int port = configuration.secure()?container.securePort(): container.port();
+ baseAddress=String.format("%s%s:%d%s", protocol , container.hostname(), port,applicationContext.application().getContextPath());
+ }
+
+
+ for (ServletRegistration servlet : applicationContext.application()
+ .getServletRegistrations().values()) {
+ if (!servletExcludes.contains(servlet.getName())) {
+ for (String mapping : servlet.getMappings()) {
+
+
+ /*String address = ProfileBuilder.getAddressFromBaseAddress(
+ baseAddress, mapping);
+ */
+ 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();
+ String state = applicationContext.lifecycle().state().remoteForm()
+ .toLowerCase();
+ serviceStateFacet.setValue(state.toLowerCase());
+ eService.addFacet(serviceStateFacet);
+
+ return eService;
+ }
+
+ @Override
+ public String toString() {
+ return RESOURCE_MANAGEMENT;
+ }
+
+}
diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java
new file mode 100644
index 0000000..d552de8
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java
@@ -0,0 +1,807 @@
+package org.gcube.smartgears.handler.resourceregistry;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.gcube.common.events.Observes.Kind.resilient;
+import static org.gcube.smartgears.handlers.ProfileEvents.addToContext;
+import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext;
+import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.activation;
+import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.failure;
+import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.part_activation;
+import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.shutdown;
+import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.stop;
+import static org.gcube.smartgears.lifecycle.container.ContainerState.active;
+import static org.gcube.smartgears.utils.Utils.rethrowUnchecked;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
+import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.events.Observes;
+import org.gcube.common.scope.api.ScopeProvider;
+import org.gcube.informationsystem.impl.embedded.HeaderImpl;
+import org.gcube.informationsystem.impl.entity.facet.CPUFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.ContainerStateFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.MemoryFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.NetworkingFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.SimplePropertyFacetImpl;
+import org.gcube.informationsystem.impl.entity.facet.SoftwareFacetImpl;
+import org.gcube.informationsystem.impl.entity.resource.HostingNodeImpl;
+import org.gcube.informationsystem.impl.relation.IsIdentifiedByImpl;
+import org.gcube.informationsystem.impl.relation.consistsof.HasPersistentMemoryImpl;
+import org.gcube.informationsystem.impl.relation.consistsof.HasVolatileMemoryImpl;
+import org.gcube.informationsystem.model.embedded.Header;
+import org.gcube.informationsystem.model.entity.Facet;
+import org.gcube.informationsystem.model.entity.Resource;
+import org.gcube.informationsystem.model.entity.facet.CPUFacet;
+import org.gcube.informationsystem.model.entity.facet.ContainerStateFacet;
+import org.gcube.informationsystem.model.entity.facet.MemoryFacet;
+import org.gcube.informationsystem.model.entity.facet.MemoryFacet.MemoryUnit;
+import org.gcube.informationsystem.model.entity.facet.NetworkingFacet;
+import org.gcube.informationsystem.model.entity.facet.SimplePropertyFacet;
+import org.gcube.informationsystem.model.entity.facet.SoftwareFacet;
+import org.gcube.informationsystem.model.entity.resource.HostingNode;
+import org.gcube.informationsystem.model.relation.ConsistsOf;
+import org.gcube.informationsystem.model.relation.IsIdentifiedBy;
+import org.gcube.informationsystem.model.relation.consistsof.HasPersistentMemory;
+import org.gcube.informationsystem.model.relation.consistsof.HasVolatileMemory;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceAlreadyPresentException;
+import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException;
+import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClient;
+import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClientFactory;
+import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisher;
+import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisherFactory;
+import org.gcube.smartgears.configuration.container.ContainerConfiguration;
+import org.gcube.smartgears.configuration.library.SmartGearsConfiguration;
+import org.gcube.smartgears.context.Property;
+import org.gcube.smartgears.context.container.ContainerContext;
+import org.gcube.smartgears.handlers.container.ContainerHandler;
+import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent.Start;
+import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
+import org.gcube.smartgears.provider.ProviderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the {@link HostingNode} {@link Resource} of the application.
+ *
+ * The manager:
+ *
+ * -
+ * creates the {@link HostingNode} {@link Resource} and the facets it
+ * {@link ConsistsOf} when the container starts for the first time;
+ * -
+ * update the {@link ContainerStateFacet} when the application becomes active,
+ * and at any lifecycle change thereafter;
+ * -
+ * schedule a periodic update of {@link Facet}s containing variables
+ * information.
+ *
+ *
+ *
+ * @author Luca Frosini
+ */
+@XmlRootElement(name = Constants.RESOURCE_MANAGEMENT)
+public class HostingNodeManager extends ContainerHandler {
+
+ private static Logger logger = LoggerFactory
+ .getLogger(HostingNodeManager.class);
+
+ public static final String MEMORY_TYPE = "memoryType";
+ public static final String MEMORY_TYPE_RAM = "RAM";
+ public static final String MEMORY_TYPE_JVM = "JVM";
+ public static final String JVM_MAX_MEMORY = "jvmMaxMemory";
+
+ public static final String MESSAGE = "message";
+
+ private ContainerContext context;
+ private AuthorizationProxy authorizationProxy;
+
+ private ScheduledFuture> periodicUpdates;
+
+ public HostingNodeManager() {
+ super();
+ this.authorizationProxy = ProviderFactory.provider()
+ .authorizationProxy();
+ }
+
+ private void setContextFromToken(String token) {
+ if (token == null || token.compareTo("") == 0) {
+ SecurityTokenProvider.instance.reset();
+ ScopeProvider.instance.reset();
+ } else {
+ SecurityTokenProvider.instance.set(token);
+ String scope = getCurrentContextName(token);
+ ScopeProvider.instance.set(scope);
+ }
+
+ }
+
+ @Override
+ public void onStart(Start e) {
+ context = e.context();
+ HostingNode hostingNode = instantiateHostingNode();
+ hostingNode = publishHostingNode(hostingNode);
+ registerObservers();
+ schedulePeriodicUpdates();
+ }
+
+ private void share(HostingNode hostingNode) {
+ logger.trace("sharing {} {}", HostingNode.NAME, Resource.NAME);
+ context.properties().add(
+ new Property(Constants.HOSTING_NODE_PROPERTY, hostingNode));
+ }
+
+ private void registerObservers() {
+
+ context.events().subscribe(new Object() {
+
+ @Observes({ activation, part_activation, shutdown, stop, failure })
+ void onChanged(ContainerLifecycle lc) {
+ HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class);
+ updateHostingNode(hostingNode);
+ }
+
+ @Observes(value = addToContext)
+ void addTo(String token) {
+ HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class);
+ addToContext(hostingNode, token);
+ }
+
+ @Observes(value = removeFromContext)
+ void removeFrom(String token) {
+ HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class);
+ removeFromContext(hostingNode, token);
+ }
+
+ });
+ }
+
+ private void schedulePeriodicUpdates() {
+
+ // register to cancel updates
+ context.events().subscribe(
+
+ new Object() {
+
+ final ScheduledExecutorService service = Executors
+ .newScheduledThreadPool(1);
+
+ // we register it in response to lifecycle events so that we can
+ // stop and resume along with application
+ @Observes(value = { activation, part_activation }, kind = resilient)
+ synchronized void restartPeriodicUpdates(ContainerLifecycle lc) {
+
+ // already running
+ if (periodicUpdates != null) {
+ return;
+ }
+
+ if (lc.state() == active) {
+ logger.info("scheduling periodic updates of {}",
+ HostingNode.NAME);
+ } else {
+ logger.info("resuming periodic updates of {}",
+ HostingNode.NAME);
+ }
+
+ final Runnable updateTask = new Runnable() {
+ public void run() {
+ HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class);
+ try {
+ updateHostingNode(hostingNode);
+ } catch (Exception e) {
+ logger.error(
+ "cannot complete periodic update of {}",
+ HostingNode.NAME, e);
+ }
+ }
+ };
+
+ periodicUpdates = service
+ .scheduleAtFixedRate(updateTask, 3, context
+ .configuration().publicationFrequency(),
+ SECONDS);
+
+ }
+
+ @Observes(value = { stop, failure, shutdown }, kind = resilient)
+ synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) {
+
+ if (periodicUpdates != null) {
+ logger.trace("stopping periodic updates of {}",
+ HostingNode.NAME);
+ try {
+ periodicUpdates.cancel(true);
+ service.shutdownNow();
+ periodicUpdates = null;
+ } catch (Exception e) {
+ logger.warn("could not stop periodic updates of {}",
+ HostingNode.NAME, e);
+ }
+ }
+ }
+
+ });
+
+ }
+
+ private HostingNode publishHostingNode(HostingNode hostingNode) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ HostingNodeManager.class.getClassLoader());
+
+ boolean create = true;
+
+ List startTokens = context.configuration().startTokens();
+ for (String token : startTokens) {
+ setContextFromToken(token);
+
+ try {
+ ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory
+ .create();
+
+ if (create) {
+
+ try {
+ hostingNode = resourceRegistryPublisher
+ .createResource(HostingNode.class,
+ hostingNode);
+
+ // TODO Add a Reference to Site
+ /*
+ * node.profile().newSite().country(cfg.site().country
+ * ()).location(cfg.site ().location())
+ * .latitude(cfg
+ * .site().latitude()).longitude(cfg.site
+ * ().longitude
+ * ()).domain(domainIn(cfg.hostname()));
+ */
+
+ } catch (ResourceAlreadyPresentException e) {
+ ResourceRegistryClient registryClient = ResourceRegistryClientFactory
+ .create();
+ hostingNode = registryClient.getInstance(
+ HostingNode.class, hostingNode.getHeader()
+ .getUUID());
+ }
+
+ create = false;
+
+ } else {
+ boolean added = resourceRegistryPublisher
+ .addResourceToContext(hostingNode);
+ if (added) {
+ logger.info(
+ "{} successfully added to current context ({})",
+ hostingNode, getCurrentContextName(token));
+ share(hostingNode);
+ } else {
+ logger.error(
+ "Unable to add {} to current context ({})",
+ hostingNode, getCurrentContextName(token));
+ }
+ }
+ share(hostingNode);
+
+ } catch (Exception e) {
+ logger.error("Unable to add {} to current context ({})",
+ hostingNode, getCurrentContextName(token), e);
+ }
+
+ }
+
+ } catch (Exception e) {
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ return hostingNode;
+ }
+
+ private String getCurrentContextName(String token) {
+ try {
+ return this.authorizationProxy.get(token).getContext();
+ } catch (Exception e) {
+ logger.error("Error retrieving context form token {}, it should never happen",
+ token, e);
+ return null;
+ }
+ }
+
+ private void removeFromContext(HostingNode hostingNode, String token) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ HostingNodeManager.class.getClassLoader());
+ setContextFromToken(token);
+
+ boolean removed = false;
+
+ ResourceRegistryPublisher resourceRegistryPublisher =
+ ResourceRegistryPublisherFactory.create();
+ removed = resourceRegistryPublisher.
+ removeResourceFromContext(hostingNode);
+
+ if (removed) {
+ logger.info(
+ "{} successfully removed from current context ({})",
+ hostingNode, getCurrentContextName(token));
+ share(hostingNode);
+ } else {
+ logger.error("Unable to remove {} from current context ({})",
+ hostingNode, getCurrentContextName(token));
+ }
+
+ share(hostingNode);
+
+ } catch (Exception e) {
+ logger.error("Unable to remove {} from current context ({})",
+ hostingNode, getCurrentContextName(token), e);
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ }
+
+ private void addToContext(HostingNode hostingNode, String token) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+ Thread.currentThread().setContextClassLoader(
+ HostingNodeManager.class.getClassLoader());
+ setContextFromToken(token);
+
+ ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory
+ .create();
+ boolean added = resourceRegistryPublisher
+ .addResourceToContext(hostingNode);
+
+ if (added) {
+ logger.info("{} successfully added to current context ({})",
+ hostingNode, getCurrentContextName(token));
+ share(hostingNode);
+ } else {
+ logger.error("Unable to add {} to current context ({})",
+ hostingNode, getCurrentContextName(token));
+ }
+
+ share(hostingNode);
+
+ } catch (Exception e) {
+ logger.error("Unable to add {} to current context ({})",
+ hostingNode, getCurrentContextName(token), e);
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ }
+
+ private HostingNode updateHostingNode(HostingNode hostingNode) {
+ ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ String previousToken = SecurityTokenProvider.instance.get();
+ try {
+
+ if (previousToken == null) {
+ setContextFromToken((String) context.configuration()
+ .startTokens().toArray()[0]);
+ }
+ Thread.currentThread().setContextClassLoader(
+ HostingNodeManager.class.getClassLoader());
+
+ ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory
+ .create();
+
+ hostingNode = updateFacets(hostingNode, resourceRegistryPublisher);
+
+ share(hostingNode);
+
+ } catch (Exception e) {
+ rethrowUnchecked(e);
+ } finally {
+ setContextFromToken(previousToken);
+ Thread.currentThread().setContextClassLoader(contextCL);
+ }
+ return hostingNode;
+
+ }
+
+ private HostingNode updateFacets(HostingNode hostingNode,
+ ResourceRegistryPublisher resourceRegistryPublisher) throws ResourceRegistryException {
+ logger.debug("Updating HostingNode");
+
+ ContainerStateFacet containerStateFacet = null;
+ MemoryFacet ramFacet = null;
+ MemoryFacet jvmMemoryFacet = null;
+ MemoryFacet disk = null;
+
+ List> consistsOfToRemove = new ArrayList<>();
+
+ List> consistsOfList = hostingNode
+ .getConsistsOf();
+ for (ConsistsOf extends Resource, ? extends Facet> c : consistsOfList) {
+ if (c.getTarget() instanceof ContainerStateFacet) {
+ containerStateFacet = (ContainerStateFacet) c.getTarget();
+ containerStateFacet = getContainerStateFacet(containerStateFacet);
+ continue;
+ }
+
+ if (c instanceof HasVolatileMemory) {
+ String memoryType = (String) c
+ .getAdditionalProperty(MEMORY_TYPE);
+ if (memoryType.compareTo(MEMORY_TYPE_RAM) == 0) {
+ ramFacet = (MemoryFacet) c.getTarget();
+ ramFacet = getRamInfo(ramFacet);
+ continue;
+ }
+
+ if (memoryType.compareTo(MEMORY_TYPE_JVM) == 0) {
+ jvmMemoryFacet = (MemoryFacet) c.getTarget();
+ jvmMemoryFacet = getJVMMemoryInfo(jvmMemoryFacet);
+ continue;
+ }
+
+ }
+
+ if (c instanceof HasPersistentMemory) {
+ disk = (MemoryFacet) c.getTarget();
+ disk = getDiskSpace(disk);
+ continue;
+ }
+
+ consistsOfToRemove.add(c);
+
+ }
+
+ // Resource Update has affect an all specified facet.
+ // Removing the one that have not to be changed
+ consistsOfList.removeAll(consistsOfToRemove);
+
+ try {
+ hostingNode = resourceRegistryPublisher.updateResource(
+ HostingNode.class, hostingNode);
+ } catch (ResourceNotFoundException e) {
+ /* Update failed trying to recreate it */
+ // ReAdding the removed relations to recreate all
+ consistsOfList.addAll(consistsOfToRemove);
+ hostingNode = resourceRegistryPublisher.createResource(
+ HostingNode.class, hostingNode);
+ }
+
+ return hostingNode;
+ }
+
+ private HostingNode instantiateHostingNode() {
+ logger.info("Creating {} {}", HostingNode.NAME, Resource.NAME);
+
+ ContainerConfiguration containerConfiguration = context.configuration();
+
+ UUID uuid = UUID.fromString(this.context.id());
+ HostingNode hostingNode = new HostingNodeImpl();
+ Header header = new HeaderImpl(uuid);
+ hostingNode.setHeader(header);
+
+ NetworkingFacet networkingFacet = new NetworkingFacetImpl();
+ try {
+ networkingFacet.setIPAddress(InetAddress.getLocalHost()
+ .getHostAddress());
+ } catch (UnknownHostException e) {
+ logger.warn("unable to detect the IP address of the host");
+ }
+ String hostname = containerConfiguration.hostname();
+ networkingFacet.setHostName(hostname);
+ networkingFacet.setDomainName(getDomain(hostname));
+
+ networkingFacet.setAdditionalProperty("Port",
+ containerConfiguration.port());
+ IsIdentifiedBy isIdentifiedBy = new IsIdentifiedByImpl<>(
+ hostingNode, networkingFacet, null);
+ hostingNode.addFacet(isIdentifiedBy);
+
+ List cpuFacets = getCPUFacets();
+ for (CPUFacet cpuFacet : cpuFacets) {
+ hostingNode.addFacet(cpuFacet);
+ }
+
+ SoftwareFacet softwareFacet = new SoftwareFacetImpl();
+ OperatingSystemMXBean mxbean = ManagementFactory
+ .getOperatingSystemMXBean();
+ softwareFacet.setGroup(mxbean.getName()); // softwareFacet.setGroup(System.getProperty("os.name"));
+ softwareFacet.setName(mxbean.getArch()); // softwareFacet.setName(System.getProperty("os.arch"));
+ softwareFacet.setVersion(mxbean.getVersion()); // softwareFacet.setName(System.getProperty("os.version"));
+ hostingNode.addFacet(softwareFacet);
+
+ SimplePropertyFacet simplePropertyFacet = addEnvironmentVariables();
+ hostingNode.addFacet(simplePropertyFacet);
+
+ ContainerStateFacet containerStateFacet = getContainerStateFacet(null);
+ hostingNode.addFacet(containerStateFacet);
+
+ MemoryFacet ramFacet = getRamInfo(null);
+ HasVolatileMemory hasVolatileRAMMemory = new HasVolatileMemoryImpl(
+ hostingNode, ramFacet, null);
+ hasVolatileRAMMemory
+ .setAdditionalProperty(MEMORY_TYPE, MEMORY_TYPE_RAM);
+ hostingNode.addFacet(hasVolatileRAMMemory);
+
+ MemoryFacet jvmMemoryFacet = getJVMMemoryInfo(null);
+ HasVolatileMemory hasVolatileJVMMemory = new HasVolatileMemoryImpl(
+ hostingNode, jvmMemoryFacet, null);
+ hasVolatileJVMMemory
+ .setAdditionalProperty(MEMORY_TYPE, MEMORY_TYPE_JVM);
+ hostingNode.addFacet(hasVolatileJVMMemory);
+
+ MemoryFacet diskFacet = getDiskSpace(null);
+ HasPersistentMemory hasPersistentMemory = new HasPersistentMemoryImpl(
+ hostingNode, diskFacet, null);
+ hostingNode.addFacet(hasPersistentMemory);
+
+ return hostingNode;
+ }
+
+ private ContainerStateFacet getContainerStateFacet(
+ ContainerStateFacet containerStateFacet) {
+ if (containerStateFacet == null) {
+ containerStateFacet = new ContainerStateFacetImpl();
+ }
+ containerStateFacet.setValue(context.lifecycle().state().remoteForm());
+ return containerStateFacet;
+ }
+
+ private MemoryFacet getDiskSpace(MemoryFacet memoryFacet) {
+ if (memoryFacet == null) {
+ memoryFacet = new MemoryFacetImpl();
+ }
+
+ long free = 0;
+ long total = 0;
+ try {
+ FileStore fileStore = Files.getFileStore(Paths.get(context
+ .configuration().persistence().location()));
+ free = fileStore.getUsableSpace() / 1048576; // 1048576 = 1024*1024
+ // user to convert
+ // bytes in MByte
+ total = fileStore.getTotalSpace() / 1048576; // 1048576 = 1024*1024
+ // user to convert
+ // bytes in MByte
+ } catch (IOException ioe) {
+ logger.warn("Unable to detect disk space information", ioe);
+ memoryFacet.setAdditionalProperty(MESSAGE,
+ "Unable to detect disk space information.");
+ }
+
+ memoryFacet.setUnit(MemoryUnit.MB);
+ memoryFacet.setSize(total);
+ memoryFacet.setUsed(total - free);
+
+ return memoryFacet;
+ }
+
+ @SuppressWarnings("restriction")
+ private MemoryFacet getRamInfo(MemoryFacet memoryFacet) {
+ if (memoryFacet == null) {
+ memoryFacet = new MemoryFacetImpl();
+ }
+
+ OperatingSystemMXBean mxbean = ManagementFactory
+ .getOperatingSystemMXBean();
+ com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean;
+ long freeMemory = sunmxbean.getFreePhysicalMemorySize() / 1048576; // in
+ // MB
+ long totalMemory = sunmxbean.getTotalPhysicalMemorySize() / 1048576; // in
+ // MB
+
+ memoryFacet.setUnit(MemoryUnit.MB);
+ memoryFacet.setSize(totalMemory);
+ memoryFacet.setUsed(totalMemory - freeMemory);
+
+ return memoryFacet;
+ }
+
+ private MemoryFacet getJVMMemoryInfo(MemoryFacet memoryFacet) {
+ if (memoryFacet == null) {
+ memoryFacet = new MemoryFacetImpl();
+ }
+
+ /* 1048576 = 1024*1024 used to convert bytes in MByte */
+ long jvmFreeMemory = Runtime.getRuntime().freeMemory() / 1048576;
+ long jvmTotalMemory = Runtime.getRuntime().totalMemory() / 1048576;
+ long jvmMaxMemory = Runtime.getRuntime().maxMemory() / 1048576;
+
+ memoryFacet.setUnit(MemoryUnit.MB);
+ memoryFacet.setSize(jvmTotalMemory);
+ memoryFacet.setUsed(jvmTotalMemory - jvmFreeMemory);
+ memoryFacet.setAdditionalProperty(JVM_MAX_MEMORY, jvmMaxMemory);
+
+ return memoryFacet;
+ }
+
+ private static String sanitizeKey(String key) {
+ return key.trim().replace(" ", "_");
+ }
+
+ private SimplePropertyFacet addEnvironmentVariables() {
+
+ ContainerConfiguration cfg = context.configuration();
+
+ Map map = new HashMap();
+ map.putAll(cfg.properties());
+ map.putAll(System.getenv());
+
+ SimplePropertyFacet simplePropertyFacet = new SimplePropertyFacetImpl();
+ simplePropertyFacet.setName("ENVIRONMENT_VARIABLES");
+ simplePropertyFacet.setValue("");
+
+ for (Map.Entry entry : map.entrySet()) {
+ String varname = entry.getKey();
+ if ((varname.compareToIgnoreCase("CLASSPATH") == 0)
+ || (varname.compareToIgnoreCase("PATH") == 0)
+ || (varname.contains("SSH")) || (varname.contains("MAIL"))
+ || (varname.compareToIgnoreCase("LS_COLORS") == 0)) {
+ continue;
+ }
+
+ simplePropertyFacet.setAdditionalProperty(
+ sanitizeKey(entry.getKey()), entry.getValue());
+
+ }
+
+ simplePropertyFacet.setAdditionalProperty("Java",
+ System.getProperty("java.version"));
+ SmartGearsConfiguration config = ProviderFactory.provider()
+ .smartgearsConfiguration();
+
+ simplePropertyFacet.setAdditionalProperty("SmartGears",
+ config.version());
+ simplePropertyFacet.setAdditionalProperty(
+ "ghn-update-interval-in-secs",
+ String.valueOf(cfg.publicationFrequency()));
+
+ return simplePropertyFacet;
+ }
+
+ private static String getDomain(String hostname) {
+ try {
+ Pattern pattern = Pattern
+ .compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
+ Matcher regexMatcher = pattern.matcher(hostname);
+ if (regexMatcher.matches()) { // it's an IP address, nothing to trim
+ return hostname;
+ }
+ return hostname.substring(hostname.indexOf(".") + 1);
+ } catch (Exception e) {
+ logger.warn("Error while getting domain from hostname");
+ return hostname;
+ }
+ }
+
+ public static final String CPU_PROCESSOR = "processor";
+ public static final String CPU_VENDOR_ID = "vendor_id";
+ public static final String CPU_MODEL_NAME = "model name";
+ public static final String CPU_CPU_MHZ = "cpu MHz";
+ public static final String CPU_MODEL_T = "model\t";
+ public static final String CPU_MODEL_B = "model\b";
+ public static final String CPU_MODEL_NUMBER = "modelNumber";
+
+ public static List getCPUFacets() {
+
+ List cpuFacets = new ArrayList<>();
+
+ File file = new File("/proc/cpuinfo");
+
+ if (!file.exists()) {
+ logger.warn("cannot acquire CPU info (no /proc/cpuinfo)");
+ return cpuFacets;
+ }
+
+ BufferedReader input = null;
+
+ try {
+ input = new BufferedReader(new FileReader(file));
+
+ String line = null;
+
+ CPUFacet cpuFacet = null;
+
+ while ((line = input.readLine()) != null) {
+
+ if ((line.startsWith(CPU_PROCESSOR))) { // add the current
+ // processor to the map
+ cpuFacet = new CPUFacetImpl();
+ cpuFacets.add(cpuFacet);
+ }
+
+ try {
+ if (line.contains(CPU_VENDOR_ID)) {
+ cpuFacet.setVendor(line.split(":")[1].trim());
+ continue;
+ }
+ } catch (Exception e) {
+ continue;
+ }
+
+ try {
+ if (line.contains(CPU_MODEL_NAME)) {
+ cpuFacet.setModel(line.split(":")[1].trim());
+ continue;
+ }
+ } catch (Exception e) {
+ continue;
+ }
+
+ try {
+ if (line.contains(CPU_CPU_MHZ)) {
+ cpuFacet.setClockSpeed(line.split(":")[1].trim());
+ continue;
+ }
+ } catch (Exception e) {
+ continue;
+ }
+
+ try {
+ if ((line.contains(CPU_MODEL_T))
+ || (line.contains(CPU_MODEL_B))) {
+ cpuFacet.setAdditionalProperty(CPU_MODEL_NUMBER,
+ line.split(":")[1].trim());
+ continue;
+ }
+ } catch (Exception e) {
+ continue;
+ }
+
+ try {
+ String[] nameValue = line.split(":");
+ cpuFacet.setAdditionalProperty(sanitizeKey(nameValue[0]),
+ line.split(":")[1].trim());
+ } catch (Exception e) {
+
+ }
+
+ }
+ } catch (Exception e) {
+ logger.warn("unable to acquire CPU info", e);
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ logger.warn("unable to close stream", e);
+ }
+ }
+ }
+ return cpuFacets;
+ }
+
+ @Override
+ public String toString() {
+ return Constants.RESOURCE_MANAGEMENT;
+ }
+}
diff --git a/src/main/resources/META-INF/gcube-application-handlers.xml b/src/main/resources/META-INF/gcube-application-handlers.xml
new file mode 100644
index 0000000..19718e4
--- /dev/null
+++ b/src/main/resources/META-INF/gcube-application-handlers.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/main/resources/META-INF/gcube-container-handlers.xml b/src/main/resources/META-INF/gcube-container-handlers.xml
new file mode 100644
index 0000000..ff86c79
--- /dev/null
+++ b/src/main/resources/META-INF/gcube-container-handlers.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler
new file mode 100644
index 0000000..5fa2b01
--- /dev/null
+++ b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler
@@ -0,0 +1 @@
+org.gcube.smartgears.handler.resourceregistry.EServiceManager
\ No newline at end of file
diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler
new file mode 100644
index 0000000..469f25f
--- /dev/null
+++ b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler
@@ -0,0 +1 @@
+org.gcube.smartgears.handler.resourceregistry.HostingNodeManager
\ No newline at end of file