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; import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotEmpty; 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. * * @author Fabio Simeoni * @author Luca Frosini (ISTI - CNR) */ public class ContainerConfiguration { @NotNull @IsValid private BaseConfiguration baseConfiguration; @IsValid private Map properties = new HashMap(); @NotNull @IsValid private Site site; @IsValid private ProxyAddress proxy; @NotEmpty @NotNull private String accountingFallbackLocation; @XmlTransient private Set allowedContext = new HashSet(); private List apps = new ArrayList(); @NotNull @IsValid private PersistenceWriter persistenceManager; @NotNull @IsValid private AuthorizationProvider authorizationProvider; /** * Returns the management mode for the container. * @return the management mode */ public Mode mode() { return baseConfiguration.getMode(); } /** * Returns the application configurations included in this configuration. * @return the application configurations */ public List apps() { return apps; } /** * Returns the configuration of an application with a given context path. * @param context the context path * @return the application configuration */ public ApplicationConfiguration app(String context) { for (ApplicationConfiguration app : apps) if (context.equals(app.context())) return app; return null; } /** * Adds the configuration of an application to this configuration. * @param app the application configuration * @return this configuration */ public synchronized ContainerConfiguration app(ApplicationConfiguration app) { int indexToRemove =-1; int index =0; for (ApplicationConfiguration application : apps){ if (app.context().equals(application.context())) indexToRemove = index; index++; } if(indexToRemove!=-1) apps.remove(indexToRemove); apps.add(app); return this; } /** * Returns the geographical site of the container. * @return the site */ public Site site() { return site; } /** * Returns the infrastructure in which the container is running. * @return the infrastructure */ public String infrastructure() { return baseConfiguration.getInfrastructure(); } /** * Returns the host name of the container. * @return the host name; */ public String hostname() { return baseConfiguration.getHostname(); } /** * Returns the port at which the container is listening for requests. * @return the port */ public int port() { return baseConfiguration.getPort(); } /** * Returns the port at which the container is listening for requests. * @return the port */ public String protocol() { return baseConfiguration.getProtocol(); } public boolean authorizeChildrenContext() { return baseConfiguration.isAuthorizeChildrenContext(); } /** * Returns the credentials. * @return the credentials */ public AuthorizationProvider authorizationProvider() { return authorizationProvider; } /** * Returns the proxy of the container. * @return the proxy */ public ProxyAddress proxy() { return proxy; } /** * Returns the persistence manager of the container. * @return the manager */ public PersistenceWriter persistence() { return persistenceManager; } /** * Returns the persistence manager of the container. * @return the manager */ public String accountingFallbackLocation() { return accountingFallbackLocation; } /** * Returns the configuration properties of the container. * @return the properties */ public Map properties() { return Collections.unmodifiableMap(properties); } /** * Returns the publication frequency for the container's profile. * @return the frquency; */ public long publicationFrequency() { return baseConfiguration.getPublicationFrequencyInSeconds(); } public Set allowedContexts() { return allowedContext; } public void allowedContexts(Set allowedContexts) { this.allowedContext = allowedContexts; } /** * Validates this configuration * * @throws IllegalStateException if the configuration is invalid */ public void validate() { List msgs = new ArrayList(); Validator validator = ValidatorFactory.validator(); for (ValidationError error : validator.validate(this)) msgs.add(error.toString()); if (!msgs.isEmpty()) throw new IllegalStateException("invalid configuration: "+msgs); } 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); } } 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; } } }