diff --git a/duniter4j-client/pom.xml b/duniter4j-client/pom.xml index db9fed8e06195fc138e0f3cc7aca76a64d498db1..e470589df59c3e3ebcfd79df6e60b245e906e741 100644 --- a/duniter4j-client/pom.xml +++ b/duniter4j-client/pom.xml @@ -86,6 +86,14 @@ <artifactId>jansi</artifactId> <version>${jansiVersion}</version> </dependency> + + <!-- spring (need to extends configuration) --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>${spring.version}</version> + <scope>provided</scope> + </dependency> </dependencies> <build> diff --git a/duniter4j-core-client/pom.xml b/duniter4j-core-client/pom.xml index 75a4c1645d819383c9cef2607fb19c7f3c5efdad..1f7a0c205dd1555998976e73d7dd5d4701b268ae 100644 --- a/duniter4j-core-client/pom.xml +++ b/duniter4j-core-client/pom.xml @@ -91,6 +91,14 @@ <artifactId>jackson-databind</artifactId> </dependency> + <!-- Spring (need for spring compatibility) --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>${spring.version}</version> + <scope>provided</scope> + </dependency> + <!-- Unit test --> <dependency> <groupId>junit</groupId> diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java index d98646f498a1846ea0202e36fbbc332a9d4b90ed..fde296ab11b891e8c8f982ad188836e3d2778030 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java @@ -25,20 +25,19 @@ package org.duniter.core.client.config; import com.google.common.base.Charsets; import lombok.extern.slf4j.Slf4j; +import org.duniter.core.client.util.spring.ConfigurableEnvironments; import org.duniter.core.exception.TechnicalException; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ApplicationConfigHelper; -import org.nuiton.config.ApplicationConfigProvider; -import org.nuiton.config.ArgumentsParserException; +import org.nuiton.config.*; import org.nuiton.version.Version; import org.nuiton.version.VersionBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.springframework.core.env.ConfigurableEnvironment; import java.io.File; import java.net.MalformedURLException; import java.net.URL; +import java.util.Arrays; import java.util.Locale; +import java.util.Properties; import java.util.Set; import static org.nuiton.i18n.I18n.t; @@ -83,28 +82,35 @@ public class Configuration { super(); this.applicationConfig = applicationConfig; this.optionKeyToNotSave = null; - // Override application version initVersion(applicationConfig); } - public Configuration(String file, String... args) { + public Configuration(ConfigurableEnvironment env, + String... args) { + this(env, "application.fake.properties", args); + } + + public Configuration(String file, + String... args) { + this(null, file, args); + } + + protected Configuration(ConfigurableEnvironment env, + String file, + String... args) { super(); - this.applicationConfig = new ApplicationConfig(); + // load all default options + Set<ApplicationConfigProvider> providers = getProviders(); + Properties defaults = getDefaults(providers, env); + + // Create Nuiton config instance + this.applicationConfig = new ApplicationConfig(ApplicationConfigInit.forAllScopesWithout( + ApplicationConfigScope.HOME + ).setDefaults(defaults)); this.applicationConfig.setEncoding(Charsets.UTF_8.name()); this.applicationConfig.setConfigFileName(file); - // get allOfToList config providers - Set<ApplicationConfigProvider> providers = - ApplicationConfigHelper.getProviders(null, - null, - null, - true); - - // load allOfToList default options - ApplicationConfigHelper.loadAllDefaultOption(applicationConfig, - providers); - // Load actions for (ApplicationConfigProvider provider : providers) { applicationConfig.loadActions(provider.getActions()); @@ -132,30 +138,35 @@ public class Configuration { throw new TechnicalException(t("duniter4j.config.parse.error"), e); } - // TODO Review this, this is very dirty to do this... - File appBasedir = applicationConfig.getOptionAsFile( - ConfigurationOption.BASEDIR.getKey()); + // Prepare base dir + fixBaseDir(applicationConfig); + } - if (appBasedir == null) { - appBasedir = new File(""); - } - if (!appBasedir.isAbsolute()) { - appBasedir = new File(appBasedir.getAbsolutePath()); - } - if (appBasedir.getName().equals("..")) { - appBasedir = appBasedir.getParentFile().getParentFile(); - } - if (appBasedir.getName().equals(".")) { - appBasedir = appBasedir.getParentFile(); - } - if (log.isInfoEnabled()) { - log.info("Application basedir: " + appBasedir); + protected static Set<ApplicationConfigProvider> getProviders() { + // get allOfToList config providers + return ApplicationConfigHelper.getProviders(null, + null, + null, + true); + } + + protected Properties getDefaults(Set<ApplicationConfigProvider> providers, ConfigurableEnvironment env) { + + // Populate defaults from providers + final Properties defaults = new Properties(); + providers.forEach(provider -> Arrays.stream(provider.getOptions()) + .filter(configOptionDef -> configOptionDef.getDefaultValue() != null) + .forEach(configOptionDef -> defaults.setProperty(configOptionDef.getKey(), configOptionDef.getDefaultValue()))); + + // Set options from env if provided + if (env != null) { + return ConfigurableEnvironments.readProperties(env, defaults); } - applicationConfig.setOption( - ConfigurationOption.BASEDIR.getKey(), - appBasedir.getAbsolutePath()); + + return defaults; } + /** * Override the version default option, from the MANIFEST implementation version (if any) * @param applicationConfig @@ -184,7 +195,32 @@ public class Configuration { applicationConfig.addAlias("-c", "--option", ConfigurationOption.NODE_CURRENCY.getKey()); applicationConfig.addAlias("--salt", "--option", ConfigurationOption.USER_SALT.getKey()); applicationConfig.addAlias("--passwd", "--option", ConfigurationOption.USER_PASSWD.getKey()); - } + } + + protected void fixBaseDir(ApplicationConfig applicationConfig) { + // TODO Review this, this is very dirty to do this... + File appBasedir = applicationConfig.getOptionAsFile( + ConfigurationOption.BASEDIR.getKey()); + + if (appBasedir == null) { + appBasedir = new File(""); + } + if (!appBasedir.isAbsolute()) { + appBasedir = new File(appBasedir.getAbsolutePath()); + } + if (appBasedir.getName().equals("..")) { + appBasedir = appBasedir.getParentFile().getParentFile(); + } + if (appBasedir.getName().equals(".")) { + appBasedir = appBasedir.getParentFile(); + } + if (log.isInfoEnabled()) { + log.info("Application basedir: " + appBasedir); + } + applicationConfig.setOption( + ConfigurationOption.BASEDIR.getKey(), + appBasedir.getAbsolutePath()); + } public File getConfigFile() { if (configFile == null) { diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java index ea5d6ef0c1796491c27a6047175b9848bbc41aa3..35b44db712cad0ccffb10eb2e14582a98ec8a944 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java @@ -44,11 +44,22 @@ public enum ConfigurationOption implements ConfigOptionDef { // ------------------------------------------------------------------------// // -- READ-ONLY OPTIONS ---------------------------------------------------// // ------------------------------------------------------------------------// + APP_NAME( + "duniter4j.name", + n("duniter4j.config.option.app.name.description"), + "duniter4j", + File.class), + + VERSION( + "duniter4j.version", + n("duniter4j.config.option.version.description"), + "1.0.0", + Version.class), BASEDIR( "duniter4j.basedir", n("duniter4j.config.option.basedir.description"), - "${user.home}/.config/duniter4j", + "${user.home}/.config/${duniter4j.name}", File.class), DATA_DIRECTORY( @@ -75,12 +86,6 @@ public enum ConfigurationOption implements ConfigOptionDef { "${duniter4j.data.directory}/cache", File.class), - VERSION( - "duniter4j.version", - n("duniter4j.config.option.version.description"), - "1.0", - Version.class), - SITE_URL( "duniter4j.site.url", n("duniter4j.config.option.site.url.description"), diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java index e4106f051c3f194de1da8ec16bf0b0a89f006b73..f73c8c029574bfdfa6babc4a283216b5b3934392 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/ModelUtils.java @@ -126,6 +126,7 @@ public class ModelUtils { if (pubkey == null || pubkey.length() < 6) { return pubkey; } + // TODO: use new pubkey minify return pubkey.substring(0, 8); } diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java index dca4bc89951f1e314584c0695a64d3a6998863b2..76d46e79c08525549a849aa1d72433e04ae70847 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java @@ -22,61 +22,20 @@ package org.duniter.core.client.model.elasticsearch; * #L% */ +import lombok.Data; +import lombok.experimental.FieldNameConstants; + /** * Created by blavenie on 01/03/16. */ +@Data +@FieldNameConstants public class UserProfile extends Record { - public static final String PROPERTY_TITLE = "title"; - public static final String PROPERTY_DESCRIPTION="description"; - public static final String PROPERTY_ADDRESS="address"; - public static final String PROPERTY_CITY="city"; - public static final String PROPERTY_EMAIL="email"; - public static final String PROPERTY_LOCALE="locale"; - private String title; private String description; private String address; + private String city; private String email; private String locale; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getLocale() { - return locale; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } } diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/util/spring/ConfigurableEnvironments.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/util/spring/ConfigurableEnvironments.java new file mode 100644 index 0000000000000000000000000000000000000000..8422c09e4471d847910eb7f0b4533b814213b6c7 --- /dev/null +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/util/spring/ConfigurableEnvironments.java @@ -0,0 +1,60 @@ +package org.duniter.core.client.util.spring; + +import com.google.common.collect.Lists; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; + +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +@Slf4j +public class ConfigurableEnvironments { + + protected ConfigurableEnvironments() { + // Helper class + } + + public static Properties readProperties(@NonNull ConfigurableEnvironment env, Properties defaultOptions) { + boolean debug = log.isDebugEnabled(); + List<MapPropertySource> sources = env.getPropertySources().stream() + .filter(source -> source instanceof MapPropertySource) + .map(source -> (MapPropertySource)source).collect(Collectors.toList()); + final Properties target = new Properties(defaultOptions); + + if (debug) log.debug("-- Reading environment properties... ---\n"); + for (MapPropertySource source: Lists.reverse(sources)) { + + if (debug) log.debug("Processing source {} ...", source.getName()); + + // Cascade properties (keep original order) + for (String key: source.getPropertyNames()) { + Object value = source.getProperty(key); + if (value != null) { + if (debug) { + if (target.containsKey(key)) log.debug(" {}={} /!\\ Overriding previous value", key, value); + else log.debug(" {}={}", key, value); + } + target.setProperty(key, value.toString()); + } + } + } + + // DEBUG + if (debug) { + log.debug("-- Environment properties - final summary ---\n"); + target.keySet() + .stream() + .map(Object::toString) + .sorted() + .forEach(key -> { + Object value = target.getProperty(key); + log.debug(" {}={}", key, value); + }); + } + + return target; + } +} diff --git a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties index 6d8cde9d3611d881401ed1628a7c7b393b99313c..84c6ceffe76cd7d9ffbc716fd494779df126fc40 100644 --- a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties +++ b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties @@ -7,6 +7,7 @@ duniter4j.client.core.timeout= duniter4j.client.notFound=Resource non found [%s] duniter4j.client.status=Http request error\: %s duniter4j.config= +duniter4j.config.option.app.name.description= duniter4j.config.option.basedir.description= duniter4j.config.option.cache.directory.description= duniter4j.config.option.data.directory.description= diff --git a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties index 291be52ea0f81e0a0ad8acc937fffc59b0c74dcb..470918a3bb70c1417bafd256fc59467bf588eef0 100644 --- a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties +++ b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties @@ -7,6 +7,7 @@ duniter4j.client.core.timeout=Délai d'attente de la requête dépassé duniter4j.client.notFound=Ressource non trouvée [%s] duniter4j.client.status=Echec de requete HTTP [%s] \: %s duniter4j.config=Options de configuration Duniter4j \:\: client +duniter4j.config.option.app.name.description= duniter4j.config.option.basedir.description=Répertoire de travail de l'application duniter4j.config.option.cache.directory.description=Répertoire pour le cache applicatif duniter4j.config.option.data.directory.description=Répertoire de stockage des données diff --git a/pom.xml b/pom.xml index 417cac1c3216bdfd056af7c3106f3d1e8b99dd48..c56c69f287084f773e38a649a1cb7e2f86365697 100644 --- a/pom.xml +++ b/pom.xml @@ -36,12 +36,12 @@ <lombok.version>1.18.20</lombok.version> <httpclient.version>4.5.10</httpclient.version> - <nuitonConfigVersion>3.0</nuitonConfigVersion> + <nuitonConfigVersion>3.4</nuitonConfigVersion> <nuitonVersionVersion>1.0-rc-2</nuitonVersionVersion> <nuitonI18nVersion>3.6.3</nuitonI18nVersion> <!-- UI versions --> - <spring.version>4.2.1.RELEASE</spring.version> + <spring.version>5.3.5</spring.version> <aspectj.version>1.8.7</aspectj.version> <!-- Unit test -->