Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
salmonb committed Sep 1, 2023
2 parents c42c476 + f1757e2 commit a411834
Show file tree
Hide file tree
Showing 77 changed files with 1,996 additions and 20 deletions.
9 changes: 9 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
<module>webfx-platform-boot-gwt</module>
<module>webfx-platform-boot-java</module>
<module>webfx-platform-boot-vertx</module>
<module>webfx-platform-conf</module>
<module>webfx-platform-conf-file-java</module>
<module>webfx-platform-console</module>
<module>webfx-platform-console-gwt</module>
<module>webfx-platform-console-java</module>
Expand Down Expand Up @@ -139,6 +141,13 @@
<module>webfx-platform-storagelocation</module>
<module>webfx-platform-storagelocation-gluon</module>
<module>webfx-platform-storagelocation-java</module>
<module>webfx-platform-substitution</module>
<module>webfx-platform-substitution-var</module>
<module>webfx-platform-substitution-var-conf</module>
<module>webfx-platform-substitution-var-env</module>
<module>webfx-platform-substitution-var-localstorage</module>
<module>webfx-platform-substitution-var-sysprop</module>
<module>webfx-platform-substitution-var-windowlocation</module>
<module>webfx-platform-uischeduler</module>
<module>webfx-platform-uischeduler-gwt</module>
<module>webfx-platform-useragent</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public FutureBroadcaster(Callable<Future<T>> sourceProducer) {

public FutureBroadcaster(Future<T> source) {
sourceProducer = null;
this.source = armSource(source);
armSource(source);
}

private Future<T> armSource(Future<T> s) {
s.onComplete(ar -> onSourceCompleted());
return s;
private void armSource(Future<T> source) {
this.source = source;
source.onComplete(ar -> onSourceCompleted());
}

private void onSourceCompleted() {
Expand All @@ -43,8 +43,8 @@ public Future<T> newClient() {
Promise<T> newClient = Promise.promise();
clients.add(newClient);
if (source == null)
source = armSource(sourceProducer.call());
if (source.isComplete())
armSource(sourceProducer.call());
if (source != null && source.isComplete())
onSourceCompleted();
return newClient.future();
}
Expand Down
32 changes: 32 additions & 0 deletions webfx-platform-conf-file-java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- File managed by WebFX (DO NOT EDIT MANUALLY) -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>

<artifactId>webfx-platform-conf-file-java</artifactId>

<dependencies>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-async</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-conf</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.webfx.platform.conf.spi.impl.file.java;

import dev.webfx.platform.async.Future;
import dev.webfx.platform.conf.Config;
import dev.webfx.platform.conf.ConfigParser;
import dev.webfx.platform.conf.SourcesConfig;
import dev.webfx.platform.conf.impl.ConfigMerger;
import dev.webfx.platform.conf.spi.ConfigLoaderProvider;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

/**
* @author Bruno Salmon
*/
public class JavaFileConfigLoader implements ConfigLoaderProvider {

private final static String SRC_CONFIG_PATH = "webfx.platform.conf.file";
private final static String SRC_CONFIG_DIR_KEY = "configDirectory";

@Override
public Future<Config> loadConfig() {
Config config = null;
try {
Config sourcesConfig = SourcesConfig.getSourcesRootConfig().childConfigAt(SRC_CONFIG_PATH);
String configDirPath = sourcesConfig.getString(SRC_CONFIG_DIR_KEY);
File configurationDirectory = new File(configDirPath);
File[] files = configurationDirectory.listFiles();
if (files != null) {
int n = files.length;
Config[] configs = new Config[n];
for (int i = 0; i < n; i++) {
Path path = files[i].toPath();
String fileContent = new String(Files.readAllBytes(path));
configs[i] = ConfigParser.parseFileConfig(fileContent, path.toString());
}
config = ConfigMerger.mergeConfigs(configs);
}
} catch (Exception e) {
return Future.failedFuture(e);
}
return Future.succeededFuture(config);
}
}
16 changes: 16 additions & 0 deletions webfx-platform-conf-file-java/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// File managed by WebFX (DO NOT EDIT MANUALLY)

module webfx.platform.conf.file.java {

// Direct dependencies modules
requires java.base;
requires webfx.platform.async;
requires webfx.platform.conf;

// Exported packages
exports dev.webfx.platform.conf.spi.impl.file.java;

// Provided services
provides dev.webfx.platform.conf.spi.ConfigLoaderProvider with dev.webfx.platform.conf.spi.impl.file.java.JavaFileConfigLoader;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dev.webfx.platform.conf.spi.impl.file.java.JavaFileConfigLoader
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Assuming that variables resolution through system properties is available (if not, this property must be overridden)
configDirectory = ${{ user.dir }}/conf
#configFile = <- no generic default value, must be overridden if the application wants to use it
17 changes: 17 additions & 0 deletions webfx-platform-conf-file-java/webfx.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>

<exported-packages>
<source-packages/>
<resource-packages/>
</exported-packages>

<dependencies>
<used-by-source-modules/>
</dependencies>

<providers>
<provider interface="dev.webfx.platform.conf.spi.ConfigLoaderProvider">dev.webfx.platform.conf.spi.impl.file.java.JavaFileConfigLoader</provider>
</providers>

</project>
44 changes: 44 additions & 0 deletions webfx-platform-conf/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- File managed by WebFX (DO NOT EDIT MANUALLY) -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>

<artifactId>webfx-platform-conf</artifactId>

<dependencies>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-async</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-resource</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-substitution</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>dev.webfx</groupId>
<artifactId>webfx-platform-util</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.webfx.platform.conf;

import dev.webfx.platform.conf.impl.RootConfig;
import dev.webfx.platform.util.keyobject.ReadOnlyKeyObject;

/**
* @author Bruno Salmon
*/
public interface Config extends ReadOnlyKeyObject {

RootConfig getRoot();

Config childConfigAt(String path);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package dev.webfx.platform.conf;

import dev.webfx.platform.async.Batch;
import dev.webfx.platform.async.Future;
import dev.webfx.platform.async.FutureBroadcaster;
import dev.webfx.platform.async.Promise;
import dev.webfx.platform.conf.impl.ConfigMerger;
import dev.webfx.platform.conf.spi.ConfigLoaderProvider;
import dev.webfx.platform.util.Arrays;
import dev.webfx.platform.util.serviceloader.MultipleServiceProviders;

import java.util.List;
import java.util.ServiceLoader;
import java.util.function.Consumer;

/**
* @author Bruno Salmon
*/
public class ConfigLoader {

public static void onConfigLoaded(Consumer<Config> configConsumer) {
onConfigLoaded(configConsumer, false);
}

public static void onConfigLoadedOrChanged(Consumer<Config> configConsumer) {
onConfigLoaded(configConsumer, false);
}

public static void onConfigLoaded(Consumer<Config> configConsumer, boolean onChangesToo) {
onConfigLoaded(null, configConsumer, onChangesToo);
}

public static void onConfigLoaded(String path, Consumer<Config> configConsumer) {
onConfigLoaded(path, configConsumer, false);
}

public static void onConfigLoadedOrChanged(String path, Consumer<Config> configConsumer) {
onConfigLoaded(path, configConsumer, false);
}

public static void onConfigLoaded(String path, Consumer<Config> configConsumer, boolean onChangesToo) {
INITIAL_LOADER.newClient().onSuccess(rootConfig -> configConsumer.accept(rootConfig.childConfigAt(path)));
}

private static final FutureBroadcaster<Config> INITIAL_LOADER = new FutureBroadcaster<>(loadRootConfig());

private static List<ConfigLoaderProvider> getProviders() {
return MultipleServiceProviders.getProviders(ConfigLoaderProvider.class, () -> ServiceLoader.load(ConfigLoaderProvider.class));
}

private static Config ROOT_CONFIG;

public static Config getRootConfig() {
return ROOT_CONFIG != null ? ROOT_CONFIG : SourcesConfig.getSourcesRootConfig();
}

private static Future<Config> loadRootConfig() {
Promise<Config> promise = Promise.promise();
new Batch<>(getProviders().toArray(new ConfigLoaderProvider[0]))
.executeParallel(Config[]::new, ConfigLoaderProvider::loadConfig)
.onFailure(promise::fail)
.onSuccess(batch -> {
Config[] sourcesConfig = { SourcesConfig.getSourcesRootConfig() };
Config[] loadedAndSourcesConfig = Arrays.concat(Config[]::new, batch.getArray(), sourcesConfig);
ROOT_CONFIG = ConfigMerger.mergeConfigs(loadedAndSourcesConfig);
promise.complete(ROOT_CONFIG);
});
return promise.future();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.webfx.platform.conf;

import dev.webfx.platform.conf.impl.RootConfig;
import dev.webfx.platform.util.keyobject.ReadOnlyKeyObject;
import dev.webfx.platform.util.keyobject.parser.TreeParser;
import dev.webfx.platform.util.keyobject.util.TreeUtil;

/**
* @author Bruno Salmon
*/
public class ConfigParser {

public static Config parseConfig(String configText, String format) {
return parsePrefixedConfig(null, configText, format);
}

public static Config parsePrefixedConfig(String prefixPath, String configText, String format) {
// Parsing the object with the format given by the extension
ReadOnlyKeyObject keyObject = TreeParser.parseObject(configText, format);
if (prefixPath != null) {
keyObject = TreeUtil.prefixObject(prefixPath, keyObject);
}
return new RootConfig(keyObject);
}

public static Config parseFileConfig(String fileContent, String filePath) {
// We determine the format and the prefixPath from the filePath and then call parsePrefixedConfig()
// So, first, we just keep the short file name
int lastSlashIndex = filePath.lastIndexOf('/');
if (lastSlashIndex > 0) {
filePath = filePath.substring(lastSlashIndex + 1);
}
// Then we get the format from the file extension
int lastDotIndex = filePath.lastIndexOf('.');
String format = filePath.substring(lastDotIndex + 1);
// Now removing the extension from the short file name
filePath = filePath.substring(0, lastDotIndex);
// Also, ignoring possible annotations such as override@
int atIndex = filePath.lastIndexOf('@');
if (atIndex >= 0)
filePath = filePath.substring(atIndex + 1);
// Now this short file name without extension will act as the prefix path, unless it contains "-" (like for
// "src-root") where in that case, it's considered to be a root configuration path (no prefix)
String prefixPath = filePath.contains("-") ? null : filePath;
return parsePrefixedConfig(prefixPath, fileContent, format);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.webfx.platform.conf;

import dev.webfx.platform.resource.Resource;

/**
* @author Bruno Salmon
*/
public final class SourcesConfig {

public final static String SRC_ROOT_CONF_PACKAGE = "dev.webfx.platform.conf";
public final static String SRC_ROOT_CONF_RESOURCE_FOLDER = SRC_ROOT_CONF_PACKAGE.replace('.', '/');
public final static String SRC_ROOT_CONF_RESOURCE_FILE_NAME = "src-root.properties";
public final static String SRC_ROOT_CONF_RESOURCE_FILE_PATH = SRC_ROOT_CONF_RESOURCE_FOLDER + "/" + SRC_ROOT_CONF_RESOURCE_FILE_NAME;
private static Config sourcesRootConfig;

public static Config getSourcesRootConfig() {
if (sourcesRootConfig == null) {
String configText = Resource.getText(SRC_ROOT_CONF_RESOURCE_FILE_PATH);
if (configText == null) {
throw new RuntimeException("❌ No sources route configuration found!");
}
sourcesRootConfig = ConfigParser.parseFileConfig(configText, SRC_ROOT_CONF_RESOURCE_FILE_PATH);
}
return sourcesRootConfig;
}

}
Loading

0 comments on commit a411834

Please sign in to comment.