diff --git a/pom.xml b/pom.xml index 7320a92..a0bc221 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,16 @@ https://code-repo.d4science.org/gCubeSystem/common-smartgears + + org.reflections + reflections + 0.9.10 + + + org.yaml + snakeyaml + 1.21 + io.github.classgraph classgraph @@ -106,12 +116,6 @@ 4.0.1 provided - - - javax.xml.bind - jaxb-api - - io.micrometer diff --git a/src/main/java/org/gcube/smartgears/Bootstrap.java b/src/main/java/org/gcube/smartgears/Bootstrap.java index ad52fd8..f1fa17f 100644 --- a/src/main/java/org/gcube/smartgears/Bootstrap.java +++ b/src/main/java/org/gcube/smartgears/Bootstrap.java @@ -86,6 +86,7 @@ public class Bootstrap implements ServletContainerInitializer { } // helpers + @SuppressWarnings("resource") private void initialiseContainer() { try { diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index ea1e571..e2df6f2 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -27,7 +27,7 @@ public class Constants { /** * The container configuration file path, relative to the container configuration directory. - */ + */ public static final String container_configuraton_file_path = "container.ini"; @@ -36,19 +36,15 @@ public class Constants { */ public static final String container_profile_file_path = "ghn.xml"; + /* public static final String container_profile_file_path_copy = "ghn.xml.copy"; - - - /** - * The library configuration resource path. - */ - public static final String library_configuration_file_path = "/META-INF/smartgears-config.xml"; + */ /** * The name of the context property that contains the node profile. - */ + public static final String container_profile_property = "ghn-profile"; - + */ /** * The default value of for the container publication frequency. @@ -59,7 +55,7 @@ public class Constants { /** * The application configuration resource path. */ - public static final String configuration_file_path = "/WEB-INF/gcube-app.xml"; + public static final String configuration_file_path = "/WEB-INF/application.yaml"; /** @@ -73,16 +69,6 @@ public class Constants { */ public static final String root_mapping = "/gcube/resource"; - /** - * The application extensions configuration resource path. - */ - public static final String extensions_file_path = "/WEB-INF/gcube-extensions.xml"; - - /** - * The default application extensions configuration resource path. - */ - public static final String default_extensions_file_path = "/META-INF/default-extensions.xml"; - /** * The application frontpage resource path. */ @@ -126,8 +112,6 @@ public class Constants { public static final String remote_management = "remote-management"; - - /** * The path of the application profile file, relative to the service configuration directory. */ diff --git a/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java new file mode 100644 index 0000000..6c5f9da --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java @@ -0,0 +1,10 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo.Id; + +@JsonTypeInfo(include=As.PROPERTY, use=Id.CLASS, property= "className") +public interface ComponentConfiguration { + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/Configurable.java b/src/main/java/org/gcube/smartgears/configuration/Configurable.java new file mode 100644 index 0000000..9bfcb3c --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/Configurable.java @@ -0,0 +1,6 @@ +package org.gcube.smartgears.configuration; + +public interface Configurable { + + void configure(ComponentConfiguration configuration); +} diff --git a/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java b/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java new file mode 100644 index 0000000..be55a56 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java @@ -0,0 +1,14 @@ +package org.gcube.smartgears.configuration; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(ElementType.TYPE) +public @interface ConfiguredWith { + + public Class value(); +} diff --git a/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java new file mode 100644 index 0000000..3e42147 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java @@ -0,0 +1,37 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; +import org.gcube.common.validator.annotations.IsValid; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.persistence.PersistenceWriter; + +@JsonInclude(value = Include.NON_NULL) +@JsonAutoDetect(fieldVisibility = Visibility.ANY) +public class PersistenceConfiguration { + + @NotNull + private Class implementationClass; + + @IsValid + private ComponentConfiguration writerConfiguration; + + protected PersistenceConfiguration() {} + + public PersistenceConfiguration(Class implementationClass, T writerConfiguration) { + super(); + this.implementationClass = implementationClass; + this.writerConfiguration = writerConfiguration; + } + + public Class getImplementationClass() { + return this.implementationClass; + } + + public ComponentConfiguration getWriterConfiguration() { + return writerConfiguration; + } + +} 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 6b2a9ec..c8624da 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -1,140 +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.ProxyAddress; -import org.gcube.smartgears.persistence.PersistenceWriter; +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; - /** - * Returns the context path of the application - * @return the context path - */ - String context(); + Set excludes= null; - boolean proxable(); + Set includes= null; - ProxyAddress proxyAddress(); + @NotEmpty @JsonProperty("persistence") + PersistenceConfiguration persistenceConfiguration; - ApplicationConfiguration proxyAddress(ProxyAddress proxy); + public Set excludes() { + return excludes; + } - /** - * Sets the context path of the application - * @param context the context path - * @return this configuration - */ - ApplicationConfiguration context(String context); + 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 serviceClass() { + return group; + } + + + public ApplicationConfiguration serviceClass(String group) { + this.group=group; + return this; + } + + public String version() { + return version; + } + + public ApplicationConfiguration version(String version) { + this.version=version; + return this; + } + + + public String description() { + return description; + } + + public ApplicationConfiguration description(String description) { + this.description=description; + return this; + } + + public boolean proxable() { + return proxable; + } - /** - * 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 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); + + } - /** - * Returns the class of the application - * @return the class - */ - String serviceClass(); + @Override + public int hashCode() { + return Objects.hash(description, excludes, group, includes, name, proxable, version); + } - /** - * Sets the class of the application. - * @param serviceClass the class - * @return this configuration - */ - ApplicationConfiguration serviceClass(String serviceClass); - - /** - * 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); + @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 - */ - PersistenceWriter 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(PersistenceWriter 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 d31bf64..144d57a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -1,26 +1,17 @@ package org.gcube.smartgears.configuration.application; -import static org.gcube.smartgears.utils.Utils.closeSafely; -import static org.gcube.smartgears.utils.Utils.unchecked; - import java.io.InputStream; -import java.lang.reflect.Modifier; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.ServiceLoader; -import java.util.Set; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -import org.gcube.smartgears.extensions.ApplicationExtension; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; 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.yaml.snakeyaml.Yaml; /** * Binds {@link ApplicationConfiguration}s to and from XML serialisations. @@ -37,21 +28,15 @@ public class ApplicationConfigurationBinder { * @return the configuration * @throws RuntimeException if the serialisation is invalid */ - public ApplicationConfiguration bind(InputStream stream) { - + public ApplicationConfiguration load(InputStream stream) { try { - - JAXBContext ctx = JAXBContext.newInstance(DefaultApplicationConfiguration.class); - - return (ApplicationConfiguration) ctx.createUnmarshaller().unmarshal(stream); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid service configuration", e); - - } - finally { - closeSafely(stream); + Yaml yaml = new Yaml(); + ObjectMapper mapper = new ObjectMapper(); + String mapAsString = mapper.writeValueAsString(yaml.load(stream)); + + return mapper.readValue(mapAsString, ApplicationConfiguration.class); + }catch (Exception e) { + throw new RuntimeException(e); } } @@ -92,7 +77,7 @@ public class ApplicationConfigurationBinder { * @param stream the serialisation * @return the extensions * @throws RuntimeException if the serialisation is invalid - */ + public ApplicationExtensions bindExtensions(InputStream stream) { //collects handler classes @@ -136,7 +121,8 @@ public class ApplicationConfigurationBinder { return scanned; } - + */ + public void scanForApplicationHandlers(ClassLoader currentClassLoader) { // TODO Auto-generated method stub } 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/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java deleted file mode 100644 index 8028765..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.gcube.smartgears.configuration.application; - -import java.io.File; -import java.util.Set; - -import org.gcube.smartgears.configuration.ProxyAddress; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.gcube.smartgears.persistence.PersistenceWriter; -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 ApplicationConfiguration application; - - - public BridgedApplicationConfiguration(ContainerConfiguration container, ApplicationConfiguration config) { - - this.application=config; - - if (application.persistence()==null) { - - String location = container.persistence().getLocation()+"/"+application.name(); - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); - - application.persistence(new LocalPersistence(location)); - - log.trace("setting persistence location for {} @ {}",application.name(), dir.getAbsolutePath()); - - } - - if (application.proxable() && container.proxy()!=null) - application.proxyAddress(container.proxy()); - - } - - public ApplicationConfiguration inner() { - return application; - } - - @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 ApplicationConfiguration description(String description) { - return application.description(description); - } - - public PersistenceWriter persistence() { - return application.persistence(); - } - - public ApplicationConfiguration persistence(PersistenceWriter manager) { - return application.persistence(manager); - } - - - 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 boolean proxable() { - return application.proxable(); - } - - @Override - public ApplicationConfiguration excludes(Exclude ... excludes) { - return application.excludes(excludes); - } - - @Override - public ApplicationConfiguration includes(Include... includes) { - return application.includes(includes); - } - - @Override - public ProxyAddress proxyAddress() { - return application.proxyAddress(); - } - - @Override - public ApplicationConfiguration proxyAddress(ProxyAddress proxy) { - return proxyAddress(proxy); - } - -} 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 94248e6..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ /dev/null @@ -1,207 +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 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.ProxyAddress; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.gcube.smartgears.persistence.PersistenceWriter; - -/** - * 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 { - - String context; - - @XmlAttribute(name = "proxable") - private boolean proxable = true; - - @XmlElement(name="name" , required=true) - @NotNull - String name; - - @XmlElement(name="group", required=true) - @NotNull - String group; - - @XmlElement(name="version", required=true) - @NotNull - String version; - - @XmlElement(name="description") - String description=""; - - @XmlElementRef - Set excludes= new LinkedHashSet(); - - @XmlElementRef - Set includes= new LinkedHashSet(); - - @XmlElementRef(type=LocalPersistence.class) - @NotNull @IsValid - private PersistenceWriter persistenceManager; - - @IsValid - ProxyAddress proxyAddress; - - @Override - public Set excludes() { - return excludes; - } - - - @Override - public Set includes() { - return includes; - } - - public DefaultApplicationConfiguration() {} - - @Override - public String name() { - return name; - } - - @Override - public String context() { - return context; - } - - @Override - public ApplicationConfiguration context(String context) { - this.context=context; - return this; - } - - @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 String description() { - return description; - } - - @Override - public ApplicationConfiguration description(String description) { - this.description=description; - return this; - } - - @Override - public boolean proxable() { - return proxable; - } - - public ProxyAddress proxyAddress() { - return proxyAddress; - } - - - public ApplicationConfiguration proxyAddress(ProxyAddress proxyAddress) { - this.proxyAddress = proxyAddress; - return this; - } - - - @Override - public PersistenceWriter persistence() { - return persistenceManager; - } - - @Override - public ApplicationConfiguration persistence(PersistenceWriter manager) { - this.persistenceManager=manager; - 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) { - - if (config.persistence()!=null) - persistence(config.persistence()); - - } - - - -} \ 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/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index 0fef04c..128b968 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -14,9 +14,9 @@ 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.persistence.PersistenceWriter; /** * The configuration of the container. @@ -46,7 +46,7 @@ public class ContainerConfiguration { @NotNull @IsValid - private PersistenceWriter persistenceManager; + private PersistenceConfiguration persistenceConfiguration; @NotNull @IsValid private AuthorizationProviderConfiguration authorizationConfiguration; @@ -72,8 +72,8 @@ public class ContainerConfiguration { this.accountingFallbackLocation = accountingFallbackLocation; } - protected void setPersistenceManager(PersistenceWriter persistenceManager) { - this.persistenceManager = persistenceManager; + protected void setPersistenceConfiguration(PersistenceConfiguration persistenceConfiguration) { + this.persistenceConfiguration = persistenceConfiguration; } protected void setAuthorizationProviderConfiguration( @@ -195,8 +195,8 @@ public class ContainerConfiguration { * Returns the persistence manager of the container. * @return the manager */ - public PersistenceWriter persistence() { - return persistenceManager; + public PersistenceConfiguration persistenceConfiguration() { + return this.persistenceConfiguration; } /** @@ -211,7 +211,7 @@ public class ContainerConfiguration { * Returns the authorization configuration. * @return AuthorizationProviderConfiguration the configuration */ - public AuthorizationProviderConfiguration getauthorizationConfiguration() { + public AuthorizationProviderConfiguration authorizationConfiguration() { return authorizationConfiguration; } @@ -254,7 +254,7 @@ public class ContainerConfiguration { public String toString() { return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties + ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation - + ", persistenceManager=" + persistenceManager.getClass().getSimpleName() + + ", persistence=" + persistenceConfiguration.getImplementationClass().getSimpleName() + ", authorizationProvider=" + authorizationConfiguration + "]"; } 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 599d605..686aba5 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -10,11 +10,15 @@ 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.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager; -import org.gcube.smartgears.persistence.LocalPersistence; +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; @@ -30,120 +34,138 @@ import org.ini4j.Profile.Section; */ public class ContainerConfigurationBinder { - public ContainerConfiguration load(InputStream stream) { try { Ini configurator = new Ini(stream); ContainerConfiguration conf = new ContainerConfiguration(); Section nodeSection = configurator.get("node"); - if (nodeSection != null ) { + if (nodeSection != null) { BaseConfiguration nodeConf = new BaseConfiguration(); nodeSection.to(nodeConf); conf.setBaseConfiguration(nodeConf); } Section propertiesSection = configurator.get("properties"); - if (propertiesSection!=null) + if (propertiesSection != null) conf.setProperties(propertiesSection.entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, Entry::getValue))); + .collect(Collectors.toMap(Entry::getKey, Entry::getValue))); Section siteSection = configurator.get("site"); if (siteSection != null) { Site siteConf = new Site(); siteSection.to(siteConf); - conf.setSite(siteConf); + conf.setSite(siteConf); } initAuthorizationPart(configurator, conf); - + initPersistencePart(configurator, conf); - + initProxyPart(configurator, conf); - - //TODO: find a solution for this shit - String location = Utils.home()+"/state"; + // 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) { + } catch (Exception e) { throw new RuntimeException(e); } } - private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + 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); + conf.setProxy(proxyConf); } } - - private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{ + + @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) + if (type == null) throw new Exception("ini file error: type not found in \"persistence\" section"); - PersistenceWriter persistenceWriter; + /* + * 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 persistenceClass = null; try { - Object persistenceImpl = Class.forName(type).newInstance(); - persistenceWriter = PersistenceWriter.class.cast(persistenceImpl); - }catch (Exception e) { + persistenceClass = (Class) Class.forName(type); + } catch (Exception e) { throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e); } - persistenceSection.to(persistenceWriter); - conf.setPersistenceManager(persistenceWriter); + if (!persistenceClass.isAnnotationPresent(ConfiguredWith.class)) + throw new Exception( + "ini file error: invalid class type in \"persistence\" section,ConfiguredWith annotation not present"); + Class 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"; + String location = Utils.home() + "/state"; File dir = new File(location); if (!dir.exists()) dir.mkdirs(); - conf.setPersistenceManager(new LocalPersistence(location)); + + conf.setPersistenceConfiguration( + new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location))); } + } - - private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + + 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) { + if (provider != null) { try { - Object authProviderImpl = Class.forName(provider).newInstance(); + Object authProviderImpl = Class.forName(provider).getDeclaredConstructor().newInstance(); authProviderFactory = AuthorizationProviderFactory.class.cast(authProviderImpl); - }catch (Exception e) { + } catch (Exception e) { throw new Exception("ini file error: invalid provider type in \"authorization\" section", e); } - } else + } else authProviderFactory = new DefaultAuthorizationProviderFactory(); - + authorizationSection.to(authProviderFactory, "factory."); - - + String type = authorizationSection.get("credentials.class"); - if (type ==null) + if (type == null) throw new Exception("ini file error: credentials type not found in \"authorization\" section"); Credentials credentials; try { - Object credentialsImpl = Class.forName(type).newInstance(); + Object credentialsImpl = Class.forName(type).getDeclaredConstructor().newInstance(); credentials = Credentials.class.cast(credentialsImpl); - }catch (Exception e) { + } 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)); + + conf.setAuthorizationProviderConfiguration( + new AuthorizationProviderConfiguration(authProviderFactory, credentials)); } } - + /** * Returns the handlers of the container from their XML serialisation. * @@ -154,24 +176,22 @@ public class ContainerConfigurationBinder { public List bindHandlers(ClassLoader classloader) { LinkedList handlers = new LinkedList(); - - //ADDING BASE Handlers (order is important) + + // ADDING BASE Handlers (order is important) handlers.add(new AccountingManager()); handlers.add(new ContainerProfileManager()); - + handlers.addAll(scanForContainerHadlers(classloader)); - + return handlers; - + } - - - + private List scanForContainerHadlers(ClassLoader classloader) throws RuntimeException { - - //TODO: scan for Container Handler - + + // TODO: scan for Container Handler + return Collections.emptyList(); } - + } diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java index 1541837..f628c6a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java @@ -3,18 +3,14 @@ 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 + @NotEmpty private String version; public SmartGearsConfiguration(){ 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/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 7aeeea8..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,14 +1,24 @@ package org.gcube.smartgears.context.application; +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.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.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Default {@link ApplicationContext} implementation. @@ -18,12 +28,15 @@ import org.gcube.smartgears.security.AuthorizationProvider; */ 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; /** @@ -35,7 +48,30 @@ 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; @@ -50,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; @@ -85,10 +133,8 @@ public class DefaultApplicationContext implements ApplicationContext { @Override public PersistenceWriter persistence() { - return configuration.persistence(); + return persistenceWriter; } - - @Override public Properties properties() { 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 454a94a..e3729a9 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -39,7 +39,7 @@ public interface ContainerContext { * Returns the persistence manager of the container. * @return the manager */ - PersistenceWriter persistence(); + PersistenceWriter persistenceWriter(); /** * Returns the properties of the container. @@ -51,5 +51,6 @@ public interface ContainerContext { 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 0cf4ad4..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,14 +1,21 @@ package org.gcube.smartgears.context.container; -import static org.gcube.smartgears.Constants.container_profile_property; +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.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Default {@link ContainerContext} implementation. @@ -18,12 +25,15 @@ import org.gcube.smartgears.security.AuthorizationProvider; */ 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 @@ -31,19 +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, AuthorizationProvider authProvider, + 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; + + } + + /* public HostingNode profile() { return properties().lookup(container_profile_property).value(HostingNode.class); - }; + };*/ @Override public ContainerConfiguration configuration() { @@ -61,8 +101,8 @@ public class DefaultContainerContext implements ContainerContext { } @Override - public PersistenceWriter persistence() { - return configuration.persistence(); + public PersistenceWriter persistenceWriter() { + return persistenceWriter; } @Override diff --git a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java index a49eb27..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,8 +53,8 @@ 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())); } /** diff --git a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java index 9658b4d..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; /** @@ -41,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 4c78aa0..c9f6437 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,18 @@ public class HttpController extends HttpExtension { } @Override - public Set excludes() { + public void stop(){ + super.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()); diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java index f3660d2..0b76baf 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java @@ -1,17 +1,16 @@ 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 javax.ws.rs.HttpMethod; 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; -import javax.ws.rs.HttpMethod; /** * An {@link ApplicationExtension} that implements the {@link HttpServlet} interface * @@ -48,10 +47,10 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx } } - @XmlAttribute @NotEmpty + @NotEmpty private String name; - @XmlAttribute @NotEmpty + @NotEmpty private String mapping; private ApplicationContext context; @@ -80,8 +79,8 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx public void stop() {} @Override - public Set excludes() { - return new HashSet(); //all managed by default + 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..534b46a 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java @@ -11,7 +11,6 @@ import javax.servlet.http.HttpServletResponse; import org.gcube.common.resources.gcore.Resources; 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; @@ -37,7 +36,7 @@ public class ConfigurationResource extends ApiResource { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - ApplicationConfiguration config = BridgedApplicationConfiguration.class.cast(context().configuration()).inner(); + ApplicationConfiguration config = context().configuration(); Resources.marshal(config,resp.getWriter()); } 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 fdbd49c..e038b33 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -4,7 +4,6 @@ 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; @@ -93,7 +92,7 @@ public class FrontPageResource extends ApiResource { values.put("status", context().lifecycle().state().toString()); - values.put("smartgears-version", provider().smartgearsConfiguration().version()); + //values.put("smartgears-version", provider().smartgearsConfiguration().version()); return values; } 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/RemoteResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java index f160cae..e3fe3f2 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java @@ -2,8 +2,6 @@ package org.gcube.smartgears.extensions.resource; import static org.gcube.smartgears.Constants.remote_management; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.smartgears.Constants; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.HttpController; @@ -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+"/*"; 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 1ec7266..571d71b 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 @@ -13,9 +13,9 @@ 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.AccessTokenSecret; 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; @@ -132,18 +132,18 @@ public class RequestValidator extends RequestHandler { log.info("d4s-user set to {} ", call.request().getHeader("d4s-user")); - String accessToken = null; + String umaToken = null; if (authHeader!=null && !authHeader.isEmpty()) if (authHeader.startsWith(BEARER_AUTH_PREFIX)) - accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); + umaToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); Secret secret = null; - if (accessToken!=null) { - secret = new AccessTokenSecret(accessToken); + if (umaToken!=null) { + secret = new UmaTokenSecret(umaToken); SimpleCredentials credentials = (SimpleCredentials)appContext.authorizationProvider().getCredentials(); KeycloakClient client = KeycloakClientFactory.newInstance(); try { - if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), accessToken)) + 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); diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index a1fbe26..3232aa5 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -13,7 +13,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map.Entry; @@ -24,7 +23,6 @@ import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration; import org.gcube.common.events.Observes; -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; @@ -53,7 +51,7 @@ public class ApplicationManager { private ApplicationContext context; - private ApplicationExtensions extensions; + private List extensions; /** * Starts application management. @@ -83,9 +81,11 @@ public class ApplicationManager { ApplicationHandlers handlers = provider().handlersFor(context); + /* extensions = provider().extensionsFor(context); extensions.validate(); - + */ + List lifecycleHandlers = handlers.lifecycleHandlers(); List requestHandlers = handlers.requestHandlers(); @@ -94,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); @@ -127,7 +128,7 @@ public class ApplicationManager { } 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) { @@ -170,7 +171,7 @@ public class ApplicationManager { } - private void register(List rqHandlers) { + private void registerHandlers(List rqHandlers) { ServletContext app = context.application(); @@ -197,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 { @@ -234,10 +235,9 @@ public class ApplicationManager { } - private void unregister(ApplicationExtensions extensions) { - - for (ApplicationExtension extension : extensions.extensions()) + private void unregister(List extensions) { + for (ApplicationExtension extension : extensions) extension.stop(); } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 5db0195..8bf1e50 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -86,7 +86,7 @@ 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()); }catch (Exception e) { diff --git a/src/main/java/org/gcube/smartgears/managers/RequestManager.java b/src/main/java/org/gcube/smartgears/managers/RequestManager.java index d1f2dec..cf28d8b 100644 --- a/src/main/java/org/gcube/smartgears/managers/RequestManager.java +++ b/src/main/java/org/gcube/smartgears/managers/RequestManager.java @@ -20,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; @@ -137,7 +137,7 @@ 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) || @@ -145,7 +145,8 @@ public class RequestManager implements Filter { excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1))) ){ //ALL handler are filtered except for unfiltrable - if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream().filter(RequestHandler::isUnfiltrable).toList(); + if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream() + .filter(RequestHandler::isUnfiltrable).collect(Collectors.toList()); List filteredHandlers = new ArrayList<>(); for (RequestHandler rh : handlersToFilter) @@ -156,7 +157,7 @@ public class RequestManager implements Filter { } } } 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 ( diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java similarity index 65% rename from src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java rename to src/main/java/org/gcube/smartgears/persistence/LocalWriter.java index 49a9026..08a3327 100644 --- a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java +++ b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java @@ -1,6 +1,5 @@ package org.gcube.smartgears.persistence; - import static org.gcube.smartgears.utils.Utils.fileAt; import static org.gcube.smartgears.utils.Utils.notNull; @@ -8,32 +7,21 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; -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 org.gcube.smartgears.configuration.ComponentConfiguration; +import org.gcube.smartgears.configuration.ConfiguredWith; -import org.gcube.common.validator.annotations.NotEmpty; -import org.gcube.common.validator.annotations.NotNull; +@ConfiguredWith(LocalWriterConfiguration.class) +public class LocalWriter implements PersistenceWriter { -@XmlRootElement(name="persistence") -@XmlAccessorType(XmlAccessType.FIELD) -public class LocalPersistence implements PersistenceWriter { - - @XmlAttribute(name="location") @NotNull @NotEmpty private String location; - protected LocalPersistence() {} - - public LocalPersistence(String location) { + @Override + public void configure(ComponentConfiguration configuration) { + this.location = ((LocalWriterConfiguration) configuration).getLocation(); - notNull("persistence location",location); - - this.location=location; - - validate(); } + public String getLocation() { return location; } 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/PersistenceWriter.java b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java index 6bbb144..b79e21a 100644 --- a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java +++ b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java @@ -2,8 +2,10 @@ package org.gcube.smartgears.persistence; import java.io.File; -public interface PersistenceWriter { - +import org.gcube.smartgears.configuration.Configurable; + +public interface PersistenceWriter extends Configurable{ + File file(String path); File writefile(String path); diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 1cf05c0..8b72b56 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -2,22 +2,15 @@ package org.gcube.smartgears.provider; 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_profile_file_path; -import static org.gcube.smartgears.Constants.default_extensions_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.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.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.UUID; import java.util.stream.Collectors; import javax.servlet.ServletContext; @@ -27,18 +20,16 @@ import org.gcube.common.events.impl.DefaultHub; import org.gcube.common.security.credentials.Credentials; 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.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; @@ -88,32 +79,14 @@ public class DefaultProvider implements Provider { Hub hub = new DefaultHub(); ContainerLifecycle lifecycle = new ContainerLifecycle(hub); - - File file = configuration.persistence().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); - - } - - AuthorizationProviderFactory authfactory = configuration.getauthorizationConfiguration() + + AuthorizationProviderFactory authfactory = configuration.authorizationConfiguration() .getAuthProviderFactory(); - Credentials credentials = configuration.getauthorizationConfiguration().getCredentials(); + Credentials credentials = configuration.authorizationConfiguration().getCredentials(); AuthorizationProvider authProvider = authfactory.connect(credentials); - containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, + containerContext = new DefaultContainerContext(configuration, hub, lifecycle, authProvider, new Properties()); } return containerContext; @@ -147,63 +120,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) + 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); - // 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); - - } - } - - ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration(context.configuration(), - configuration); - + 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()); } @@ -235,62 +165,8 @@ public class DefaultProvider implements Provider { } } - @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 @@ -305,7 +181,7 @@ public class DefaultProvider implements Provider { ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - return binder.bind(config); + return binder.load(config); } catch (RuntimeException e) { diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index fc80175..c0c61b6 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -4,11 +4,10 @@ import java.util.List; import javax.servlet.ServletContext; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.publishing.Publisher; @@ -25,8 +24,9 @@ public interface Provider { /** * Returns the runtime properties. * @return the properties. - */ + SmartGearsConfiguration smartgearsConfiguration(); + */ /** * Assembles and returns the context of the container. @@ -65,12 +65,7 @@ public interface Provider { */ ApplicationHandlers handlersFor(ApplicationContext application); - /** - * Returns the API extensions associated with a given application. - * @param application the context of the application - * @return the extensions - */ - ApplicationExtensions extensionsFor(ApplicationContext application); + List extensionsFor(ApplicationContext application); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index 9c74a8e..7c432ff 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -12,8 +12,8 @@ import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.security.ContextBean; -import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.Secret; +import org.gcube.common.security.secrets.UmaTokenSecret; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; @@ -61,7 +61,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { public Secret getSecretForContext(String context) { try { TokenResponse response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); - return new AccessTokenSecret(response.getAccessToken()); + return new UmaTokenSecret(response.getAccessToken()); } catch (Exception e) { LOG.error("error getting OIDToken from keycloak",e); diff --git a/src/main/resources/META-INF/default-extensions.xml b/src/main/resources/META-INF/default-extensions.xml deleted file mode 100644 index 26845b3..0000000 --- a/src/main/resources/META-INF/default-extensions.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/main/resources/META-INF/profile.xml b/src/main/resources/META-INF/profile.xml deleted file mode 100644 index 3bc929b..0000000 --- a/src/main/resources/META-INF/profile.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Service - - ${description} - ${serviceClass} - common-smartgears - 1.0.0 - - - ${description} - common-smartgears - 4.0.0-SNAPSHOT - - org.gcube.core - common-smartgears - 4.0.0-SNAPSHOT - - Library - - common-smartgears-4.0.0-SNAPSHOT.jar - - - - - - diff --git a/src/test/java/utils/ConfigurationTest.java b/src/test/java/utils/ConfigurationTest.java new file mode 100644 index 0000000..1765ab2 --- /dev/null +++ b/src/test/java/utils/ConfigurationTest.java @@ -0,0 +1,88 @@ +package utils; + +import java.io.InputStream; +import java.util.List; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.smartgears.configuration.PersistenceConfiguration; +import org.gcube.smartgears.configuration.application.ApplicationConfiguration; +import org.gcube.smartgears.configuration.application.GCubeExclude; +import org.gcube.smartgears.persistence.LocalWriter; +import org.gcube.smartgears.persistence.LocalWriterConfiguration; +import org.junit.Test; +import org.yaml.snakeyaml.Yaml; + +import junit.framework.Assert; + +public class ConfigurationTest { + + static final String yamlConf = "name: test\n" + + "group: group\n" + + "version: 1.0.0\n" + + "description: pippo\n" + + "proxable: true\n" + + "excludes:\n" + + "- path: /pippo/*\n" + + "- handlers: [H1, H2]\n" + + " path: /trip\n" + + "persistence:\n" + + " implementationClass: org.gcube.smartgears.persistence.LocalWriter\n" + + " writerConfiguration:\n" + + " className: org.gcube.smartgears.persistence.LocalWriterConfiguration\n" + + " location: /tmp"; + + static final String yamlConfBase = "name: test\n" + + "group: group\n" + + "version: 1.0.0\n" + + "description: pippo"; + + @Test + public void deserialize() { + Yaml yaml = new Yaml(); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("applicationTest.yaml"); + ApplicationConfiguration customer = yaml.load(inputStream); + + } + + @Test + public void serialize() throws Exception{ + ApplicationConfiguration configuration =new ApplicationConfiguration(); + configuration.name("test").serviceClass("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip")); + configuration.persistenceConfiguration(new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration("/tmp"))); + /* + ObjectMapper mapper = new ObjectMapper(); + String value = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(configuration); + System.out.println(value); + Map res = mapper.readValue(value, Map.class); + + + + Yaml yaml = new Yaml(); + String yamlValue = yaml.dump(res); + System.out.println(yamlValue); + */ + + Yaml yaml = new Yaml(); + ObjectMapper mapper = new ObjectMapper(); + String mapAsString = mapper.writeValueAsString(yaml.load(yamlConf)); + System.out.println(mapAsString); + + ApplicationConfiguration conf2 = mapper.readValue(mapAsString, ApplicationConfiguration.class); + Assert.assertTrue(configuration.equals(conf2)); + } + + @Test + public void serializeBase() throws Exception{ + ObjectMapper mapper = new ObjectMapper(); + Yaml yaml = new Yaml(); + + String mapAsString = mapper.writeValueAsString(yaml.load(yamlConfBase)); + System.out.println(mapAsString); + + ApplicationConfiguration conf2 = mapper.readValue(mapAsString, ApplicationConfiguration.class); + Assert.assertEquals("test", conf2.name()); + + } +} diff --git a/src/test/java/utils/PersistenceWriterTest.java b/src/test/java/utils/PersistenceWriterTest.java index a73e280..23abf16 100644 --- a/src/test/java/utils/PersistenceWriterTest.java +++ b/src/test/java/utils/PersistenceWriterTest.java @@ -4,6 +4,7 @@ import java.io.File; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.ComponentConfiguration; import org.gcube.smartgears.persistence.PersistenceWriter; public class PersistenceWriterTest implements PersistenceWriter{ @@ -33,5 +34,10 @@ public class PersistenceWriterTest implements PersistenceWriter{ public long getFreeSpace() { return 0; } + + @Override + public void configure(ComponentConfiguration configuration) { + + } } diff --git a/src/test/java/utils/TestProvider.java b/src/test/java/utils/TestProvider.java index 7dd0014..6d27894 100644 --- a/src/test/java/utils/TestProvider.java +++ b/src/test/java/utils/TestProvider.java @@ -1,15 +1,15 @@ package utils; import java.io.File; +import java.util.List; import javax.servlet.ServletContext; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.provider.DefaultProvider; public class TestProvider extends DefaultProvider { @@ -21,7 +21,7 @@ public class TestProvider extends DefaultProvider { public ApplicationContext context; public ApplicationConfiguration configuration; public ApplicationHandlers handlers; - public ApplicationExtensions extensions; + public List extensions; public void use(ApplicationConfiguration configuration) { @@ -32,18 +32,18 @@ public class TestProvider extends DefaultProvider { this.handlers=handlers; } - public void use(ApplicationExtensions extensions) { + public void use(List extensions) { this.extensions=extensions; } - + /* @Override public SmartGearsConfiguration smartgearsConfiguration() { SmartGearsConfiguration conf = new SmartGearsConfiguration(); conf.version("0.0.1-TEST"); return conf ; - } + }*/ @Override @@ -57,7 +57,7 @@ public class TestProvider extends DefaultProvider { } @Override - public ApplicationExtensions extensionsFor(ApplicationContext context) { + public List extensionsFor(ApplicationContext context) { return extensions==null?super.extensionsFor(context):extensions; } } diff --git a/src/test/java/utils/TestUtils.java b/src/test/java/utils/TestUtils.java deleted file mode 100644 index a043481..0000000 --- a/src/test/java/utils/TestUtils.java +++ /dev/null @@ -1,155 +0,0 @@ -package utils; - -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; -import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.handlers.application.ApplicationHandler; - - -public class TestUtils { - - - public static String location = "/tmp/ghn-home"; - public static String context_root = "test-app"; - public static String context_root_path = "/" + context_root; - public static String servlet_name = "test"; - public static String scope = "/gcube/devsec"; - - public static class Box { - - T t; - - public void put(T t) { - this.t=t; - } - - public T get() { - return t; - } - - } - - - /** - * Serialises a {@link ApplicationConfiguration} to XML. - * - * @param config the configuration - * @return the serialisation - * @throws RuntimeException if the configuration cannot be serialised - */ - public static String bind(ApplicationConfiguration config) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(DefaultApplicationConfiguration.class); - if (config.persistence()!=null) - classes.add(config.persistence().getClass()); - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(config, writer); - - return writer.toString(); - - - } catch (JAXBException e) { - - throw new RuntimeException("invalid application configuration", e); - - } - } - - /** - * Serialises application handlers. - * - * @param handlers the handlers - * @return the serialisation - * @throws RuntimeException if the handlers cannot be serialised - */ - public static String bind(ApplicationHandlers handlers) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(ApplicationHandlers.class); - - for (ApplicationHandler h : handlers.lifecycleHandlers()) - classes.add(h.getClass()); - - for (ApplicationHandler h : handlers.requestHandlers()) - classes.add(h.getClass()); - - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(handlers, writer); - - return writer.toString(); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid handler configuration", e); - - } - } - - /** - * Serialises application extensions. - * - * @param extensions the extensions - * @return the serialisation - * @throws RuntimeException if the extensions cannot be serialised - */ - public static String bind(ApplicationExtensions extensions) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(ApplicationExtensions.class); - - for (ApplicationExtension h : extensions.extensions()) - classes.add(h.getClass()); - - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(extensions, writer); - - return writer.toString(); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid handler configuration", e); - - } - } - -} diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 0000000..c684c27 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,18 @@ +name: test +group: group +version: 1.0.0 +#not mandatory +description: pippo +#not mandatory +proxable: true +#not mandatory +excludes: + - path: /pippo/* + - handlers: [H1, H2] + path: /trip +#not mandatory +persistence: + implementationClass: org.gcube.smartgears.persistence.LocalWriter + writerConfiguration: + className: org.gcube.smartgears.persistence.LocalWriterConfiguration + location: /tmp \ No newline at end of file