handler configuration removed

test removed
master
Lucio Lelii 2 years ago
parent a285c20b38
commit f54efc1e4e

@ -38,12 +38,6 @@ public class Constants {
public static final String container_profile_file_path_copy = "ghn.xml.copy";
/**
* The container lifecycle configuration resource path.
*/
public static final String container_handlers_file_path = "/META-INF/container-handlers.xml";
public static final String container_handlers_file_name = "gcube-container-handlers.xml";
/**
* The library configuration resource path.
@ -62,24 +56,11 @@ public class Constants {
public static final long default_container_publication_frequency_in_seconds = 60;
/**
* The application configuration resource path.
*/
public static final String configuration_file_path = "/WEB-INF/gcube-app.xml";
/**
* The application lifecycle configuration resource path.
*/
public static final String handlers_file_path = "/WEB-INF/gcube-handlers.xml";
/**
* The default application lifecycle configuration resource path.
*/
public static final String default_handlers_file_path = "/META-INF/default-handlers.xml";
public static final String application_handlers_file_name = "gcube-application-handlers.xml";
/**
* The wildcard exclude directive.

@ -1,10 +1,13 @@
package org.gcube.smartgears.configuration.application;
import static org.gcube.smartgears.utils.Utils.*;
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;
@ -12,7 +15,11 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import org.gcube.smartgears.extensions.ApplicationExtension;
import org.gcube.smartgears.handlers.application.ApplicationHandler;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager;
import org.gcube.smartgears.handlers.application.request.RequestAccounting;
import org.gcube.smartgears.handlers.application.request.RequestValidator;
/**
* Binds {@link ApplicationConfiguration}s to and from XML serialisations.
@ -54,25 +61,27 @@ public class ApplicationConfigurationBinder {
* @return the handlers
* @throws RuntimeException if the serialisation is invalid
*/
public ApplicationHandlers bindHandlers(InputStream stream) {
//collects handler classes
Set<Class<?>> classes = scanForHandlers();
try {
JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class<?>[0]));
return (ApplicationHandlers) ctx.createUnmarshaller().unmarshal(stream);
} catch (JAXBException e) {
throw unchecked(e);
}
finally {
closeSafely(stream);
}
public ApplicationHandlers bindHandlers(ClassLoader classLoader) {
List<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
//ADDING BASE Handler (order is important)
requestHandlers.add(new RequestValidator());
requestHandlers.add(new RequestAccounting());
//TODO scan RequestHAndler form classloader
List<ApplicationLifecycleHandler> lifecycleHandlers = new LinkedList<ApplicationLifecycleHandler>();
//ADDING BASE Handler (order is important)
lifecycleHandlers.add(new ProfileManager());
//TODO scan ApplicationLifecycleHandler form classloader
return new ApplicationHandlers(lifecycleHandlers, requestHandlers);
}
/**
@ -103,28 +112,7 @@ public class ApplicationConfigurationBinder {
}
}
private Set<Class<?>> scanForHandlers() throws RuntimeException {
@SuppressWarnings("all")
ServiceLoader<ApplicationHandler> handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationHandler.class);
Set<Class<?>> scanned = new HashSet<Class<?>>();
for (ApplicationHandler<?> handler : handlerLoader) {
Class<?> handlerClass = handler.getClass();
if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
continue;
else
scanned.add(handlerClass);
}
//add top-level configuration
scanned.add(ApplicationHandlers.class);
return scanned;
}
private Set<Class<?>> scanForExtensions() throws RuntimeException {
@ -146,4 +134,8 @@ public class ApplicationConfigurationBinder {
return scanned;
}
public void scanForApplicationHandlers(ClassLoader currentClassLoader) {
// TODO Auto-generated method stub
}
}

@ -1,21 +1,11 @@
package org.gcube.smartgears.configuration.application;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.common.validator.ValidationError;
import org.gcube.common.validator.Validator;
import org.gcube.common.validator.ValidatorFactory;
import org.gcube.common.validator.annotations.IsValid;
import org.gcube.smartgears.handlers.application.ApplicationHandler;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.w3c.dom.Element;
/**
* The {@link ApplicationHandler}s that manage the application.
@ -23,24 +13,24 @@ import org.w3c.dom.Element;
* @author Fabio Simeoni
*
*/
@XmlRootElement(name="handlers")
public class ApplicationHandlers {
@XmlElement(name="lifecycle") @IsValid
private LifecycleHandlers lifecycleHandlers = new LifecycleHandlers();
private List<ApplicationLifecycleHandler> lifecycleHandlers = new LinkedList<ApplicationLifecycleHandler>();
@XmlElement(name="request") @IsValid
private RequestHandlers requestHandlers = new RequestHandlers();
private List<RequestHandler> requestHandlers = new LinkedList<RequestHandler>();
public ApplicationHandlers() {}
public ApplicationHandlers(List<ApplicationLifecycleHandler> lifecycleHandlers, List<RequestHandler> requestHandlers) {
this.lifecycleHandlers = lifecycleHandlers;
this.requestHandlers = requestHandlers;
}
/**
* Returns the {@link ApplicationLifecycleHandler}s for the service.
* @return the lifecycle handlers
*/
public List<ApplicationLifecycleHandler> lifecycleHandlers() {
return lifecycleHandlers.values;
return lifecycleHandlers;
}
/**
@ -48,8 +38,8 @@ public class ApplicationHandlers {
* @param handlers the lifecycle handlers
* @return this configuration
*/
public ApplicationHandlers set(ApplicationLifecycleHandler ... handlers) {
this.lifecycleHandlers = new LifecycleHandlers(Arrays.asList(handlers));
public ApplicationHandlers setLifecycleHandlers(List<ApplicationLifecycleHandler> handlers) {
this.lifecycleHandlers = handlers;
return this;
}
@ -58,7 +48,7 @@ public class ApplicationHandlers {
* @return the lifetime handlers
*/
public List<RequestHandler> requestHandlers() {
return requestHandlers.values;
return requestHandlers;
}
/**
@ -66,75 +56,11 @@ public class ApplicationHandlers {
* @param handlers the request handlers
* @return this configuration
*/
public ApplicationHandlers set(RequestHandler ... handlers) {
this.requestHandlers = new RequestHandlers(Arrays.asList(handlers));
public ApplicationHandlers setRequetHandlers(List<RequestHandler> handlers) {
this.requestHandlers = handlers;
return this;
}
public void validate() {
List<String> msgs = new ArrayList<String>();
Validator validator = ValidatorFactory.validator();
for (ValidationError error : validator.validate(this))
msgs.add(error.toString());
if (!msgs.isEmpty())
throw new IllegalStateException("invalid configuration: "+msgs);
}
//////////////// HELPER BINDING CLASSES
//used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension
private static class LifecycleHandlers {
@SuppressWarnings("all")
LifecycleHandlers() { //needed for deserialisation
}
LifecycleHandlers(List<ApplicationLifecycleHandler> handlers) {
this.values=handlers;
}
@XmlAnyElement(lax=true)
List<ApplicationLifecycleHandler> values = new ArrayList<ApplicationLifecycleHandler>();
//since we use @AnyElement, after deserialisation, we check there are no DOM elements
@SuppressWarnings("unused")
void afterUnmarshal(Unmarshaller u, Object parent) {
for (Object o : values)
if (o instanceof Element)
throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName());
}
}
//used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension
private static class RequestHandlers {
@SuppressWarnings("all")
RequestHandlers() { //needed for deserialisation
}
RequestHandlers(List<RequestHandler> handlers) {
this.values=handlers;
}
@XmlAnyElement(lax=true)
List<RequestHandler> values = new ArrayList<RequestHandler>();
//since we use @AnyElement, after deserialisation, we check there are no DOM elements
@SuppressWarnings("unused")
void afterUnmarshal(Unmarshaller u, Object parent) {
for (Object o : values)
if (o instanceof Element)
throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName());
}
}
public void mergeWith(ApplicationHandlers other){
List<ApplicationLifecycleHandler> lifecycles = other.lifecycleHandlers();

@ -85,8 +85,6 @@ public class BaseConfiguration {
this.infrastructure = infrastructure;
}
@Override
public String toString() {

@ -1,16 +1,12 @@
package org.gcube.smartgears.configuration.container;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.bind.annotation.XmlTransient;
@ -23,14 +19,8 @@ import org.gcube.common.validator.annotations.NotNull;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.configuration.ProxyAddress;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.persistence.LocalPersistence;
import org.gcube.smartgears.persistence.PersistenceWriter;
import org.gcube.smartgears.security.AuthorizationProvider;
import org.gcube.smartgears.security.Credentials;
import org.gcube.smartgears.security.DefaultAuthorizationProvider;
import org.gcube.smartgears.utils.Utils;
import org.ini4j.Ini;
import org.ini4j.Profile.Section;
/**
* The configuration of the container.
@ -69,6 +59,35 @@ public class ContainerConfiguration {
@NotNull @IsValid
private AuthorizationProvider authorizationProvider;
protected void setBaseConfiguration(BaseConfiguration baseConfiguration) {
this.baseConfiguration = baseConfiguration;
}
protected void setProperties(Map<String, String> properties) {
this.properties = properties;
}
protected void setSite(Site site) {
this.site = site;
}
protected void setProxy(ProxyAddress proxy) {
this.proxy = proxy;
}
protected void setAccountingFallbackLocation(String accountingFallbackLocation) {
this.accountingFallbackLocation = accountingFallbackLocation;
}
protected void setPersistenceManager(PersistenceWriter persistenceManager) {
this.persistenceManager = persistenceManager;
}
protected void setAuthorizationProvider(AuthorizationProvider authorizationProvider) {
this.authorizationProvider = authorizationProvider;
}
/**
* Returns the management mode for the container.
* @return the management mode
@ -243,116 +262,14 @@ public class ContainerConfiguration {
}
public static ContainerConfiguration load(InputStream stream) {
try {
Ini configurator = new Ini(stream);
ContainerConfiguration conf = new ContainerConfiguration();
Section nodeSection = configurator.get("node");
if (nodeSection != null ) {
BaseConfiguration nodeConf = new BaseConfiguration();
nodeSection.to(nodeConf);
conf.baseConfiguration = nodeConf;
}
Section propertiesSection = configurator.get("properties");
if (propertiesSection!=null)
conf.properties = propertiesSection.entrySet().stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Section siteSection = configurator.get("site");
if (siteSection != null) {
Site siteConf = new Site();
siteSection.to(siteConf);
conf.site = siteConf;
}
initAuthorizationPart(configurator, conf);
initPersistencePart(configurator, conf);
initProxyPart(configurator, conf);
//TODO: find a solution for this shit
String location = Utils.home()+"/state";
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
conf.accountingFallbackLocation = location;
// END Shit
return conf;
}catch (Exception e) {
throw new RuntimeException(e);
}
@Override
public String toString() {
return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties
+ ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation
+ ", persistenceManager=" + persistenceManager.getClass().getSimpleName()
+ ", authorizationProvider=" + authorizationProvider.getClass().getSimpleName() + "]";
}
private static void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section proxySection = configurator.get("proxy");
if (proxySection != null) {
ProxyAddress proxyConf = new ProxyAddress();
proxySection.to(proxyConf);
conf.proxy = proxyConf;
}
}
private static void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section persistenceSection = configurator.get("persistence");
if (persistenceSection != null) {
String type = persistenceSection.get("class");
if (type ==null)
throw new Exception("ini file error: type not found in \"persistence\" section");
PersistenceWriter persistenceWriter;
try {
Object persistenceImpl = Class.forName(type).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);
conf.persistenceManager = persistenceWriter;
} else {
String location = Utils.home()+"/state";
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
conf.persistenceManager = new LocalPersistence(location);
}
}
private static void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section authorizationSection = configurator.get("authorization");
if (authorizationSection != null) {
String provider = authorizationSection.get("provider");
AuthorizationProvider authProvider;
if (provider!=null) {
try {
Object authProviderImpl = Class.forName(provider).newInstance();
authProvider = AuthorizationProvider.class.cast(authProviderImpl);
}catch (Exception e) {
throw new Exception("ini file error: invalid provider type in \"authorization\" section", e);
}
} else
authProvider = new DefaultAuthorizationProvider();
String type = authorizationSection.get("credentials.class");
if (type ==null)
throw new Exception("ini file error: credentials type not found in \"authorization\" section");
Credentials credentials;
try {
Object credentialsImpl = Class.forName(type).newInstance();
credentials = Credentials.class.cast(credentialsImpl);
}catch (Exception e) {
throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e);
}
authorizationSection.to(credentials, "credentials.");
authProvider.connect(credentials);
conf.authorizationProvider = authProvider;
}
}
}

@ -1,18 +1,26 @@
package org.gcube.smartgears.configuration.container;
import static org.gcube.smartgears.utils.Utils.*;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.ServiceLoader;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.gcube.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.ProfileContainerManager;
import org.gcube.smartgears.persistence.LocalPersistence;
import org.gcube.smartgears.persistence.PersistenceWriter;
import org.gcube.smartgears.security.AuthorizationProvider;
import org.gcube.smartgears.security.AuthorizationProviderFactory;
import org.gcube.smartgears.security.Credentials;
import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory;
import org.gcube.smartgears.utils.Utils;
import org.ini4j.Ini;
import org.ini4j.Profile.Section;
/**
* Binds {@link ContainerConfiguration}s to and from XML serialisations.
@ -22,31 +30,117 @@ import org.gcube.smartgears.utils.Utils;
*/
public class ContainerConfigurationBinder {
/**
* Returns a {@link ContainerConfiguration} from its XML serialisation.
*
* @param stream the serialisation
* @return the configuration
* @throws RuntimeException if the serialisation is invalid
*/
public ContainerConfiguration bind(InputStream stream) {
public ContainerConfiguration load(InputStream stream) {
try {
JAXBContext ctx = JAXBContext.newInstance(ContainerConfiguration.class);
ContainerConfiguration config = (ContainerConfiguration) ctx.createUnmarshaller().unmarshal(stream);
Ini configurator = new Ini(stream);
ContainerConfiguration conf = new ContainerConfiguration();
Section nodeSection = configurator.get("node");
if (nodeSection != null ) {
BaseConfiguration nodeConf = new BaseConfiguration();
nodeSection.to(nodeConf);
conf.setBaseConfiguration(nodeConf);
}
Section propertiesSection = configurator.get("properties");
if (propertiesSection!=null)
conf.setProperties(propertiesSection.entrySet().stream()
.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);
}
initAuthorizationPart(configurator, conf);
return config;
} catch (JAXBException e) {
initPersistencePart(configurator, conf);
initProxyPart(configurator, conf);
throw new RuntimeException("invalid container configuration", e);
//TODO: find a solution for this shit
String location = Utils.home()+"/state";
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
conf.setAccountingFallbackLocation(location);
// END Shit
return conf;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section proxySection = configurator.get("proxy");
if (proxySection != null) {
ProxyAddress proxyConf = new ProxyAddress();
proxySection.to(proxyConf);
conf.setProxy(proxyConf);
}
finally {
}
private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section persistenceSection = configurator.get("persistence");
if (persistenceSection != null) {
String type = persistenceSection.get("class");
if (type ==null)
throw new Exception("ini file error: type not found in \"persistence\" section");
PersistenceWriter persistenceWriter;
try {
Object persistenceImpl = Class.forName(type).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);
conf.setPersistenceManager(persistenceWriter);
} else {
String location = Utils.home()+"/state";
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
conf.setPersistenceManager(new LocalPersistence(location));
}
}
private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{
Section authorizationSection = configurator.get("authorization");
if (authorizationSection != null) {
String provider = authorizationSection.get("factory");
AuthorizationProviderFactory<?> authProviderFactory;
if (provider!=null) {
try {
Object authProviderImpl = Class.forName(provider).newInstance();
authProviderFactory = AuthorizationProviderFactory.class.cast(authProviderImpl);
}catch (Exception e) {
throw new Exception("ini file error: invalid provider type in \"authorization\" section", e);
}
} else
authProviderFactory = new DefaultAuthorizationProviderFactory();
Utils.closeSafely(stream);
String type = authorizationSection.get("credentials.class");
if (type ==null)
throw new Exception("ini file error: credentials type not found in \"authorization\" section");
Credentials credentials;
try {
Object credentialsImpl = Class.forName(type).newInstance();
credentials = Credentials.class.cast(credentialsImpl);
}catch (Exception e) {
throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e);
}
authorizationSection.to(credentials, "credentials.");
AuthorizationProvider authProvider = authProviderFactory.connect(credentials);
conf.setAuthorizationProvider(authProvider);
}
}
@ -57,45 +151,27 @@ public class ContainerConfigurationBinder {
* @return the handlers
* @throws RuntimeException if the serialisation is invalid
*/
public ContainerHandlers bindHandlers(InputStream stream) {
//collects handler classes
Set<Class<?>> classes = scanForConfigurationElements();
try {
JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class<?>[0]));
public List<ContainerHandler> bindHandlers(ClassLoader classloader) {
return (ContainerHandlers) ctx.createUnmarshaller().unmarshal(stream);
} catch (JAXBException e) {
throw unchecked(e);
}
LinkedList<ContainerHandler> handlers = new LinkedList<ContainerHandler>();
//ADDING BASE Handler (order is important)
handlers.add(new AccountingManager());
handlers.add(new ProfileContainerManager());
handlers.addAll(scanForContainerHadlers(classloader));
return handlers;
}
private Set<Class<?>> scanForConfigurationElements() throws RuntimeException {
@SuppressWarnings("all")
ServiceLoader<ContainerHandler> handlerLoader = (ServiceLoader) ServiceLoader.load(ContainerHandler.class);
Set<Class<?>> scanned = new HashSet<Class<?>>();
for (ContainerHandler handler : handlerLoader) {
Class<?> handlerClass = handler.getClass();
if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT)
continue;
else
scanned.add(handlerClass);
}
//add top-level configuration
scanned.add(ContainerHandlers.class);
return scanned;
private List<? extends ContainerHandler> scanForContainerHadlers(ClassLoader classloader) throws RuntimeException {
//TODO: scan for Container Handler
return Collections.emptyList();
}
}

@ -1,50 +0,0 @@
package org.gcube.smartgears.configuration.container;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.smartgears.handlers.container.ContainerHandler;
/**
* The {@link ContainerHandler}s that manage the application.
*
* @author Fabio Simeoni
*
*/
@XmlRootElement(name="handlers")
public class ContainerHandlers {
@XmlAnyElement(lax=true)
List<ContainerHandler> handlers = new ArrayList<ContainerHandler>();
public ContainerHandlers() {}
/**
* Returns the {@link ContainerHandler}s for the service.
* @return the lifecycle handlers
*/
public List<ContainerHandler> get() {
return handlers;
}
/**
* Sets the {@link ContainerHandler}s for the service.
* @param handlers the lifecycle handlers
* @return this configuration
*/
public ContainerHandlers set(ContainerHandler ... handlers) {
this.handlers = Arrays.asList(handlers);
return this;
}
public void mergeWith(ContainerHandlers other){
List<ContainerHandler> handlers = other.get();
for (ContainerHandler handler : handlers)
if (!this.get().contains(handler))
this.get().add(handler);
}
}

@ -5,8 +5,6 @@ package org.gcube.smartgears.handlers.container.lifecycle;
import static org.gcube.smartgears.Constants.accounting_management;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.accounting.persistence.AccountingPersistenceFactory;
import org.gcube.smartgears.handlers.container.ContainerHandler;
import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent;
@ -16,7 +14,6 @@ import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@XmlRootElement(name = accounting_management)
public class AccountingManager extends ContainerHandler {
private static Logger logger = LoggerFactory.getLogger(AccountingManager.class);

@ -19,8 +19,6 @@ import static org.gcube.smartgears.lifecycle.container.ContainerState.active;
import java.util.Collections;
import java.util.concurrent.ScheduledFuture;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.common.events.Observes;
import org.gcube.common.resources.gcore.HostingNode;
import org.gcube.smartgears.configuration.Mode;
@ -52,10 +50,9 @@ import org.slf4j.LoggerFactory;
* @author Fabio Simeoni
* @see ProfileBuilder
*/
@XmlRootElement(name = profile_management)
public class ProfileManager extends ContainerHandler {
public class ProfileContainerManager extends ContainerHandler {
private static Logger log = LoggerFactory.getLogger(ProfileManager.class);
private static Logger log = LoggerFactory.getLogger(ProfileContainerManager.class);
private ContainerContext context;

@ -83,7 +83,6 @@ public class ApplicationManager {
registerObservers();
ApplicationHandlers handlers = provider().handlersFor(context);
handlers.validate();
ApplicationExtensions extensions = provider().extensionsFor(context);
extensions.validate();

@ -16,7 +16,6 @@ import java.util.Set;
import org.gcube.common.events.Observes;
import org.gcube.common.events.Observes.Kind;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.configuration.container.ContainerHandlers;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.handlers.container.ContainerHandler;
@ -61,18 +60,15 @@ public class ContainerManager {
saveContainerState();
ContainerHandlers handlers = provider().containerHandlers();
List<ContainerHandler> handlers = provider().containerHandlers();
log.trace("managing container lifecycle with {}", handlers.get());
log.trace("managing container lifecycle with {}", handlers);
startHandlers(handlers.get());
startHandlers(handlers);
context.lifecycle().moveTo(active);
log.trace("loading keys for starting token ...");
//loadKeyForToken(context.configuration().startTokens());
log.trace("keys loaded for starting token ...");
return context;
}
catch(RuntimeException e) {
@ -103,10 +99,9 @@ public class ContainerManager {
//List<String> tokensToRemove = new ArrayList<String>();
context.configuration().validate();
Set<String> foundContexts;
try {
foundContexts = context.configuration().allowedContexts();
foundContexts = context.configuration().authorizationProvider().getAllowedContexts();
} catch (Exception e) {
log.error("error authorizing container",e);
throw new RuntimeException("error authorizing container, moving the container to failed",e);

@ -1,17 +1,12 @@
package org.gcube.smartgears.provider;
import static org.gcube.smartgears.Constants.application_handlers_file_name;
import static org.gcube.smartgears.Constants.configuration_file_path;
import static org.gcube.smartgears.Constants.container_configuraton_file_path;
import static org.gcube.smartgears.Constants.container_handlers_file_name;
import static org.gcube.smartgears.Constants.container_handlers_file_path;
import static org.gcube.smartgears.Constants.container_profile_file_path;
import static org.gcube.smartgears.Constants.default_extensions_file_path;
import static org.gcube.smartgears.Constants.default_handlers_file_path;
import static org.gcube.smartgears.Constants.extensions_file_path;
import static org.gcube.smartgears.Constants.ghn_home_env;
import static org.gcube.smartgears.Constants.ghn_home_property;
import static org.gcube.smartgears.Constants.handlers_file_path;
import static org.gcube.smartgears.Constants.library_configuration_file_path;
import static org.gcube.smartgears.Constants.profile_file_path;
@ -19,21 +14,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletContext;
import org.gcube.common.events.Hub;
import org.gcube.common.events.impl.DefaultHub;
import org.gcube.common.scan.ClasspathScanner;
import org.gcube.common.scan.ClasspathScannerFactory;
import org.gcube.common.scan.matchers.NameMatcher;
import org.gcube.common.scan.resources.ClasspathResource;
import org.gcube.informationsystem.publisher.RegistryPublisherFactory;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.smartgears.configuration.Mode;
@ -44,7 +31,6 @@ import org.gcube.smartgears.configuration.application.ApplicationHandlers;
import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder;
import org.gcube.smartgears.configuration.container.ContainerHandlers;
import org.gcube.smartgears.configuration.library.SmartGearsConfiguration;
import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder;
import org.gcube.smartgears.context.Properties;
@ -52,6 +38,7 @@ 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.handlers.container.ContainerHandler;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
import org.gcube.smartgears.security.AuthorizationProvider;
@ -78,7 +65,7 @@ public class DefaultProvider implements Provider {
protected DefaultProvider(File configFile) {
this.configFile = configFile;
}
protected DefaultProvider(){};
@ -87,18 +74,6 @@ public class DefaultProvider implements Provider {
if(containerContext==null){
ContainerConfiguration configuration = containerConfiguration();
/*
if (configuration.persistence()==null) {
String location = Utils.home()+"/state";
File dir = new File(location);
if (!dir.exists())
dir.mkdirs();
configuration.persistence(new LocalPersistence(location));
log.trace("setting persistence location for container @ {}",dir.getAbsolutePath());
}*/
Hub hub = new DefaultHub();
@ -128,17 +103,11 @@ public class DefaultProvider implements Provider {
}
@Override
public ContainerHandlers containerHandlers() {
public List<ContainerHandler> containerHandlers() {
try {
//TODO retrieve handler classes
if (config == null)
throw new IllegalStateException("invalid distribution: cannot find " + container_handlers_file_path);
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
ContainerHandlers defaultHandlers = binder.bindHandlers(config);
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){
@ -146,35 +115,7 @@ public class DefaultProvider implements Provider {
currentClassLoader = currentClassLoader.getParent();
}
try{
if (currentClassLoader instanceof URLClassLoader){
URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ;
if (urls!=null && urls.length>0){
ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet<URL>(Arrays.asList(urls)));
Collection<ClasspathResource> resources = scanner.scan(new NameMatcher(container_handlers_file_name));
for (URL url: urls)
log.trace("URL: "+ url.toString());
if (resources==null || resources.isEmpty())
log.info("no custom container handlers found in the classpath");
for (ClasspathResource res : resources){
try{
ContainerHandlers customHandlers= binder.bindHandlers(res.stream());
defaultHandlers.mergeWith(customHandlers);
log.trace("container hadlers found in {}",res.name());
}catch(Exception e){
log.warn("error loading not default container handlers {}",res.name(),e);
}
}
}
} else log.info("this classloader is not instance of {} : ",URLClassLoader.class.getName(), currentClassLoader.getClass().getName());
}catch(Exception e){
log.warn("cannot load custom handlers for container from the root classloader",e);
}
List<ContainerHandler> defaultHandlers = binder.bindHandlers(currentClassLoader);
return defaultHandlers;
@ -250,15 +191,10 @@ public class DefaultProvider implements Provider {
try {
// it's in a library, using
InputStream defaultHandlersStream = getClass().getResourceAsStream(default_handlers_file_path);
if (defaultHandlersStream == null)
throw new IllegalStateException("invalid distribution: cannot find " + default_handlers_file_path);
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
ApplicationHandlers defaultHandlers = binder.bindHandlers(defaultHandlersStream);
//searching for smartegars related application handlers in the common classloader
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
@ -267,40 +203,8 @@ public class DefaultProvider implements Provider {
currentClassLoader = currentClassLoader.getParent();
}
try{
if (currentClassLoader instanceof URLClassLoader){
URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ;
if (urls!=null && urls.length>0){
ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet<URL>(Arrays.asList(urls)));
Collection<ClasspathResource> resources = scanner.scan(new NameMatcher(application_handlers_file_name));
if (resources==null || resources.isEmpty())
log.info("no custom smartgears related application handlers found in the classpath");
for (ClasspathResource res : resources){
try{
ApplicationHandlers customHandlers= binder.bindHandlers(res.stream());
defaultHandlers.mergeWith(customHandlers);
log.trace("application hadlers found in {}",res.name());
}catch(Exception e){
log.warn("error loading smartgears related application handlers {}",res.name(),e);
}
}
}
}
}catch(Exception e){
log.warn("cannot load smartgears related handlers for application from the root classloader",e);
}
InputStream appSpecificHandlersStream = context.application().getResourceAsStream(handlers_file_path);
if (appSpecificHandlersStream !=null ){
defaultHandlers.mergeWith(binder.bindHandlers(appSpecificHandlersStream));
log.trace("{} uses default lifecycle with app spceific handler as it includes {}", context.name(), handlers_file_path);
} else
log.trace("{} uses the default lifecycle as it does not include {}", context.name(), handlers_file_path);
ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader);
return defaultHandlers;
@ -393,9 +297,9 @@ public class DefaultProvider implements Provider {
private ContainerConfiguration containerConfiguration() {
if (configFile==null) {
String home = Utils.home();
if (home == null)
throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env
+ " or the system property " + ghn_home_property + " must be defined");
@ -407,7 +311,7 @@ public class DefaultProvider implements Provider {
configFile = new File(homeDir,container_configuraton_file_path);
log.trace("reading container configuration @ {} ", configFile.getAbsolutePath());
}
@ -416,11 +320,11 @@ public class DefaultProvider implements Provider {
ContainerConfiguration configuration;
try (InputStream stream = new FileInputStream(configFile)){
configuration= ContainerConfiguration.load(stream);
configuration= new ContainerConfigurationBinder().load(stream);
}catch (Exception e) {
throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid");
throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid", e);
}
return configuration;
}

@ -1,14 +1,16 @@
package org.gcube.smartgears.provider;
import java.util.List;
import javax.servlet.ServletContext;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.smartgears.configuration.application.ApplicationExtensions;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
import org.gcube.smartgears.configuration.container.ContainerHandlers;
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.handlers.container.ContainerHandler;
import org.gcube.smartgears.security.AuthorizationProvider;
/**
@ -37,7 +39,7 @@ public interface Provider {
* Returns the handlers associated with the container.
* @return the handlers
*/
ContainerHandlers containerHandlers();
List<ContainerHandler> containerHandlers();
/**

@ -4,7 +4,5 @@ import java.util.Set;
public interface AuthorizationProvider {
void connect(Credentials credentials) throws Exception;
Set<String> getAllowedContexts();
}

@ -0,0 +1,7 @@
package org.gcube.smartgears.security;
public interface AuthorizationProviderFactory<T extends AuthorizationProvider> {
T connect(Credentials credentials);
}

@ -10,6 +10,9 @@ public class SimpleCredentials implements Credentials{
@NotNull @NotEmpty
String secret;
@NotNull @NotEmpty
String endpoint;
public String getClientID() {
return clientID;
@ -17,6 +20,14 @@ public class SimpleCredentials implements Credentials{
public void setClientID(String clientID) {
this.clientID = clientID;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getSecret() {

@ -1,5 +1,6 @@
package org.gcube.smartgears.security;
package org.gcube.smartgears.security.defaults;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
@ -11,6 +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.scope.impl.ScopeBean;
import org.gcube.smartgears.security.AuthorizationProvider;
import org.gcube.smartgears.security.SimpleCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,20 +21,20 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider {
private static Logger LOG = LoggerFactory.getLogger(DefaultAuthorizationProvider.class);
private SimpleCredentials credentials;
private KeycloakClient client = KeycloakClientFactory.newInstance();
@Override
public void connect(Credentials credentials) {
this.credentials = (SimpleCredentials)credentials;
private SimpleCredentials credentials;
public DefaultAuthorizationProvider(SimpleCredentials credentials) {
this.credentials = credentials;
}
@Override
public Set<String> getAllowedContexts() {
Set<String> contexts = new HashSet<String>();
try {
TokenResponse response = client.queryOIDCToken(credentials.getClientID(), credentials.getSecret());
TokenResponse response = client.queryOIDCToken(new URL(credentials.getEndpoint()), credentials.getClientID(), credentials.getSecret());
Map<String, Access> resourceAccess = ModelUtils.getAccessTokenFrom(response).getResourceAccess();
for (String context : resourceAccess.keySet()) {
try {

@ -0,0 +1,17 @@
package org.gcube.smartgears.security.defaults;
import org.gcube.smartgears.security.AuthorizationProviderFactory;
import org.gcube.smartgears.security.Credentials;
import org.gcube.smartgears.security.SimpleCredentials;
public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory<DefaultAuthorizationProvider>{
@Override
public DefaultAuthorizationProvider connect(Credentials credentials) {
if (!SimpleCredentials.class.isInstance(credentials))
throw new IllegalArgumentException("invalid credential type passed");
return new DefaultAuthorizationProvider((SimpleCredentials)credentials);
}
}

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<handlers>
<accounting-management />
<profile-management />
</handlers>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<handlers>
<lifecycle>
<profile-management />
</lifecycle>
<request>
<request-validation />
<request-accounting />
</request>
</handlers>

@ -1,4 +0,0 @@
org.gcube.smartgears.handlers.application.lifecycle.ProfileManager
org.gcube.smartgears.handlers.application.request.RequestValidator
org.gcube.smartgears.handlers.application.request.RequestAccounting
org.gcube.smartgears.handlers.application.request.RequestContextRetriever

@ -1,2 +0,0 @@
org.gcube.smartgears.handlers.container.lifecycle.ProfileManager
org.gcube.smartgears.handlers.container.lifecycle.AccountingManager

@ -1,187 +0,0 @@
package app;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.smartgears.extensions.HttpExtension.Method;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.logging.LoggingFeature;
import utils.TestUtils;
public class Request {
private String path="";
private String scope = TestUtils.scope;
//private OutBoundHeaders headers = new OutBoundHeaders();
private String method = HttpMethod.GET;
private String body = null;
private boolean logged = false;
Map<String, List<Object>> headers = new HashMap<>();
public static Request request() {
return new Request();
}
private Request() {
}
public Request at(String path) {
this.path=path;
return this;
}
public Request logging() {
logged=true;
return this;
}
public Request inScope(String scope) {
this.scope=scope;
return this;
}
public Request with(String body) {
this.body=body;
return this;
}
public Request with(String name, String value) {
this.headers.put(name, Collections.singletonList(value));
return this;
}
public Request using(Method method) {
this.method=method.getValue();
return this;
}
public String path() {
return path;
}
public String body() {
return body;
}
public String method() {
return method;
}
public String scope() {
return scope;
}
ClientResponse make(final int port) {
// we make a scoped call in a separate thread, with which we then synchronize for completion.
// this helps isolate the caller's thread (Main normally) from the app's thread,
// starting with the scope itself.
final CountDownLatch latch = new CountDownLatch(1);
class Box {
volatile WebApplicationException failure;
volatile ClientResponse response;
}
final Box box = new Box();
new Thread() {
public void run() {
AuthorizationProvider.instance.set(new Caller(new UserInfo("test", new ArrayList<String>()),"DEFAULT"));
try {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient();
if (logged)
client.register(new LoggingFeature(Logger.getLogger(getClass().getName())));
Builder builder = client.target(address(path,port)).request();
builder.header("gcube-scope", scope);
for (Entry<String,List<Object>> header : headers.entrySet())
for (Object value : header.getValue())
builder.header(header.getKey(), value);
if (method.equals(HttpMethod.DELETE))
builder.delete();
else {
System.err.println("making request @ "+address(path,port));
ClientResponse response = builder.method(method,ClientResponse.class);
//throws an exception if there response has error status
if (response.getStatus()>300)
throw new WebApplicationException(response.getStatus());
box.response=response;
}
} catch (WebApplicationException t) {
box.failure=t;
}
latch.countDown();
};
}.start();
try {
if (!latch.await(2000, TimeUnit.MILLISECONDS))
throw new RuntimeException("application has not responded in time");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (box.failure !=null)
throw box.failure;
else
return box.response;
}
private String address(String path, long port) {
path = (path.isEmpty() || path.startsWith("/"))?path:"/"+path;
return "http://localhost:" + port+ "/" + TestUtils.context_root+path;
}
}

@ -1,437 +0,0 @@
package app;
import static org.gcube.smartgears.Constants.configuration_file_path;
import static org.gcube.smartgears.Constants.extensions_file_path;
import static org.gcube.smartgears.Constants.ghn_home_property;
import static org.gcube.smartgears.Constants.handlers_file_path;
import static utils.TestUtils.context_root;
import static utils.TestUtils.context_root_path;
import static utils.TestUtils.location;
import static utils.TestUtils.servlet_name;
import java.io.File;
import java.io.InputStream;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.smartgears.Constants;
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.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.managers.ContainerManager;
import org.gcube.smartgears.provider.ProviderFactory;
import org.glassfish.jersey.client.ClientResponse;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.impl.base.path.BasicPath;
import utils.TestProvider;
import utils.TestUtils;
/**
* Simulates a single-servlet application to be transformed into a gCube resource.
* <p>
* <ul>
* <li>uses a default configuration that can be customised (cf. {@link #configuration()});
* <li>can be configured with the default handlers (cf. {@link #useDefaultHandlers()}) or custom ones (
* {@link #handlers()}), including those that are not deployable through standard means, such as mocks (
* {@link #bypassHandlerDeployment()};
* <li>can be started to have a default behaviour when called, ({@link #start()}) or else a custom behaviour (
* {@link #startWith(Runnable)};
* </ul>
* can be called in a default scope ({@link #call()} or in a specific scope ({@link #callIn(String)}). Calls are blocking but always
* configured and executed in a separate thread;
*
* @author Fabio Simeoni
*
*/
public class SomeApp {
private final Tomcat tomcat = new Tomcat();
private WebArchive war = defaultWar();
private ContainerConfiguration containerConfiguration;
private ApplicationConfiguration configuration;
private ApplicationHandlers handlers = new ApplicationHandlers();
private ApplicationExtensions extensions = new ApplicationExtensions();
private TestProvider provider = new TestProvider(new File("src/test/resources/test-configuration.ini"));
private boolean deployHandlers = true;
private boolean deployExtensions = true;
private boolean deployConfiguration = true;
private boolean clean=true;
public SomeApp() {
if (ContainerManager.instance!=null)
ContainerManager.instance.stop(true);
tomcat.getConnector().setPort(0);
tomcat.setBaseDir(location);
System.setProperty(ghn_home_property,location);
containerConfiguration = defaultContainerConfiguration();
configuration = defaultConfiguration();
}
/**
* Sets a {@link TestProvider} to resolve dependencies at runtime.
*
* @param provider the provider
*/
public void set(TestProvider provider) {
this.provider = provider;
}
/**
* Runs the test with the state left by previous run.
* <p>
* Use only within a single test!
*/
public void dirtyRun() {
this.clean = false;
}
/**
* Returns the configuration of the application.
* <p>
* The initial configuration is based on defaults, but can be changed and extended.
*
* @return the configuration
*/
public ApplicationConfiguration configuration() {
return configuration;
}
/**
* Returns the configuration of the containerConfiguration.
* <p>
* The initial configuration is based on defaults, but can be changed and extended.
*
* @return the configuration
*/
public ContainerConfiguration containerConfiguration() {
return containerConfiguration;
}
/**
* Returns the handlers that manage the application, none by default.
*
* @return the handlers
*/
public ApplicationHandlers handlers() {
return handlers;
}
/**
* Avoids deployment of the configured handlers in the application's WAR.
* <p>
* The handlers will instead be directly available at runtime.
*/
public void bypassHandlerDeployment() {
provider.use(handlers());
deployHandlers = false;
}
/**
* Avoids resource configuration deployment.
*/
public void asExternal() {
configuration.context(context_root_path);
containerConfiguration.app(configuration);
bypassConfigurationDeployment();
bypassExtensionsDeployment();
bypassHandlerDeployment();
}
/**
* Avoids resource configuration deployment.
*/
public void withExternal(ApplicationConfiguration config) {
config.context(context_root_path);
containerConfiguration.app(config.context()).merge(config);
}
public void bypassConfigurationDeployment() {
deployConfiguration = false;
}
public void usePublisher(ScopedPublisher publisher) {
provider.use(publisher);
}
/**
* Uses default handlers.
*/
public void useDefaultHandlers() {
deployHandlers = false;
}
/**
* Returns the extensions of the application, none by default.
*
* @return the handlers
*/
public ApplicationExtensions extensions() {
return extensions;
}
/**
* Uses default extensions.
*/
public void useDefaultExtensions() {
deployExtensions = false;
}
/**
* Avoids deployment of the configured extensions in the application's WAR.
* <p>
* The extensions will instead be directly available at runtime.
*/
public void bypassExtensionsDeployment() {
provider.use(extensions());
deployExtensions = false;
}
/**
* Starts the application.
*
* @return the context of the application
*/
public ApplicationContext start() {
return startWith(new Runnable() {
@Override
public void run() {
System.err.println("test servlet invoked with no particular task");
}
});
}
/**
* Starts the application, injecting test logic in its single servlet
*
* @param test test logic
* @return the context of the application
*/
public ApplicationContext startWith(Runnable test) {
// install provider
ProviderFactory.testProvider(provider);
if (clean)
cleanupInstallation();
if (deployConfiguration)
deployConfiguration();
if (deployHandlers)
deployHandlers();
if (deployExtensions)
deployExtensions();
try {
System.err.println("deploying with " + war.toString(true));
StandardContext ctx = (StandardContext) tomcat.addWebapp(context_root_path, warFile().getAbsolutePath());
// tells tomcat to look also for exploded directories such as this project's (finds initializer)
((StandardJarScanner) ctx.getJarScanner()).setScanAllDirectories(true);
//this starts webapp and always comes back
tomcat.start();
ApplicationContext context = provider.context;
if (context==null)
throw new RuntimeException("app failed @ startup");
Wrapper webapp = (Wrapper) tomcat.getHost().findChild(context_root_path).findChild(servlet_name);
if (webapp!=null) {
webapp.setServlet(new TestServlet(test));
//context.container().configuration().port(port());
containerConfiguration = context.container().configuration();
}
return context;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Retuens <code>true</code> if the application was successfully start in the container.
*
* @return <code>true</code> if the application was successfully start in the container
*/
public boolean isActive() {
return tomcat.getHost().findChild("/" + context_root).findChild(servlet_name) != null;
}
/**
* Makes a request to the application.
*/
public String send(Request call) {
return (String) call.make(port()).getEntity();
}
/**
* Makes a request to the application.
*/
public ClientResponse httpSend(Request call) {
return call.make(port());
}
/**
* Stops the application
*/
public void stop() {
try {
tomcat.stop();
tomcat.destroy();
} catch (Exception e) {
System.err.println("WARNING: could not clearly stop container:");
e.printStackTrace();
}
}
public File containerConfigurationFile() {
return new File(location,Constants.container_configuraton_file_path);
}
// helpers
/**
* Includes the configuration in the application's WAR.
*/
private void deployConfiguration() {
String xml = TestUtils.bind(configuration());
System.err.println("deploying with configuration:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(configuration_file_path));
}
/**
* Includes the handlers in the application's WAR.
*/
private void deployHandlers() {
String xml = TestUtils.bind(handlers());
System.err.println("deploying with handlers:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(handlers_file_path));
}
/**
* Includes the extensions in the application's WAR.
*/
private void deployExtensions() {
String xml = TestUtils.bind(extensions());
System.err.println("deploying with extensions:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(extensions_file_path));
}
private File warFile() {
File warFile = new File(location, "test.war");
if (warFile.exists() && !warFile.delete())
System.out.println("could not delete old deployment");; // seems safer than plain overwrite to avoid war corruption
war.as(ZipExporter.class).exportTo(warFile, true);
return warFile;
}
private WebArchive defaultWar() {
WebArchive war = ShrinkWrap.create(WebArchive.class);
war.setWebXML(new File("src/test/java/app/web.xml"));
return war;
}
private ApplicationConfiguration defaultConfiguration() {
return new DefaultApplicationConfiguration().serviceClass("test-class").name("test-app").version("1.0");
}
private ContainerConfiguration defaultContainerConfiguration() {
InputStream is = SomeApp.class.getResourceAsStream("/test-configuration.ini");
return ContainerConfiguration.load(is);
}
public int port() {
return tomcat.getConnector().getLocalPort();
}
private void cleanupInstallation() {
System.out.println("cleaning installation in location "+location);
File installation = new File(location);
if (installation.exists())
try {
FileUtils.deleteDirectory(installation);
}
catch(Exception e) {
throw new RuntimeException(e);
}
installation.mkdirs();
}
}

@ -1,30 +0,0 @@
package app;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "test", urlPatterns = "/test")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Runnable test;
public TestServlet(Runnable test) {
this.test=test;
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
test.run();
}
}

@ -1,15 +0,0 @@
<web-app>
<display-name>test-app</display-name>
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>app.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

@ -0,0 +1,20 @@
package test;
import java.io.InputStream;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder;
import org.junit.Test;
public class BinderTest {
@Test
public void bindConfig() throws Exception {
InputStream stream = BinderTest.class.getResourceAsStream("/container.ini");
ContainerConfiguration conf = new ContainerConfigurationBinder().load(stream);
System.out.println(conf.toString());
}
}

@ -1,36 +0,0 @@
package test.application;
import static org.junit.Assert.*;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager;
import org.gcube.smartgears.lifecycle.application.ApplicationState;
import org.gcube.smartgears.lifecycle.container.ContainerState;
import org.junit.Test;
import app.SomeApp;
public class AppLifecycleTest {
@Test
public void applicationGoesDownIfContainerDoes() {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager());
ApplicationContext actx = app.start();
assertEquals(ApplicationState.active,actx.lifecycle().state());
ContainerContext ctx = actx.container();
assertEquals(ContainerState.active,ctx.lifecycle().state());
ctx.lifecycle().moveTo(ContainerState.stopped);
assertEquals(ApplicationState.stopped,actx.lifecycle().state());
}
}

@ -1,214 +0,0 @@
package test.application;
import static app.Request.request;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.fail;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.request_not_authorized_error;
import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed;
import static org.gcube.smartgears.lifecycle.application.ApplicationState.stopped;
import static utils.TestUtils.scope;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.WebApplicationException;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.application.Exclude;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager;
import org.gcube.smartgears.handlers.application.request.RequestValidator;
import org.junit.Test;
import app.SomeApp;
public class CallValidationTest {
@Test
public void rejectsCallsWhenServiceIsInactive() {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager()).set(new RequestValidator());
Runnable test = new Runnable() {
@Override
public void run() {
fail("call should have been rejected");
}
};
ApplicationContext context = app.startWith(test);
context.lifecycle().moveTo(stopped);
try {
app.send(request());
}
catch(WebApplicationException e) {
assertEquals(application_unavailable_error.code(), e.getResponse().getStatus());
}
context.lifecycle().moveTo(failed);
try {
app.send(request());
}
catch(WebApplicationException e) {
assertEquals(application_failed_error.code(), e.getResponse().getStatus());
}
}
@Test
public void rejectsCallsWithoutScope() throws Throwable {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager()).set(new RequestValidator());
app.start();
try {
app.send(request().inScope(null));; //call in no scope
fail();
}
catch(WebApplicationException e) {
assertEquals(request_not_authorized_error.code(), e.getResponse().getStatus());
}
}
@Test
public void rejectsCallsWithBadScope() throws Throwable {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager()).set(new RequestValidator());
app.start();
try {
app.send(request().inScope("/bad/scope")); //call in no scope
fail();
}
catch(WebApplicationException e) {
assertEquals(invalid_request_error.code(), e.getResponse().getStatus());
}
}
@Test
public void propagatesScope() throws Throwable {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager()).set(new RequestValidator());
Runnable test = new Runnable() {
@Override
public void run() {
assertEquals(scope,SecurityTokenProvider.instance.get());
}
};
app.startWith(test);
app.send(request());
}
@Test
public void respectsAllExcludeWildCard() throws Throwable {
SomeApp app = new SomeApp();
app.configuration().excludes().add(new Exclude(Constants.WILDCARD));
app.handlers().set(new ProfileManager()).set(new RequestValidator());
final CountDownLatch latch = new CountDownLatch(1);
Runnable test = new Runnable() {
@Override
public void run() {
latch.countDown();
}
};
app.startWith(test);
app.send(request().inScope(null));
latch.await(500,TimeUnit.MILLISECONDS);
}
@Test
public void respectsExcludeWildCard() throws Throwable {
SomeApp app = new SomeApp();
app.configuration().excludes().add(new Exclude("/path"+Constants.WILDCARD));
app.handlers().set(new ProfileManager()).set(new RequestValidator());
final CountDownLatch latch = new CountDownLatch(1);
Runnable test = new Runnable() {
@Override
public void run() {
latch.countDown();
}
};
app.startWith(test);
app.send(request().at("path/test").inScope(null));
latch.await(500,TimeUnit.MILLISECONDS);
}
@Test
public void respectsExactExclude() throws Throwable {
SomeApp app = new SomeApp();
app.configuration().excludes().add(new Exclude("/path"));
app.handlers().set(new ProfileManager()).set(new RequestValidator());
final CountDownLatch latch = new CountDownLatch(1);
Runnable test = new Runnable() {
@Override
public void run() {
latch.countDown();
}
};
app.startWith(test);
app.send(request().at("path").inScope(null));
latch.await(500,TimeUnit.MILLISECONDS);
}
}

@ -1,112 +0,0 @@
package test.application;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
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.DefaultApplicationConfiguration;
import org.gcube.smartgears.configuration.application.Include;
import org.gcube.smartgears.extensions.ApplicationExtension;
import org.gcube.smartgears.persistence.LocalPersistence;
import org.junit.Test;
public class ConfigurationTest {
@Test
public void configurationBinds() throws Exception {
String xml = "<application mode='offline' context='ctx' isSecure='true'>" +
"<name>name</name>" +
"<group>class</group>" +
"<version>version</version>" +
"<description>desc</description>" +
"<scope>start/scope</scope>"+
"<scope>another/start/scope</scope>"+
"<include>/pathBis</include>" +
"<persistence location='target'/>" +
"</application>";
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
ApplicationConfiguration bound = binder.bind(new ByteArrayInputStream(xml.getBytes()));
System.out.println(bound);
assertEquals(sampleConfiguration(),bound);
}
@Test
public void extensionsBind() throws Exception {
String xml = "<extensions>" +
"<remote-management name='custom' mapping='custom' />" +
"</extensions>";
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
ApplicationExtensions bound = binder.bindExtensions(new ByteArrayInputStream(xml.getBytes()));
assertNotNull(bound.extensions());
assertEquals(1,bound.extensions().size());
ApplicationExtension ext = bound.extensions().get(0);
assertEquals("custom",ext.name());
assertEquals("custom",ext.mapping());
}
/*@Test
public void configurationsMerge() throws Exception {
ApplicationConfiguration original = sampleConfiguration();
ApplicationConfiguration one = sampleConfiguration();
ApplicationConfiguration two = new DefaultApplicationConfiguration();
two.mode(Mode.online);
two.persistence(new DefaultPersistence(new File(".").getAbsolutePath()));
two.startScopes("yet/another/one");
one.merge(two);
assertEquals(one.mode(), two.mode());
assertEquals(one.name(), original.name());
assertEquals(one.persistence(), two.persistence());
Set<String> merged = new HashSet<>(original.startScopes());
merged.addAll(two.startScopes());
assertEquals(merged,one.startScopes());
}*/
//helpers
private ApplicationConfiguration sampleConfiguration() {
return new DefaultApplicationConfiguration()
.context("ctx")
.name("name")
.serviceClass("class")
.includes(new Include("/pathBis"))
.version("version")
.description("desc")
.persistence(new LocalPersistence("target"));
}
}

@ -1,288 +0,0 @@
package test.application;
import static app.Request.request;
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.extensions.ApiResource.handles;
import static org.gcube.smartgears.extensions.ApiResource.method;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import static org.gcube.smartgears.extensions.HttpExtension.Method.POST;
import static org.gcube.smartgears.extensions.HttpExtension.Method.PUT;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.WebApplicationException;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.extensions.ApiResource;
import org.gcube.smartgears.extensions.ApiSignature;
import org.gcube.smartgears.extensions.HttpController;
import org.gcube.smartgears.extensions.HttpExtension;
import org.glassfish.jersey.client.ClientResponse;
import org.junit.Test;
import app.Request;
import app.SomeApp;
public class ControllerTest {
String name = "name";
String extension_path = "/ext";
String extension_mapping = "/ext/*";
String resource_path = "/resource";
@Test
public void dispatchesToResource() {
// returns a given type
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain"));
// requires same type
Request request = request().at(resource()).with(accept, "text/plain");
SomeApp app = startAppWith(signature);
app.send(request);
}
@Test
public void toleratesTrainingSlashes() {
// returns a given type
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain"));
// requires same type
Request request = request().at(resource()).with(accept, "text/plain");
SomeApp app = startAppWith(signature);
app.send(request);
}
@Test
public void handlesUnknownResources() {
ApiSignature signature = handles(resource_path);
// points to not existing resource
Request request = request().at(resource() + "/bad");
SomeApp app = startAppWith(signature);
try {
app.send(request);
fail();
} catch (WebApplicationException e) {
assertEquals(resource_notfound_error.code(), e.getResponse().getStatus());
}
}
@Test
public void handlesUnsupportedMethods() {
ApiSignature signature = handles(resource_path).with(method(GET)).with(method(PUT));
Request request = request().at(resource()).using(POST);
SomeApp app = startAppWith(signature);
try {
app.send(request);
fail();
} catch (WebApplicationException e) {
assertEquals(method_unsupported_error.code(), e.getResponse().getStatus());
assertNotNull(e.getResponse().getHeaders().toString(),e.getResponse().getHeaders().get(allow));
}
}
@Test
public void enforcesAcceptHeaders() {
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain"));
Request request = request().at(resource()).with(accept, "text/xml");
SomeApp app = startAppWith(signature);
try {
app.send(request);
fail();
} catch (WebApplicationException e) {
assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus());
}
}
@Test
public void enforcesAcceptHeadersEvenWhenResourceDeclaresNone() {
ApiSignature signature = handles(resource_path).with(method(GET));
Request request = request().at(resource()).with(accept, "text/xml");
SomeApp app = startAppWith(signature);
try {
app.send(request);
fail();
} catch (WebApplicationException e) {
assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus());
}
}
@Test
public void enforcesMultiValuedAcceptHeader() {
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain"));
Request request = request().at(resource()).with(accept, "text/xml").with(accept,"text/plain");
SomeApp app = startAppWith(signature);
app.send(request);
}
@Test
public void setsContentTypeIfUnsetAndUnambiguous() {
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain"));
Request request = request().at(resource()).with(accept, "text/plain");
SomeApp app = startAppWith(signature);
ClientResponse response = app.httpSend(request);
assertTrue(response.getHeaders().get(content_type).get(0).contains("text/plain"));
}
@Test
public void doesntSetContentTypeIfUnsetButAmbiguous() {
ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain","text/xml"));
Request request = request().at(resource()).with(accept, "text/plain");
SomeApp app = startAppWith(signature);
ClientResponse response = app.httpSend(request);
System.out.println(response.getHeaders());
assertNull(response.getHeaders().get(content_type));
}
@Test
public void enforcesMultiValuedContentTypeHeader() {
ApiSignature signature = handles(resource_path).with(method(POST).accepts("application/xml"));
Request request = request().at(resource()).using(POST).with(content_type, "text/xml").with(content_type,"text/plain");
SomeApp app = startAppWith(signature);
try {
app.send(request);
fail();
} catch (WebApplicationException e) {
assertEquals(incoming_contenttype_unsupported_error.code(), e.getResponse().getStatus());
}
}
@Test
public void acceptsContentTypeHeadersWhenResourceDeclaresNone() {
ApiSignature signature = handles(resource_path).with(method(POST));
Request request = request().at(resource()).using(POST).with(content_type, "text/xml");
SomeApp app = startAppWith(signature);
app.httpSend(request);
}
///////////////////////////////// helpers
private String resource() {
return Constants.root_mapping + extension_path + resource_path;
}
SomeApp startAppWith(ApiSignature signature) {
SomeApp app = new SomeApp();
app.extensions().set(controllerWith(signature));
app.bypassExtensionsDeployment();
app.bypassHandlerDeployment();
app.start();
return app;
}
@SuppressWarnings("serial")
HttpExtension controllerWith(final ApiSignature signature) {
return new HttpController(name, extension_mapping) {
{
addResources(new ApiResource(signature) {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
if (!supports(Method.valueOf(req.getMethod())))
super.doGet(req, resp);
else
resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping());
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
if (!supports(Method.valueOf(req.getMethod())))
super.doPost(req, resp);
else
resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping());
}
@Override
public void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
if (!supports(Method.valueOf(req.getMethod())))
super.doPut(req, resp);
else
resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping());
}
});
}
@Override
public String toString() {
return "SUT controller";
}
};
}
}

@ -1,184 +0,0 @@
package test.application;
import static app.Request.request;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.extensions.ApplicationExtension;
import org.gcube.smartgears.extensions.HttpExtension;
import org.gcube.smartgears.extensions.resource.RemoteResource;
import org.gcube.smartgears.handlers.application.request.RequestError;
import org.junit.Test;
import app.SomeApp;
public class ExtensionsTest {
String name = "name";
String extension_path="/ext";
@Test
public void areInstalledAndInitialised() {
final String response = "output";
@SuppressWarnings("serial")
ApplicationExtension extension = new HttpExtension(name,extension_path) {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
assertNotNull(context()); //init has been invoked
res.getWriter().write(response);
}
};
SomeApp app = new SomeApp();
app.extensions().set(extension);
//we're only testing correct installation, not configuration now anything else
app.bypassExtensionsDeployment();
app.start();
String actual = app.send(request().at(Constants.root_mapping+extension_path));
assertEquals(response,actual);
}
@SuppressWarnings("serial")
@XmlRootElement(name="unknown")
static class UnknownExtension extends HttpExtension {
UnknownExtension() {}
public UnknownExtension(String name, String mapping) {
super(name, mapping);
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
}
}
@Test
public void failAppIfNotConfigured() {
SomeApp app = new SomeApp();
app.bypassHandlerDeployment();
app.extensions().set(new UnknownExtension(name,extension_path));
ApplicationContext context= app.start();
assertEquals(failed,context.lifecycle().state());
}
@Test
public void failAppIfConfiguredBadly() {
SomeApp app = new SomeApp();
RemoteResource extension = new RemoteResource();
extension.name("");
extension.mapping("");
app.extensions().set(extension);
app.bypassHandlerDeployment();
ApplicationContext context= app.start();
assertEquals(failed,context.lifecycle().state());
}
@Test
public void throwErrorsConvertedInHttpResponses() {
final RequestError error = invalid_request_error;
@SuppressWarnings("serial")
ApplicationExtension extension = new HttpExtension(name,extension_path) {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
error.fire();
}
};
SomeApp app = new SomeApp();
app.extensions().set(extension);
//we're only testing correct installation, not configuration now anything else
app.bypassExtensionsDeployment();
app.start();
try {
app.send(request().at(Constants.root_mapping+extension_path));
fail();
}
catch(WebApplicationException e) {
assertEquals(error.code(),e.getResponse().getStatus());
}
}
@Test
public void areManagedLikeNativeServlets() {
@SuppressWarnings("serial")
ApplicationExtension extension = new HttpExtension(name,extension_path) {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
}
};
SomeApp app = new SomeApp();
app.extensions().set(extension);
app.bypassExtensionsDeployment();
//installs default filters
app.useDefaultHandlers();
app.start();
//call in no scope
try {
app.send(request().at(Constants.root_mapping+extension_path).inScope(null));
fail();
}
catch(WebApplicationException e) {
assertEquals((String)e.getResponse().getEntity(),invalid_request_error.code(),e.getResponse().getStatus());
}
}
}

@ -1,74 +0,0 @@
package test.application;
import static junit.framework.Assert.*;
import static org.gcube.smartgears.Constants.*;
import java.io.File;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.resources.gcore.Resources;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
import org.junit.BeforeClass;
import org.junit.Test;
import app.SomeApp;
public class ProfileManagementTest {
public static ApplicationContext ctx;
@BeforeClass
public static void startApp() {
SomeApp app = new SomeApp();
app.handlers().set(new ProfileManager());
ctx = app.start();
}
@Test
public void createsStoresAndPublishesAValidProfile() throws Exception {
GCoreEndpoint profile = ctx.profile();
assertNotNull(profile);
//assert profile has been created
File file = ctx.configuration().persistence().file(profile_file_path);
assertTrue(file.exists());
assertFalse(profile.scopes().isEmpty());
Resources.validate(profile);
//assert status matches lifecycle's current state
ApplicationLifecycle lc = ctx.lifecycle();
assertEquals(profile.profile().deploymentData().status(),lc.state().remoteForm());
}
@Test
public void loadsAndUpdatesProfile() throws Exception {
SomeApp runtwice = new SomeApp();
runtwice.handlers().set(new ProfileManager());
runtwice.dirtyRun();
ApplicationContext ctx = runtwice.start();
GCoreEndpoint profile = ctx.profile();
assertNotNull(profile);
Resources.validate(profile);
}
}

@ -1,129 +0,0 @@
package test.application;
import static app.Request.request;
import static org.gcube.smartgears.Constants.application_xml;
import static org.gcube.smartgears.Constants.content_type;
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
import static org.gcube.smartgears.extensions.HttpExtension.Method.POST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.resources.gcore.Resources;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.extensions.resource.ConfigurationResource;
import org.gcube.smartgears.extensions.resource.FrontPageResource;
import org.gcube.smartgears.extensions.resource.LifecycleResource;
import org.gcube.smartgears.extensions.resource.LifecycleResource.State;
import org.gcube.smartgears.extensions.resource.ProfileResource;
import org.gcube.smartgears.lifecycle.application.ApplicationState;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import app.Request;
import app.SomeApp;
public class RemoteResourceTest {
static final String path = "/resource";
static JAXBContext jaxb;
static ApplicationContext context;
static SomeApp app;
@BeforeClass
public static void setup() throws Exception {
jaxb = JAXBContext.newInstance(State.class);
app = new SomeApp();
app.useDefaultHandlers();
app.useDefaultExtensions();
context = app.start();
}
@Test
public void showsFrontpage() throws Exception {
// unscoped request
Request request = request().at(resource(FrontPageResource.mapping)).inScope(null);
app.send(request);
//Thread.sleep(50000); enable to check interactively in browser
}
@Test
public void showsConfiguration() throws Exception {
//unscoped request
Request request = request().at(resource(ConfigurationResource.mapping)).inScope(null);
app.send(request);
}
@Test
public void showsProfile() throws Exception {
//unscoped request
Request request = request().at(resource(ProfileResource.mapping)).inScope(null);
String outcome = app.send(request);
GCoreEndpoint profile = Resources.unmarshal(GCoreEndpoint.class, new StringReader(outcome));
assertEquals(context.profile().id(), profile.id());
assertEquals(context.profile().profile().deploymentData().status(), profile.profile().deploymentData().status());
}
@Test
public void currentState() throws Exception {
Request request = request().at(resource(LifecycleResource.mapping)).using(GET).inScope(null);
String outcome = app.send(request);
State state = (State) jaxb.createUnmarshaller().unmarshal(new StringReader(outcome));
assertEquals(context.lifecycle().state(),ApplicationState.valueOf(state.value));
}
@Ignore
@Test
public void changeState() throws Exception {
ApplicationState newstate = ApplicationState.stopped;
assertFalse(context.lifecycle().state()==newstate);
Request request = request().at(resource(LifecycleResource.mapping)).using(POST).inScope(null)
.with(content_type, application_xml).with("<state>stopped</state>");
app.httpSend(request);
assertTrue(context.lifecycle().state()==newstate);
request = request().at(resource(LifecycleResource.mapping)).using(POST).inScope(null)
.with(content_type, application_xml).with("<state>active</state>");
}
// helper
private String resource(String resource) {
return Constants.root_mapping + path + resource;
}
}

@ -1,231 +0,0 @@
package test.application;
import static app.Request.request;
import static org.gcube.smartgears.Constants.profile_file_path;
import static org.gcube.smartgears.lifecycle.application.ApplicationState.active;
import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import org.gcube.common.resources.gcore.Resource;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.informationsystem.publisher.exception.RegistryNotFoundException;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.ApplicationEvent;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent.Start;
import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.persistence.LocalPersistence;
import org.junit.After;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import app.SomeApp;
import utils.TestUtils.Box;
public class StartupTest {
SomeApp app = new SomeApp();
@After
public void teardown() {
app.stop();
}
@Test
public void succeedsWithDefaults() throws Exception {
app.useDefaultHandlers();
app.useDefaultExtensions();
ApplicationContext ctx = app.start();
assertEquals(active,ctx.lifecycle().state());
//profile is shared in servlet context
assertEquals(ctx,ctx.application().getAttribute(Constants.context_attribute));
}
@Test
public void stillStoresProfileWhenPublicationFails() throws Exception {
app.useDefaultHandlers();
ScopedPublisher failingPublisher = Mockito.mock(ScopedPublisher.class);
when(failingPublisher.create(any(Resource.class), Matchers.anyListOf(String.class))).thenThrow(new RegistryNotFoundException());
app.usePublisher(failingPublisher);
ApplicationContext ctx = app.start();
Thread.sleep(100); //a little bit of time for failure to propagate
//application has failed
assertEquals(failed,ctx.lifecycle().state());
//profile has been created
File file = ctx.configuration().persistence().file(profile_file_path);
assertTrue(file.exists());
}
@Test
@SuppressWarnings("all")
public void invokesLifecycleHandlers() {
ApplicationLifecycleHandler witness = mock(ApplicationLifecycleHandler.class);
app.handlers().set(witness);
//as we're using mocks, let us bypass JAXB configuration mechanisms
app.bypassHandlerDeployment();
app.start();
verify(witness).onEvent(any(ApplicationEvent.class));
}
@Test
@SuppressWarnings("all")
public void registersRequestsHandlers() {
Box<Boolean> handlerIsInvoked = new Box<Boolean>();
RequestHandler witness = mock(RequestHandler.class);
app.handlers().set(witness);
app.bypassHandlerDeployment();
app.start();
app.send(request());
//invoked for request and response
verify(witness,times(2)).onEvent(isA(ApplicationEvent.class));
}
//@Ignore //inexplicable sometimes fails as configuration is not removed
@Test
public void failsIfConfigurationIsInvalid() {
app.configuration().name(null).serviceClass(null).description(null).version(null).persistence(null);
ApplicationContext ctx = app.start();
assertEquals(failed,ctx.lifecycle().state());
}
@Test
public void failsIfHandlerFails() throws Throwable {
ApplicationLifecycleHandler failingHandler = mock(ApplicationLifecycleHandler.class);
doThrow(new RuntimeException("simulated handler failure")).when(failingHandler).onEvent(isA(Start.class));
app.handlers().set(failingHandler);
app.bypassHandlerDeployment();
ApplicationContext ctx = app.start();
assertEquals(failed,ctx.lifecycle().state());
}
@Test
public void canUseExternalConfiguration() {
app.asExternal();
app.start();
assertTrue(app.isActive());
}
@Test
public void canUseMergedConfiguration() {
ApplicationConfiguration config = new DefaultApplicationConfiguration();
config.persistence(new LocalPersistence(new File(".").getAbsolutePath()));
ApplicationContext context = app.start();
assertTrue(app.isActive());
app.withExternal(config);
assertEquals(config.persistence(),context.configuration().persistence());
}
@Test
public void failsIfAllStartScopesAreInvalid() throws Exception {
ApplicationConfiguration config = new DefaultApplicationConfiguration();
//config.startScopes("bad/scope","even/badder");
app.useDefaultHandlers();
ApplicationContext context = app.start();
app.withExternal(config);
assertEquals(failed,context.lifecycle().state());
}
@Test
public void canStartInVreScope() throws Exception {
ApplicationConfiguration config = new DefaultApplicationConfiguration();
//tring vre = "/"+app.containerConfiguration().infrastructure()+"/"+app.containerConfiguration().startVOs().get(0)+"/vre";
//config.startScopes(vre,"/bad/scope");
app.useDefaultHandlers();
ApplicationContext context = app.start();
app.withExternal(config);
assertEquals(active,context.lifecycle().state());
//Set<String> runningScopes = new HashSet<>(context.profile(GCoreEndpoint.class).scopes().asCollection());
//assertEquals(singleton(vre),runningScopes);
}
@Test(expected=RuntimeException.class)
public void failsIfConfigurationIsMissing() {
app.bypassConfigurationDeployment();
app.start();
}
}

@ -1,40 +0,0 @@
package test.container;
import java.io.StringWriter;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.ini4j.Ini;
import org.ini4j.Profile.Section;
import org.junit.Test;
public class ConfigurationTest {
@Test
public void containerConfigurationBinds() throws Exception {
ContainerConfiguration bound = ContainerConfiguration
.load(ConfigurationTest.class.getResourceAsStream("/test-configuration.ini"));
bound.validate();
}
@Test
public void iniStore() throws Exception {
Ini ini = new Ini();
// lets add a section, it will create needed intermediate sections as well
ini.add("root/child/sub");
Section rsec = ini.get("root");
rsec.add("test", "team");
Section csec = rsec.getChild("child");
csec.add("testchild", "pappo");
Section ssec = csec.getChild("sub");
ssec.add("testSec", "pippo");
StringWriter sw = new StringWriter();
ini.store(sw);
}
}

@ -1,79 +0,0 @@
package test.container;
import static org.junit.Assert.*;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.lifecycle.application.ApplicationState;
import org.gcube.smartgears.lifecycle.container.ContainerState;
import org.gcube.smartgears.managers.ContainerManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import app.SomeApp;
public class ContainerLifecycleTest {
SomeApp app;
@Before
public void init() {
app = new SomeApp();
}
@After
public void teardown() {
app.stop();
}
@Test
public void containerGoesToPartActiveWhenAppFails() {
ApplicationContext actx = app.start();
ContainerContext ctx = actx.container();
assertEquals(ContainerState.active,ctx.lifecycle().state());
actx.lifecycle().moveTo(ApplicationState.failed);
assertEquals(ContainerState.partActive,ctx.lifecycle().state());
}
@Test
public void containerGoesToPartActiveWhenAppStops() {
ApplicationContext actx = app.start();
ContainerContext ctx = actx.container();
assertEquals(ContainerState.active,ctx.lifecycle().state());
actx.lifecycle().moveTo(ApplicationState.stopped);
assertEquals(ContainerState.partActive,ctx.lifecycle().state());
}
//used interactively to study shutdown
@Ignore
@Test
public void containerShutsdown() throws Exception {
ApplicationContext actx = app.start();
ContainerContext ctx = actx.container();
assertEquals(ContainerState.active,ctx.lifecycle().state());
ContainerManager.instance.stop(true);
app.stop();
Thread.sleep(10000);
}
}

@ -1,98 +0,0 @@
package test.container;
import static junit.framework.Assert.*;
import static org.gcube.smartgears.Constants.*;
import static org.gcube.smartgears.lifecycle.container.ContainerState.*;
import java.io.File;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.gcube.common.events.Observes;
import org.gcube.common.resources.gcore.HostingNode;
import org.gcube.common.resources.gcore.Resources;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.context.container.ContainerContext;
import org.junit.Test;
import app.SomeApp;
public class ProfileManagementTest {
@Test
public void createsStoresAndPublishesAValidProfile() throws Exception {
ContainerContext ctx = startAppAndGetContainerContext();
HostingNode node = ctx.profile();
assertNotNull(node);
//assert profile has been created
File profile = ctx.configuration().persistence().file(container_profile_file_path);
assertTrue(profile.exists());
assertFalse(node.scopes().isEmpty());
Resources.validate(node);
}
@Test
public void loadsAndUpdatesProfile() throws Exception {
startAppAndGetContainerContext();
SomeApp runtwice = new SomeApp();
runtwice.dirtyRun();
ContainerContext ctx = runtwice.start().container();
assertNotNull(ctx.profile());
HostingNode node = ctx.profile();
Resources.validate(node);
}
@Test
public void periodicallyUpdatesAndPublishesProfile() throws Exception {
SomeApp app = new SomeApp();
//app.containerConfiguration().publicationFrequency(1);
ContainerContext ctx = app.start().container();
final CountDownLatch latch = new CountDownLatch(1);
assertEquals(active,ctx.lifecycle().state());
ctx.events().subscribe(new Object() {
@Observes
void profileHasChangedAfterPeriodicUpdate(HostingNode ignore) {
latch.countDown();
}
});
if (!latch.await(4,TimeUnit.SECONDS))
fail();
ctx.lifecycle().moveTo(stopped); //should stop periodic updates
}
ContainerContext startAppAndGetContainerContext() {
SomeApp app = new SomeApp();
ApplicationContext appCtx = app.start();
return appCtx.container();
}
}

@ -1,65 +0,0 @@
package test.container;
import static org.gcube.smartgears.Constants.*;
import static org.gcube.smartgears.lifecycle.container.ContainerState.*;
import static org.junit.Assert.*;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.junit.After;
import org.junit.Test;
import app.SomeApp;
public class StartupTest {
SomeApp app = new SomeApp();
@After
public void teardown() {
app.stop();
}
@Test(expected=RuntimeException.class)
public void failsIfHomeIsNotConfigured() {
System.clearProperty(ghn_home_property);
app.start();
assertFalse(app.isActive());
}
@Test(expected=RuntimeException.class)
public void failsIfInstallationFolderIsInvalid() {
System.setProperty(ghn_home_property,"foo");
app.start();
assertFalse(app.isActive());
}
@Test(expected=RuntimeException.class)
public void failsIfConfigurationIsInvalid() {
//app.containerConfiguration().hostname(null);
app.start();
assertFalse(app.isActive());
}
@Test
public void leavesContainerToActive() {
ApplicationContext ctx = app.start();
assertEquals(active,ctx.container().lifecycle().state());
assertTrue(app.isActive());
}
}

@ -0,0 +1,41 @@
[node]
; mandatory
; optional fields: mode (=online), publication-frequency-seconds (=60), authorizeChildrenContext (=false)
mode = online
hostname = dlib29.isti.cnr.it
protocol= http
port = 8080
infrastructure = gcube
authorizeChildrenContext = true
publicationFrequencyInSeconds = 60
[properties]
; not mandatory
SmartGearsDistribution = 0.0.1
SmartGearsDistributionBundle = UnBundled
[site]
; mandatory
; optional fields: latitude, logitude
country = it
location = rome
;[proxy]
; not mandatory
;protocol = https
;hostname = proxy
;port = 80
[authorization]
; mandatory
; optional fields: provider factory (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory)
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
credentials.class = org.gcube.smartgears.security.SimpleCredentials
credentials.clientID = testClient
credentials.secret = testSecret
credentials.endpoint = testSecret
;[persistence]
; not mandatory (default is LocalPersistence writing in the ghn home)
;class = utils.PersistenceWriterTest
;location = /tmp

@ -28,11 +28,12 @@ port = 80
[authorization]
; mandatory
; optional fields: provider (=org.gcube.smartgears.security.DefaultAuthorizationProvider)
provider = org.gcube.smartgears.security.DefaultAuthorizationProvider
; optional fields: factory provider (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory)
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
credentials.class = org.gcube.smartgears.security.SimpleCredentials
credentials.clientID = testClient
credentials.secret = testSecret
credentials.enpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
[persistence]
; not mandatory (default is LocalPersistence writing in the ghn home)

Loading…
Cancel
Save