PersistenceConfiguration(Class extends PersistenceWriter> implementationClass, T writerConfiguration) {
+ super();
+ this.implementationClass = implementationClass;
+ this.writerConfiguration = writerConfiguration;
+ }
+
+ public Class extends PersistenceWriter> getImplementationClass() {
+ return this.implementationClass;
+ }
+
+ public ComponentConfiguration getWriterConfiguration() {
+ return writerConfiguration;
+ }
+
+}
diff --git a/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java b/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java
new file mode 100644
index 0000000..731b20c
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java
@@ -0,0 +1,42 @@
+package org.gcube.smartgears.configuration;
+
+import org.gcube.common.validator.annotations.NotEmpty;
+import org.gcube.common.validator.annotations.NotNull;
+
+public class ProxyAddress {
+
+ @NotNull @NotEmpty
+ String protocol = "http";
+
+ @NotNull @NotEmpty
+ String hostname;
+
+ @NotNull
+ Integer port;
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+
+}
diff --git a/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java
new file mode 100644
index 0000000..43d6311
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java
@@ -0,0 +1,15 @@
+package org.gcube.smartgears.configuration;
+
+public class SmartgearsConfiguration {
+
+ private String version;
+
+ public SmartgearsConfiguration(String version) {
+ super();
+ this.version = version;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+}
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java
index c7e1257..8f46c9d 100644
--- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java
+++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java
@@ -1,167 +1,182 @@
package org.gcube.smartgears.configuration.application;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
import java.util.Set;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.persistence.Persistence;
+import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect;
+import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
+import org.gcube.com.fasterxml.jackson.annotation.JsonInclude;
+import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include;
+import org.gcube.com.fasterxml.jackson.annotation.JsonProperty;
+import org.gcube.common.validator.ValidationError;
+import org.gcube.common.validator.Validator;
+import org.gcube.common.validator.ValidatorFactory;
+import org.gcube.common.validator.annotations.NotEmpty;
+import org.gcube.common.validator.annotations.NotNull;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
/**
- * The configuration of the application.
- *
- * @author Fabio Simeoni
+ * The configuration of a managed app.
+ *
+ * Includes the list of its client services.
+ *
+ * @author Lucio Lelii
*
*/
-public interface ApplicationConfiguration {
+@JsonInclude(value = Include.NON_NULL)
+@JsonAutoDetect(fieldVisibility = Visibility.ANY)
+public class ApplicationConfiguration {
+
+ @NotNull
+ String name;
+
+ @NotNull
+ String group;
+
+ @NotNull
+ String version;
+
+ String description="";
+
+ @JsonIgnore
+ String context;
+
+ private boolean proxable = true;
+
+ Set excludes= new HashSet<>();
+
+ Set includes= new HashSet<>();
+
+ @NotEmpty @JsonProperty("persistence")
+ PersistenceConfiguration persistenceConfiguration;
+
+ public Set excludes() {
+ return excludes;
+ }
+
+ public Set includes() {
+ return includes;
+ }
+
+ public ApplicationConfiguration() {}
+
+ public String name() {
+ return name;
+ }
+
+ public String context() {
+ return context;
+ }
+
+ public ApplicationConfiguration excludes(GCubeExclude ... excludes) {
+ this.excludes=new HashSet(Arrays.asList(excludes));
+ return this;
+ }
+
+ public ApplicationConfiguration includes(GCubeInclude... includes) {
+ this.includes=new HashSet(Arrays.asList(includes));
+ return this;
+ }
+
+ public ApplicationConfiguration context(String context) {
+ this.context = context;
+ return this;
+ }
+
+ public ApplicationConfiguration name(String name) {
+ this.name=name;
+ return this;
+ }
+
+ public ApplicationConfiguration persistenceConfiguration(PersistenceConfiguration configuration) {
+ this.persistenceConfiguration = configuration;
+ return this;
+ }
+
+ public ApplicationConfiguration proxable(boolean proxable) {
+ this.proxable = proxable;
+ return this;
+ }
+
+ public String group() {
+ return group;
+ }
+
+
+ public ApplicationConfiguration group(String group) {
+ this.group=group;
+ return this;
+ }
+
+ public String version() {
+ return version;
+ }
+
+ public ApplicationConfiguration version(String version) {
+ this.version=version;
+ return this;
+ }
- /**
- * Returns the management mode of the application.
- * @return the management mode
- */
- Mode mode();
+ public String description() {
+ return description;
+ }
-
-
- /**
- * Returns the context path of the application
- * @return the context path
- */
- String context();
-
- boolean proxied();
-
- /**
- * Sets the context path of the application
- * @param context the context path
- * @return this configuration
- */
- ApplicationConfiguration context(String context);
-
- /**
- * Sets the management mode of this application.
- * @param the management mode
- * @return this configuration
- */
- ApplicationConfiguration mode(Mode mode);
-
-
- /**
- * Returns the name of the application.
- * @return the name
- */
- String name();
-
-
- /**
- * Sets the name of the application.
- * @param name the name
- * @return this configuration
- */
- ApplicationConfiguration name(String name);
+ public ApplicationConfiguration description(String description) {
+ this.description=description;
+ return this;
+ }
- /**
- * Returns the class of the application
- * @return the class
- */
- String serviceClass();
+ public boolean proxable() {
+ return proxable;
+ }
+
+ public PersistenceConfiguration persistenceConfiguration() {
+ return persistenceConfiguration;
+ }
+
+ public void validate() {
+
+ List msgs = new ArrayList();
+
+ Validator validator = ValidatorFactory.validator();
+
+ for (ValidationError error : validator.validate(this))
+ msgs.add(error.toString());
+
+ if (!this.excludes().isEmpty() && !this.includes().isEmpty())
+ msgs.add("exclude tags and includes tags are mutually exclusive");
+
+ if (!msgs.isEmpty())
+ throw new IllegalStateException("invalid configuration: "+msgs);
+
+ }
- /**
- * Sets the class of the application.
- * @param serviceClass the class
- * @return this configuration
- */
- ApplicationConfiguration serviceClass(String serviceClass);
+ @Override
+ public int hashCode() {
+ return Objects.hash(description, excludes, group, includes, name, proxable, version);
+ }
- /**
- * Returns the version of the application.
- * @return the version
- */
- String version();
-
- /**
- * Sets the version of the application.
- * @param version the version
- * @return this configuration
- */
- ApplicationConfiguration version(String version);
-
- /**
- * Returns the description of the application.
- * @return the description
- */
- String description();
-
- /**
- * Sets the description of the application.
- * @param description the description
- * @return this configuration
- */
- ApplicationConfiguration description(String description);
-
- ProxyAddress proxyAddress();
-
- ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress);
-
- /**
- * Returns the tokens in which the application operates when it first starts.
- * @return the tokens
- */
- Set startTokens();
-
- /**
- * Sets the tokens in which the application operates when it first starts.
- * @param scopes the scopes
- * @return this configuration
- */
- ApplicationConfiguration startTokens(Set tokens);
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ApplicationConfiguration other = (ApplicationConfiguration) obj;
+ return Objects.equals(description, other.description)
+ && Objects.equals(excludes, other.excludes) && Objects.equals(group, other.group)
+ && Objects.equals(includes, other.includes) && Objects.equals(name, other.name)
+ && proxable == other.proxable && Objects.equals(version, other.version);
+ }
- /**
- * Returns the persistence manager of the application.
- * @return the manager
- */
- Persistence persistence();
-
- /**
- * Returns a set of request paths that should not be subjected to request management.
- * @return the set of exclude paths.
- */
- Set excludes();
-
- /**
- * Returns a set of request paths that should be subjected to request management.
- * @return the set of exclude paths.
- */
- Set includes();
-
-
- /**
- * Sets the persistence manager of the application.
- * @param manager the manager
- * @return this configuration
- */
- ApplicationConfiguration persistence(Persistence manager);
-
-
- /**
- * Validates this configuration.
- *
- * @throws IllegalStateException if the configuration is not valid
- */
- void validate();
-
-
- /**
- * Merges this configuration with another configuration
- * @param config the other configuration
- */
- void merge(ApplicationConfiguration config);
-
- ApplicationConfiguration excludes(Exclude ... excludes);
-
- ApplicationConfiguration includes(Include ... includes);
-
-
-
}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java
index 9a81583..f7699a1 100644
--- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java
+++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java
@@ -1,18 +1,22 @@
package org.gcube.smartgears.configuration.application;
-import static org.gcube.smartgears.utils.Utils.*;
-
+import java.io.File;
import java.io.InputStream;
-import java.lang.reflect.Modifier;
-import java.util.HashSet;
-import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.LinkedList;
+import java.util.List;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-
-import org.gcube.smartgears.extensions.ApplicationExtension;
-import org.gcube.smartgears.handlers.application.ApplicationHandler;
+import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
+import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
+import org.gcube.smartgears.handlers.application.RequestHandler;
+import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager;
+import org.gcube.smartgears.handlers.application.request.RequestAccounting;
+import org.gcube.smartgears.handlers.application.request.RequestMetrics;
+import org.gcube.smartgears.handlers.application.request.RequestValidator;
+import org.gcube.smartgears.persistence.LocalWriter;
+import org.gcube.smartgears.persistence.LocalWriterConfiguration;
+import org.gcube.smartgears.utils.Utils;
+import org.yaml.snakeyaml.Yaml;
/**
* Binds {@link ApplicationConfiguration}s to and from XML serialisations.
@@ -29,21 +33,28 @@ public class ApplicationConfigurationBinder {
* @return the configuration
* @throws RuntimeException if the serialisation is invalid
*/
- public ApplicationConfiguration bind(InputStream stream) {
-
+ public ApplicationConfiguration load(InputStream stream) {
try {
+ Yaml yaml = new Yaml();
+ ObjectMapper mapper = new ObjectMapper();
+ String mapAsString = mapper.writeValueAsString(yaml.load(stream));
- JAXBContext ctx = JAXBContext.newInstance(DefaultApplicationConfiguration.class);
+ ApplicationConfiguration conf = mapper.readValue(mapAsString, ApplicationConfiguration.class);
- return (ApplicationConfiguration) ctx.createUnmarshaller().unmarshal(stream);
+ if (conf.persistenceConfiguration() == null) {
+ String location = String.format("%s/state/%s_%s", Utils.home(), conf.group(), conf.name());
+ File dir = new File(location);
+ if (!dir.exists())
+ dir.mkdirs();
- } catch (JAXBException e) {
+ conf.persistenceConfiguration(
+ new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location)));
- throw new RuntimeException("invalid service configuration", e);
+ }
- }
- finally {
- closeSafely(stream);
+ return conf;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
}
@@ -54,96 +65,82 @@ public class ApplicationConfigurationBinder {
* @return the handlers
* @throws RuntimeException if the serialisation is invalid
*/
- public ApplicationHandlers bindHandlers(InputStream stream) {
+ public ApplicationHandlers bindHandlers(ClassLoader classLoader) {
- //collects handler classes
- Set> classes = scanForHandlers();
+ List requestHandlers = new LinkedList();
- try {
+ // ADDING BASE Handler (order is important)
+ requestHandlers.add(new RequestMetrics());
+ requestHandlers.add(new RequestValidator());
+ requestHandlers.add(new RequestAccounting());
- JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class>[0]));
+ // TODO scan RequestHAndler form classloader
- return (ApplicationHandlers) ctx.createUnmarshaller().unmarshal(stream);
+ List lifecycleHandlers = new LinkedList();
- } catch (JAXBException e) {
+ // ADDING BASE Handler (order is important)
+ lifecycleHandlers.add(new ApplicationProfileManager());
- throw unchecked(e);
+ // TODO scan ApplicationLifecycleHandler form classloader
+
+ return new ApplicationHandlers(lifecycleHandlers, requestHandlers);
- }
- finally {
- closeSafely(stream);
- }
}
-
+
/**
* Returns the extensions of the application from their XML serialisation.
*
* @param stream the serialisation
* @return the extensions
* @throws RuntimeException if the serialisation is invalid
+ *
+ * public ApplicationExtensions
+ * bindExtensions(InputStream stream) {
+ *
+ * //collects handler classes Set> classes =
+ * scanForExtensions();
+ *
+ * try {
+ *
+ * JAXBContext ctx =
+ * JAXBContext.newInstance(classes.toArray(new
+ * Class>[0]));
+ *
+ * return (ApplicationExtensions)
+ * ctx.createUnmarshaller().unmarshal(stream);
+ *
+ * } catch (JAXBException e) {
+ *
+ * throw unchecked(e);
+ *
+ * } finally { closeSafely(stream); } }
+ *
+ *
+ *
+ * private Set> scanForExtensions() throws
+ * RuntimeException {
+ *
+ * @SuppressWarnings("all")
+ * ServiceLoader handlerLoader =
+ * (ServiceLoader)
+ * ServiceLoader.load(ApplicationExtension.class);
+ *
+ * Set> scanned = new HashSet>();
+ *
+ * for (ApplicationExtension handler : handlerLoader) {
+ * Class> handlerClass = handler.getClass(); if
+ * (handlerClass.isInterface() ||
+ * handlerClass.getModifiers() == Modifier.ABSTRACT)
+ * continue; else scanned.add(handlerClass); }
+ *
+ * //add top-level configuration
+ * scanned.add(ApplicationExtensions.class);
+ *
+ * return scanned; }
*/
- public ApplicationExtensions bindExtensions(InputStream stream) {
- //collects handler classes
- Set> classes = scanForExtensions();
-
- try {
-
- JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class>[0]));
-
- return (ApplicationExtensions) ctx.createUnmarshaller().unmarshal(stream);
-
- } catch (JAXBException e) {
-
- throw unchecked(e);
-
- }
- finally {
- closeSafely(stream);
- }
+ public void scanForApplicationHandlers(ClassLoader currentClassLoader) {
+ // TODO Auto-generated method stub
}
-
-
-
- private Set> scanForHandlers() throws RuntimeException {
- @SuppressWarnings("all")
- ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationHandler.class);
-
- Set> scanned = new HashSet>();
-
- for (ApplicationHandler> handler : handlerLoader) {
- Class> handlerClass = handler.getClass();
- if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
- continue;
- else
- scanned.add(handlerClass);
- }
-
- //add top-level configuration
- scanned.add(ApplicationHandlers.class);
-
- return scanned;
- }
-
- private Set> scanForExtensions() throws RuntimeException {
-
- @SuppressWarnings("all")
- ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationExtension.class);
-
- Set> scanned = new HashSet>();
-
- for (ApplicationExtension handler : handlerLoader) {
- Class> handlerClass = handler.getClass();
- if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
- continue;
- else
- scanned.add(handlerClass);
- }
-
- //add top-level configuration
- scanned.add(ApplicationExtensions.class);
-
- return scanned;
- }
}
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java
deleted file mode 100644
index 53496de..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.gcube.smartgears.configuration.application;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.annotation.XmlAnyElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.validator.ValidationError;
-import org.gcube.common.validator.Validator;
-import org.gcube.common.validator.ValidatorFactory;
-import org.gcube.common.validator.annotations.IsValid;
-import org.gcube.smartgears.extensions.ApplicationExtension;
-import org.w3c.dom.Element;
-
-/**
- * The {@link ApplicationExtension}s that manage the application.
- *
- * @author Fabio Simeoni
- *
- */
-@XmlRootElement(name="extensions")
-public class ApplicationExtensions {
-
- @XmlAnyElement(lax=true) @IsValid
- List extensions = new ArrayList();
-
- public ApplicationExtensions() {}
-
- /**
- * Returns the extensions for the application.
- * @return the extensions
- */
- public List extensions() {
- return extensions;
- }
-
- /**
- * Sets the extensions for the application.
- * @param extensions the extensions
- * @return this configuration
- */
- public ApplicationExtensions set(ApplicationExtension ... extensions) {
- this.extensions = Arrays.asList(extensions);
- return this;
- }
-
- @Override
- public String toString() {
- return extensions.toString();
- }
-
- public void validate() {
-
- List msgs = new ArrayList();
-
- Validator validator = ValidatorFactory.validator();
-
- for (ValidationError error : validator.validate(this))
- msgs.add(error.toString());
-
- if (!msgs.isEmpty())
- throw new IllegalStateException("invalid configuration: "+msgs);
-
- }
-
- //since we use @AnyElement, after deserialisation, we check there are no DOM elements
- void afterUnmarshal(Unmarshaller u, Object parent) {
- for (Object o : extensions)
- if (o instanceof Element)
- throw new RuntimeException("invalid extensions detected: "+Element.class.cast(o).getLocalName());
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java
index a0c553c..eade558 100644
--- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java
+++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java
@@ -1,21 +1,11 @@
package org.gcube.smartgears.configuration.application;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.annotation.XmlAnyElement;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import org.gcube.common.validator.ValidationError;
-import org.gcube.common.validator.Validator;
-import org.gcube.common.validator.ValidatorFactory;
-import org.gcube.common.validator.annotations.IsValid;
import org.gcube.smartgears.handlers.application.ApplicationHandler;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.RequestHandler;
-import org.w3c.dom.Element;
/**
* The {@link ApplicationHandler}s that manage the application.
@@ -23,24 +13,24 @@ import org.w3c.dom.Element;
* @author Fabio Simeoni
*
*/
-@XmlRootElement(name="handlers")
public class ApplicationHandlers {
- @XmlElement(name="lifecycle") @IsValid
- private LifecycleHandlers lifecycleHandlers = new LifecycleHandlers();
+ private List lifecycleHandlers = new LinkedList();
- @XmlElement(name="request") @IsValid
- private RequestHandlers requestHandlers = new RequestHandlers();
+ private List requestHandlers = new LinkedList();
- public ApplicationHandlers() {}
+ public ApplicationHandlers(List lifecycleHandlers, List requestHandlers) {
+ this.lifecycleHandlers = lifecycleHandlers;
+ this.requestHandlers = requestHandlers;
+ }
/**
* Returns the {@link ApplicationLifecycleHandler}s for the service.
* @return the lifecycle handlers
*/
public List lifecycleHandlers() {
- return lifecycleHandlers.values;
+ return lifecycleHandlers;
}
/**
@@ -48,8 +38,8 @@ public class ApplicationHandlers {
* @param handlers the lifecycle handlers
* @return this configuration
*/
- public ApplicationHandlers set(ApplicationLifecycleHandler ... handlers) {
- this.lifecycleHandlers = new LifecycleHandlers(Arrays.asList(handlers));
+ public ApplicationHandlers setLifecycleHandlers(List handlers) {
+ this.lifecycleHandlers = handlers;
return this;
}
@@ -58,7 +48,7 @@ public class ApplicationHandlers {
* @return the lifetime handlers
*/
public List requestHandlers() {
- return requestHandlers.values;
+ return requestHandlers;
}
/**
@@ -66,75 +56,11 @@ public class ApplicationHandlers {
* @param handlers the request handlers
* @return this configuration
*/
- public ApplicationHandlers set(RequestHandler ... handlers) {
- this.requestHandlers = new RequestHandlers(Arrays.asList(handlers));
+ public ApplicationHandlers setRequetHandlers(List handlers) {
+ this.requestHandlers = handlers;
return this;
}
-
- public void validate() {
-
- List msgs = new ArrayList();
-
- Validator validator = ValidatorFactory.validator();
-
- for (ValidationError error : validator.validate(this))
- msgs.add(error.toString());
-
- if (!msgs.isEmpty())
- throw new IllegalStateException("invalid configuration: "+msgs);
-
- }
-
- //////////////// HELPER BINDING CLASSES
-
- //used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension
-
- private static class LifecycleHandlers {
-
- @SuppressWarnings("all")
- LifecycleHandlers() { //needed for deserialisation
- }
-
- LifecycleHandlers(List handlers) {
- this.values=handlers;
- }
-
- @XmlAnyElement(lax=true)
- List values = new ArrayList();
-
-
- //since we use @AnyElement, after deserialisation, we check there are no DOM elements
- @SuppressWarnings("unused")
- void afterUnmarshal(Unmarshaller u, Object parent) {
- for (Object o : values)
- if (o instanceof Element)
- throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName());
- }
-
- }
-
- //used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension
- private static class RequestHandlers {
-
- @SuppressWarnings("all")
- RequestHandlers() { //needed for deserialisation
- }
-
- RequestHandlers(List handlers) {
- this.values=handlers;
- }
-
- @XmlAnyElement(lax=true)
- List values = new ArrayList();
-
- //since we use @AnyElement, after deserialisation, we check there are no DOM elements
- @SuppressWarnings("unused")
- void afterUnmarshal(Unmarshaller u, Object parent) {
- for (Object o : values)
- if (o instanceof Element)
- throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName());
- }
- }
+
public void mergeWith(ApplicationHandlers other){
List lifecycles = other.lifecycleHandlers();
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java
deleted file mode 100644
index caa3de1..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.gcube.smartgears.configuration.application;
-
-import static org.gcube.smartgears.configuration.Mode.offline;
-
-import java.io.File;
-import java.util.Set;
-
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.configuration.container.ContainerConfiguration;
-import org.gcube.smartgears.persistence.DefaultPersistence;
-import org.gcube.smartgears.persistence.Persistence;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- * @author Fabio Simeoni
- * @author Luca Frosini (ISTI - CNR)
- */
-public class BridgedApplicationConfiguration implements ApplicationConfiguration {
-
- private static Logger log = LoggerFactory.getLogger(ApplicationConfiguration.class);
-
- private final ContainerConfiguration container;
- private final ApplicationConfiguration application;
-
-
- public BridgedApplicationConfiguration(ContainerConfiguration container, ApplicationConfiguration config) {
-
- this.container=container;
- this.application=config;
-
- if (application.persistence()==null) {
-
- String location = container.persistence().location()+"/"+application.name();
- File dir = new File(location);
- if (!dir.exists())
- dir.mkdirs();
-
- application.persistence(new DefaultPersistence(location));
-
- log.trace("setting persistence location for {} @ {}",application.name(), dir.getAbsolutePath());
- }
-
- }
-
- public ApplicationConfiguration inner() {
- return application;
- }
-
- public Mode mode() {
- return container.mode()==offline?offline:application.mode();
- }
-
- @Override
- public String context() {
- return application.context();
- }
-
- @Override
- public ApplicationConfiguration context(String context) {
- return application.context(context);
- }
-
- public String name() {
- return application.name();
- }
-
- public ApplicationConfiguration name(String name) {
- return application.name(name);
- }
-
- public String serviceClass() {
- return application.serviceClass();
- }
-
- public ApplicationConfiguration serviceClass(String group) {
- return application.serviceClass(group);
- }
-
- public String version() {
- return application.version();
- }
-
- public ApplicationConfiguration version(String version) {
- return application.version(version);
- }
-
- public String description() {
- return application.description();
- }
-
- public ProxyAddress proxyAddress() {
- return application.proxyAddress();
- }
-
- public ApplicationConfiguration description(String description) {
- return application.description(description);
- }
-
- public Persistence persistence() {
- return application.persistence();
- }
-
- public ApplicationConfiguration persistence(Persistence manager) {
- return application.persistence(manager);
- }
-
- public ApplicationConfiguration mode(Mode mode) {
- return application.mode(mode);
- }
-
- public void validate() {
-
- application.validate();
-
- }
-
- @Override
- public Set excludes() {
- return application.excludes();
- }
-
- @Override
- public Set includes() {
- return application.includes();
- }
-
- @Override
- public void merge(ApplicationConfiguration config) {
- application.merge(config);
- }
-
-
- @Override
- public Set startTokens() {
- return application.startTokens();
- }
-
- @Override
- public ApplicationConfiguration startTokens(Set tokens) {
- return application.startTokens(tokens);
- }
-
-
- @Override
- public boolean proxied() {
- return application.proxied();
- }
-
- @Override
- public ApplicationConfiguration excludes(Exclude ... excludes) {
- return application.excludes(excludes);
- }
-
- @Override
- public ApplicationConfiguration includes(Include... includes) {
- return application.includes(includes);
- }
-
- @Override
- public ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress) {
- return application.proxyAddress(proxyaddress);
- }
-
-
-}
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java
deleted file mode 100644
index a4fe514..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package org.gcube.smartgears.configuration.application;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-
-import org.gcube.common.validator.ValidationError;
-import org.gcube.common.validator.Validator;
-import org.gcube.common.validator.ValidatorFactory;
-import org.gcube.common.validator.annotations.IsValid;
-import org.gcube.common.validator.annotations.NotNull;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.persistence.DefaultPersistence;
-import org.gcube.smartgears.persistence.Persistence;
-
-/**
- * The configuration of a managed app.
- *
- * Includes the list of its client services.
- *
- * @author Fabio Simeoni
- * @author Luca Frosini (ISTI - CNR)
- *
- */
-@XmlRootElement(name="application")
-public class DefaultApplicationConfiguration implements ApplicationConfiguration {
-
-
- @XmlAttribute
- private Mode mode = Mode.online;
-
- @XmlAttribute(name="context")
- String context;
-
- @XmlElement(name="name" , required=true)
- @NotNull
- String name;
-
- @XmlElement(name="group", required=true)
- @NotNull
- String group;
-
- @XmlElement(name="version", required=true)
- @NotNull
- String version;
-
- @XmlTransient
- Set tokens = new HashSet();
-
- @XmlElement(name="description")
- String description="";
-
- @XmlElementRef
- @IsValid
- ProxyAddress proxyAddress;
-
- @XmlElementRef
- Set excludes= new LinkedHashSet();
-
- @XmlElementRef
- Set includes= new LinkedHashSet();
-
- @XmlElementRef(type=DefaultPersistence.class)
- @NotNull @IsValid
- private Persistence persistenceManager;
-
- @Override
- public Set excludes() {
- return excludes;
- }
-
-
- @Override
- public Set includes() {
- return includes;
- }
-
- public DefaultApplicationConfiguration() {}
-
- @Override
- public Mode mode() {
- return mode;
- }
-
- @Override
- public String name() {
- return name;
- }
-
- @Override
- public String context() {
- return context;
- }
-
- @Override
- public ApplicationConfiguration context(String context) {
- this.context=context;
- return this;
- }
-
- public ProxyAddress proxyAddress() {
- return proxyAddress;
- }
-
- @Override
- public ApplicationConfiguration excludes(Exclude ... excludes) {
- this.excludes=new HashSet(Arrays.asList(excludes));
- return this;
- }
-
- @Override
- public ApplicationConfiguration includes(Include... includes) {
- this.includes=new HashSet(Arrays.asList(includes));
- return this;
- }
-
- @Override
- public ApplicationConfiguration name(String name) {
- this.name=name;
- return this;
- }
-
- @Override
- public String serviceClass() {
- return group;
- }
-
-
- @Override
- public ApplicationConfiguration serviceClass(String group) {
- this.group=group;
- return this;
- }
-
- @Override
- public String version() {
- return version;
- }
-
- @Override
- public ApplicationConfiguration version(String version) {
- this.version=version;
- return this;
- }
-
- @Override
- public Set startTokens() {
- return tokens;
- }
-
- @Override
- public ApplicationConfiguration startTokens(Set tokens) {
- this.tokens.addAll(tokens);
- return this;
- }
-
- @Override
- public String description() {
- return description;
- }
-
- @Override
- public ApplicationConfiguration description(String description) {
- this.description=description;
- return this;
- }
-
- @Override
- public boolean proxied() {
- return proxyAddress!=null;
- }
-
- @Override
- public Persistence persistence() {
- return persistenceManager;
- }
-
- @Override
- public ApplicationConfiguration persistence(Persistence manager) {
- this.persistenceManager=manager;
- return this;
- }
-
- @Override
- public ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress) {
- this.proxyAddress = proxyaddress;
- return this;
- }
-
- @Override
- public ApplicationConfiguration mode(Mode mode) {
- this.mode=mode;
- return this;
- }
-
- @Override
- public void validate() {
-
- List msgs = new ArrayList();
-
- Validator validator = ValidatorFactory.validator();
-
- for (ValidationError error : validator.validate(this))
- msgs.add(error.toString());
-
- if (!this.excludes().isEmpty() && !this.includes().isEmpty())
- msgs.add("exclude tags and includes tags are mutually exclusive");
-
- if (!msgs.isEmpty())
- throw new IllegalStateException("invalid configuration: "+msgs);
-
- }
-
-
- @Override
- public void merge(ApplicationConfiguration config) {
-
- mode(config.mode());
-
- if (config.persistence()!=null)
- persistence(config.persistence());
-
- //scopes.addAll(config.startScopes());
-
- }
-
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/Exclude.java b/src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java
similarity index 68%
rename from src/main/java/org/gcube/smartgears/configuration/application/Exclude.java
rename to src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java
index 579758b..264500b 100644
--- a/src/main/java/org/gcube/smartgears/configuration/application/Exclude.java
+++ b/src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java
@@ -3,20 +3,14 @@ package org.gcube.smartgears.configuration.application;
import java.util.ArrayList;
import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlValue;
+import org.gcube.common.validator.annotations.NotEmpty;
-@XmlRootElement(name="exclude")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class Exclude {
+public class GCubeExclude {
- @XmlAttribute(name="handlers")
+ @NotEmpty
private List handlers = new ArrayList();
- @XmlValue
+ @NotEmpty
private String path;
public List getHandlers() {
@@ -27,14 +21,14 @@ public class Exclude {
return path;
}
- protected Exclude() {}
+ protected GCubeExclude() {}
- public Exclude(String path) {
+ public GCubeExclude(String path) {
super();
this.path = path;
}
- public Exclude(List handlers, String path) {
+ public GCubeExclude(List handlers, String path) {
super();
this.handlers = handlers;
this.path = path;
@@ -57,7 +51,7 @@ public class Exclude {
return false;
if (getClass() != obj.getClass())
return false;
- Exclude other = (Exclude) obj;
+ GCubeExclude other = (GCubeExclude) obj;
if (handlers == null) {
if (other.handlers != null)
return false;
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/Include.java b/src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java
similarity index 69%
rename from src/main/java/org/gcube/smartgears/configuration/application/Include.java
rename to src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java
index e8486c7..8991456 100644
--- a/src/main/java/org/gcube/smartgears/configuration/application/Include.java
+++ b/src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java
@@ -3,20 +3,14 @@ package org.gcube.smartgears.configuration.application;
import java.util.ArrayList;
import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlValue;
+import org.gcube.common.validator.annotations.NotEmpty;
-@XmlRootElement(name="include")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class Include {
+public class GCubeInclude {
- @XmlAttribute(name="handlers")
+ @NotEmpty
private List handlers = new ArrayList();
- @XmlValue
+ @NotEmpty
private String path;
public List getHandlers() {
@@ -27,14 +21,14 @@ public class Include {
return path;
}
- protected Include() {}
+ protected GCubeInclude() {}
- public Include(String path) {
+ public GCubeInclude(String path) {
super();
this.path = path;
}
- public Include(List handlers, String path) {
+ public GCubeInclude(List handlers, String path) {
super();
this.handlers = handlers;
this.path = path;
@@ -57,7 +51,7 @@ public class Include {
return false;
if (getClass() != obj.getClass())
return false;
- Include other = (Include) obj;
+ GCubeInclude other = (GCubeInclude) obj;
if (handlers == null) {
if (other.handlers != null)
return false;
diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java b/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java
deleted file mode 100644
index ae9bb97..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.gcube.smartgears.configuration.application;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.validator.annotations.NotNull;
-
-@XmlRootElement(name="proxy")
-public class ProxyAddress {
-
-
- @XmlAttribute
- String protocol = "http";
-
- @XmlElement
- @NotNull
- String hostname;
-
- @XmlElement
- Integer port;
-
- public String hostname() {
- return hostname;
- }
-
- public ProxyAddress hostname(String hostname) {
- this.hostname = hostname;
- return this;
- }
-
- public Integer port() {
- return port;
- }
-
- public ProxyAddress port(int port) {
- this.port = port;
- return this;
- }
-
- public String protocol() {
- return protocol;
- }
-
- public ProxyAddress protocol(String protocol) {
- this.protocol = protocol;
- return this;
- }
-
-
- @Override
- public String toString() {
- return "ProxyAddress [protocol=" + protocol + ", hostname=" + hostname + ", port=" + port + "]";
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((hostname == null) ? 0 : hostname.hashCode());
- result = prime * result + ((port == null) ? 0 : port.hashCode());
- result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ProxyAddress other = (ProxyAddress) obj;
- if (hostname == null) {
- if (other.hostname != null)
- return false;
- } else if (!hostname.equals(other.hostname))
- return false;
- if (port == null) {
- if (other.port != null)
- return false;
- } else if (!port.equals(other.port))
- return false;
- if (protocol == null) {
- if (other.protocol != null)
- return false;
- } else if (!protocol.equals(other.protocol))
- return false;
- return true;
- }
-
-
-
-
-
-}
diff --git a/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java
new file mode 100644
index 0000000..31af311
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java
@@ -0,0 +1,99 @@
+package org.gcube.smartgears.configuration.container;
+
+import static org.gcube.smartgears.Constants.default_container_publication_frequency_in_seconds;
+
+import org.gcube.common.validator.annotations.NotEmpty;
+import org.gcube.common.validator.annotations.NotNull;
+import org.gcube.smartgears.configuration.Mode;
+
+public class BaseConfiguration {
+
+
+ Mode mode = Mode.online;
+
+ @NotNull @NotEmpty
+ String hostname;
+
+ @NotNull
+ Integer port;
+
+ @NotNull @NotEmpty
+ String protocol="http";
+
+ boolean authorizeChildrenContext = false;
+
+ @NotNull @NotEmpty
+ String infrastructure;
+
+ long publicationFrequencyInSeconds = default_container_publication_frequency_in_seconds;
+
+ public Mode getMode() {
+ return mode;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public Integer getPort() {
+ return port;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public boolean isAuthorizeChildrenContext() {
+ return authorizeChildrenContext;
+ }
+
+ public String getInfrastructure() {
+ return infrastructure;
+ }
+
+
+
+ public long getPublicationFrequencyInSeconds() {
+ return publicationFrequencyInSeconds;
+ }
+
+ public void setPublicationFrequencyInSeconds(long publicationFrequencyInSeconds) {
+ this.publicationFrequencyInSeconds = publicationFrequencyInSeconds;
+ }
+
+ public void setMode(Mode mode) {
+ this.mode = mode;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public void setPort(Integer port) {
+ this.port = port;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public void setAuthorizeChildrenContext(boolean authorizeChildrenContext) {
+ this.authorizeChildrenContext = authorizeChildrenContext;
+ }
+
+ public void setInfrastructure(String infrastructure) {
+ this.infrastructure = infrastructure;
+ }
+
+
+ @Override
+ public String toString() {
+ return "BaseConfiguration [mode=" + mode + ", hostname=" + hostname + ", port=" + port + ", protocol="
+ + protocol + ", authorizeChildrenContext=" + authorizeChildrenContext + ", infrastructure="
+ + infrastructure + ", publicationFrequency=" + publicationFrequencyInSeconds
+ + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java
index f138d93..128b968 100644
--- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java
+++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java
@@ -1,20 +1,10 @@
package org.gcube.smartgears.configuration.container;
-import static org.gcube.smartgears.Constants.default_container_publication_frequency_in_seconds;
-import static org.gcube.smartgears.utils.Utils.notNull;
-
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
import org.gcube.common.validator.ValidationError;
import org.gcube.common.validator.Validator;
@@ -22,11 +12,11 @@ import org.gcube.common.validator.ValidatorFactory;
import org.gcube.common.validator.annotations.IsValid;
import org.gcube.common.validator.annotations.NotEmpty;
import org.gcube.common.validator.annotations.NotNull;
+import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration;
import org.gcube.smartgears.configuration.Mode;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
+import org.gcube.smartgears.configuration.ProxyAddress;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
-import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration;
-import org.gcube.smartgears.persistence.DefaultPersistence;
-import org.gcube.smartgears.persistence.Persistence;
/**
* The configuration of the container.
@@ -34,78 +24,75 @@ import org.gcube.smartgears.persistence.Persistence;
* @author Fabio Simeoni
* @author Luca Frosini (ISTI - CNR)
*/
-@XmlRootElement(name="container")
public class ContainerConfiguration {
-
- @XmlAttribute
- private Mode mode = Mode.online;
-
- @XmlElement
- @NotNull @IsValid
- String hostname;
-
- @XmlElement
- @NotNull
- Integer port;
-
- @XmlElement(name ="authentication-endpoint")
- String authenticationEnpoint = null;
-
- @XmlElement(name ="protocol")
- @NotNull @IsValid
- String protocol="http";
-
- @XmlElement
- boolean authorizeChildrenContext = false;
-
- @XmlElement
- @NotNull@IsValid
- String infrastructure;
+ @NotNull @IsValid
+ private BaseConfiguration baseConfiguration;
- @XmlElement
- @NotNull @IsValid
- Site site;
-
- @XmlElement(name="token")
- @NotNull @NotEmpty
- List tokens = new ArrayList();
+ @IsValid
+ private Map properties = new HashMap();
+
+ @NotNull @IsValid
+ private Site site;
- @XmlTransient
- Set allowedContext = new HashSet();
-
- @XmlElementRef(type=DefaultApplicationConfiguration.class)
- List apps = new ArrayList();
-
- @XmlElement(name="property")
@IsValid
- List properties = new ArrayList();
+ private ProxyAddress proxy;
+
+ @NotEmpty @NotNull
+ private String accountingFallbackLocation;
+
+ private List apps = new ArrayList();
+
- @XmlElement(name="publication-frequency")
- long publicationFrequency = default_container_publication_frequency_in_seconds;
+
+ @NotNull @IsValid
+ private PersistenceConfiguration persistenceConfiguration;
+
+ @NotNull @IsValid
+ private AuthorizationProviderConfiguration authorizationConfiguration;
- @XmlElementRef(type=DefaultPersistence.class)
- @IsValid
- private Persistence persistenceManager;
-
+
+ protected void setBaseConfiguration(BaseConfiguration baseConfiguration) {
+ this.baseConfiguration = baseConfiguration;
+ }
+
+ protected void setProperties(Map properties) {
+ this.properties = properties;
+ }
+
+ protected void setSite(Site site) {
+ this.site = site;
+ }
+
+ protected void setProxy(ProxyAddress proxy) {
+ this.proxy = proxy;
+ }
+
+ protected void setAccountingFallbackLocation(String accountingFallbackLocation) {
+ this.accountingFallbackLocation = accountingFallbackLocation;
+ }
+
+ protected void setPersistenceConfiguration(PersistenceConfiguration persistenceConfiguration) {
+ this.persistenceConfiguration = persistenceConfiguration;
+ }
+
+ protected void setAuthorizationProviderConfiguration(
+ AuthorizationProviderConfiguration authorizationConfiguration) {
+ this.authorizationConfiguration = authorizationConfiguration;
+ }
+
+ public void setApps(List apps) {
+ this.apps = apps;
+ }
+
/**
* Returns the management mode for the container.
* @return the management mode
*/
public Mode mode() {
- return mode;
+ return baseConfiguration.getMode();
}
-
- /**
- * Sets the management mode for the container.
- * @param mode the management mode
- * @return this configuration
- */
- public ContainerConfiguration mode(Mode mode) {
- this.mode=mode;
- return this;
- }
-
+
/**
* Returns the application configurations included in this configuration.
* @return the application configurations
@@ -113,21 +100,21 @@ public class ContainerConfiguration {
public List apps() {
return apps;
}
-
+
/**
* Returns the configuration of an application with a given context path.
* @param context the context path
* @return the application configuration
*/
public ApplicationConfiguration app(String context) {
-
+
for (ApplicationConfiguration app : apps)
if (context.equals(app.context()))
return app;
-
+
return null;
}
-
+
/**
* Adds the configuration of an application to this configuration.
* @param app the application configuration
@@ -146,7 +133,7 @@ public class ContainerConfiguration {
apps.add(app);
return this;
}
-
+
/**
* Returns the geographical site of the container.
* @return the site
@@ -155,143 +142,77 @@ public class ContainerConfiguration {
return site;
}
- /**
- * Sets the geographical site of the container.
- * @param site the site
- * @return this configuration
- */
- public ContainerConfiguration site(Site site) {
- this.site=site;
- return this;
- }
-
+
/**
* Returns the infrastructure in which the container is running.
* @return the infrastructure
*/
public String infrastructure() {
- return infrastructure;
+ return baseConfiguration.getInfrastructure();
}
- /**
- * Sets the infrastructure in which the container is running.
- * @param infrastructure the infrastructure
- * @return this configuration
- */
- public ContainerConfiguration infrastructure(String infrastructure) {
- this.infrastructure=infrastructure;
- return this;
- }
-
-
-
+
/**
* Returns the host name of the container.
* @return the host name;
*/
public String hostname() {
- return hostname;
+ return baseConfiguration.getHostname();
}
-
- /**
- * Sets the host name of the container.
- * @param name the host name
- * @return this configuration
- */
- public ContainerConfiguration hostname(String name) {
- this.hostname=name;
- return this;
- }
-
+
/**
* Returns the port at which the container is listening for requests.
* @return the port
*/
public int port() {
- return port;
+ return baseConfiguration.getPort();
}
-
-
+
+
/**
* Returns the port at which the container is listening for requests.
* @return the port
*/
public String protocol() {
- return protocol;
- }
-
-
- public String authenticationEnpoint() {
- return authenticationEnpoint;
- }
-
- public ContainerConfiguration authenticationEnpoint(String endpoint) {
- this.authenticationEnpoint = endpoint;
- return this;
+ return baseConfiguration.getProtocol();
}
- /**
- * Sets the port at which the container is listening for requests.
- * @param port the port
- * @return this configuration
- */
- public ContainerConfiguration port(int port) {
- this.port=port;
- return this;
- }
-
- public ContainerConfiguration protocol(String protocol) {
- this.protocol=protocol;
- return this;
- }
-
+
public boolean authorizeChildrenContext() {
- return authorizeChildrenContext;
- }
-
- public ContainerConfiguration authorizeChildrenContext(boolean authorizeChildrenContext) {
- this.authorizeChildrenContext = authorizeChildrenContext;
- return this;
+ return baseConfiguration.isAuthorizeChildrenContext();
}
/**
- * Returns the VOs in which the container initially operates.
- * @return the VOs
+ * Returns the proxy of the container.
+ * @return the proxy
*/
- public List startTokens() {
- return tokens;
+ public ProxyAddress proxy() {
+ return proxy;
}
-
- /**
- * Sets the VOs in which the container initially operates.
- * @param vos the VOs
- * @return this configuration
- */
- public ContainerConfiguration startTokens(List tokens) {
-
- notNull("start Tokens",tokens);
-
- this.tokens = tokens;
-
- return this;
- }
-
+
+
/**
* Returns the persistence manager of the container.
* @return the manager
*/
- public Persistence persistence() {
- return persistenceManager;
+ public PersistenceConfiguration persistenceConfiguration() {
+ return this.persistenceConfiguration;
}
/**
- * Sets the persistence manager of the container.
- * @param manager the manager
- * @return this configuration
+ * Returns the persistence manager of the container.
+ * @return the manager
*/
- public ContainerConfiguration persistence(Persistence manager) {
- this.persistenceManager=manager;
- return this;
+ public String accountingFallbackLocation() {
+ return accountingFallbackLocation;
+ }
+
+ /**
+ * Returns the authorization configuration.
+ * @return AuthorizationProviderConfiguration the configuration
+ */
+ public AuthorizationProviderConfiguration authorizationConfiguration() {
+ return authorizationConfiguration;
}
/**
@@ -299,48 +220,15 @@ public class ContainerConfiguration {
* @return the properties
*/
public Map properties() {
- Map map = new HashMap();
- for (Property prop : properties)
- map.put(prop.name, prop.value);
- return map;
+ return Collections.unmodifiableMap(properties);
}
- /**
- * Adds a configuration property to the container.
- * @param the name of the property
- * @param the value of the property
- * @return this configuration
- */
- public ContainerConfiguration property(String name, String value) {
- properties.add(new Property(name, value));
- return this;
- }
-
/**
* Returns the publication frequency for the container's profile.
* @return the frquency;
*/
public long publicationFrequency() {
- return publicationFrequency;
- }
-
- /**
- * Sets the publication frequency for the container's profile.
- * @param frequency the frequency
- * @return this configuration
- */
- public ContainerConfiguration publicationFrequency(long frequency) {
- this.publicationFrequency=frequency;
- return this;
- }
-
-
- public Set allowedContexts() {
- return allowedContext;
- }
-
- public void allowedContexts(Set allowedContexts) {
- this.allowedContext = allowedContexts;
+ return baseConfiguration.getPublicationFrequencyInSeconds();
}
/**
@@ -353,7 +241,7 @@ public class ContainerConfiguration {
List msgs = new ArrayList();
Validator validator = ValidatorFactory.validator();
-
+
for (ValidationError error : validator.validate(this))
msgs.add(error.toString());
@@ -362,159 +250,14 @@ public class ContainerConfiguration {
}
-
-
- static class Property {
-
- @XmlAttribute @NotNull
- String name;
-
- @XmlAttribute @NotNull
- String value;
-
- Property() {}
-
- Property(String key, String value) {
- this.name=key;
- this.value=value;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((value == null) ? 0 : value.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Property other = (Property) obj;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- if (value == null) {
- if (other.value != null)
- return false;
- } else if (!value.equals(other.value))
- return false;
- return true;
- }
-
- }
-
-
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((allowedContext == null) ? 0 : allowedContext.hashCode());
- result = prime * result + ((apps == null) ? 0 : apps.hashCode());
- result = prime * result + ((authenticationEnpoint == null) ? 0 : authenticationEnpoint.hashCode());
- result = prime * result + (authorizeChildrenContext ? 1231 : 1237);
- result = prime * result + ((hostname == null) ? 0 : hostname.hashCode());
- result = prime * result + ((infrastructure == null) ? 0 : infrastructure.hashCode());
- result = prime * result + ((mode == null) ? 0 : mode.hashCode());
- result = prime * result + ((persistenceManager == null) ? 0 : persistenceManager.hashCode());
- result = prime * result + ((port == null) ? 0 : port.hashCode());
- result = prime * result + ((properties == null) ? 0 : properties.hashCode());
- result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
- result = prime * result + (int) (publicationFrequency ^ (publicationFrequency >>> 32));
- result = prime * result + ((site == null) ? 0 : site.hashCode());
- result = prime * result + ((tokens == null) ? 0 : tokens.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ContainerConfiguration other = (ContainerConfiguration) obj;
- if (allowedContext == null) {
- if (other.allowedContext != null)
- return false;
- } else if (!allowedContext.equals(other.allowedContext))
- return false;
- if (apps == null) {
- if (other.apps != null)
- return false;
- } else if (!apps.equals(other.apps))
- return false;
- if (authenticationEnpoint == null) {
- if (other.authenticationEnpoint != null)
- return false;
- } else if (!authenticationEnpoint.equals(other.authenticationEnpoint))
- return false;
- if (authorizeChildrenContext != other.authorizeChildrenContext)
- return false;
- if (hostname == null) {
- if (other.hostname != null)
- return false;
- } else if (!hostname.equals(other.hostname))
- return false;
- if (infrastructure == null) {
- if (other.infrastructure != null)
- return false;
- } else if (!infrastructure.equals(other.infrastructure))
- return false;
- if (mode != other.mode)
- return false;
- if (persistenceManager == null) {
- if (other.persistenceManager != null)
- return false;
- } else if (!persistenceManager.equals(other.persistenceManager))
- return false;
- if (port == null) {
- if (other.port != null)
- return false;
- } else if (!port.equals(other.port))
- return false;
- if (properties == null) {
- if (other.properties != null)
- return false;
- } else if (!properties.equals(other.properties))
- return false;
- if (protocol == null) {
- if (other.protocol != null)
- return false;
- } else if (!protocol.equals(other.protocol))
- return false;
- if (publicationFrequency != other.publicationFrequency)
- return false;
- if (site == null) {
- if (other.site != null)
- return false;
- } else if (!site.equals(other.site))
- return false;
- if (tokens == null) {
- if (other.tokens != null)
- return false;
- } else if (!tokens.equals(other.tokens))
- return false;
- return true;
- }
-
@Override
public String toString() {
- return "ContainerConfiguration [mode=" + mode + ", hostname=" + hostname + ", port=" + port + ", authenticationEnpoint=" + authenticationEnpoint + ", protocol=" + protocol
- + ", authorizeChildrenContext=" + authorizeChildrenContext + ", infrastructure=" + infrastructure
- + ", site=" + site + ", tokens=" + tokens + ", allowedContext=" + allowedContext + ", apps=" + apps
- + ", properties=" + properties + ", publicationFrequency=" + publicationFrequency
- + ", persistenceManager=" + persistenceManager + "]";
+ return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties
+ + ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation
+ + ", persistence=" + persistenceConfiguration.getImplementationClass().getSimpleName()
+ + ", authorizationProvider=" + authorizationConfiguration + "]";
}
-
+
+
+
}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java
index 7d112a0..382a803 100644
--- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java
+++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java
@@ -1,18 +1,31 @@
package org.gcube.smartgears.configuration.container;
-import static org.gcube.smartgears.utils.Utils.*;
-
+import java.io.File;
import java.io.InputStream;
-import java.lang.reflect.Modifier;
-import java.util.HashSet;
-import java.util.ServiceLoader;
-import java.util.Set;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import org.gcube.common.security.credentials.Credentials;
+import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration;
+import org.gcube.smartgears.configuration.ComponentConfiguration;
+import org.gcube.smartgears.configuration.ConfiguredWith;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
+import org.gcube.smartgears.configuration.ProxyAddress;
+import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.handlers.container.ContainerHandler;
+import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager;
+import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager;
+import org.gcube.smartgears.persistence.LocalWriter;
+import org.gcube.smartgears.persistence.LocalWriterConfiguration;
+import org.gcube.smartgears.persistence.PersistenceWriter;
+import org.gcube.smartgears.security.AuthorizationProviderFactory;
+import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory;
import org.gcube.smartgears.utils.Utils;
+import org.ini4j.Ini;
+import org.ini4j.Profile.Section;
/**
* Binds {@link ContainerConfiguration}s to and from XML serialisations.
@@ -22,34 +35,138 @@ import org.gcube.smartgears.utils.Utils;
*/
public class ContainerConfigurationBinder {
- /**
- * Returns a {@link ContainerConfiguration} from its XML serialisation.
- *
- * @param stream the serialisation
- * @return the configuration
- * @throws RuntimeException if the serialisation is invalid
- */
- public ContainerConfiguration bind(InputStream stream) {
-
+ public ContainerConfiguration load(InputStream stream) {
try {
+ Ini configurator = new Ini(stream);
+ ContainerConfiguration conf = new ContainerConfiguration();
- JAXBContext ctx = JAXBContext.newInstance(ContainerConfiguration.class);
+ Section nodeSection = configurator.get("node");
+ if (nodeSection != null) {
+ BaseConfiguration nodeConf = new BaseConfiguration();
+ nodeSection.to(nodeConf);
+ conf.setBaseConfiguration(nodeConf);
+ }
- ContainerConfiguration config = (ContainerConfiguration) ctx.createUnmarshaller().unmarshal(stream);
-
- return config;
+ Section propertiesSection = configurator.get("properties");
+ if (propertiesSection != null)
+ conf.setProperties(propertiesSection.entrySet().stream()
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
- } catch (JAXBException e) {
+ Section siteSection = configurator.get("site");
+ if (siteSection != null) {
+ Site siteConf = new Site();
+ siteSection.to(siteConf);
+ conf.setSite(siteConf);
+ }
- throw new RuntimeException("invalid container configuration", e);
+ initAuthorizationPart(configurator, conf);
- }
- finally {
-
- Utils.closeSafely(stream);
+ initPersistencePart(configurator, conf);
+
+ initProxyPart(configurator, conf);
+
+ // TODO: find a solution for this shit
+ String location = Utils.home() + "/state";
+ File dir = new File(location);
+ if (!dir.exists())
+ dir.mkdirs();
+ conf.setAccountingFallbackLocation(location);
+ // END Shit
+
+ return conf;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
}
-
+
+ private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception {
+ Section proxySection = configurator.get("proxy");
+ if (proxySection != null) {
+ ProxyAddress proxyConf = new ProxyAddress();
+ proxySection.to(proxyConf);
+ conf.setProxy(proxyConf);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception {
+ Section persistenceSection = configurator.get("persistence");
+ if (persistenceSection != null) {
+ String type = persistenceSection.get("class");
+ if (type == null)
+ throw new Exception("ini file error: type not found in \"persistence\" section");
+ /*
+ * PersistenceWriter persistenceWriter; try { Object persistenceImpl =
+ * Class.forName(type).getDeclaredConstructor().newInstance(); persistenceWriter
+ * = PersistenceWriter.class.cast(persistenceImpl); }catch (Exception e) { throw
+ * new
+ * Exception("ini file error: invalid persistence type in \"persistence\" section"
+ * , e); }
+ */
+ // persistenceSection.to(persistenceWriter);
+
+ Class extends PersistenceWriter> persistenceClass = null;
+ try {
+ persistenceClass = (Class extends PersistenceWriter>) Class.forName(type);
+ } catch (Exception e) {
+ throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e);
+ }
+ if (!persistenceClass.isAnnotationPresent(ConfiguredWith.class))
+ throw new Exception(
+ "ini file error: invalid class type in \"persistence\" section,ConfiguredWith annotation not present");
+ Class extends ComponentConfiguration> writerConfClass = persistenceClass
+ .getAnnotation(ConfiguredWith.class).value();
+ ComponentConfiguration writerConfiguration = writerConfClass.getDeclaredConstructor().newInstance();
+ persistenceSection.to(writerConfiguration, ".");
+ conf.setPersistenceConfiguration(
+ new PersistenceConfiguration((Class) persistenceClass, writerConfiguration));
+ } else {
+ String location = Utils.home() + "/state";
+ File dir = new File(location);
+ if (!dir.exists())
+ dir.mkdirs();
+
+ conf.setPersistenceConfiguration(
+ new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location)));
+ }
+
+ }
+
+ private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception {
+ Section authorizationSection = configurator.get("authorization");
+ if (authorizationSection != null) {
+
+ String provider = authorizationSection.get("factory");
+ AuthorizationProviderFactory> authProviderFactory;
+ if (provider != null) {
+ try {
+ Object authProviderImpl = Class.forName(provider).getDeclaredConstructor().newInstance();
+ authProviderFactory = AuthorizationProviderFactory.class.cast(authProviderImpl);
+ } catch (Exception e) {
+ throw new Exception("ini file error: invalid provider type in \"authorization\" section", e);
+ }
+ } else
+ authProviderFactory = new DefaultAuthorizationProviderFactory();
+
+ authorizationSection.to(authProviderFactory, "factory.");
+
+ String type = authorizationSection.get("credentials.class");
+ if (type == null)
+ throw new Exception("ini file error: credentials type not found in \"authorization\" section");
+ Credentials credentials;
+ try {
+ Object credentialsImpl = Class.forName(type).getDeclaredConstructor().newInstance();
+ credentials = Credentials.class.cast(credentialsImpl);
+ } catch (Exception e) {
+ throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e);
+ }
+ authorizationSection.to(credentials, "credentials.");
+
+ conf.setAuthorizationProviderConfiguration(
+ new AuthorizationProviderConfiguration(authProviderFactory, credentials));
+ }
+ }
+
/**
* Returns the handlers of the container from their XML serialisation.
*
@@ -57,45 +174,35 @@ public class ContainerConfigurationBinder {
* @return the handlers
* @throws RuntimeException if the serialisation is invalid
*/
- public ContainerHandlers bindHandlers(InputStream stream) {
+ public List bindHandlers(ClassLoader classloader) {
- //collects handler classes
- Set> classes = scanForConfigurationElements();
+ LinkedList handlers = new LinkedList();
+ // ADDING BASE Handlers (order is important)
+ handlers.add(new AccountingManager());
+ handlers.add(new ContainerProfileManager());
+
+ handlers.addAll(scanForContainerHadlers(classloader));
+
+ return handlers;
+
+ }
+
+ private List extends ContainerHandler> scanForContainerHadlers(ClassLoader classloader) throws RuntimeException {
+
+ // TODO: scan for Container Handler
+
+ return Collections.emptyList();
+ }
+
+ public SmartgearsConfiguration loadSmartgearsProperty() {
try {
-
- JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class>[0]));
-
- return (ContainerHandlers) ctx.createUnmarshaller().unmarshal(stream);
-
- } catch (JAXBException e) {
-
- throw unchecked(e);
-
+ Ini configurator = new Ini(this.getClass().getResourceAsStream("smartgears-config.ini"));
+ String version = configurator.get("smartgears").get("version");
+ return new SmartgearsConfiguration(version);
+ }catch (Exception e) {
+ throw new RuntimeException(e);
}
}
-
-
-
- private Set> scanForConfigurationElements() throws RuntimeException {
- @SuppressWarnings("all")
- ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ContainerHandler.class);
-
- Set> scanned = new HashSet>();
-
- for (ContainerHandler handler : handlerLoader) {
- Class> handlerClass = handler.getClass();
- if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
- continue;
- else
- scanned.add(handlerClass);
- }
-
- //add top-level configuration
- scanned.add(ContainerHandlers.class);
-
- return scanned;
- }
-
}
diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java
deleted file mode 100644
index 73534b8..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.gcube.smartgears.configuration.container;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAnyElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.smartgears.handlers.container.ContainerHandler;
-
-/**
- * The {@link ContainerHandler}s that manage the application.
- *
- * @author Fabio Simeoni
- *
- */
-@XmlRootElement(name="handlers")
-public class ContainerHandlers {
-
- @XmlAnyElement(lax=true)
- List handlers = new ArrayList();
-
- public ContainerHandlers() {}
-
- /**
- * Returns the {@link ContainerHandler}s for the service.
- * @return the lifecycle handlers
- */
- public List get() {
- return handlers;
- }
-
- /**
- * Sets the {@link ContainerHandler}s for the service.
- * @param handlers the lifecycle handlers
- * @return this configuration
- */
- public ContainerHandlers set(ContainerHandler ... handlers) {
- this.handlers = Arrays.asList(handlers);
- return this;
- }
-
- public void mergeWith(ContainerHandlers other){
- List handlers = other.get();
- for (ContainerHandler handler : handlers)
- if (!this.get().contains(handler))
- this.get().add(handler);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/container/Site.java b/src/main/java/org/gcube/smartgears/configuration/container/Site.java
index cc41f4f..e81ce0b 100644
--- a/src/main/java/org/gcube/smartgears/configuration/container/Site.java
+++ b/src/main/java/org/gcube/smartgears/configuration/container/Site.java
@@ -1,8 +1,5 @@
package org.gcube.smartgears.configuration.container;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-
import org.gcube.common.validator.annotations.NotNull;
/**
@@ -11,97 +8,28 @@ import org.gcube.common.validator.annotations.NotNull;
* @author Fabio Simeoni
*
*/
-@XmlRootElement(name="site")
public class Site {
- @XmlElement
@NotNull
String country;
- @XmlElement
@NotNull
String location;
- @XmlElement
- @NotNull
- String latitude;
-
- @XmlElement
- @NotNull
- String longitude;
-
- /**
- * Returns the country.
- * @return the country
- */
- public String country() {
+ public String getCountry() {
return country;
}
- /**
- * Sets the country.
- * @param the country
- * @return this configuration
- */
- public Site country(String country) {
- this.country=country;
- return this;
- }
-
-
- /**
- * Returns the latitude.
- * @return the latitude
- */
- public String latitude() {
- return latitude;
+ public void setCountry(String country) {
+ this.country = country;
}
- /**
- * Sets the latitude.
- * @param the latitude
- * @return this configuration
- */
- public Site latitude(String latitude) {
- this.latitude=latitude;
- return this;
- }
-
-
- /**
- * Returns the longitude.
- * @return the longitude
- */
- public String longitude() {
- return longitude;
- }
-
- /**
- * Sets the longitude.
- * @param the longitude
- * @return this configuration
- */
- public Site longitude(String longitude) {
- this.longitude=longitude;
- return this;
- }
-
- /**
- * Returns the location.
- * @return the location
- */
- public String location() {
+ public String getLocation() {
return location;
}
- /**
- * Sets the location.
- * @param the location
- * @return this location
- */
- public Site location(String location) {
- this.location=location;
- return this;
+ public void setLocation(String location) {
+ this.location = location;
}
@Override
@@ -109,9 +37,7 @@ public class Site {
final int prime = 31;
int result = 1;
result = prime * result + ((country == null) ? 0 : country.hashCode());
- result = prime * result + ((latitude == null) ? 0 : latitude.hashCode());
result = prime * result + ((location == null) ? 0 : location.hashCode());
- result = prime * result + ((longitude == null) ? 0 : longitude.hashCode());
return result;
}
@@ -129,24 +55,12 @@ public class Site {
return false;
} else if (!country.equals(other.country))
return false;
- if (latitude == null) {
- if (other.latitude != null)
- return false;
- } else if (!latitude.equals(other.latitude))
- return false;
if (location == null) {
if (other.location != null)
return false;
} else if (!location.equals(other.location))
return false;
- if (longitude == null) {
- if (other.longitude != null)
- return false;
- } else if (!longitude.equals(other.longitude))
- return false;
return true;
}
-
-
}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java
deleted file mode 100644
index 1541837..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.gcube.smartgears.configuration.library;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.validator.ValidationError;
-import org.gcube.common.validator.Validator;
-import org.gcube.common.validator.ValidatorFactory;
-import org.gcube.common.validator.annotations.NotEmpty;
-
-@XmlRootElement(name="smartgears")
-public class SmartGearsConfiguration {
-
- @XmlAttribute @NotEmpty
- private String version;
-
- public SmartGearsConfiguration(){
- }
-
- public String version() {
- return version;
- }
-
- public SmartGearsConfiguration version(String version) {
- this.version=version;
- return this;
- }
-
-
- /**
- * Validates this configuration
- *
- * @throws IllegalStateException if the configuration is invalid
- */
- public void validate() {
-
- List msgs = new ArrayList();
-
- Validator validator = ValidatorFactory.validator();
-
- for (ValidationError error : validator.validate(this))
- msgs.add(error.toString());
-
- if (!msgs.isEmpty())
- throw new IllegalStateException("invalid configuration: "+msgs);
-
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((version == null) ? 0 : version.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- SmartGearsConfiguration other = (SmartGearsConfiguration) obj;
- if (version == null) {
- if (other.version != null)
- return false;
- } else if (!version.equals(other.version))
- return false;
- return true;
- }
-
-
-
-}
diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java
deleted file mode 100644
index 11a9b42..0000000
--- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.gcube.smartgears.configuration.library;
-
-import java.io.InputStream;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-
-import org.gcube.smartgears.configuration.container.ContainerConfiguration;
-import org.gcube.smartgears.utils.Utils;
-
-/**
- * Binds {@link ContainerConfiguration}s to and from XML serialisations.
- *
- * @author Fabio Simeoni
- *
- */
-public class SmartGearsConfigurationBinder {
-
- /**
- * Returns a {@link ContainerConfiguration} from its XML serialisation.
- *
- * @param stream the serialisation
- * @return the configuration
- * @throws RuntimeException if the serialisation is invalid
- */
- public SmartGearsConfiguration bind(InputStream stream) {
-
- try {
-
- JAXBContext ctx = JAXBContext.newInstance(SmartGearsConfiguration.class);
-
- SmartGearsConfiguration config = (SmartGearsConfiguration) ctx.createUnmarshaller().unmarshal(stream);
-
- return config;
-
- } catch (JAXBException e) {
-
- throw new RuntimeException("invalid library configuration", e);
-
- }
- finally {
-
- Utils.closeSafely(stream);
- }
- }
-
-}
diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java
index 033cb34..949c420 100644
--- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java
+++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java
@@ -7,7 +7,8 @@ import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.context.Properties;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
-import org.gcube.smartgears.persistence.Persistence;
+import org.gcube.smartgears.persistence.PersistenceWriter;
+import org.gcube.smartgears.security.AuthorizationProvider;
/**
* The management context of an application.
@@ -33,9 +34,6 @@ public interface ApplicationContext {
* @return the configuration
*/
ApplicationConfiguration configuration();
-
-
- T profile(Class type);
/**
* Returns the lifecycle of the application.
@@ -56,7 +54,7 @@ public interface ApplicationContext {
*
* @return the manager
*/
- Persistence persistence();
+ PersistenceWriter persistence();
/**
* Returns the servlet context of the application.
@@ -78,5 +76,11 @@ public interface ApplicationContext {
* @return the properties
*/
Properties properties();
-
+
+ /**
+ * Returns the authorization provider.
+ * @return the AuhtorizationProvider
+ **/
+ AuthorizationProvider authorizationProvider();
+
}
diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java
index 96f2b3a..5cf5735 100644
--- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java
+++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java
@@ -1,16 +1,24 @@
package org.gcube.smartgears.context.application;
-import static org.gcube.smartgears.Constants.profile_property;
+import static org.gcube.smartgears.Constants.profile_file_path;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.ObjectInputStream;
+import java.util.UUID;
import javax.servlet.ServletContext;
import org.gcube.common.events.Hub;
-import org.gcube.common.resources.gcore.GCoreEndpoint;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.context.Properties;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
-import org.gcube.smartgears.persistence.Persistence;
+import org.gcube.smartgears.persistence.PersistenceWriter;
+import org.gcube.smartgears.security.AuthorizationProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Default {@link ApplicationContext} implementation.
@@ -20,12 +28,15 @@ import org.gcube.smartgears.persistence.Persistence;
*/
public class DefaultApplicationContext implements ApplicationContext {
+ private static Logger log = LoggerFactory.getLogger(DefaultApplicationContext.class);
+
private final ContainerContext container;
private final ServletContext sctx;
private final ApplicationConfiguration configuration;
private final ApplicationLifecycle lifecycle;
private final Properties properties;
private final Hub hub;
+ private final PersistenceWriter persistenceWriter;
private final String id;
/**
@@ -37,14 +48,37 @@ public class DefaultApplicationContext implements ApplicationContext {
* @param lifecycle the lifecycle
* @param properties the properties
*/
- public DefaultApplicationContext(String id,ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) {
+ public DefaultApplicationContext(ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) {
+
+ PersistenceConfiguration persistenceWriterConf = configuration.persistenceConfiguration();
+
+ try {
+ persistenceWriter = persistenceWriterConf.getImplementationClass().getDeclaredConstructor().newInstance();
+ persistenceWriter.configure(persistenceWriterConf.getWriterConfiguration());
+ }catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ File file = persistenceWriter.file(profile_file_path);
+ String id = null;
+ if (file.exists()) {
+ log.info("loading persisted state for application {}", sctx.getContextPath());
+ try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
+ id = (String) ois.readObject();
+ } catch (Exception e) {
+ log.error("error loading persisted state, creating new uuid", e);
+ }
+ }
+ if (id == null)
+ id = UUID.randomUUID().toString();
+
this.id = id;
this.container=container;
this.sctx = sctx;
this.configuration=configuration;
this.hub=hub;
this.lifecycle = lifecycle;
- this.properties=properties;
+ this.properties=properties;
}
/**
@@ -52,9 +86,21 @@ public class DefaultApplicationContext implements ApplicationContext {
* @param context the other instance
*/
public DefaultApplicationContext(ApplicationContext context) {
- this(context.id(), context.container(),context.application(),context.configuration(),context.events(), context.lifecycle(), new Properties(context.properties()));
+ this(context.id(), context.persistence(), context.container(),context.application(),context.configuration(),context.events(), context.lifecycle(), new Properties(context.properties()));
}
+ private DefaultApplicationContext(String id, PersistenceWriter writer, ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) {
+ this.id = id;
+ this.container=container;
+ this.sctx = sctx;
+ this.configuration=configuration;
+ this.hub=hub;
+ this.lifecycle = lifecycle;
+ this.properties=properties;
+ this.persistenceWriter = writer;
+
+ }
+
@Override
public ServletContext application() {
return sctx;
@@ -65,16 +111,6 @@ public class DefaultApplicationContext implements ApplicationContext {
return container;
}
- @Override
- @SuppressWarnings("all")
- public T profile(Class type) {
-
- if (type==GCoreEndpoint.class)
- return (T) properties().lookup(profile_property).value(GCoreEndpoint.class);
-
- throw new IllegalArgumentException("unsupported profile type: "+type);
- }
-
@Override
public String name() { //little shortcut for ease of logging
return configuration.name();
@@ -96,10 +132,10 @@ public class DefaultApplicationContext implements ApplicationContext {
}
@Override
- public Persistence persistence() {
- return configuration.persistence();
+ public PersistenceWriter persistence() {
+ return persistenceWriter;
}
-
+
@Override
public Properties properties() {
return properties;
@@ -110,4 +146,12 @@ public class DefaultApplicationContext implements ApplicationContext {
return id;
}
+ /**
+ * Returns the authorization provider.
+ * @return the AuhtorizationProvider
+ **/
+ public AuthorizationProvider authorizationProvider() {
+ return container().authorizationProvider();
+ }
+
}
diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java
index 3c7ae53..e3729a9 100644
--- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java
+++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java
@@ -4,7 +4,8 @@ import org.gcube.common.events.Hub;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.Properties;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
-import org.gcube.smartgears.persistence.Persistence;
+import org.gcube.smartgears.persistence.PersistenceWriter;
+import org.gcube.smartgears.security.AuthorizationProvider;
/**
* The management context of the container.
@@ -21,11 +22,6 @@ public interface ContainerContext {
*/
ContainerConfiguration configuration();
- /**
- * Returns the resource profile of a given type of the container.
- * @return the profile
- */
- T profile(Class type);
/**
* Returns the lifecycle of the container
@@ -43,7 +39,7 @@ public interface ContainerContext {
* Returns the persistence manager of the container.
* @return the manager
*/
- Persistence persistence();
+ PersistenceWriter persistenceWriter();
/**
* Returns the properties of the container.
@@ -52,5 +48,9 @@ public interface ContainerContext {
Properties properties();
String id();
+
+ AuthorizationProvider authorizationProvider();
+
+
}
diff --git a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java
index 0a599f7..cde9c96 100644
--- a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java
+++ b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java
@@ -1,12 +1,21 @@
package org.gcube.smartgears.context.container;
-import static org.gcube.smartgears.Constants.*;
+import static org.gcube.smartgears.Constants.container_profile_file_path;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.ObjectInputStream;
+import java.util.UUID;
+
import org.gcube.common.events.Hub;
-import org.gcube.common.resources.gcore.HostingNode;
+import org.gcube.smartgears.configuration.PersistenceConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.Properties;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
-import org.gcube.smartgears.persistence.Persistence;
+import org.gcube.smartgears.persistence.PersistenceWriter;
+import org.gcube.smartgears.security.AuthorizationProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Default {@link ContainerContext} implementation.
@@ -16,11 +25,15 @@ import org.gcube.smartgears.persistence.Persistence;
*/
public class DefaultContainerContext implements ContainerContext {
+ private static Logger log = LoggerFactory.getLogger(DefaultContainerContext.class);
+
private final ContainerConfiguration configuration;
private final ContainerLifecycle lifecycle;
private final Properties properties;
private final Hub hub;
+ private final AuthorizationProvider authorizationProvider;
private final String id;
+ private final PersistenceWriter persistenceWriter;
/**
* Creates an instance with mandatory parameters.
* @param configuration the configuration
@@ -28,23 +41,49 @@ public class DefaultContainerContext implements ContainerContext {
* @param lifecycle the lifecycle
* @param properties the properties
*/
- public DefaultContainerContext(String id,ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle,
+ public DefaultContainerContext(ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle, AuthorizationProvider authProvider,
Properties properties) {
- this.id = id;
this.configuration=configuration;
this.hub=hub;
this.lifecycle = lifecycle;
this.properties=properties;
+ this.authorizationProvider = authProvider;
+
+ PersistenceConfiguration persistenceWriterConf = configuration.persistenceConfiguration();
+
+ try {
+ persistenceWriter = persistenceWriterConf.getImplementationClass().getDeclaredConstructor().newInstance();
+ persistenceWriter.configure(persistenceWriterConf.getWriterConfiguration());
+ }catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ File file = persistenceWriter.file(container_profile_file_path);
+
+ String id = null;
+ if (file.exists()) {
+ log.info("loading persisted state for container");
+ try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
+ id = (String) ois.readObject();
+ } catch (Exception e) {
+ log.error("error loading persisted state, creating new uuid", e);
+ }
+
+ }
+ if (id == null) {
+ id = UUID.randomUUID().toString();
+ log.info("container id created is {}", id);
+
+ }
+
+ this.id = id;
+
}
-
- @SuppressWarnings("all")
- public T profile(Class type) {
-
- if (type==HostingNode.class)
- return (T) properties().lookup(container_profile_property).value(HostingNode.class);
-
- throw new IllegalArgumentException("unsupported profile type: "+type);
- };
+
+ /*
+ public HostingNode profile() {
+ return properties().lookup(container_profile_property).value(HostingNode.class);
+ };*/
@Override
public ContainerConfiguration configuration() {
@@ -62,8 +101,8 @@ public class DefaultContainerContext implements ContainerContext {
}
@Override
- public Persistence persistence() {
- return configuration.persistence();
+ public PersistenceWriter persistenceWriter() {
+ return persistenceWriter;
}
@Override
@@ -76,6 +115,8 @@ public class DefaultContainerContext implements ContainerContext {
return id;
}
-
+ public AuthorizationProvider authorizationProvider() {
+ return authorizationProvider;
+ }
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java
index 6fab2bd..1be961e 100644
--- a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java
@@ -9,7 +9,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.gcube.smartgears.Constants;
-import org.gcube.smartgears.configuration.application.Exclude;
+import org.gcube.smartgears.configuration.application.GCubeExclude;
/**
* A resource-specifc API handled by an {@link HttpController}.
@@ -53,10 +53,10 @@ public abstract class ApiResource extends HttpExtension {
}
@Override
- public Set excludes() {
- return Collections.singleton(new Exclude(Constants.root_mapping+mapping()));
+ public Set excludes() {
+ return Collections.singleton(new GCubeExclude(Constants.root_mapping+mapping()));
}
-
+
/**
* Returns true
if this resource supports a given method.
* @param method the method
diff --git a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java
index c4216d6..0d130d1 100644
--- a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java
+++ b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java
@@ -4,7 +4,7 @@ import java.util.Set;
import javax.servlet.Servlet;
-import org.gcube.smartgears.configuration.application.Exclude;
+import org.gcube.smartgears.configuration.application.GCubeExclude;
import org.gcube.smartgears.context.application.ApplicationContext;
/**
@@ -22,6 +22,8 @@ public interface ApplicationExtension extends Servlet {
*/
void init(ApplicationContext context) throws Exception;
+ void stop();
+
/**
* Returns the name of this extension.
* @return the name
@@ -39,5 +41,5 @@ public interface ApplicationExtension extends Servlet {
* Returns the set of request paths that should be excluded from request management.
* @return the set of request paths that should be excluded from request management
*/
- Set excludes();
+ Set excludes();
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpController.java b/src/main/java/org/gcube/smartgears/extensions/HttpController.java
index 8a2d7a7..cab2e79 100644
--- a/src/main/java/org/gcube/smartgears/extensions/HttpController.java
+++ b/src/main/java/org/gcube/smartgears/extensions/HttpController.java
@@ -1,8 +1,13 @@
package org.gcube.smartgears.extensions;
-import static org.gcube.smartgears.Constants.*;
-import static org.gcube.smartgears.handlers.application.request.RequestError.*;
-import static org.gcube.smartgears.utils.Utils.*;
+import static org.gcube.smartgears.Constants.accept;
+import static org.gcube.smartgears.Constants.allow;
+import static org.gcube.smartgears.Constants.content_type;
+import static org.gcube.smartgears.handlers.application.request.RequestError.incoming_contenttype_unsupported_error;
+import static org.gcube.smartgears.handlers.application.request.RequestError.method_unsupported_error;
+import static org.gcube.smartgears.handlers.application.request.RequestError.outgoing_contenttype_unsupported_error;
+import static org.gcube.smartgears.handlers.application.request.RequestError.resource_notfound_error;
+import static org.gcube.smartgears.utils.Utils.notNull;
import java.io.IOException;
import java.util.Collection;
@@ -17,7 +22,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.gcube.smartgears.configuration.application.Exclude;
+import org.gcube.smartgears.configuration.application.GCubeExclude;
import org.gcube.smartgears.context.application.ApplicationContext;
/**
@@ -69,9 +74,17 @@ public class HttpController extends HttpExtension {
}
@Override
- public Set excludes() {
+ public void stop(){
+ for (ApiResource resource : resources.values())
+ resource.stop();
- Set resourceExcludes = new LinkedHashSet();
+ }
+
+
+ @Override
+ public Set excludes() {
+
+ Set resourceExcludes = new LinkedHashSet();
for (ApiResource resource : resources.values())
resourceExcludes.addAll(resource.excludes());
@@ -176,8 +189,6 @@ public class HttpController extends HttpExtension {
case OPTIONS:
resource.doOptions(request, response);
break;
- case TRACE:
- resource.doTrace(request, response);
}
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java
index c97a9e7..ef0e3e8 100644
--- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java
+++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java
@@ -1,17 +1,15 @@
package org.gcube.smartgears.extensions;
-import static org.gcube.common.events.impl.Utils.*;
+import static org.gcube.common.events.impl.Utils.valid;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServlet;
-import javax.xml.bind.annotation.XmlAttribute;
import org.gcube.common.validator.annotations.NotEmpty;
-import org.gcube.smartgears.configuration.application.Exclude;
+import org.gcube.smartgears.configuration.application.GCubeExclude;
import org.gcube.smartgears.context.application.ApplicationContext;
-
/**
* An {@link ApplicationExtension} that implements the {@link HttpServlet} interface
*
@@ -27,13 +25,31 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx
*
*/
public static enum Method {
- GET, PUT, POST, HEAD, DELETE, OPTIONS, TRACE
+ GET("GET"),
+ PUT("PUT"),
+ POST("POST"),
+ HEAD("HEAD"),
+ DELETE("DELETE"),
+ OPTIONS("OPTIONS");
+
+
+ private String value;
+
+
+ private Method(String value) {
+ this.value = value;
+ }
+
+
+ public String getValue() {
+ return this.value;
+ }
}
- @XmlAttribute @NotEmpty
+ @NotEmpty
private String name;
- @XmlAttribute @NotEmpty
+ @NotEmpty
private String mapping;
private ApplicationContext context;
@@ -59,8 +75,11 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx
}
@Override
- public Set excludes() {
- return new HashSet(); //all managed by default
+ public void stop() {}
+
+ @Override
+ public Set excludes() {
+ return new HashSet(); //all managed by default
}
protected ApplicationContext context() {
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java
index 0e3c939..ded8c0d 100644
--- a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java
@@ -1,6 +1,6 @@
package org.gcube.smartgears.extensions.resource;
-import static org.gcube.smartgears.Constants.application_xml;
+import static org.gcube.smartgears.Constants.application_json;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import java.io.IOException;
@@ -9,9 +9,8 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.gcube.common.resources.gcore.Resources;
+import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
-import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
@@ -27,7 +26,7 @@ public class ConfigurationResource extends ApiResource {
public static final String mapping = "/configuration";
- private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_xml));
+ private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
ConfigurationResource() {
super(signature);
@@ -37,8 +36,8 @@ public class ConfigurationResource extends ApiResource {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- ApplicationConfiguration config = BridgedApplicationConfiguration.class.cast(context().configuration()).inner();
- Resources.marshal(config,resp.getWriter());
+ ApplicationConfiguration config = context().configuration();
+ new ObjectMapper().writeValue(resp.getWriter(), config);
}
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java
index a587d0c..c008853 100644
--- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java
@@ -4,18 +4,14 @@ import static org.gcube.smartgears.Constants.application_xhtml;
import static org.gcube.smartgears.Constants.frontpage_file_path;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_error;
-import static org.gcube.smartgears.provider.ProviderFactory.provider;
import static org.gcube.smartgears.utils.Utils.closeSafely;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -23,10 +19,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.gcube.common.resources.gcore.GCoreEndpoint;
-import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
+import org.gcube.smartgears.provider.ProviderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -93,42 +88,12 @@ public class FrontPageResource extends ApiResource {
values.put("version", context().configuration().version());
String infrastructure = context().container().configuration().infrastructure();
- StringBuilder voValue = new StringBuilder();
-
- Collection scopes = context().profile(GCoreEndpoint.class).scopes().asCollection();
- Set vos = new HashSet();
-
- //pre-process
- for (String scope : scopes) {
- ScopeBean bean = new ScopeBean(scope);
- switch (bean.type()) {
- case INFRASTRUCTURE:
- infrastructure = bean.name();
- break;
- case VO:
- vos.add(bean.name());
- break;
- case VRE:
- vos.add(bean.enclosingScope().name());
- infrastructure=bean.enclosingScope().enclosingScope().name();
- }
- }
-
- //build vo value
- int i = 0;
- int max = vos.size()-1;
- for (String vo : vos) {
- String voPrefix = i == 0 ? "" : (i==max?" and ":", ");
- voValue.append(voPrefix+"" + vo + "");
- i++;
- }
-
+
values.put("infra", infrastructure);
- values.put("vos", voValue.toString());
values.put("status", context().lifecycle().state().toString());
- values.put("smartgears-version", provider().smartgearsConfiguration().version());
+ values.put("smartgears-version", ProviderFactory.provider().smartgearsConfiguration().getVersion());
return values;
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java
new file mode 100644
index 0000000..a084d12
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java
@@ -0,0 +1,105 @@
+package org.gcube.smartgears.extensions.resource;
+
+import static org.gcube.smartgears.Constants.application_json;
+import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Set;
+import java.util.Timer;
+import java.util.stream.Collectors;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
+import org.gcube.common.health.api.HealthCheck;
+import org.gcube.common.health.api.ReadinessChecker;
+import org.gcube.smartgears.context.application.ApplicationContext;
+import org.gcube.smartgears.extensions.ApiResource;
+import org.gcube.smartgears.extensions.ApiSignature;
+import org.gcube.smartgears.health.HealthManager;
+import org.gcube.smartgears.health.HealthResponse;
+import org.gcube.smartgears.health.HealthTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.ClassInfoList;
+import io.github.classgraph.ScanResult;
+
+public class HealthResource extends ApiResource {
+
+ private static final long serialVersionUID = 1L;
+
+ private static Logger log = LoggerFactory.getLogger(HealthResource.class);
+
+ public static final String mapping = "/health";
+
+ private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
+
+ private HealthManager manager;
+
+ private HealthTask task;
+
+ private Timer timer;
+
+ HealthResource() {
+ super(signature);
+ }
+
+ @Override
+ public void init(ApplicationContext context) throws Exception {
+ Set> annotatedReadiness;
+
+ try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo().scan()) {
+
+ ClassInfoList classInfos = result.getClassesWithAnnotation(ReadinessChecker.class.getName());
+
+ annotatedReadiness = classInfos.stream().map(ClassInfo::loadClass)
+ .filter(c -> HealthCheck.class.isAssignableFrom(c)).collect(Collectors.toSet());
+ }
+
+ manager = new HealthManager();
+ for (Class> readnessClass : annotatedReadiness)
+ try {
+ manager.register((HealthCheck) readnessClass.getDeclaredConstructor().newInstance());
+ log.info("added class {} to health manager", readnessClass.getCanonicalName());
+ } catch (Throwable e) {
+ log.error("healthChecker class {} cannot be instantiated", readnessClass.getCanonicalName(), e);
+ }
+
+ task = new HealthTask(manager);
+
+ timer = new Timer(true);
+
+ timer.scheduleAtFixedRate(task, 10000, 60000);
+
+ super.init(context);
+ }
+
+ public void stop() {
+ if (timer!=null)
+ timer.cancel();
+ }
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ PrintWriter out = resp.getWriter();
+ resp.setContentType("application/json");
+ resp.setCharacterEncoding("UTF-8");
+ HealthResponse response = readiness();
+
+ new ObjectMapper().writeValue(out, response);
+
+ out.flush();
+ }
+
+ public HealthResponse readiness() {
+ return task.getResponse();
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java
index 072ca7f..7532484 100644
--- a/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java
@@ -11,8 +11,6 @@ import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlValue;
import org.gcube.common.resources.gcore.Resources;
import org.gcube.smartgears.extensions.ApiResource;
@@ -86,10 +84,8 @@ public class LifecycleResource extends ApiResource {
// helper classes
- @XmlRootElement(name="state")
public static class State {
- @XmlValue
public String value;
State() {
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java
new file mode 100644
index 0000000..51cb27d
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java
@@ -0,0 +1,38 @@
+package org.gcube.smartgears.extensions.resource;
+
+import static org.gcube.smartgears.Constants.plain_text;
+import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.gcube.smartgears.extensions.ApiResource;
+import org.gcube.smartgears.extensions.ApiSignature;
+
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.prometheus.PrometheusMeterRegistry;
+
+public class MetricsResource extends ApiResource {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String mapping = "/metrics";
+
+ private static final ApiSignature signature = handles(mapping).with(method(GET).produces(plain_text));
+
+
+ MetricsResource() {
+ super(signature);
+ }
+
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ PrometheusMeterRegistry registry = (PrometheusMeterRegistry) Metrics.globalRegistry.getRegistries().stream().findFirst().get();
+ registry.scrape(resp.getWriter());
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java
index 9e76f66..0ac19c8 100644
--- a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java
@@ -9,8 +9,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.gcube.common.resources.gcore.GCoreEndpoint;
-import org.gcube.common.resources.gcore.Resources;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
@@ -36,7 +34,8 @@ public class ProfileResource extends ApiResource {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- Resources.marshal(context().profile(GCoreEndpoint.class),resp.getWriter());
+ //Resources.marshal(context().profile(),resp.getWriter());
+ //TODO: return something to show
}
}
diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java
index 1acbf96..e3fe3f2 100644
--- a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java
+++ b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java
@@ -1,8 +1,6 @@
package org.gcube.smartgears.extensions.resource;
-import static org.gcube.smartgears.Constants.*;
-
-import javax.xml.bind.annotation.XmlRootElement;
+import static org.gcube.smartgears.Constants.remote_management;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.extensions.ApiResource;
@@ -14,7 +12,6 @@ import org.gcube.smartgears.extensions.HttpController;
* @author Fabio Simeoni
*
*/
-@XmlRootElement(name = remote_management)
public class RemoteResource extends HttpController {
private static final String default_mapping = Constants.root_mapping+"/*";
@@ -27,7 +24,7 @@ public class RemoteResource extends HttpController {
public RemoteResource() {
super(remote_management, default_mapping);
addResources(new FrontPageResource(), new ConfigurationResource(), new ProfileResource(),
- new LifecycleResource());
+ new LifecycleResource(), new MetricsResource(), new HealthResource());
}
@Override
diff --git a/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java b/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java
index 6c3e374..c928c50 100644
--- a/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java
+++ b/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java
@@ -3,21 +3,14 @@ package org.gcube.smartgears.handlers;
import java.util.Collection;
public interface ProfilePublisher {
-
- /**
- * Adds for the first time the current resource profile of the application in one or more scopes.
- * @param scopes the scopes
- */
- void addTo(Collection tokens);
+
+ void addTo(Collection contexts);
void addToAll();
-
+
void update();
- /**
- * Removes the application from one or more scopes.
- * @param scopes the scopes
- */
- void removeFrom(Collection tokens);
+ void removeFrom(Collection contexts);
-}
\ No newline at end of file
+
+}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java b/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java
index 07f83e2..95fa9d2 100644
--- a/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java
+++ b/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java
@@ -22,6 +22,10 @@ public abstract class RequestHandler extends AbstractHandler implements Applicat
abstract public String getName();
+ public boolean isUnfiltrable() {
+ return false;
+ }
+
/**
* Initialises the handler.
*
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java
similarity index 55%
rename from src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java
rename to src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java
index 5859cb8..8c9eafe 100644
--- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java
+++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java
@@ -2,36 +2,31 @@ package org.gcube.smartgears.handlers.application.lifecycle;
import static org.gcube.common.events.Observes.Kind.resilient;
import static org.gcube.smartgears.Constants.profile_management;
-import static org.gcube.smartgears.Constants.profile_property;
import static org.gcube.smartgears.handlers.ProfileEvents.addToContext;
import static org.gcube.smartgears.handlers.ProfileEvents.changed;
-import static org.gcube.smartgears.handlers.ProfileEvents.published;
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.lifecycle.application.ApplicationState.failed;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import javax.xml.bind.annotation.XmlRootElement;
-
import org.gcube.common.events.Observes;
import org.gcube.common.events.Observes.Kind;
-import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.context.Property;
import org.gcube.smartgears.context.application.ApplicationContext;
-import org.gcube.smartgears.handlers.OfflineProfilePublisher;
-import org.gcube.smartgears.handlers.ProfilePublisher;
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.publishing.Publisher;
import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,29 +47,24 @@ import org.slf4j.LoggerFactory;
*
*
* @author Fabio Simeoni
- * @see ProfileBuilder
- * @see ProfilePublisherImpl
*/
-@XmlRootElement(name = profile_management)
-public class ProfileManager extends ApplicationLifecycleHandler {
+public class ApplicationProfileManager extends ApplicationLifecycleHandler {
- Logger log = LoggerFactory.getLogger(ProfileManager.class);
+ Logger log = LoggerFactory.getLogger(ApplicationProfileManager.class);
private ApplicationContext context;
- private ProfileBuilder builder;
- private ProfilePublisher publisher;
-
private ScheduledFuture> periodicUpdates;
+ private static final String PUBLISHED_PROP = "published";
+ private List publishers = ProviderFactory.provider().publishers();
+
@Override
public void onStart(ApplicationLifecycleEvent.Start e) {
context = e.context();
- builder = new ProfileBuilder(context);
activated();
-
- schedulePeriodicUpdates();
+
// note we don't fire profile events, but wait for the final startup
// outcome which
// will result in a state change. only then we publish and store the
@@ -89,16 +79,13 @@ public class ProfileManager extends ApplicationLifecycleHandler {
private void activated(){
- GCoreEndpoint profile = loadOrCreateProfile();
- share(profile);
-
- publisher = context.container().configuration().mode()!=Mode.offline?
- new ProfilePublisherImpl(context):
- new OfflineProfilePublisher();
-
+ publishers = context.container().configuration().mode()!=Mode.offline?
+ ProviderFactory.provider().publishers():
+ Collections.emptyList();
registerObservers();
+ schedulePeriodicUpdates();
}
// helpers
@@ -109,141 +96,100 @@ public class ProfileManager extends ApplicationLifecycleHandler {
@Observes({ activation, stop, failure })
void onChanged(ApplicationLifecycle lc) {
- GCoreEndpoint profile = context.profile(GCoreEndpoint.class);
-
- profile.profile().deploymentData().status(lc.state().remoteForm());
-
log.debug("moving app {} to {}",context.name(), lc.state().remoteForm());
// since we do not know the observers, they will deal with
// failures and their consequences
// any that comes back will be logged in this event thread
- context.events().fire(profile, changed);
+ context.events().fire(context, changed);
}
+ /*
@Observes(value = published)
void shareAfterPublish(GCoreEndpoint profile) {
share(profile); // publish may produce a new profile instance
- }
+ }*/
@Observes(value = changed, kind = Kind.safe)
- void publishAfterChange(GCoreEndpoint profile) {
+ void publishAfterChange(ApplicationContext context) {
- boolean firstPublication = profile.scopes().isEmpty();
//if we've failed before first publication do not try to publish
//(we may well have failed there)
- try {
-
- if (firstPublication) {
- if (context.lifecycle().state()!= failed)
- publishFirstTime(profile);
- }
- else{
- log.debug("update app {} profile",context.name());
- publisher.update(); // if successful, triggers share.
+ if (!context.properties().contains(PUBLISHED_PROP)) {
+ log.info("publishing application for the first time");
+ context.properties().add(new Property(PUBLISHED_PROP, true));
+ if (context.lifecycle().state() != ApplicationState.failed) {
+ publishers.forEach(p -> {
+ try {
+ p.create(context,
+ context.container().authorizationProvider().getContexts());
+ }catch (Exception e) {
+ log.error("cannot publish {} for first time with publisher type {} (see details)",context.name(), p.getClass().getCanonicalName(), e);
+ }
+ });
}
}
- catch (Exception e) {
-
- log.error("cannot publish "+context.name()+" (see details)", e);
-
- // since we've failed no published event is fired and profile
- // will not be stored.
- // we do it manually to ensure we leave some local trace of the
- // changed profile.
- //TODO: CHECK --- store(profile);
- }
-
-
-
- }
-
- @Observes(value = addToContext)
- void addTo(String token) {
- try {
- log.trace("publishing application with new token");
- publisher.addTo(Collections.singleton(token));
- publisher.update();
- }catch (Exception e) {
-
- log.error("cannot add token {} (see details)",token, e);
-
- // since we've failed no published event is fired and profile
- // will not be stored.
- // we do it manually to ensure we leave some local trace of the
- // changed profile.
- //TODO: CHECK --- store(profile);
- }
-
- }
-
- @Observes(value = removeFromContext)
- void removeFrom(String token) {
- try {
- log.trace("unpublishing application with token");
- publisher.removeFrom(Collections.singleton(token));
- publisher.update();
- }catch (Exception e) {
-
- log.error("cannot remove token {} (see details)",token, e);
-
- // since we've failed no published event is fired and profile
- // will not be stored.
- // we do it manually to ensure we leave some local trace of the
- // changed profile.
- //TODO: CHECK --- store(profile);
- }
+ else
+ publishers.forEach(p -> {
+ try {
+ p.update(context);
+ }catch (Exception e) {
+ log.error("cannot publish {} with publisher type {} (see details)",context.name(), p.getClass().getCanonicalName(), e);
+ }
+ });
}
});
- }
+ //registering ContextObserver in container HUB
+ context.container().events().subscribe(new Object() {
- private void share(GCoreEndpoint profile) {
+ @Observes(value = addToContext)
+ void addTo(String scope) {
+ log.info("add_to_context event arrived in app {}", context.name());
+ for (Publisher publisher: publishers)
+ try {
+ log.debug("publishing application in context {}", scope);
+ publisher.create(context,
+ Collections.singleton(scope));
- log.trace("sharing profile for {}", context.name());
+ }catch (Exception e) {
- context.properties().add(new Property(profile_property, profile));
- }
+ log.error("cannot add context {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e);
- private void publishFirstTime(GCoreEndpoint profile) {
+ // since we've failed no published event is fired and profile
+ // will not be stored.
+ // we do it manually to ensure we leave some local trace of the
+ // changed profile.
+ //TODO: CHECK --- store(profile);
+ }
- try {
+ }
- publisher.addToAll();
+ @Observes(value = removeFromContext)
+ void removeFrom(String scope) {
+ log.info("remove_from_context event arrived in app {}", context.name());
+ for (Publisher publisher: publishers)
+ try {
+ log.debug("unpublishing application from scope {}", scope);
+ publisher.remove(context,
+ Collections.singleton(scope));
+ }catch (Exception e) {
- } catch (Exception e) {
- log.warn("publishing failed",e);
- }
- }
+ log.error("cannot remove scope {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e);
- private GCoreEndpoint loadOrCreateProfile() {
+ // since we've failed no published event is fired and profile
+ // will not be stored.
+ // we do it manually to ensure we leave some local trace of the
+ // changed profile.
+ //TODO: CHECK --- store(profile);
+ }
- return create();
- }
-
- private GCoreEndpoint create() {
-
- log.info("creating profile for {}", context.name());
-
- try {
-
- GCoreEndpoint profile = new GCoreEndpoint();
- profile.setId(context.id());
-
- builder.fill(profile);
-
- return profile;
-
- } catch (RuntimeException e) {
-
- // this is a critical startup failure: it will fail the application
- throw new RuntimeException("cannot create profile for " + context.name(), e);
-
- }
+ }
+ });
}
@@ -270,16 +216,16 @@ public class ProfileManager extends ApplicationLifecycleHandler {
final Runnable updateTask = new Runnable() {
public void run() {
- GCoreEndpoint profile = context.profile(GCoreEndpoint.class);
-
//if handling of event generates failures these will be reported
//for resilience we do not fail the application
- log.trace("firing change event on application {} profile", context.name());
- context.events().fire(profile,changed);
+ log.trace("firing change event on application {} ", context.name());
+ context.events().fire(context,changed);
}
};
- periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, Constants.application_republish_frequency_in_minutes, Constants.application_republish_frequency_in_minutes , TimeUnit.MINUTES);
+ periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask,
+ Constants.application_republish_frequency_in_minutes,
+ Constants.application_republish_frequency_in_minutes , TimeUnit.MINUTES);
}
@@ -294,7 +240,7 @@ public class ProfileManager extends ApplicationLifecycleHandler {
periodicUpdates=null;
}
catch(Exception e) {
- log.warn("could not stop periodic updates of application {} profile", context.name(),e);
+ log.warn("could not stop periodic updates of application {}", context.name(),e);
}
}
}
@@ -302,8 +248,8 @@ public class ProfileManager extends ApplicationLifecycleHandler {
});
}
-
-
+
+
@Override
public String toString() {
return profile_management;
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java
deleted file mode 100644
index da9c635..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.gcube.smartgears.handlers.application.lifecycle;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-
-import javax.servlet.ServletRegistration;
-
-import org.gcube.common.resources.gcore.GCoreEndpoint;
-import org.gcube.common.resources.gcore.HostingNode;
-import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
-import org.gcube.smartgears.configuration.container.ContainerConfiguration;
-import org.gcube.smartgears.context.application.ApplicationContext;
-
-public class ProfileBuilder {
-
- private static List servletExcludes = Arrays.asList("default","jsp");
-
- // private static final Logger log = LoggerFactory.getLogger(ProfileBuilder.class);
-
- private ApplicationContext context;
-
- public ProfileBuilder(ApplicationContext context) {
- this.context = context;
- }
-
- public void fill(GCoreEndpoint endpoint) {
-
-
- ApplicationConfiguration configuration = context.configuration();
- ContainerConfiguration container = context.container().configuration();
-
-
- endpoint.profile()
- .description(configuration.description())
- .serviceName(configuration.name())
- .serviceClass(configuration.serviceClass())
- .version(configuration.version())
- .serviceId(configuration.name() + configuration.serviceClass() + configuration.version())
- .ghnId(context.container().profile(HostingNode.class).id());
-
- endpoint.profile().newDeploymentData()
- .activationTime(Calendar.getInstance())
- .status((context.lifecycle().state().remoteForm()));
-
- endpoint.profile().endpoints().clear();
-
- 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());
- }
-
- for (ServletRegistration servlet : context.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);
- endpoint.profile().endpoints().add().nameAndAddress(servlet.getName(),URI.create(address));
- }
-
-
- }
-
-}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java
deleted file mode 100644
index 54f9930..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package org.gcube.smartgears.handlers.application.lifecycle;
-
-import static org.gcube.smartgears.handlers.ProfileEvents.published;
-import static org.gcube.smartgears.utils.Utils.notEmpty;
-import static org.gcube.smartgears.utils.Utils.rethrowUnchecked;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
-import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.resources.gcore.GCoreEndpoint;
-import org.gcube.informationsystem.publisher.ScopedPublisher;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.context.application.ApplicationContext;
-import org.gcube.smartgears.handlers.ProfilePublisher;
-import org.gcube.smartgears.provider.ProviderFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Publishes the current resource profile of the application.
- *
- *Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update()}.
- *
- *
- * @author Fabio Simeoni
- *
- */
-public class ProfilePublisherImpl implements ProfilePublisher {
-
- private static final Logger log = LoggerFactory.getLogger(ProfilePublisherImpl.class);
-
- //the underlying IS publisher
- private final ScopedPublisher publisher;
-
- private final ApplicationContext context;
-
- private AuthorizationProxy authProxy ;
-
- /**
- * Creates an instance for a given application.
- * @param context the context of the application
- */
- public ProfilePublisherImpl(ApplicationContext context) {
- this.context = context;
- this.publisher=ProviderFactory.provider().publisherFor(context);
- this.authProxy = ProviderFactory.provider().authorizationProxy();
- }
-
- /**
- * Adds for the first time the current resource profile of the application in one or more scopes.
- * @param scopes the scopes
- */
- @Override
- public void addTo(Collection tokens) {
-
- notEmpty("tokens",tokens);
-
- GCoreEndpoint profile = context.profile(GCoreEndpoint.class);
-
- /* TODO: reintroduce it when scope will be removed
- //TODO: remove when move to new IS
- Collection retainedContexts = new ArrayList(context.container().configuration().allowedContexts());
- retainedContexts.removeAll(profile.scopes().asCollection());
- profile.scopes().asCollection().addAll(retainedContexts);
-
-
- String previousToken = SecurityTokenProvider.instance.get();
- try {
- for (String token: tokens){
- log.info("creating profile with token {}", token);
- SecurityTokenProvider.instance.set(token);
- profile = publisher.create(profile);
- SecurityTokenProvider.instance.reset();
- }
- }catch (Exception e) {
- rethrowUnchecked(e);
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- }
- */
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
-
- log.debug("using context {}",contextCL.getClass().getSimpleName());
-
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
- if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.create(profile, resolveScopesFromTokens(tokens));
-
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL);
- }
-
- sharePublished(profile);
- log.debug("shared profile with scopes {}", profile.scopes().asCollection());
- }
-
- @Override
- public void addToAll() {
- this.addTo(context.configuration().startTokens());
- }
-
-
- @Override
- public void update() {
-
-
- GCoreEndpoint profile = context.profile(GCoreEndpoint.class);
-
- /* TODO: reintroduce it when scope will be removed
- String previousToken = SecurityTokenProvider.instance.get();
- try {
-
- for (String token: context.configuration().startTokens()){
- SecurityTokenProvider.instance.set(token);
- profile = publisher.update(profile);
- SecurityTokenProvider.instance.reset();
- }
-
- }
- catch (Exception e) {
- rethrowUnchecked(e);
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- }
- */
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
-
- log.debug("using context {}",contextCL.getClass().getSimpleName());
-
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]);
-
- if (context.container().configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.update(profile);
-
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- if (context.container().configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(contextCL);
- }
-
- sharePublished(profile);
- }
-
-
- /**
- * Removes the application from one or more scopes.
- * @param scopes the scopes
- */
- @Override
- public void removeFrom(Collection tokens) {
-
- GCoreEndpoint profile = context.profile(GCoreEndpoint.class);
-
- /* TODO: reintroduce it when scope will be removed
- String previousToken = SecurityTokenProvider.instance.get();
- try {
-
- for (String token: tokens){
- SecurityTokenProvider.instance.set(token);
- profile = publisher.remove(profile);
- SecurityTokenProvider.instance.reset();
- }
-
- }
- catch (Exception e) {
-
- rethrowUnchecked(e);
-
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- }
- */
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
-
- log.debug("using context {}",contextCL.getClass().getSimpleName());
-
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
- if (context.container().configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.remove(profile, resolveScopesFromTokens(tokens));
-
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- if (context.container().configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(contextCL);
- }
- log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection());
- sharePublished(profile);
- }
-
-
-
- private void sharePublished(GCoreEndpoint profile) {
- context.events().fire(profile,published);
- }
-
- private List resolveScopesFromTokens(Collection tokens){
- List scopes = new ArrayList(tokens.size());
- for (String token: tokens)
- try{
- scopes.add(this.authProxy.get(token).getContext());
- }catch (Exception e) {
- log.warn("error retrieving token {} , it should never happen",token);
- }
- return scopes;
- }
-
-}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java
index 61f7b33..db65ce8 100644
--- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java
+++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java
@@ -1,16 +1,10 @@
package org.gcube.smartgears.handlers.application.request;
-import static org.gcube.smartgears.Constants.called_method_header;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
import org.gcube.accounting.datamodel.UsageRecord.OperationResult;
import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord;
import org.gcube.accounting.persistence.AccountingPersistence;
import org.gcube.accounting.persistence.AccountingPersistenceFactory;
-import org.gcube.common.authorization.library.provider.AuthorizationProvider;
-import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.scope.api.ScopeProvider;
+import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.context.application.ApplicationContext;
@@ -21,100 +15,133 @@ import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-@XmlRootElement(name = Constants.request_accounting)
public class RequestAccounting extends RequestHandler {
private static Logger log = LoggerFactory.getLogger(RequestAccounting.class);
- private static ThreadLocal startCallThreadLocal = new ThreadLocal();
-
-
+ private static ThreadLocal startCallThreadLocal = new ThreadLocal();
+
+ private static final String UNKNOWN = "Unknown";
+
@Override
public String getName() {
return Constants.request_accounting;
}
-
+
@Override
public void handleRequest(RequestEvent e) {
- ApplicationContext context = e.context();
-
- String calledMethod = e.request().getHeader(called_method_header);
- if (calledMethod==null){
- calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length());
+ ApplicationContext appContext = e.context();
+
+ String context = getContext(appContext);
+
+ if (InnerMethodName.instance.get() == null) {
+ String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length());
if (calledMethod.isEmpty())
calledMethod = "/";
- calledMethod= e.request().getMethod()+" "+calledMethod;
+ calledMethod = e.request().getMethod() + " " + calledMethod;
+ InnerMethodName.instance.set(calledMethod);
}
- InnerMethodName.instance.set(calledMethod);
- String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN";
+
+ String caller = SecretManagerProvider.instance.get() != null
+ ? SecretManagerProvider.instance.get().getOwner().getId()
+ : UNKNOWN;
startCallThreadLocal.set(System.currentTimeMillis());
- log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ",
- context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(),
- caller, e.request().getRemoteHost(), ScopeProvider.instance.get());
-
+
+ log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", appContext.configuration().name(),
+ appContext.configuration().group(), InnerMethodName.instance.get(), caller,
+ e.request().getRemoteHost(), context);
+
}
@Override
public void handleResponse(ResponseEvent e) {
- ApplicationContext context = e.context();
-
- boolean resetScope = false;
- if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){
- String infrastructure = e.context().container().configuration().infrastructure();
- ScopeProvider.instance.set("/"+infrastructure);
- resetScope = true;
+ ApplicationContext appContext = e.context();
+
+ try {
+
+ String context = getContext(appContext);
+
+ String caller = SecretManagerProvider.instance.get() != null
+ ? SecretManagerProvider.instance.get().getOwner().getId()
+ : UNKNOWN;
+ String callerQualifier = UNKNOWN;
+ // retieves caller Ip when there is a proxy
+ String callerIp = e.request().getHeader("x-forwarded-for");
+ if (callerIp == null)
+ callerIp = e.request().getRemoteHost();
+
+ boolean success = e.response().getStatus() < 400;
+
+ if (appContext.container().configuration().mode() != Mode.offline)
+ generateAccounting(caller, callerQualifier, callerIp == null ? UNKNOWN : callerIp, success, context,
+ appContext);
+
+ long durationInMillis = System.currentTimeMillis() - startCallThreadLocal.get();
+
+ /*
+ * Metrics.globalRegistry.timer("smartgears.requests",
+ * "response",Integer.toString(e.response().getStatus()) , "context", context,
+ * "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp,
+ * "caller-username", caller, "service-class",
+ * appContext.configuration().serviceClass(), "service-name",
+ * appContext.configuration().name(), "method",
+ * InnerMethodName.instance.get()).record(durationInMillis,
+ * TimeUnit.MILLISECONDS);
+ */
+
+ log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis",
+ appContext.configuration().name(), appContext.configuration().group(),
+ InnerMethodName.instance.get(), caller, callerIp, context, success ? "SUCCEDED" : "FAILED",
+ e.response().getStatus(), durationInMillis);
+
+ } catch (Exception e1) {
+ log.error("error on accounting", e);
+ throw e1;
+ } finally {
+ startCallThreadLocal.remove();
+ InnerMethodName.instance.reset();
}
-
- String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN";
- String callerQualifier = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getTokenQualifier(): "UNKNOWN";
- //retieves caller Ip when there is a proxy
- String callerIp = e.request().getHeader("x-forwarded-for");
- if(callerIp==null)
- callerIp=e.request().getRemoteHost();
-
- boolean success = e.response().getStatus()<400;
-
- if (context.container().configuration().mode()!=Mode.offline)
- generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context);
-
- log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis",
- context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(),
- caller, callerIp, ScopeProvider.instance.get(), success?"SUCCEDED":"FAILED", e.response().getStatus(), System.currentTimeMillis()-startCallThreadLocal.get());
- startCallThreadLocal.remove();
- InnerMethodName.instance.reset();
- if (resetScope)
- ScopeProvider.instance.reset();
+
}
- void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){
- AccountingPersistenceFactory.setFallbackLocation(context.container().persistence().location());
+ void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success,
+ String gcubeContext, ApplicationContext appContext) {
+ AccountingPersistenceFactory
+ .setFallbackLocation(appContext.container().configuration().accountingFallbackLocation());
AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence();
ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord();
- try{
-
+ try {
+
serviceUsageRecord.setConsumerId(caller);
serviceUsageRecord.setCallerQualifier(callerQualifier);
- serviceUsageRecord.setScope(ScopeProvider.instance.get());
- serviceUsageRecord.setServiceClass(context.configuration().serviceClass());
- serviceUsageRecord.setServiceName(context.configuration().name());
-
- serviceUsageRecord.setHost(context.container().configuration().hostname()+":"+context.container().configuration().port());
+ serviceUsageRecord.setScope(gcubeContext);
+ serviceUsageRecord.setServiceClass(appContext.configuration().group());
+ serviceUsageRecord.setServiceName(appContext.configuration().name());
+
+ serviceUsageRecord.setHost(appContext.container().configuration().hostname() + ":"
+ + appContext.container().configuration().port());
serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get());
serviceUsageRecord.setCallerHost(remoteHost);
- serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED);
- serviceUsageRecord.setDuration(System.currentTimeMillis()-startCallThreadLocal.get());
+ serviceUsageRecord.setOperationResult(success ? OperationResult.SUCCESS : OperationResult.FAILED);
+ serviceUsageRecord.setDuration(System.currentTimeMillis() - startCallThreadLocal.get());
persistence.account(serviceUsageRecord);
-
- }catch(Exception ex){
- log.warn("invalid record passed to accounting ",ex);
+
+ } catch (Exception ex) {
+ log.warn("invalid record passed to accounting ", ex);
}
}
+ private String getContext(ApplicationContext appContext) {
+ String infrastructure = appContext.container().configuration().infrastructure();
+ String context = "/" + infrastructure;
+ if (SecretManagerProvider.instance.get() != null)
+ context = SecretManagerProvider.instance.get().getContext();
+ return context;
+ }
+
@Override
public String toString() {
return getName();
}
-
-
}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java
deleted file mode 100644
index e5b984e..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.gcube.smartgears.handlers.application.request;
-
-import static org.gcube.common.authorization.client.Constants.authorizationService;
-import static org.gcube.smartgears.Constants.scope_header;
-import static org.gcube.smartgears.Constants.token_header;
-import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error;
-import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
-
-import java.util.Base64;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
-import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
-import org.gcube.common.authorization.library.AuthorizationEntry;
-import org.gcube.common.authorization.library.provider.AccessTokenProvider;
-import org.gcube.common.authorization.library.provider.AuthorizationProvider;
-import org.gcube.common.authorization.library.provider.ClientInfo;
-import org.gcube.common.authorization.library.provider.ExternalServiceInfo;
-import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.authorization.library.provider.UserInfo;
-import org.gcube.common.authorization.library.utils.Caller;
-import org.gcube.common.scope.api.ScopeProvider;
-import org.gcube.common.scope.impl.ScopeBean;
-import org.gcube.smartgears.Constants;
-import org.gcube.smartgears.handlers.application.RequestEvent;
-import org.gcube.smartgears.handlers.application.RequestHandler;
-import org.gcube.smartgears.handlers.application.ResponseEvent;
-import org.gcube.smartgears.utils.GcubeJwt;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@XmlRootElement(name = Constants.request_context_retriever)
-public class RequestContextRetriever extends RequestHandler {
-
- private static Logger log = LoggerFactory.getLogger(RequestContextRetriever.class);
-
- private static final String BEARER_AUTH_PREFIX ="Bearer";
- private static final String BASIC_AUTH_PREFIX ="Basic";
-
-
- @Override
- public String getName() {
- return Constants.request_context_retriever;
- }
-
- @Override
- public void handleRequest(RequestEvent call) {
- String token = call.request().getParameter(token_header)==null? call.request().getHeader(token_header):call.request().getParameter(token_header);
- String scope = call.request().getParameter(scope_header)==null? call.request().getHeader(scope_header):call.request().getParameter(scope_header);
-
- String authHeader = call.request().getHeader(Constants.authorization_header);
-
- log.trace("authorization header is {}",authHeader);
- log.trace("token header is {}",token);
- log.trace("scope header is {}",scope);
-
- String retrievedUser = null;
- String accessToken = null;
- if (authHeader!=null && !authHeader.isEmpty()) {
- if (authHeader.startsWith(BEARER_AUTH_PREFIX))
- accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim();
- else if (token==null && authHeader.startsWith(BASIC_AUTH_PREFIX)) {
- String basicAuthToken = authHeader.substring(BASIC_AUTH_PREFIX.length()).trim();
- String decodedAuth = new String(Base64.getDecoder().decode(basicAuthToken.getBytes()));
- String[] splitAuth = decodedAuth.split(":");
- token = splitAuth[1];
- retrievedUser = splitAuth[0];
- }
- }
-
- //Gives priority to the umaToken
- if (accessToken!=null) {
- this.retreiveAndSetInfoUmaToken(accessToken, token, call);
- } else if (token!=null)
- this.retreiveAndSetInfoGcubeToken(token, retrievedUser, call);
- else if (scope!=null)
- ScopeProvider.instance.set(scope);
-
- }
-
- @Override
- public void handleResponse(ResponseEvent e) {
- SecurityTokenProvider.instance.reset();
- AuthorizationProvider.instance.reset();
- AccessTokenProvider.instance.reset();
- ScopeProvider.instance.reset();
- log.debug("resetting all the Thread local for this call.");
- }
-
- private void retreiveAndSetInfoGcubeToken(String token, String retrievedUser, RequestEvent call){
- log.trace("retrieving context using token {} ", token);
- AuthorizationEntry authEntry = null;
- try{
- authEntry = authorizationService().get(token);
- if (retrievedUser != null && !authEntry.getClientInfo().getId().equals(retrievedUser))
- throw new Exception("user and token owner are not the same");
- }catch(ObjectNotFound onf){
- log.warn("rejecting call to {}, invalid token {}",call.context().name(),token);
- invalid_request_error.fire(call.context().name()+" invalid token : "+token);
- }catch(Exception e){
- log.error("error contacting authorization service",e);
- internal_server_error.fire("error contacting authorization service");
- }
-
- AuthorizationProvider.instance.set(new Caller(authEntry.getClientInfo(), authEntry.getQualifier()));
- SecurityTokenProvider.instance.set(token);
- ScopeProvider.instance.set(authEntry.getContext());
- log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), authEntry.getContext());
- }
-
- private void retreiveAndSetInfoUmaToken(String accessToken, String gcubeToken, RequestEvent call){
- log.debug("using UMA token for authorization");
- log.trace("retrieving context using uma token {} ", accessToken);
-
- AccessTokenProvider.instance.set(accessToken);
- parseAccessTokenAndSet(accessToken);
- log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), ScopeProvider.instance.get());
- }
-
- private void parseAccessTokenAndSet(String umaToken) {
-
- String realUmaTokenEncoded = umaToken.split("\\.")[1];
-
- String realUmaToken = new String(Base64.getDecoder().decode(realUmaTokenEncoded.getBytes()));
-
- ObjectMapper mapper = new ObjectMapper();
-
- GcubeJwt jwt = null;
- try {
- jwt = mapper.readValue(realUmaToken, GcubeJwt.class);
- }catch(Exception e){
- log.error("error decoding uma token",e);
- internal_server_error.fire("error parsing access token");
- }
-
- ScopeBean scopeBean = null;
- try {
- scopeBean = new ScopeBean(jwt.getContext());
- }catch(Exception e){
- log.error("error decoding uma token",e);
- internal_server_error.fire("invalid context in access token");
- }
-
- ClientInfo clientInfo;
- if (!jwt.isExternalService())
- clientInfo = new UserInfo(jwt.getUsername(), jwt.getRoles(), jwt.getEmail(), jwt.getFirstName(), jwt.getLastName());
- else
- clientInfo = new ExternalServiceInfo(jwt.getUsername(), "unknown", jwt.getRoles());
-
- log.info("caller type is {}",clientInfo.getType());
- AuthorizationProvider.instance.set(new Caller(clientInfo, "token"));
-
- ScopeProvider.instance.set(scopeBean.toString());
-
- }
-
-
-
-}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java
new file mode 100644
index 0000000..30793be
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java
@@ -0,0 +1,47 @@
+package org.gcube.smartgears.handlers.application.request;
+
+import java.time.Duration;
+
+import org.gcube.smartgears.Constants;
+import org.gcube.smartgears.handlers.application.RequestEvent;
+import org.gcube.smartgears.handlers.application.RequestHandler;
+import org.gcube.smartgears.handlers.application.ResponseEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.micrometer.core.instrument.Metrics;
+
+public class RequestMetrics extends RequestHandler {
+
+ private static Logger log = LoggerFactory.getLogger(RequestMetrics.class);
+
+ private static ThreadLocal startCallThreadLocal = new ThreadLocal();
+
+ private static final String HTTP_REQUEST_METRICS_NAME = "http.server.requests";
+
+ @Override
+ public String getName() {
+ return Constants.request_metrics;
+ }
+
+ @Override
+ public boolean isUnfiltrable() {
+ return true;
+ }
+
+ @Override
+ public void handleRequest(RequestEvent e) {
+ startCallThreadLocal.set(System.currentTimeMillis());
+ }
+
+ @Override
+ public void handleResponse(ResponseEvent e) {
+ String statusCode = Integer.toString(e.response().getStatus());
+ Metrics.globalRegistry.timer(HTTP_REQUEST_METRICS_NAME, "status", statusCode).record(Duration.ofMillis(System.currentTimeMillis() - startCallThreadLocal.get()));
+ startCallThreadLocal.remove();
+ log.debug("metrics for current call saved");
+ }
+
+
+
+}
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java
index a35ec9a..8135571 100644
--- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java
+++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java
@@ -1,47 +1,39 @@
package org.gcube.smartgears.handlers.application.request;
-import static org.gcube.common.authorization.client.Constants.authorizationService;
+import static org.gcube.smartgears.Constants.token_header;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
-import java.util.Collections;
-import java.util.List;
+import java.util.Set;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.authorization.library.PolicyUtils;
-import org.gcube.common.authorization.library.policies.Policy;
-import org.gcube.common.authorization.library.policies.User2ServicePolicy;
-import org.gcube.common.authorization.library.policies.UserEntity;
-import org.gcube.common.authorization.library.provider.AccessTokenProvider;
-import org.gcube.common.authorization.library.provider.AuthorizationProvider;
-import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.authorization.library.provider.ServiceIdentifier;
-import org.gcube.common.scope.api.ScopeProvider;
-import org.gcube.common.scope.impl.ScopeBean;
-import org.gcube.common.scope.impl.ScopeBean.Type;
+import org.gcube.common.keycloak.KeycloakClient;
+import org.gcube.common.keycloak.KeycloakClientException;
+import org.gcube.common.keycloak.KeycloakClientFactory;
+import org.gcube.common.security.ContextBean;
+import org.gcube.common.security.ContextBean.Type;
+import org.gcube.common.security.providers.SecretManagerProvider;
+import org.gcube.common.security.secrets.GCubeSecret;
+import org.gcube.common.security.secrets.Secret;
+import org.gcube.common.security.secrets.UmaTokenSecret;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.RequestEvent;
import org.gcube.smartgears.handlers.application.RequestHandler;
-import org.gcube.smartgears.utils.Utils;
+import org.gcube.smartgears.handlers.application.ResponseEvent;
+import org.gcube.smartgears.security.SimpleCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-@XmlRootElement(name = Constants.request_validation)
public class RequestValidator extends RequestHandler {
- @XmlAttribute(required=false, name="oauth")
- @Deprecated
- boolean oauthCompatibility = false;
-
private static Logger log = LoggerFactory.getLogger(RequestValidator.class);
- private ApplicationContext context;
+ private static final String BEARER_AUTH_PREFIX ="Bearer";
+
+ private ApplicationContext appContext;
@Override
public String getName() {
@@ -53,27 +45,31 @@ public class RequestValidator extends RequestHandler {
log.trace("executing request validator ON REQUEST");
- log.trace("accessToken is null? {} \nGcubeToken is null ? {} \nscope rpvideris null? {}",
- AccessTokenProvider.instance.get()==null,
- SecurityTokenProvider.instance.get()==null,
- ScopeProvider.instance.get()==null);
-
- context = call.context();
+ appContext = call.context();
+
+ SecretManagerProvider.instance.set(getSecret(call));
validateAgainstLifecycle(call);
rejectUnauthorizedCalls(call);
- if (context.container().configuration().mode()!=Mode.offline) {
+ if (appContext.container().configuration().mode()!=Mode.offline) {
validateScopeCall();
- validatePolicy(ScopeProvider.instance.get(), call);
+ validatePolicy(call);
}
}
+ @Override
+ public void handleResponse(ResponseEvent e) {
+ log.debug("resetting all the Thread local for this call.");
+ SecretManagerProvider.instance.reset();
+ }
+
+
private void validateAgainstLifecycle(RequestEvent call) {
- switch(context.lifecycle().state()) {
+ switch(appContext.lifecycle().state()) {
case stopped :
application_unavailable_error.fire(); break;
@@ -85,36 +81,36 @@ public class RequestValidator extends RequestHandler {
//nothing to do, but avoids warnings
}
-
}
private void validateScopeCall() {
- String scope = ScopeProvider.instance.get();
+ String context = SecretManagerProvider.instance.get().getContext();
- if (scope == null) {
- log.warn("rejecting unscoped call to {}",context.name());
+ if (context == null) {
+ log.warn("rejecting unscoped call to {}",appContext.name());
invalid_request_error.fire("call is unscoped");
}
- ScopeBean bean = new ScopeBean(scope);
+ ContextBean bean = new ContextBean(context);
- ContainerConfiguration conf = context.container().configuration();
- if (!conf.allowedContexts().contains(scope) &&
- !(conf.authorizeChildrenContext() && bean.is(Type.VRE) && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) {
- log.warn("rejecting call to {} in invalid context {}, allowed context are {}",context.name(),scope,context.container().configuration().allowedContexts());
- invalid_request_error.fire(context.name()+" cannot be called in scope "+scope);
+ ContainerConfiguration conf = appContext.container().configuration();
+ Set allowedContexts =appContext.authorizationProvider().getContexts();
+ if (!allowedContexts.contains(context) &&
+ !(conf.authorizeChildrenContext() && bean.is(Type.VRE)
+ && allowedContexts.contains(bean.enclosingScope().toString()) ) ) {
+ log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),context,allowedContexts);
+ invalid_request_error.fire(appContext.name()+" cannot be called in scope "+context);
}
}
private void rejectUnauthorizedCalls(RequestEvent call){
- String token = SecurityTokenProvider.instance.get();
- String accessToken = AccessTokenProvider.instance.get();
-
- if (token == null && accessToken==null){
- log.warn("rejecting call to {}, authorization required",context.name(),token);
- RequestError.request_not_authorized_error.fire(context.name()+": authorization required");
+ Secret secret = SecretManagerProvider.instance.get();
+
+ if (secret == null){
+ log.warn("rejecting call to {}, authorization required",appContext.name());
+ RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required");
}
}
@@ -123,45 +119,39 @@ public class RequestValidator extends RequestHandler {
return getName();
}
- private void validatePolicy(String scope, RequestEvent call){
- log.info("accessing policy validator in scope {} ", scope);
+ private void validatePolicy(RequestEvent call){
+ //TODO: must be re-thought
+ }
- ServiceIdentifier serviceIdentifier = Utils.getServiceInfo(call.context()).getServiceIdentifier();
+ private Secret getSecret(RequestEvent call){
+ String token = call.request().getParameter(token_header)==null? call.request().getHeader(token_header):call.request().getParameter(token_header);
+ String authHeader = call.request().getHeader(Constants.authorization_header);
- String previousToken = SecurityTokenProvider.instance.get();
- try {
- String serviceToken = context.configuration().startTokens().stream().findFirst().get();
- SecurityTokenProvider.instance.set(serviceToken);
- String callerId = AuthorizationProvider.instance.get().getClient().getId();
- List policies = Collections.emptyList();
+ log.trace("authorization header is {}",authHeader);
+ log.trace("token header is {}", token);
+
+ log.info("d4s-user set to {} ", call.request().getHeader("d4s-user"));
+
+ String umaToken = null;
+ if (authHeader!=null && !authHeader.isEmpty())
+ if (authHeader.startsWith(BEARER_AUTH_PREFIX))
+ umaToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim();
+
+ Secret secret = null;
+ if (umaToken!=null) {
+ secret = new UmaTokenSecret(umaToken);
+ SimpleCredentials credentials = (SimpleCredentials)appContext.authorizationProvider().getCredentials();
+ KeycloakClient client = KeycloakClientFactory.newInstance();
try {
- policies = authorizationService().getPolicies(scope);
- }catch (Exception e) {
- log.error("error contacting authorization services for policies");
+ if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), umaToken))
+ RequestError.request_not_authorized_error.fire("access token verification error");
+ }catch (KeycloakClientException e) {
+ RequestError.internal_server_error.fire("error contacting keycloak client", e);
}
-
- for (Policy policy: policies) {
- log.debug("policy: {}", policy.getPolicyAsString() );
-
- if (PolicyUtils.isPolicyValidForClient(policy.getServiceAccess(), serviceIdentifier )) {
- boolean toReject = false;
- UserEntity entity = (((User2ServicePolicy) policy).getEntity());
- if (entity.getIdentifier()!=null)
- toReject = entity.getIdentifier().equals(callerId);
- else if (entity.getExcludes().isEmpty())
- toReject = true;
- else toReject = !entity.getExcludes().contains(callerId);
- if (toReject) {
- log.error("rejecting call to {} : {} is not allowed to contact the service ",context.name(), callerId);
- RequestError.request_not_authorized_error.fire("rejecting call to "+context.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() );
- }
- }
-
- }
- }finally {
- SecurityTokenProvider.instance.set(previousToken);
- }
+ } else if (token!=null && !token.isEmpty())
+ secret = new GCubeSecret(token);
+ return secret;
}
diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java
index a879731..019e2ab 100644
--- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java
+++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java
@@ -5,8 +5,6 @@ package org.gcube.smartgears.handlers.container.lifecycle;
import static org.gcube.smartgears.Constants.accounting_management;
-import javax.xml.bind.annotation.XmlRootElement;
-
import org.gcube.accounting.persistence.AccountingPersistenceFactory;
import org.gcube.smartgears.handlers.container.ContainerHandler;
import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent;
@@ -16,7 +14,6 @@ import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
-@XmlRootElement(name = accounting_management)
public class AccountingManager extends ContainerHandler {
private static Logger logger = LoggerFactory.getLogger(AccountingManager.class);
diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java
new file mode 100644
index 0000000..58440b0
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java
@@ -0,0 +1,220 @@
+package org.gcube.smartgears.handlers.container.lifecycle;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.gcube.common.events.Observes.Kind.critical;
+import static org.gcube.common.events.Observes.Kind.resilient;
+import static org.gcube.smartgears.Constants.profile_management;
+import static org.gcube.smartgears.handlers.ProfileEvents.addToContext;
+import static org.gcube.smartgears.handlers.ProfileEvents.changed;
+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 java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+
+import org.gcube.common.events.Observes;
+import org.gcube.smartgears.configuration.Mode;
+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;
+import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
+import org.gcube.smartgears.lifecycle.container.ContainerState;
+import org.gcube.smartgears.provider.ProviderFactory;
+import org.gcube.smartgears.publishing.Publisher;
+import org.gcube.smartgears.utils.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * Manages the resource profile of the application.
+ *
+ *
+ * The manager:
+ *
+ *
+ * - creates the profile when the application starts for the first time;
+ *
- loads the profile when the application restarts;
+ *
- publishes the profile when the application becomes active, and at any
+ * lifecycle change thereafter;
+ *
- stores the profile locally after each publication;
+ *
+ *
+ * @author Fabio Simeoni
+ * @see ProfileBuilder
+ * @see ProfilePublisherImpl
+ */
+public class ContainerProfileManager extends ContainerHandler {
+
+ Logger log = LoggerFactory.getLogger(ContainerProfileManager.class);
+
+ private ContainerContext context;
+ private ScheduledFuture> periodicUpdates;
+ private static final String PUBLISHED_PROP = "published";
+ private List publishers;
+
+
+ @Override
+ public void onStart(ContainerLifecycleEvent.Start e) {
+
+ context = e.context();
+
+ activated();
+
+ // note we don't fire profile events, but wait for the final startup
+ // outcome which
+ // will result in a state change. only then we publish and store the
+ // profile
+ // this avoids the redundancy and performance penalty of storing and
+ // publishing multiple
+ // times in rapid succession (which would be correct). Revise if proves
+ // problematic in corner
+ // cases.
+
+ }
+
+
+ private void activated(){
+ publishers = context.configuration().mode()!=Mode.offline?
+ ProviderFactory.provider().publishers():
+ Collections.emptyList();
+ registerObservers();
+ schedulePeriodicUpdates();
+ }
+
+ private void registerObservers() {
+ context.events().subscribe(new Object() {
+ @Observes({ activation, part_activation, shutdown, stop, failure })
+ void onChanged(ContainerLifecycle lc) {
+
+ // since we do not know the observers, they will deal with failures and their consequences
+ // any that comes back will be logged in this event thread
+ context.events().fire(context, changed);
+ }
+
+ @Observes(value = changed, kind = critical)
+ void publishAfterChange(ContainerContext context) {
+ log.info("Publish after profile Change event called");
+ //if we've failed before first publication do not try to publish
+ //(we may well have failed there)
+ if (!context.properties().contains(PUBLISHED_PROP)) {
+ context.properties().add(new Property(PUBLISHED_PROP, true));
+ log.info("publishing container for the first time");
+ if (context.lifecycle().state() != ContainerState.failed) {
+ publishers.forEach(p -> {
+ try {
+ p.create(context,
+ context.authorizationProvider().getContexts());
+ }catch (Exception e) {
+ log.error("cannot publish container for first time with publisher type {} (see details)", p.getClass().getCanonicalName(), e);
+ }
+ });
+ }
+ }
+ else
+ publishers.forEach(p -> {
+ try {
+ p.update(context);
+ }catch (Exception e) {
+ log.error("cannot publish container with publisher type {} (see details)", p.getClass().getCanonicalName(), e);
+ }
+ });
+
+ }
+
+ @Observes(value = addToContext)
+ void addTo(String scope) {
+ log.info("add_to_context event arrived in container");
+ for (Publisher publisher: publishers)
+ try {
+ log.trace("publishing container within new scope");
+ publisher.create(context,
+ Collections.singleton(scope));
+
+ }catch (Exception e) {
+
+ log.error("cannot add container to {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e);
+
+ // since we've failed no published event is fired and profile
+ // will not be stored.
+ // we do it manually to ensure we leave some local trace of the
+ // changed profile.
+ //TODO: CHECK --- store(profile);
+ }
+
+ }
+
+ @Observes(value = removeFromContext)
+ void removeFrom(String scope) {
+ log.info("remove_from_context event arrived in container");
+ for (Publisher publisher: publishers)
+ try {
+ log.trace("unpublishing container from context {}", scope);
+ publisher.remove(context,
+ Collections.singleton(scope));
+
+ }catch (Exception e) {
+
+ log.error("cannot remove container from {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e);
+
+ // since we've failed no published event is fired and profile
+ // will not be stored.
+ // we do it manually to ensure we leave some local trace of the
+ // changed profile.
+ //TODO: CHECK --- store(profile);
+ }
+ }
+ });
+ }
+
+
+ private void schedulePeriodicUpdates() {
+ // register to cancel updates
+ context.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, part_activation }, kind = resilient)
+ synchronized void restartPeriodicUpdates(ContainerLifecycle lc) {
+ //already running
+ if (periodicUpdates!=null)
+ return;
+ if (lc.state()==active)
+ log.info("scheduling periodic updates of container profile");
+ else
+ log.info("resuming periodic updates of container profile");
+ final Runnable updateTask = new Runnable() {
+ public void run() {
+ context.events().fire(context,changed);
+ }
+ };
+ periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, 3, context.configuration()
+ .publicationFrequency(), SECONDS);
+ }
+ @Observes(value = { stop, failure, shutdown }, kind = resilient)
+ synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) {
+ if (periodicUpdates != null){
+ log.trace("stopping periodic updates of container profile");
+ try {
+ periodicUpdates.cancel(true);
+ periodicUpdates=null;
+ }
+ catch(Exception e) {
+ log.warn("could not stop periodic updates of container profile",e);
+ }
+ }
+ }
+ });
+ }
+ @Override
+ public String toString() {
+ return profile_management;
+ }
+}
+
diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java
deleted file mode 100644
index 3f1ac67..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java
+++ /dev/null
@@ -1,375 +0,0 @@
-package org.gcube.smartgears.handlers.container.lifecycle;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.gcube.common.resources.gcore.HostingNode;
-import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.GHNType;
-import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.Processor;
-import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.Variable;
-import org.gcube.common.resources.gcore.utils.Group;
-import org.gcube.smartgears.configuration.container.ContainerConfiguration;
-import org.gcube.smartgears.configuration.library.SmartGearsConfiguration;
-import org.gcube.smartgears.context.container.ContainerContext;
-import org.gcube.smartgears.provider.ProviderFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author Fabio Simeoni
- * @author Luca Frosini (ISTI - CNR)
- *
- */
-public class ProfileBuilder {
-
- private static Logger log = LoggerFactory.getLogger(ProfileBuilder.class);
-
- private ContainerContext context;
-
- public ProfileBuilder(ContainerContext context) {
- this.context = context;
- }
-
- public HostingNode create() {
-
- HostingNode node = new HostingNode();
-
- ContainerConfiguration cfg = context.configuration();
-
- node.newProfile().infrastructure(cfg.infrastructure());
-
- addSiteTo(node);
-
- String ip = "not resolved";
- try {
- ip = InetAddress.getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- log.warn("unable to detect the IP address of the host");
- }
-
- node.profile().newDescription().activationTime(Calendar.getInstance()).name(cfg.hostname() + ":" + cfg.port());
-
- node.profile().description().networkAdapters().add().mtu(0).name("local-adapter").ipAddress(ip).inboundIP("")
- .outboundIP("");
-
- node.profile().description().newOperatingSystem().name(System.getProperty("os.name"))
- .version(System.getProperty("os.version")).release("");
-
- node.profile().description().newArchitecture().platformType(System.getProperty("os.arch")).smpSize(0)
- .smtSize(0);
-
- ArrayList> info = cpuInfo();
-
- Group processors = node.profile().description().processors();
-
- for (HashMap map : info)
-
- processors.add().bogomips(new BigDecimal(map.get("bogomips")))
- .clockSpeedMhz(new BigDecimal(map.get("cpu_MHz"))).family(map.get("cpu_family"))
- .modelName(map.get("model_name")).model(map.get("model")).vendor(map.get("vendor_id"))
- .cacheL1(new Integer(map.get("cache_size"))).cacheL1D(0).cacheL1I(0).cacheL2(0);
-
- addVariablesTo(node);
-
- update(node,false);
-
- node.profile().description().type(GHNType.Static);
- // String type = (String) context.getProperty(GHNContext.GHN_TYPE, false);
- // if (type.compareToIgnoreCase(Type.DYNAMIC.toString()) == 0) description.setType(Description.Type.Dynamic);
- // else if (type.compareToIgnoreCase(Type.STATIC.toString()) == 0) description.setType(Description.Type.Static);
- // else if (type.compareToIgnoreCase(Type.SELFCLEANING.toString()) == 0)
- // description.setType(Description.Type.Selfcleaning);
- //
- // file system
- node.profile().description().localFileSystems().add().name("").type("").readOnly(false)
- .root(cfg.persistence().location());
-
- return node;
- }
-
- @SuppressWarnings("all")
- private ArrayList> cpuInfo() {
-
- ArrayList> map = new ArrayList>();
-
- File file = new File("/proc/cpuinfo");
-
- if (!file.exists()) {
- log.warn("cannot acquire CPU info (no /proc/cpuinfo)");
- return map;
- }
-
- BufferedReader input = null;
-
- try {
- input = new BufferedReader(new FileReader(file));
-
- String line = null;
-
- HashMap currentProcessor = null;
-
- while ((line = input.readLine()) != null) {
-
- if ((line.startsWith("processor"))) { // add the current processor to the map
-
- if (currentProcessor != null)
- map.add((HashMap) currentProcessor.clone());
-
- currentProcessor = new HashMap();
- }
-
- try {
- if (line.contains("vendor_id"))
- currentProcessor.put("vendor_id", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- try {
- if (line.contains("cpu family"))
- currentProcessor.put("cpu_family", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- try {
- if ((line.contains("model\t")) || (line.contains("model\b")))
- currentProcessor.put("model", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- try {
- if (line.contains("model name"))
- currentProcessor.put("model_name", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- try {
- if (line.contains("cpu MHz"))
- currentProcessor.put("cpu_MHz", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- try {
- if (line.contains("cache size"))
- currentProcessor.put("cache_size", line.split(":")[1].trim().split(" ")[0]);
- } catch (Exception ex) {
- }
- try {
- if (line.contains("bogomips"))
- currentProcessor.put("bogomips", line.split(":")[1].trim());
- } catch (Exception ex) {
- }
- }
-
- if (currentProcessor != null)
- map.add(currentProcessor);
-
- } catch (Exception e) {
-
- log.warn("unable to acquire CPU info", e);
-
- } finally {
-
- if (input != null)
- try {
- input.close();
- } catch (IOException e) {
- log.warn("unable to close stream", e);
- }
- }
- return map;
- }
-
- private long getFreeSpace() {
- long free = 0;
- try {
- free = Files.getFileStore(Paths.get(context.configuration().persistence().location())).getUsableSpace()/1024;
- } catch (IOException ioe) {
- log.warn("unable to detect the free space on the disk", ioe);
- }
- return free;
- }
-
- public void update(HostingNode node,boolean onLoad) {
-
- ContainerConfiguration cfg = context.configuration();
-
- if (onLoad) {
-
- log.info("updating ghn profile");
-
- node.profile().description().activationTime(Calendar.getInstance()).name(cfg.hostname() + ":" + cfg.port());
-
- addVariablesTo(node);
-
- addSiteTo(node);
-
- }
-
- node.profile().description().status(context.lifecycle().state().remoteForm());
-
- Map mem = memoryUsage();
-
- node.profile().description().newMainMemory().ramAvailable(mem.get("MemoryAvailable"))
- .ramSize(mem.get("MemoryTotalSize")).virtualAvailable(mem.get("VirtualAvailable"))
- .virtualSize(mem.get("VirtualSize"));
-
- node.profile().description().localAvailableSpace(getFreeSpace());
-
- node.profile().description().uptime(uptime());
-
- node.profile().description().lastUpdate(Calendar.getInstance());
-
- Map loads = loadStatistics();
-
- node.profile().description().newLoad().lastMin(loads.get("1min") == null ? 0 : loads.get("1min"))
- .last5Mins(loads.get("5mins") == null ? 0 : loads.get("5mins"))
- .last15Mins(loads.get("15mins") == null ? 0 : loads.get("15mins"));
-
- }
-
- private void addSiteTo(HostingNode node) {
-
- ContainerConfiguration cfg = context.configuration();
-
- node.profile().newSite().country(cfg.site().country()).location(cfg.site().location())
- .latitude(cfg.site().latitude()).longitude(cfg.site().longitude()).domain(domainIn(cfg.hostname()));
- }
-
- private void addVariablesTo(HostingNode node) {
-
- ContainerConfiguration cfg = context.configuration();
-
- Group variables = node.profile().description().environmentVariables();
-
- // Cleaning variables to avoid duplicates
- variables.removeAll(node.profile().description().environmentVariables());
-
- Map map = new HashMap();
- map.putAll(cfg.properties());
- map.putAll(System.getenv());
-
- 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;
- variables.add().keyAndValue(entry.getKey(), entry.getValue());
- }
-
- /* The following code is useless can be removed
- Map envvars = new HashMap();
- for (String varname : envvars.keySet()) {
-
- // a bit of filtering
- if ((varname.compareToIgnoreCase("CLASSPATH") == 0) || (varname.compareToIgnoreCase("PATH") == 0)
- || (varname.contains("SSH")) || (varname.contains("MAIL"))
- || (varname.compareToIgnoreCase("LS_COLORS") == 0))
- continue;
-
- variables.add().keyAndValue(varname, envvars.get(varname));
- }
- */
-
-
- String osVersion = System.getProperty("os.name");
- if(osVersion.compareToIgnoreCase("Linux")==0) {
- LinuxDistributionInfo linuxDistributionInfo = new LinuxDistributionInfo();
- Map info = linuxDistributionInfo.getInfo();
- for(String key : info.keySet()) {
- variables.add().keyAndValue(key, info.get(key));
- }
- }
-
- variables.add().keyAndValue("Java", System.getProperty("java.version"));
-
- SmartGearsConfiguration config = ProviderFactory.provider().smartgearsConfiguration();
- variables.add().keyAndValue("SmartGears",config.version());
-
- variables.add().keyAndValue("ghn-update-interval-in-secs", String.valueOf(cfg.publicationFrequency()));
-
- }
-
- public String uptime() {
- String lines = "", linetemp = null;
- try {
- Process p = Runtime.getRuntime().exec("uptime");
- p.waitFor();
- BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
- while ((linetemp = input.readLine()) != null)
- lines += linetemp;
- input.close();
- p.destroy();
- lines = lines.split(",")[0].split("up")[1].trim();
- } catch (Exception e) {
- log.warn("unable to detect the uptime of this machine", e);
- lines = "unable to detect";
- }
- return lines;
- }
-
- public Map loadStatistics() {
-
- Map result = new HashMap();
- try {
- File loadadv = new File("/proc/loadavg");
- if (loadadv.exists()) {
- Reader reader = new FileReader(loadadv);
- int c;
- StringBuilder content = new StringBuilder();
- while ((c = reader.read()) != -1)
- content.append((char) c);
- reader.close();
- Pattern p = Pattern.compile("^(.*?)\\s{1}(.*?)\\s{1}(.*?)\\s{1}(.*)$");
- Matcher matcher = p.matcher(content.toString());
- if ((matcher.matches()) && (matcher.groupCount() > 3)) {
- result.put("1min", new Double(matcher.group(1)));
- result.put("5mins", new Double(matcher.group(2)));
- result.put("15mins", new Double(matcher.group(3).split("\\s")[0]));
- }
- }
- } catch (Exception ioe) {
- log.warn("unable to detect the load values of this machine", ioe);
- }
- return result;
- }
-
- @SuppressWarnings("all")
- public Map memoryUsage() {
- Map map = new HashMap();
- java.lang.management.OperatingSystemMXBean mxbean = java.lang.management.ManagementFactory
- .getOperatingSystemMXBean();
- com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean;
- long freeMemory = sunmxbean.getFreePhysicalMemorySize() / 1048576; // in MB
- long availableMemory = sunmxbean.getTotalPhysicalMemorySize() / 1048576; // in MB
- map.put("MemoryAvailable", freeMemory);
- map.put("MemoryTotalSize", availableMemory);
- long ramVirtualAvailable = Runtime.getRuntime().freeMemory() / 1048576; // in MB
- long ramVirtualSize = Runtime.getRuntime().totalMemory() / 1048576; // in MB
- map.put("VirtualAvailable", ramVirtualAvailable);
- map.put("VirtualSize", ramVirtualSize);
- return map;
- }
-
- private String domainIn(String hostname) {
- Pattern pattern = Pattern.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})");
- java.util.regex.Matcher regexMatcher = pattern.matcher(hostname);
- if (regexMatcher.matches()) //it's an IP address, nothing to trim
- return hostname;
- String[] tokens = hostname.split("\\.");
- if (tokens.length < 2)
- return hostname;
- else
- return tokens[tokens.length-2]+ "." + tokens[tokens.length-1];
- }
-}
diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java
deleted file mode 100644
index ad9a450..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.gcube.smartgears.handlers.container.lifecycle;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.gcube.common.events.Observes.Kind.critical;
-import static org.gcube.common.events.Observes.Kind.resilient;
-import static org.gcube.smartgears.Constants.container_profile_property;
-import static org.gcube.smartgears.Constants.profile_management;
-import static org.gcube.smartgears.handlers.ProfileEvents.addToContext;
-import static org.gcube.smartgears.handlers.ProfileEvents.changed;
-import static org.gcube.smartgears.handlers.ProfileEvents.published;
-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 java.util.Collections;
-import java.util.concurrent.ScheduledFuture;
-
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.events.Observes;
-import org.gcube.common.resources.gcore.HostingNode;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.context.Property;
-import org.gcube.smartgears.context.container.ContainerContext;
-import org.gcube.smartgears.handlers.OfflineProfilePublisher;
-import org.gcube.smartgears.handlers.ProfilePublisher;
-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.utils.Utils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- * Manages the resource profile of the container.
- *
- *
- * The manager:
- *
- *
- * - creates the profile when the container starts for the first time;
- *
- loads the profile when the container restarts;
- *
- publishes the profile when the container becomes active, and at any lifecycle change thereafter;
- *
- stores the profile locally after each publication;
- *
- *
- * @author Fabio Simeoni
- * @see ProfileBuilder
- */
-@XmlRootElement(name = profile_management)
-public class ProfileManager extends ContainerHandler {
-
- private static Logger log = LoggerFactory.getLogger(ProfileManager.class);
-
- private ContainerContext context;
-
- private ProfileBuilder builder;
- private ProfilePublisher publisher;
-
-
- private ScheduledFuture> periodicUpdates;
-
- @Override
- public void onStart(Start e) {
-
- context = e.context();
- builder = new ProfileBuilder(context);
-
- activated();
-
- // note we don't fire profile events, but wait for the final startup response which
- // will result in a state change. only then we publish and store the profile
- // this avoids the redundancy and performance penalty of storing and publishing multiple
- // times in rapid succession (which would be correct). Revise if proves problematic in corner
- // cases.
-
- }
-
- private void activated(){
- HostingNode profile = loadOrCreateProfile();
-
- share(profile);
-
- publisher = context.configuration().mode()!=Mode.offline?
- new ProfilePublisherImpl(context):
- new OfflineProfilePublisher();
-
- registerObservers();
-
- schedulePeriodicUpdates();
- }
-
- private void registerObservers() {
-
- context.events().subscribe(new Object() {
-
- @Observes({ activation, part_activation, shutdown, stop, failure })
- void onChanged(ContainerLifecycle lc) {
-
- HostingNode profile = context.profile(HostingNode.class);
-
- profile.profile().description().status(lc.state().remoteForm());
-
- // since we do not know the observers, they will deal with failures and their consequences
- // any that comes back will be logged in this event thread
- context.events().fire(profile, changed);
-
- }
-
-
- @Observes(value = published)
- void shareAfterPublish(HostingNode profile) {
-
- share(profile); // publish may produce a new profile instance
-
- }
-
- @Observes(value = changed, kind = critical)
- void publishAfterChange(HostingNode profile) {
- log.info("Publish after profile Change event called");
- publish(profile); // if successful, triggers share and store.
-
- }
-
- @Observes(value = addToContext)
- void addTo(String token) {
- try {
- log.trace("publishing container with new token");
- publisher.addTo(Collections.singleton(token));
- publisher.update();
- }catch (Exception e) {
-
- log.error("cannot add token {} (see details)",token, e);
-
- // since we've failed no published event is fired and profile
- // will not be stored.
- // we do it manually to ensure we leave some local trace of the
- // changed profile.
- //TODO: CHECK --- store(profile);
- }
-
- }
-
- @Observes(value = removeFromContext)
- void removeFrom(String token) {
- try {
- log.trace("unpublishing container with new token");
- publisher.removeFrom(Collections.singleton(token));
- publisher.update();
- }catch (Exception e) {
-
- log.error("cannot remove token {} (see details)",token, e);
-
- // since we've failed no published event is fired and profile
- // will not be stored.
- // we do it manually to ensure we leave some local trace of the
- // changed profile.
- //TODO: CHECK --- store(profile);
- }
-
- }
- });
- }
-
- private HostingNode loadOrCreateProfile() {
-
- return createProfile();
-
- }
-
- private void share(HostingNode profile) {
-
- log.trace("sharing container profile");
- context.properties().add(new Property(container_profile_property, profile));
- }
-
- private HostingNode createProfile() {
-
- log.info("creating container profile");
-
- try {
- HostingNode node = builder.create();
- node.setId(context.id());
- return node;
- } catch (Throwable e) {
-
- // this is a critical startup failure: it will fail the application
- throw new RuntimeException("cannot create container profile", e);
-
- }
-
- }
-
- private void publish(HostingNode profile) {
-
- //ContainerConfiguration configuration = context.configuration();
-
- // first-publication vs. routine publication: when we delete scopes let's make sure there is
- // at least one left of it will be re-triggered
- boolean firstPublication = profile.scopes().isEmpty();
-
- try {
-
- if (firstPublication)
- publisher.addToAll();
- else
- publisher.update();
-
- } catch (Exception e) {
-
- log.error("cannot publish container (see details)", e);
-
- // since we've failed no published event is fired and profile will not be stored.
- // we do it manually to ensure we leave some local trace of the changed profile.
- //store(profile);
-
- }
- }
-
- private void schedulePeriodicUpdates() {
-
- // register to cancel updates
- context.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, part_activation }, kind = resilient)
- synchronized void restartPeriodicUpdates(ContainerLifecycle lc) {
-
- //already running
- if (periodicUpdates!=null)
- return;
-
- if (lc.state()==active)
- log.info("scheduling periodic updates of container profile");
-
- else
- log.info("resuming periodic updates of container profile");
-
- final Runnable updateTask = new Runnable() {
- public void run() {
- HostingNode profile = context.profile(HostingNode.class);
-
- try {
- builder.update(profile, false);
- }
- catch(Exception e) {
- //we may fail in the update of the profile
- log.error("cannot complete periodic update of container profile",e);
- }
-
- //if handling of event generates failures these will be reported
- //for resilience we do not fail the application
- log.trace("firing change event on container profile");
- context.events().fire(profile,changed);
- }
- };
-
- periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, 3, context.configuration()
- .publicationFrequency(), SECONDS);
-
- }
-
- @Observes(value = { stop, failure, shutdown }, kind = resilient)
- synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) {
-
- if (periodicUpdates != null){
- log.trace("stopping periodic updates of container profile");
-
- try {
- periodicUpdates.cancel(true);
- periodicUpdates=null;
- }
- catch(Exception e) {
- log.warn("could not stop periodic updates of container profile",e);
- }
- }
- }
-
- });
-
- }
-
- @Override
- public String toString() {
- return profile_management;
- }
-}
diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java
deleted file mode 100644
index f40a4a5..0000000
--- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package org.gcube.smartgears.handlers.container.lifecycle;
-
-import static org.gcube.smartgears.utils.Utils.notEmpty;
-import static org.gcube.smartgears.utils.Utils.rethrowUnchecked;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
-import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.resources.gcore.HostingNode;
-import org.gcube.informationsystem.publisher.ScopedPublisher;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.context.container.ContainerContext;
-import org.gcube.smartgears.handlers.ProfileEvents;
-import org.gcube.smartgears.handlers.ProfilePublisher;
-import org.gcube.smartgears.provider.ProviderFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Publishes the resource profile of the container.
- *
- * Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update(List)}.
- *
- * @author Fabio Simeoni
- *
- */
-public class ProfilePublisherImpl implements ProfilePublisher {
-
- private static final Logger log = LoggerFactory.getLogger(ProfilePublisherImpl.class);
-
- //the underlying IS publisher
- private final ScopedPublisher publisher;
- //private final AuthorizationProvider authorization;
- private final ContainerContext context;
-
- private AuthorizationProxy authProxy ;
-
- /**
- * Creates an instance for the container.
- * @param context the context of the application
- */
- public ProfilePublisherImpl(ContainerContext context) {
- this.context = context;
- this.publisher=ProviderFactory.provider().publisherFor(context);
- this.authProxy = ProviderFactory.provider().authorizationProxy();
- }
-
- /**
- * Adds the current resource profile of the application in one or more
- * scopes. The scopes are retrieved from tokens
- * @param tokens the tokens
- */
- public void addTo(Collection tokens) {
-
- notEmpty("tokens",tokens);
-
- log.info("publishing container with tokens {}", tokens);
-
- HostingNode profile = context.profile(HostingNode.class);
-
- /* TODO: reintroduce it when scope will be removed
- //TODO: remove when move to new IS
- Collection retainedContexts = new ArrayList(context.configuration().allowedContexts());
- retainedContexts.removeAll(profile.scopes().asCollection());
- profile.scopes().asCollection().addAll(retainedContexts);
-
- log.trace("profile scopes on create are {} ",profile.scopes().asCollection());
-
- String previousToken = SecurityTokenProvider.instance.get();
-
- try {
- for (String token: tokens){
- log.info("creating profile with token {}", token);
- SecurityTokenProvider.instance.set(token);
- profile = publisher.create(profile);
- SecurityTokenProvider.instance.reset();
- }
-
- update();
-
- } catch (Exception e) {
- log.warn("error adding scopes",e);
- rethrowUnchecked(e);
-
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- }*/
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
- log.debug("using context {}",contextCL.getClass().getSimpleName());
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.create(profile, resolveScopesFromTokens(tokens));
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally {
- SecurityTokenProvider.instance.set(previousToken);
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(contextCL);
- }
-
- sharePublished(profile);
-
- }
-
- /**
- * Adds the current resource profile of the application in one or more scopes.
- */
- public void addToAll() {
- addTo(context.configuration().startTokens());
- }
-
- /**
- * Updates the current resource profile of the application in its current scopes.
- */
- public void update() {
-
- HostingNode profile = context.profile(HostingNode.class);
- /* TODO: reintroduce it when scope will be removed
- Collection tokens = context.configuration().startTokens();
-
- log.info("updating container with tokens {}", tokens);
-
- String previousToken = SecurityTokenProvider.instance.get();
-
- try {
- for (String token: tokens){
- SecurityTokenProvider.instance.set(token);
- profile = publisher.update(profile);
- SecurityTokenProvider.instance.reset();
- }
- sharePublished(profile);
-
- }
- catch (Exception e) {
- log.warn("error updating container",e);
- rethrowUnchecked(e);
-
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- }*/
-
-
- log.debug("[update] resource scopes are : {} ",profile.scopes().asCollection());
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
- log.debug("using context {}",contextCL.getClass().getSimpleName());
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]);
-
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.update(profile);
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally {
- SecurityTokenProvider.instance.set(previousToken);
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(contextCL);
- }
-
- sharePublished(profile);
- }
-
- /**
- * Removes the container from one or more scopes.
- * @param tokens the tokens
- */
- public void removeFrom(Collection tokens) {
-
- HostingNode profile = context.profile(HostingNode.class);
-
- log.info("removing container with tokens {}", tokens);
-
- /* TODO: reintroduce it when scope will be removed
- String previousToken = SecurityTokenProvider.instance.get();
-
- try {
-
- for (String token: tokens){
- SecurityTokenProvider.instance.set(token);
- profile = publisher.remove(profile);
- SecurityTokenProvider.instance.reset();
- }
-
- update();
-
- }
- catch (Exception e) {
- log.warn("error removing scopes",e);
- rethrowUnchecked(e);
-
- } finally{
- SecurityTokenProvider.instance.set(previousToken);
- } */
-
- ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
- log.debug("using context {}",contextCL.getClass().getSimpleName());
- String previousToken = SecurityTokenProvider.instance.get();
- try{//This classloader set is needed for the jaxb context
- if (previousToken==null)
- SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader());
- profile = publisher.remove(profile, resolveScopesFromTokens(tokens));
- } catch (Exception e) {
- rethrowUnchecked(e);
- } finally {
- SecurityTokenProvider.instance.set(previousToken);
- if (context.configuration().mode()!=Mode.root)
- Thread.currentThread().setContextClassLoader(contextCL);
- }
-
- log.debug("after remove container profile contains scopes {}",profile.scopes().asCollection());
- sharePublished(profile);
- }
-
- private void sharePublished(HostingNode profile) {
- context.events().fire(profile,ProfileEvents.published);
- }
-
- private List resolveScopesFromTokens(Collection tokens){
- List scopes = new ArrayList(tokens.size());
- for (String token: tokens)
- try{
- scopes.add(this.authProxy.get(token).getContext());
- }catch (Exception e) {
- log.warn("error retrieving token {} , it should never happen",token);
- }
- return scopes;
- }
-}
diff --git a/src/main/java/org/gcube/smartgears/health/HealthManager.java b/src/main/java/org/gcube/smartgears/health/HealthManager.java
new file mode 100644
index 0000000..2fe5e40
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/health/HealthManager.java
@@ -0,0 +1,19 @@
+package org.gcube.smartgears.health;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.gcube.common.health.api.HealthCheck;
+
+public class HealthManager {
+
+ private List checks = new LinkedList<>();
+
+ public void register(HealthCheck check){
+ checks.add(check);
+ }
+
+ public List getChecks() {
+ return checks;
+ }
+}
diff --git a/src/main/java/org/gcube/smartgears/health/HealthResponse.java b/src/main/java/org/gcube/smartgears/health/HealthResponse.java
new file mode 100644
index 0000000..c1f9dbd
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/health/HealthResponse.java
@@ -0,0 +1,35 @@
+package org.gcube.smartgears.health;
+
+import java.util.List;
+
+import org.gcube.com.fasterxml.jackson.annotation.JsonInclude;
+import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include;
+import org.gcube.common.health.api.Status;
+import org.gcube.common.health.api.response.HealthCheckResponse;
+import org.gcube.common.validator.annotations.NotNull;
+
+@JsonInclude(Include.NON_NULL)
+public class HealthResponse {
+
+ @NotNull
+ private Status status;
+
+ private List checks;
+
+
+
+ public HealthResponse(Status status, List checks) {
+ super();
+ this.status = status;
+ this.checks = checks;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public List getChecks() {
+ return checks;
+ }
+
+}
diff --git a/src/main/java/org/gcube/smartgears/health/HealthTask.java b/src/main/java/org/gcube/smartgears/health/HealthTask.java
new file mode 100644
index 0000000..ef755d6
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/health/HealthTask.java
@@ -0,0 +1,49 @@
+package org.gcube.smartgears.health;
+
+import java.util.List;
+import java.util.TimerTask;
+import java.util.stream.Collectors;
+
+import org.gcube.common.health.api.HealthCheck;
+import org.gcube.common.health.api.Status;
+import org.gcube.common.health.api.response.HealthCheckResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HealthTask extends TimerTask{
+
+ private static final Logger log = LoggerFactory.getLogger(HealthTask.class);
+
+ private HealthResponse response;
+
+ private HealthManager healthManager;
+
+ public HealthTask(HealthManager healthManager) {
+ this.healthManager = healthManager;
+ }
+
+ @Override
+ public void run() {
+
+ List checks = healthManager.getChecks();
+
+ List responses = checks.stream().map(c -> this.wrap(c)).collect(Collectors.toList());
+ Status totalStatus = responses.stream().anyMatch(r -> r.getStatus().equals(Status.DOWN)) ? Status.DOWN : Status.UP;
+
+ this.response = new HealthResponse(totalStatus, responses);
+ log.debug("health task executed with total status {}",totalStatus);
+ }
+
+ public HealthResponse getResponse() {
+ return response;
+ }
+
+ private HealthCheckResponse wrap(HealthCheck check){
+ try {
+ return check.check();
+ }catch (Throwable t) {
+ return HealthCheckResponse.builder(check.getName()).down().withMessage(t.getMessage()).build();
+ }
+
+ }
+}
diff --git a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java
new file mode 100644
index 0000000..fd087bf
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java
@@ -0,0 +1,31 @@
+package org.gcube.smartgears.health;
+
+import java.util.Set;
+
+import org.gcube.common.health.api.HealthCheck;
+import org.gcube.common.health.api.ReadinessChecker;
+import org.gcube.common.health.api.response.HealthCheckResponse;
+import org.gcube.smartgears.provider.ProviderFactory;
+
+@ReadinessChecker
+public class KeyCloakHealthCheck implements HealthCheck{
+
+ private static final String CHECK_NAME = "authorization-check" ;
+
+ public String getName(){
+ return CHECK_NAME;
+ }
+
+ @Override
+ public HealthCheckResponse check() {
+ try {
+ Set contexts = ProviderFactory.provider().containerContext().authorizationProvider().getContexts();
+ if (contexts.isEmpty())
+ return HealthCheckResponse.builder(CHECK_NAME).down().withMessage("no contexts are defined for the client id provided").build();
+ return HealthCheckResponse.builder(CHECK_NAME).up().build();
+ }catch (Exception e) {
+ return HealthCheckResponse.builder(CHECK_NAME).down().withMessage(e.getMessage()).build();
+ }
+ }
+
+}
diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java
index 7f3e735..3232aa5 100644
--- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java
+++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java
@@ -15,7 +15,6 @@ import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
-import java.util.stream.Collectors;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
@@ -23,25 +22,18 @@ import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
-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.smartgears.Constants;
-import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.configuration.application.ApplicationExtensions;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.extensions.ApplicationExtension;
import org.gcube.smartgears.extensions.RequestExceptionBarrier;
-import org.gcube.smartgears.handlers.ProfileEvents;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.ApplicationPipeline;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
-import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,6 +51,8 @@ public class ApplicationManager {
private ApplicationContext context;
+ private List extensions;
+
/**
* Starts application management.
*
@@ -74,19 +68,9 @@ public class ApplicationManager {
for (Entry servlet : application.getServletRegistrations().entrySet())
log.trace("servlet {} : {} {} ", application.getServletContextName(),servlet.getKey(), servlet.getValue().getMappings());
-
+ context.configuration().validate();
- /* if (context.configuration().secure() &&
- container.configuration().securePort()==null)
- throw new IllegalStateException(
- String.format("Application %s cannot be managed because is declared as secure without a secure connector port declared in the container", context.application().getContextPath()));
- */
-
- if (context.container().configuration().mode()!=Mode.offline) {
- context.configuration().startTokens(generateTokensForApplication(container).stream().collect(Collectors.toSet()));
- context.configuration().validate();
- }
saveApplicationState();
// make context available to application in case it is gcube-aware
@@ -96,13 +80,12 @@ public class ApplicationManager {
registerObservers();
ApplicationHandlers handlers = provider().handlersFor(context);
- handlers.validate();
-
-
- ApplicationExtensions extensions = provider().extensionsFor(context);
+ /*
+ extensions = provider().extensionsFor(context);
extensions.validate();
-
+ */
+
List lifecycleHandlers = handlers.lifecycleHandlers();
List requestHandlers = handlers.requestHandlers();
@@ -111,11 +94,12 @@ public class ApplicationManager {
log.trace("managing {} requests with {}", context.name(), requestHandlers);
log.trace("extending {} API with {}", context.name(), extensions);
+ extensions = provider().extensionsFor(context);
// order is important here: first add APIs
- register(extensions);
+ registerExtension(extensions);
// then intercept them all
- register(requestHandlers);
+ registerHandlers(requestHandlers);
// start lifecycle management
start(lifecycleHandlers);
@@ -143,43 +127,8 @@ public class ApplicationManager {
}
- private List generateTokensForApplication(ContainerContext container){
- log.info("generating token for app {}",context.configuration().name());
-
- SecurityTokenProvider.instance.set(container.configuration().startTokens().get(0));
- try {
- AuthorizationProxy authProxy = provider().authorizationProxy();
- try {
- return authProxy.generateServiceToken(Utils.getServiceInfo(context), container.configuration().startTokens());
- }catch (Exception e) {
- log.error("error generating service token",e);
- throw new RuntimeException(e);
- }
- } catch (Exception e) {
- throw new RuntimeException("error contacting authorization service",e);
- } finally{
- SecurityTokenProvider.instance.reset();
- }
-
-
- }
-
- private String generateApplicationToken(String containerToken, AuthorizationProxy authProxy){
- SecurityTokenProvider.instance.set(containerToken);
- try {
- log.info("generating token for app {} with container token {} ",context.configuration().name(), containerToken);
- return authProxy.generateServiceToken(Utils.getServiceInfo(context));
- } catch (Exception e) {
- throw new RuntimeException("error contacting authorization service",e);
- } finally{
- SecurityTokenProvider.instance.reset();
- }
-
- }
-
-
private void saveApplicationState() {
- File file = context.configuration().persistence().file(profile_file_path);
+ File file = context.persistence().file(profile_file_path);
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){
oos.writeObject(context.id());
}catch (Exception e) {
@@ -205,7 +154,10 @@ public class ApplicationManager {
context.lifecycle().tryMoveTo(stopped);
context.events().fire(context, ApplicationLifecycle.stop);
-
+
+ if (extensions != null)
+ unregister(extensions);
+
stopLifecycleHandlers();
log.info("stopping application events for {}", context.name());
@@ -219,7 +171,7 @@ public class ApplicationManager {
}
- private void register(List rqHandlers) {
+ private void registerHandlers(List rqHandlers) {
ServletContext app = context.application();
@@ -246,11 +198,11 @@ public class ApplicationManager {
}
}
- private void register(ApplicationExtensions extensions) {
+ private void registerExtension(List extensions) {
ServletContext application = context.application();
- for (ApplicationExtension extension : extensions.extensions())
+ for (ApplicationExtension extension : extensions)
try {
@@ -282,6 +234,14 @@ public class ApplicationManager {
}
}
+
+ private void unregister(List extensions) {
+
+ for (ApplicationExtension extension : extensions)
+ extension.stop();
+
+ }
+
private void start(List handlers) {
@@ -320,28 +280,6 @@ public class ApplicationManager {
log.warn("cannot stop {} after container has stopped", context.name());
}
- @Observes(value = ContextEvents.ADD_TOKEN_TO_APPLICATION, kind = critical)
- void onAddToken(String containerToken) {
- log.trace("event add received with token {} ",containerToken);
- String appToken = generateApplicationToken(containerToken, provider().authorizationProxy());
- context.configuration().startTokens().add(appToken);
- log.trace("app token created : {} ", appToken);
- context.events().fire(appToken, ProfileEvents.addToContext);
- context.events().fire(appToken, Constants.token_registered);
- saveApplicationState();
- }
-
- @Observes(value = ContextEvents.REMOVE_TOKEN_FROM_APPLICATION, kind = critical)
- void onRemoveToken(String containerToken) {
- log.trace("event remove received with token {} ",containerToken);
- String appToken = generateApplicationToken(containerToken, provider().authorizationProxy());
- context.configuration().startTokens().remove(appToken);
- log.trace("app token removed : {} ", appToken);
- context.events().fire(appToken, ProfileEvents.removeFromContext);
- context.events().fire(appToken, Constants.token_removed);
- saveApplicationState();
- }
-
};
context.container().events().subscribe(observer);
@@ -352,7 +290,8 @@ public class ApplicationManager {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("initilizing context {} ",context.name());
- context.events().fire(context.application().getContextPath(), ApplicationLifecycle.activation);
+
+ context.events().fire(context, ApplicationLifecycle.activation);
log.info("webApp {} initialized ",context.name());
}
diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java
index 3d7a9d2..8bf1e50 100644
--- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java
+++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java
@@ -10,19 +10,12 @@ import static org.gcube.smartgears.provider.ProviderFactory.provider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
-import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
-import org.gcube.common.authorization.library.AuthorizationEntry;
-import org.gcube.common.authorization.library.provider.ClientInfo;
-import org.gcube.common.authorization.library.provider.ContainerInfo;
import org.gcube.common.events.Observes;
import org.gcube.common.events.Observes.Kind;
import org.gcube.smartgears.configuration.Mode;
-import org.gcube.smartgears.configuration.container.ContainerHandlers;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.handlers.ProfileEvents;
@@ -47,8 +40,6 @@ public class ContainerManager {
public static ContainerManager instance = new ContainerManager();
- private AuthorizationProxy authProvider = provider().authorizationProxy();
-
private ContainerContext context;
private ContainerPipeline pipeline;
@@ -70,18 +61,15 @@ public class ContainerManager {
saveContainerState();
- ContainerHandlers handlers = provider().containerHandlers();
+ List handlers = provider().containerHandlers();
- log.trace("managing container lifecycle with {}", handlers.get());
+ log.trace("managing container lifecycle with {}", handlers);
- startHandlers(handlers.get());
+
+ startHandlers(handlers);
context.lifecycle().moveTo(active);
-
- log.trace("loading keys for starting token ...");
- //loadKeyForToken(context.configuration().startTokens());
- log.trace("keys loaded for starting token ...");
-
+
return context;
}
catch(RuntimeException e) {
@@ -98,10 +86,9 @@ public class ContainerManager {
private void saveContainerState() {
- File file = context.configuration().persistence().file(container_profile_file_path);
+ File file = context.persistenceWriter().file(container_profile_file_path);
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){
oos.writeObject(context.id());
- oos.writeObject(context.configuration().startTokens());
}catch (Exception e) {
log.error("error serializing cointainer state");
throw new RuntimeException(e);
@@ -112,59 +99,24 @@ public class ContainerManager {
private void validateContainer(ContainerContext context) {
//List tokensToRemove = new ArrayList();
context.configuration().validate();
- Set foundContexts= new HashSet();
-
+ Set foundContexts;
+
try {
- List entries = authProvider.get(context.configuration().startTokens());
-
- log.info("requesting auth on {} tokens returned {} entries", context.configuration().startTokens().size(),entries.size());
-
- for (AuthorizationEntry entry : entries ) {
- log.info("the container will be started in context {}",entry.getContext());
- foundContexts.add(entry.getContext());
- }
-
+ foundContexts = context.authorizationProvider().getContexts();
} catch (Exception e) {
- log.error("error contacting auth service on container",e);
+ log.error("error authorizing container",e);
+ throw new RuntimeException("error authorizing container, moving the container to failed",e);
}
if (foundContexts.isEmpty()){
- log.error("no valid starting token are specified, moving the container to failed");
- throw new RuntimeException("no valid starting token are specified");
+ log.error("no valid contexts found, moving the container to failed");
+ throw new RuntimeException("no valid contexts found, moving the container to failed");
}
- //context.configuration().startTokens().removeAll(tokensToRemove);
- context.configuration().allowedContexts(foundContexts);
- }
-
- private String resolveTokenForAdd(Set alreadyAddedContext, String token){
- try {
- AuthorizationEntry entry = authProvider.get(token);
- ClientInfo info = entry.getClientInfo();
- log.info("resolved authorization entry for container {}",entry);
- if (alreadyAddedContext.contains(entry.getContext())){
- log.warn("the token {} cannot be used, another token with the same context {} found ", entry.getContext());
- } else if(!entry.getContext().startsWith("/"+context.configuration().infrastructure())){
- log.warn("the token {} cannot be used, is not in the infrastructure {} of the container ", token,context.configuration().infrastructure());
- }else if (!(info instanceof ContainerInfo)){
- log.warn("the token {} cannot be used, is not for a container token ", token);
- } else if (!((ContainerInfo)info).getHost().equals(context.configuration().hostname())
- || context.configuration().port()!=((ContainerInfo)info).getPort()){
- log.warn("the token {} cannot be used, the client id {} resolved with the token is not the same of the one specified in this container ", token, info.getId());
- } else
- return entry.getContext();
- }catch(ObjectNotFound onf){
- log.error("token {} not valid", token);
- } catch (Exception e) {
- log.error("error contacting authorization for token {}",token,e);
- }
- return null;
}
public void manage(ApplicationContext app) {
-
app.events().subscribe(this);
-
}
@Observes(value={ApplicationLifecycle.failure,ApplicationLifecycle.stop},kind=Kind.critical)
@@ -172,40 +124,16 @@ public class ContainerManager {
context.lifecycle().tryMoveTo(ContainerState.partActive);
}
- @Observes(value=ContextEvents.ADD_TOKEN_TO_CONTAINER,kind=Kind.critical)
- void addToken(String token) {
- log.trace("adding token {} to container", token);
- String newContext;
- if ((newContext = resolveTokenForAdd(context.configuration().allowedContexts(), token))!=null) {
- context.configuration().startTokens().add(token);
- context.configuration().allowedContexts().add(newContext);
- saveContainerState();
- //loadKeyForToken(Arrays.asList(token));
- context.events().fire(token, ContextEvents.ADD_TOKEN_TO_APPLICATION);
- context.events().fire(token, ProfileEvents.addToContext);
- log.trace("token added and event fired");
- } else log.warn("trying to add an invalid token");
+ @Observes(value=ContextEvents.ADD_CONTEXT_TO_CONTAINER,kind=Kind.critical)
+ void addContext(String scope) {
+ log.info("adding context {} event send", context);
+ context.events().fire(scope, ProfileEvents.addToContext);
}
- @Observes(value=ContextEvents.REMOVE_TOKEN_FROM_CONTAINER,kind=Kind.critical)
- void removeToken(String token) {
- log.trace("removing token {} from container", token);
- AuthorizationEntry entry;
- try {
- entry = authProvider.get(token);
- } catch (Exception e) {
- log.error("error resolving token to remove");
- return;
- }
-
- if (context.configuration().startTokens().contains(token)) {
- context.configuration().startTokens().remove(token);
- context.configuration().allowedContexts().remove(entry.getContext());
- saveContainerState();
- context.events().fire(token, ContextEvents.REMOVE_TOKEN_FROM_APPLICATION);
- context.events().fire(token, ProfileEvents.removeFromContext);
- log.trace("token removed and event fired");
- } else log.warn("cannot remove token, it is not present in the container");
+ @Observes(value=ContextEvents.REMOVE_CONTEXT_FROM_CONTAINER,kind=Kind.critical)
+ void removeContext(String scope) {
+ log.info("removing context {} event send", context);
+ context.events().fire(scope, ProfileEvents.removeFromContext);
}
/**
diff --git a/src/main/java/org/gcube/smartgears/managers/ContextEvents.java b/src/main/java/org/gcube/smartgears/managers/ContextEvents.java
index 8b771c2..224093b 100644
--- a/src/main/java/org/gcube/smartgears/managers/ContextEvents.java
+++ b/src/main/java/org/gcube/smartgears/managers/ContextEvents.java
@@ -2,12 +2,9 @@ package org.gcube.smartgears.managers;
public class ContextEvents {
- public static final String ADD_TOKEN_TO_CONTAINER ="AddTokenToContainer";
+ public static final String ADD_CONTEXT_TO_CONTAINER ="AddContextToContainer";
- public static final String ADD_TOKEN_TO_APPLICATION ="AddTokenToApplication";
+ public static final String REMOVE_CONTEXT_FROM_CONTAINER ="RemoveContextFromContainer";
- public static final String REMOVE_TOKEN_FROM_CONTAINER ="RemoveTokenFromContainer";
-
- public static final String REMOVE_TOKEN_FROM_APPLICATION ="RemoveTokenFromApplication";
}
diff --git a/src/main/java/org/gcube/smartgears/managers/RequestManager.java b/src/main/java/org/gcube/smartgears/managers/RequestManager.java
index 11cf66c..cf28d8b 100644
--- a/src/main/java/org/gcube/smartgears/managers/RequestManager.java
+++ b/src/main/java/org/gcube/smartgears/managers/RequestManager.java
@@ -8,6 +8,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -19,8 +20,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.gcube.common.authorization.library.exception.AuthorizationException;
-import org.gcube.smartgears.configuration.application.Exclude;
-import org.gcube.smartgears.configuration.application.Include;
+import org.gcube.smartgears.configuration.application.GCubeExclude;
+import org.gcube.smartgears.configuration.application.GCubeInclude;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.application.DefaultApplicationContext;
import org.gcube.smartgears.handlers.application.ApplicationPipeline;
@@ -136,27 +137,27 @@ public class RequestManager implements Filter {
log.debug("check wich handler should be excluded {}", path);
if (!context.configuration().excludes().isEmpty()) {
- for (Exclude exclude : context.configuration().excludes()){
+ for (GCubeExclude exclude : context.configuration().excludes()){
String excludePath= exclude.getPath();
log.trace("exclude is {}",exclude);
- if (
- (WILDCARD).equals(excludePath) ||
+ if ((WILDCARD).equals(excludePath) ||
(excludePath.endsWith(WILDCARD) && path!=null && path.startsWith(excludePath.substring(0,excludePath.length()-2))) ||
excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1)))
){
- //ALL handler are filtered
- if (exclude.getHandlers().isEmpty()) return Collections.emptyList();
+ //ALL handler are filtered except for unfiltrable
+ if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream()
+ .filter(RequestHandler::isUnfiltrable).collect(Collectors.toList());
List filteredHandlers = new ArrayList<>();
- for (RequestHandler rh : handlersToFilter){
- if (!exclude.getHandlers().contains(rh.getName()))
+ for (RequestHandler rh : handlersToFilter)
+ if (rh.isUnfiltrable() || !exclude.getHandlers().contains(rh.getName()))
filteredHandlers.add(rh);
- }
+
return filteredHandlers;
}
}
} else if (!context.configuration().includes().isEmpty()) {
- for (Include include : context.configuration().includes()){
+ for (GCubeInclude include : context.configuration().includes()){
String includePath= include.getPath();
log.trace("include is {}",include);
if (
@@ -168,10 +169,10 @@ public class RequestManager implements Filter {
if (include.getHandlers().isEmpty()) return handlersToFilter;
List filteredHandlers = new ArrayList<>();
- for (RequestHandler rh : handlersToFilter){
- if (include.getHandlers().contains(rh.getName()))
+ for (RequestHandler rh : handlersToFilter)
+ if (rh.isUnfiltrable() || include.getHandlers().contains(rh.getName()))
filteredHandlers.add(rh);
- }
+
return filteredHandlers;
}
}
@@ -213,37 +214,6 @@ public class RequestManager implements Filter {
}
- // helpers
- /*
- private boolean shouldExcludeRequest(HttpServletRequest request) {
-
- String query = request.getQueryString();
-
- log.debug("servletPath is {} and pathInfo is {}",request.getServletPath(), request.getPathInfo());
-
- if ("wsdl".equals(query) || "wsdl=1".equals(query))
- return true;
-
- String path = request.getServletPath()==null?"":request.getServletPath();
-
- path += request.getPathInfo() ==null?"":request.getPathInfo();
-
-
- log.debug("check if should exclude call with path {}", path);
-
- for (Exclude exclude : context.configuration().excludes()){
- if (!exclude.getHandlers().isEmpty()) continue;
- String excludePath= exclude.getPath();
- log.trace("exclude is {}",exclude);
- if (
- (EXCLUDE_ALL).equals(exclude) ||
- (excludePath.endsWith(EXCLUDE_ALL) && path!=null && path.startsWith(excludePath.substring(0,excludePath.length()-2))) ||
- excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1)))
- )
- return true;
- }
- return false;
- }*/
private void handleError(HttpServletRequest request, HttpServletResponse response,Throwable t) throws IOException {
diff --git a/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java b/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java
deleted file mode 100644
index 21dbbc3..0000000
--- a/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.gcube.smartgears.persistence;
-
-
-import static org.gcube.smartgears.utils.Utils.*;
-
-import java.io.File;
-
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-
-import org.gcube.common.validator.annotations.NotNull;
-
-@XmlRootElement(name="persistence")
-public class DefaultPersistence implements Persistence {
-
- @XmlAttribute(name="location") @NotNull
- private String location;
-
- public DefaultPersistence() {}
-
- public DefaultPersistence(String location) {
-
- notNull("persistence location",location);
-
- this.location=location;
- validate();
- }
-
- @Override
- public String location() {
- return location;
- }
-
- @Override
- public File writefile(String path) {
-
- notNull("relative path", path);
-
- return fileAt(new File(location, path).getAbsolutePath()).toWrite();
- }
-
- @Override
- public File file(String path) {
-
- notNull("relative path", path);
-
- return fileAt(new File(location, path).getAbsolutePath()).toRead();
- }
-
-
- //called after JAXB unmarshalling to purge unavailable handlers
- void afterUnmarshal(Unmarshaller u, Object parent) {
-
- validate();
- }
-
- public void validate() {
-
- File locationDir = new File(location);
- if (!(locationDir.exists() && locationDir.isDirectory() && locationDir.canRead() && locationDir.canWrite()))
- throw new IllegalStateException("invalid node configuration: home "+location+" does not exist or is not a directory or cannot be accessed in read/write mode");
-
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((location == null) ? 0 : location.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- DefaultPersistence other = (DefaultPersistence) obj;
- if (location == null) {
- if (other.location != null)
- return false;
- } else if (!location.equals(other.location))
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- return "local persistence in "+location;
- }
-
-}
diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java
new file mode 100644
index 0000000..08a3327
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java
@@ -0,0 +1,68 @@
+package org.gcube.smartgears.persistence;
+
+import static org.gcube.smartgears.utils.Utils.fileAt;
+import static org.gcube.smartgears.utils.Utils.notNull;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.gcube.smartgears.configuration.ComponentConfiguration;
+import org.gcube.smartgears.configuration.ConfiguredWith;
+
+@ConfiguredWith(LocalWriterConfiguration.class)
+public class LocalWriter implements PersistenceWriter {
+
+ private String location;
+
+ @Override
+ public void configure(ComponentConfiguration configuration) {
+ this.location = ((LocalWriterConfiguration) configuration).getLocation();
+
+ }
+
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+
+ @Override
+ public File writefile(String path) {
+
+ notNull("relative path", path);
+
+ return fileAt(new File(location, path).getAbsolutePath()).toWrite();
+ }
+
+ @Override
+ public File file(String path) {
+
+ notNull("relative path", path);
+
+ return fileAt(new File(location, path).getAbsolutePath()).toRead();
+ }
+
+
+ public void validate() {
+
+ File locationDir = new File(location);
+ if (!(locationDir.exists() && locationDir.isDirectory() && locationDir.canRead() && locationDir.canWrite()))
+ throw new IllegalStateException("invalid node configuration: home "+location+" does not exist or is not a directory or cannot be accessed in read/write mode");
+
+ }
+
+ @Override
+ public long getFreeSpace() {
+ try {
+ return Files.getFileStore(Paths.get(location)).getUsableSpace();
+ }catch (Exception e) {
+ return -1;
+ }
+ }
+
+}
diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java b/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java
new file mode 100644
index 0000000..41d0f14
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java
@@ -0,0 +1,24 @@
+package org.gcube.smartgears.persistence;
+
+import org.gcube.common.validator.annotations.NotEmpty;
+import org.gcube.common.validator.annotations.NotNull;
+import org.gcube.smartgears.configuration.ComponentConfiguration;
+
+public class LocalWriterConfiguration implements ComponentConfiguration{
+
+ @NotEmpty @NotNull
+ private String location;
+
+ protected LocalWriterConfiguration() {}
+
+ public LocalWriterConfiguration(String location) {
+ super();
+ this.location = location;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+
+}
diff --git a/src/main/java/org/gcube/smartgears/persistence/Persistence.java b/src/main/java/org/gcube/smartgears/persistence/Persistence.java
deleted file mode 100644
index 058480e..0000000
--- a/src/main/java/org/gcube/smartgears/persistence/Persistence.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.gcube.smartgears.persistence;
-
-import java.io.File;
-
-public interface Persistence {
-
- String location();
-
- File file(String path);
-
- File writefile(String path);
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java
new file mode 100644
index 0000000..b79e21a
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java
@@ -0,0 +1,17 @@
+package org.gcube.smartgears.persistence;
+
+import java.io.File;
+
+import org.gcube.smartgears.configuration.Configurable;
+
+public interface PersistenceWriter extends Configurable{
+
+ File file(String path);
+
+ File writefile(String path);
+
+ long getFreeSpace();
+
+ String getLocation();
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java
index 1466d25..1308cc8 100644
--- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java
+++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java
@@ -1,66 +1,52 @@
package org.gcube.smartgears.provider;
-import static org.gcube.common.authorization.client.Constants.authorizationService;
import static org.gcube.smartgears.Constants.configuration_file_path;
import static org.gcube.smartgears.Constants.container_configuraton_file_path;
-import static org.gcube.smartgears.Constants.container_handlers_file_name;
-import static org.gcube.smartgears.Constants.application_handlers_file_name;
-import static org.gcube.smartgears.Constants.container_handlers_file_path;
-import static org.gcube.smartgears.Constants.container_profile_file_path;
-import static org.gcube.smartgears.Constants.default_extensions_file_path;
-import static org.gcube.smartgears.Constants.default_handlers_file_path;
-import static org.gcube.smartgears.Constants.extensions_file_path;
import static org.gcube.smartgears.Constants.ghn_home_env;
import static org.gcube.smartgears.Constants.ghn_home_property;
-import static org.gcube.smartgears.Constants.handlers_file_path;
-import static org.gcube.smartgears.Constants.library_configuration_file_path;
-import static org.gcube.smartgears.Constants.profile_file_path;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
+import java.util.ArrayList;
import java.util.List;
-import java.util.UUID;
+import java.util.Set;
+import java.util.stream.Collectors;
import javax.servlet.ServletContext;
-import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
+
import org.gcube.common.events.Hub;
import org.gcube.common.events.impl.DefaultHub;
-import org.gcube.common.scan.ClasspathScanner;
-import org.gcube.common.scan.ClasspathScannerFactory;
-import org.gcube.common.scan.matchers.NameMatcher;
-import org.gcube.common.scan.resources.ClasspathResource;
-import org.gcube.informationsystem.publisher.RegistryPublisherFactory;
-import org.gcube.informationsystem.publisher.ScopedPublisher;
-import org.gcube.smartgears.configuration.Mode;
+import org.gcube.common.security.credentials.Credentials;
+import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder;
-import org.gcube.smartgears.configuration.application.ApplicationExtensions;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
-import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder;
-import org.gcube.smartgears.configuration.container.ContainerHandlers;
-import org.gcube.smartgears.configuration.library.SmartGearsConfiguration;
-import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder;
import org.gcube.smartgears.context.Properties;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.application.DefaultApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.context.container.DefaultContainerContext;
+import org.gcube.smartgears.extensions.ApplicationExtension;
+import org.gcube.smartgears.extensions.resource.RemoteResource;
+import org.gcube.smartgears.handlers.container.ContainerHandler;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
-import org.gcube.smartgears.persistence.DefaultPersistence;
+import org.gcube.smartgears.publishing.Publisher;
+import org.gcube.smartgears.publishing.SmartgearsProfilePublisher;
+import org.gcube.smartgears.security.AuthorizationProvider;
+import org.gcube.smartgears.security.AuthorizationProviderFactory;
import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.ClassInfoList;
+import io.github.classgraph.ScanResult;
+
/**
* Default implementation of the {@link Provider} interface.
*
@@ -72,107 +58,56 @@ public class DefaultProvider implements Provider {
private static Logger log = LoggerFactory.getLogger(Provider.class);
private ContainerContext containerContext;
- //TODO: do the same with applicationContext (with a map)
+ // TODO: do the same with applicationContext (with a map)
- protected DefaultProvider(){};
+ private File configFile = null;
+
+ protected DefaultProvider(File configFile) {
+ this.configFile = configFile;
+ }
+
+ List publishers;
+
+ protected DefaultProvider() {
+ };
- @SuppressWarnings("unchecked")
@Override
public ContainerContext containerContext() {
- if(containerContext==null){
+ if (containerContext == null) {
ContainerConfiguration configuration = containerConfiguration();
- if (configuration.persistence()==null) {
- String location = Utils.home()+"/state";
- File dir = new File(location);
- if (!dir.exists())
- dir.mkdirs();
- configuration.persistence(new DefaultPersistence(location));
-
- log.trace("setting persistence location for container @ {}",dir.getAbsolutePath());
- }
-
Hub hub = new DefaultHub();
ContainerLifecycle lifecycle = new ContainerLifecycle(hub);
+
+ AuthorizationProviderFactory> authfactory = configuration.authorizationConfiguration()
+ .getAuthProviderFactory();
+ Credentials credentials = configuration.authorizationConfiguration().getCredentials();
- File file = configuration.persistence().file(container_profile_file_path);
+ AuthorizationProvider authProvider = authfactory.connect(credentials);
- String id = null;
- List tokens = null;
- if (file.exists()){
- log.info("loading persisted state for container");
- try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
- id = (String)ois.readObject();
- tokens = (List) ois.readObject();
- }catch(Exception e){
- log.error("error loading persisted state, creating new uuid",e);
- }
-
- }
- if (id==null){
- id = UUID.randomUUID().toString();
- log.info("container id created is {}",id);
-
- }
-
- if (tokens!=null)
- configuration.startTokens(tokens);
-
- containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, new Properties());
+ containerContext = new DefaultContainerContext(configuration, hub, lifecycle, authProvider,
+ new Properties());
}
return containerContext;
}
@Override
- public ContainerHandlers containerHandlers() {
+ public List containerHandlers() {
try {
- InputStream config = getClass().getResourceAsStream(container_handlers_file_path);
-
- if (config == null)
- throw new IllegalStateException("invalid distribution: cannot find " + container_handlers_file_path);
-
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
- ContainerHandlers defaultHandlers = binder.bindHandlers(config);
-
+
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
- if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){
+ if (currentClassLoader.getParent() != null
+ && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
log.trace("probably i'm in a webapp classloader");
currentClassLoader = currentClassLoader.getParent();
}
-
-
- try{
- if (currentClassLoader instanceof URLClassLoader){
- URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ;
- if (urls!=null && urls.length>0){
- ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet(Arrays.asList(urls)));
- Collection resources = scanner.scan(new NameMatcher(container_handlers_file_name));
-
- for (URL url: urls)
- log.trace("URL: "+ url.toString());
-
- if (resources==null || resources.isEmpty())
- log.info("no custom container handlers found in the classpath");
-
- for (ClasspathResource res : resources){
- try{
- ContainerHandlers customHandlers= binder.bindHandlers(res.stream());
- defaultHandlers.mergeWith(customHandlers);
- log.trace("container hadlers found in {}",res.name());
- }catch(Exception e){
- log.warn("error loading not default container handlers {}",res.name(),e);
- }
- }
- }
- } else log.info("this classloader is not instance of {} : ",URLClassLoader.class.getName(), currentClassLoader.getClass().getName());
- }catch(Exception e){
- log.warn("cannot load custom handlers for container from the root classloader",e);
- }
+ List defaultHandlers = binder.bindHandlers(currentClassLoader);
return defaultHandlers;
@@ -186,63 +121,20 @@ public class DefaultProvider implements Provider {
@Override
public ApplicationContext contextFor(ContainerContext context, ServletContext application) {
- ApplicationConfiguration configuration = null;
ApplicationConfiguration embedded = configurationFor(application);
- ApplicationConfiguration external = context.configuration().app(application.getContextPath());
-
-
-
- //shouldn't happen: management shouldn't have started at all
- if (embedded==null && external==null)
- throw new AssertionError("application @ "+application.getContextPath()+" is not distributed with "
- + configuration_file_path+" and there is no external configuration for it in "+container_configuraton_file_path);
-
- //no embedded configuration
- if (embedded == null) {
-
- configuration = external ;
-
- log.info("loaded configuration for application "+configuration.name()+" from "+container_configuraton_file_path);
- }
- else {
-
- configuration = embedded;
-
- if (external == null)
-
- log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path);
-
- else {
-
- configuration.merge(external);
-
- log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path+" and "+container_configuraton_file_path);
-
- }
- }
-
- // TODO we can check scopes here instead of in BridgedApplicationConfiguration constructor
- ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration(context.configuration(),
- configuration);
+
+ // shouldn't happen: management shouldn't have started at all
+ if (embedded == null)
+ throw new AssertionError("application @ " + application.getContextPath() + " is not distributed with "
+ + configuration_file_path + " and there is no external configuration for it in "
+ + container_configuraton_file_path);
+
Hub hub = new DefaultHub();
- ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, configuration.name());
+ ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, embedded.name());
- File file = bridgedConfiguration.persistence().file(profile_file_path);
- String id= null;
- if (file.exists()){
- log.info("loading persisted state for application {}", application.getContextPath());
- try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
- id = (String)ois.readObject();
- }catch(Exception e){
- log.error("error loading persisted state, creating new uuid",e);
- }
- }
- if (id==null)
- id = UUID.randomUUID().toString();
-
- return new DefaultApplicationContext(id, context, application, bridgedConfiguration, hub, lifecycle,
+ return new DefaultApplicationContext(context, application, embedded, hub, lifecycle,
new Properties());
}
@@ -251,140 +143,46 @@ public class DefaultProvider implements Provider {
try {
- // it's in a library, using
- InputStream defaultHandlersStream = getClass().getResourceAsStream(default_handlers_file_path);
-
- if (defaultHandlersStream == null)
- throw new IllegalStateException("invalid distribution: cannot find " + default_handlers_file_path);
-
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
- ApplicationHandlers defaultHandlers = binder.bindHandlers(defaultHandlersStream);
-
- //searching for smartegars related application handlers in the common classloader
+ // searching for smartegars related application handlers in the common
+ // classloader
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
- if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){
+ if (currentClassLoader.getParent() != null
+ && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
log.trace("probably i'm in a webapp classloader");
currentClassLoader = currentClassLoader.getParent();
}
-
-
- try{
- if (currentClassLoader instanceof URLClassLoader){
- URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ;
- if (urls!=null && urls.length>0){
- ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet(Arrays.asList(urls)));
- Collection resources = scanner.scan(new NameMatcher(application_handlers_file_name));
- if (resources==null || resources.isEmpty())
- log.info("no custom smartgears related application handlers found in the classpath");
-
- for (ClasspathResource res : resources){
- try{
- ApplicationHandlers customHandlers= binder.bindHandlers(res.stream());
- defaultHandlers.mergeWith(customHandlers);
- log.trace("application hadlers found in {}",res.name());
- }catch(Exception e){
- log.warn("error loading smartgears related application handlers {}",res.name(),e);
- }
- }
- }
- }
- }catch(Exception e){
- log.warn("cannot load smartgears related handlers for application from the root classloader",e);
- }
-
- InputStream appSpecificHandlersStream = context.application().getResourceAsStream(handlers_file_path);
-
- if (appSpecificHandlersStream !=null ){
- defaultHandlers.mergeWith(binder.bindHandlers(appSpecificHandlersStream));
- log.trace("{} uses default lifecycle with app spceific handler as it includes {}", context.name(), handlers_file_path);
- } else
- log.trace("{} uses the default lifecycle as it does not include {}", context.name(), handlers_file_path);
-
- return defaultHandlers;
+ ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader);
+ return defaultHandlers;
} catch (RuntimeException e) {
- throw new RuntimeException("cannot install handlers for application @ " + context.name()+" (see cause) ", e);
+ throw new RuntimeException("cannot install handlers for application @ " + context.name() + " (see cause) ",
+ e);
}
}
-
- @Override
- public ApplicationExtensions extensionsFor(ApplicationContext context) {
-
- try {
-
- InputStream config = context.application().getResourceAsStream(extensions_file_path);
-
- if (config == null) {
-
- log.trace("{} uses default extensions as it does not include {}", context.name(), extensions_file_path);
-
- // it's in a library, using
- config = getClass().getResourceAsStream(default_extensions_file_path);
-
- if (config == null)
- throw new IllegalStateException("invalid distribution: cannot find " + default_extensions_file_path);
-
- } else
- log.info("{} uses custom extensions @ {}", context.name(), extensions_file_path);
-
- ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
-
- return binder.bindExtensions(config);
-
- } catch (RuntimeException e) {
-
- throw new RuntimeException("cannot install extensions for application @ " + context.name()+" (see cause) ", e);
-
- }
- }
-
-
- @Override
- public SmartGearsConfiguration smartgearsConfiguration() {
-
- try {
-
- InputStream config = getClass().getResourceAsStream(library_configuration_file_path);
-
- if (config == null)
- throw new IllegalStateException("invalid distribution: cannot find " + library_configuration_file_path);
-
- SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder();
-
- SmartGearsConfiguration configuration = binder.bind(config);
-
- configuration.validate();
-
- return configuration;
-
- } catch (RuntimeException e) {
-
- throw new RuntimeException("cannot read library configuration (see cause) ", e);
-
- }
-
+ public List extensionsFor(ApplicationContext context){
+ return List.of(new RemoteResource());
}
// helpers
-
private ApplicationConfiguration configurationFor(ServletContext application) {
try {
InputStream config = application.getResourceAsStream(configuration_file_path);
- if (config == null)
+ if (config == null)
return null;
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
- return binder.bind(config);
+ return binder.load(config);
} catch (RuntimeException e) {
@@ -395,76 +193,101 @@ public class DefaultProvider implements Provider {
private ContainerConfiguration containerConfiguration() {
- String home = Utils.home();
+ if (configFile == null) {
- if (home == null)
- throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env
- + " or the system property " + ghn_home_property + " must be defined");
+ String home = Utils.home();
- File homeDir = new File(home);
+ if (home == null)
+ throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env
+ + " or the system property " + ghn_home_property + " must be defined");
- if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite()))
- throw new IllegalStateException("invalid node configuration: home "+home+" does not exist or is not a directory or cannot be accessed in read/write mode");
+ File homeDir = new File(home);
- File config = new File(homeDir,container_configuraton_file_path);
+ if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite()))
+ throw new IllegalStateException("invalid node configuration: home " + home
+ + " does not exist or is not a directory or cannot be accessed in read/write mode");
- if (!(config.exists() && config.canRead()))
- throw new IllegalStateException("invalid node configuration: file "+config.getAbsolutePath()+" does not exist or cannot be accessed");
+ configFile = new File(homeDir, container_configuraton_file_path);
-
- log.trace("reading container configuration @ {} ", config.getAbsolutePath());
-
- ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
-
- FileInputStream stream = null;
- try {
-
- stream = new FileInputStream(config);
-
- }
- catch(Exception e) {
- throw new RuntimeException("unexpected exception reading container configuration file see cause)",e);
+ log.trace("reading container configuration @ {} ", configFile.getAbsolutePath());
}
- ContainerConfiguration configuration = binder.bind(stream);
+ if (!(configFile.exists() && configFile.canRead()))
+ throw new IllegalStateException("invalid node configuration: file " + configFile.getAbsolutePath()
+ + " does not exist or cannot be accessed");
- try {
- stream.close();
- }
- catch(Exception e) {
- log.warn("could not close stream when reading container configuration @ "+config.getAbsolutePath()+" (see cause)",e);
+ ContainerConfiguration configuration;
+ try (InputStream stream = new FileInputStream(configFile)) {
+ configuration = new ContainerConfigurationBinder().load(stream);
+ } catch (Exception e) {
+ throw new IllegalStateException(
+ "invalid node configuration: file " + configFile.getAbsolutePath() + " is invalid", e);
}
return configuration;
}
+
+ @Override
+ public synchronized List publishers() {
+ if (this.publishers == null) {
+
+ Set> annotatedPublishers;
+
+ try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo()
+ .addClassLoader(Thread.currentThread().getContextClassLoader()).scan()) {
+
+ ClassInfoList classInfos = result.getClassesWithAnnotation(SmartgearsProfilePublisher.class.getName());
+
+ annotatedPublishers = classInfos.stream().map(ClassInfo::loadClass)
+ .filter(c -> Publisher.class.isAssignableFrom(c)).collect(Collectors.toSet());
+
+ }
+ /*
+ * Collection urls =
+ * ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()
+ * ); urls.removeIf(url -> url.toString().endsWith(".so") ||
+ * url.toString().endsWith(".zip") );
+ *
+ *
+ * ConfigurationBuilder reflectionConf = new
+ * ConfigurationBuilder().addUrls(urls).setScanners(new
+ * TypeAnnotationsScanner(), new SubTypesScanner());
+ *
+ * Reflections reflection = new Reflections(reflectionConf);
+ *
+ * = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class);
+ */
+
+ List foundPublishers = new ArrayList();
+ for (Class> annotatedPublisher : annotatedPublishers) {
+ try {
+ foundPublishers.add((Publisher) annotatedPublisher.getDeclaredConstructor().newInstance());
+ log.info("added class {} to publishers", annotatedPublisher);
+ } catch (Throwable e) {
+ log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(), e);
+ }
+
+ }
+ this.publishers = foundPublishers;
+
+ if (foundPublishers.isEmpty())
+ log.warn("no publishers found in classloader");
+ }
+
+ return this.publishers;
+ }
+
+ @Override
+ public SmartgearsConfiguration smartgearsConfiguration() {
+ ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
+ return binder.loadSmartgearsProperty();
+ }
+
/*
- @Override
- public RegistryPublisher publisherFor(ContainerContext context) {
- return context.configuration().mode()==Mode.online?
- RegistryPublisherFactory.create(): new OfflinePublisher();
- }
-
- @Override
- public RegistryPublisher publisherFor(ApplicationContext context) {
- return context.configuration().mode()==Mode.online?
- RegistryPublisherFactory.create(): new OfflinePublisher();
- }*/
-
- @Override
- public ScopedPublisher publisherFor(ContainerContext context) {
- return context.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher()
- : new OfflinePublisher();
- }
-
- @Override
- public ScopedPublisher publisherFor(ApplicationContext context) {
- return context.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher()
- : new OfflinePublisher();
- }
-
- @Override
- public AuthorizationProxy authorizationProxy() {
- return authorizationService();
- }
+ * @Override public AuthorizationProvider authorizationProvider() { return
+ * containerContext.authorizationProvider(); }
+ */
+
+
}
diff --git a/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java b/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java
deleted file mode 100644
index 4f1cc1d..0000000
--- a/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.gcube.smartgears.provider;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-import org.gcube.common.resources.gcore.Resource;
-import org.gcube.informationsystem.publisher.ScopedPublisher;
-import org.gcube.informationsystem.publisher.exception.RegistryNotFoundException;
-import org.gcube.smartgears.configuration.Mode;
-
-/**
- * An implementation of {@link ScopedPublisher} that simulates remote publication.
- *
- * Used for applications and or containers that operate in {@link Mode#offline}.
- *
- * @author Fabio Simeoni
- *
- */
-public class OfflinePublisher implements ScopedPublisher {
-
- @Override
- public T update(T resource){
- // do nothing
- return resource;
- }
-
- @Override
- public T create(T resource, List