Skip to content

Commit

Permalink
PlatformConfig: Add PlatformConfigProvider interface with StandardPla…
Browse files Browse the repository at this point in the history
…tformConfigProvider and TestPlatformConfigProvider implementations

the previous behavior is moved to the StandardPlatformConfigProvider class

Signed-off-by: Jon Harper <jon.harper87@gmail.com>
  • Loading branch information
jonenst committed Sep 10, 2019
1 parent 912fbba commit 61a9303
Show file tree
Hide file tree
Showing 10 changed files with 387 additions and 84 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
/commons/target/
/computation-local/target/
/computation/target/
/config-test/target/
/contingency/target/
/contingency/contingency-api/target/
/contingency/contingency-dsl/target/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@

import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;

/**
*
Expand All @@ -42,89 +40,9 @@ public static synchronized void setDefaultConfig(PlatformConfig defaultConfig) {
PlatformConfig.defaultConfig = defaultConfig;
}

/**
* Returns the list of default config directories: they are defined by the system properties
* "powsybl.config.dirs" or "itools.config.dir".
* If none is defined, it defaults to the single directory ${HOME}/.itools.
*/
private static Path[] getDefaultConfigDirs(FileSystem fileSystem) {
Objects.requireNonNull(fileSystem);
String directories = System.getProperty("powsybl.config.dirs", System.getProperty("itools.config.dir"));
Path[] configDirs = null;
if (directories != null) {
configDirs = Arrays.stream(directories.split(":"))
.map(PlatformEnv::substitute)
.map(fileSystem::getPath)
.toArray(Path[]::new);
}
if (configDirs == null || configDirs.length == 0) {
configDirs = new Path[] {fileSystem.getPath(System.getProperty("user.home"), ".itools") };
}
return configDirs;
}

/**
* Loads a {@link ModuleConfigRepository} from the list of specified config directories.
* Configuration properties values encountered first in the list of directories
* take precedence over the values defined in subsequent directories.
* Configuration properties encountered in environment variables take precedence
* over the values defined in config directories.
*/
private static ModuleConfigRepository loadModuleRepository(Path[] configDirs, String configName) {
List<ModuleConfigRepository> repositoriesFromPath = Arrays.stream(configDirs)
.map(configDir -> loadModuleRepository(configDir, configName))
.collect(Collectors.toList());
List<ModuleConfigRepository> repositories = new ArrayList<>();
repositories.add(new EnvironmentModuleConfigRepository(System.getenv(), FileSystems.getDefault()));
repositories.addAll(repositoriesFromPath);
return new StackedModuleConfigRepository(repositories);
}

/**
* Loads a {@link ModuleConfigRepository} from a single directory.
* Reads from yaml file if it exists, else from xml file, else from properties file.
*/
private static ModuleConfigRepository loadModuleRepository(Path configDir, String configName) {
Path yamlConfigFile = configDir.resolve(configName + ".yml");
if (Files.exists(yamlConfigFile)) {
LOGGER.info("Platform configuration defined by YAML file {}", yamlConfigFile);
return new YamlModuleConfigRepository(yamlConfigFile);
} else {
Path xmlConfigFile = configDir.resolve(configName + ".xml");
if (Files.exists(xmlConfigFile)) {
LOGGER.info("Platform configuration defined by XML file {}", xmlConfigFile);
return new XmlModuleConfigRepository(xmlConfigFile);
} else {
LOGGER.info("Platform configuration defined by .properties files of directory {}", configDir);
return new PropertiesModuleConfigRepository(configDir);
}
}
}

/**
* Loads the default {@link ModuleConfigRepository}.
* Configuration properties are read from environment variables and from the list of directories
* defined by the system properties "powsybl.config.dirs" or "itools.config.dir", or by default from ${HOME}/.itools.
* Configuration properties values from environment variables
* take precedence over the values defined in config directories.
* Configuration properties values encountered first in the list of directories
* take precedence over the values defined in subsequent directories.
*/
public static ModuleConfigRepository loadDefaultModuleRepository() {
FileSystem fileSystem = FileSystems.getDefault();
Path[] configDirs = getDefaultConfigDirs(fileSystem);
String configName = System.getProperty("powsybl.config.name", System.getProperty("itools.config.name", "config"));

return loadModuleRepository(configDirs, configName);
}

public static synchronized PlatformConfig defaultConfig() {
if (defaultConfig == null) {
FileSystem fileSystem = FileSystems.getDefault();
Path[] configDirs = getDefaultConfigDirs(fileSystem);
String configName = System.getProperty("powsybl.config.name", System.getProperty("itools.config.name", "config"));

defaultConfig = new PlatformConfig(() -> loadModuleRepository(configDirs, configName), configDirs[0]);
defaultConfig = new StandardPlatformConfigProvider().getPlatformConfig();
}
return defaultConfig;
}
Expand All @@ -134,7 +52,7 @@ public PlatformConfig(ModuleConfigRepository repository) {
}

public PlatformConfig(ModuleConfigRepository repository, FileSystem fileSystem) {
this(() -> repository, getDefaultConfigDirs(fileSystem)[0]);
this(() -> repository, StandardPlatformConfigProvider.getDefaultConfigDir(fileSystem));
}

public PlatformConfig(ModuleConfigRepository repository, Path configDir) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.powsybl.commons.config;

/**
* Provides the default PlatformConfig to {@link PlatformConfig#defaultConfig()}
*
* @author Jon Harper <jon.harper at rte-france.com>
*/
public interface PlatformConfigProvider {

String getName();

PlatformConfig getPlatformConfig();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.powsybl.commons.config;

import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.auto.service.AutoService;

/**
* The standard powsybl PlatformConfig provider. It uses System Properties to
* get config dirs (powsybl.config.dirs, itools.config.dir; defaults to
* $HOME/.itools) and reads configuration from yaml, xml or java properties
* files. The config dir names can use the keywords from {@link PlatformEnv}
* (e.g. app.root, user.home). It also uses
* {@link EnvironmentModuleConfigRepository} to read configuration from
* environment variables.
*
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
@AutoService(PlatformConfigProvider.class)
public class StandardPlatformConfigProvider implements PlatformConfigProvider {

private static final Logger LOGGER = LoggerFactory.getLogger(StandardPlatformConfigProvider.class);
private static final String NAME = "standard";

@Override
public String getName() {
return NAME;
}

/**
* Returns the list of default config directories: they are defined by the system properties
* "powsybl.config.dirs" or "itools.config.dir".
* If none is defined, it defaults to the single directory ${HOME}/.itools.
*/
private static Path[] getDefaultConfigDirs(FileSystem fileSystem) {
Objects.requireNonNull(fileSystem);
String directories = System.getProperty("powsybl.config.dirs", System.getProperty("itools.config.dir"));
Path[] configDirs = null;
if (directories != null) {
configDirs = Arrays.stream(directories.split(":"))
.map(PlatformEnv::substitute)
.map(fileSystem::getPath)
.toArray(Path[]::new);
}
if (configDirs == null || configDirs.length == 0) {
configDirs = new Path[] {fileSystem.getPath(System.getProperty("user.home"), ".itools") };
}
return configDirs;
}

private static Path getDefaultConfigDir(Path[] configDirs) {
return configDirs[0];
}

/**
* Loads a {@link ModuleConfigRepository} from the list of specified config directories.
* Configuration properties values encountered first in the list of directories
* take precedence over the values defined in subsequent directories.
* Configuration properties encountered in environment variables take precedence
* over the values defined in config directories.
*/
private static ModuleConfigRepository loadModuleRepository(Path[] configDirs, String configName) {
List<ModuleConfigRepository> repositoriesFromPath = Arrays.stream(configDirs)
.map(configDir -> loadModuleRepository(configDir, configName))
.collect(Collectors.toList());
List<ModuleConfigRepository> repositories = new ArrayList<>();
repositories.add(new EnvironmentModuleConfigRepository(System.getenv(), FileSystems.getDefault()));
repositories.addAll(repositoriesFromPath);
return new StackedModuleConfigRepository(repositories);
}

/**
* Loads a {@link ModuleConfigRepository} from a single directory.
* Reads from yaml file if it exists, else from xml file, else from properties file.
*/
public static ModuleConfigRepository loadModuleRepository(Path configDir, String configName) {
Path yamlConfigFile = configDir.resolve(configName + ".yml");
if (Files.exists(yamlConfigFile)) {
LOGGER.info("Platform configuration defined by YAML file {}", yamlConfigFile);
return new YamlModuleConfigRepository(yamlConfigFile);
} else {
Path xmlConfigFile = configDir.resolve(configName + ".xml");
if (Files.exists(xmlConfigFile)) {
LOGGER.info("Platform configuration defined by XML file {}", xmlConfigFile);
return new XmlModuleConfigRepository(xmlConfigFile);
} else {
LOGGER.info("Platform configuration defined by .properties files of directory {}", configDir);
return new PropertiesModuleConfigRepository(configDir);
}
}
}

private static ModuleConfigRepository getDefaultModuleRepository(Path[] configDirs) {
String configName = System.getProperty("powsybl.config.name", System.getProperty("itools.config.name", "config"));
return loadModuleRepository(configDirs, configName);
}

@Override
public PlatformConfig getPlatformConfig() {
FileSystem fileSystem = FileSystems.getDefault();
Path[] configDirs = getDefaultConfigDirs(fileSystem);
ModuleConfigRepository repository = getDefaultModuleRepository(configDirs);
return new PlatformConfig(repository, configDirs[0]);
}

public static Path getDefaultConfigDir(FileSystem fileSystem) {
return getDefaultConfigDir(getDefaultConfigDirs(fileSystem));
}

public static ModuleConfigRepository getDefaultModuleRepository(FileSystem fileSystem) {
Path[] configDirs = getDefaultConfigDirs(fileSystem);
return getDefaultModuleRepository(configDirs);
}

public static PlatformConfig getPlatformConfig(ModuleConfigRepository repository, FileSystem fileSystem) {
return getPlatformConfig(repository, getDefaultConfigDir(fileSystem));
}

public static PlatformConfig getPlatformConfig(ModuleConfigRepository repository, Path path) {
return new PlatformConfig(repository, path);
}

}
81 changes: 81 additions & 0 deletions config-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019, RTE (http://www.rte-france.com)
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<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>com.powsybl</groupId>
<artifactId>powsybl-core</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>

<artifactId>powsybl-config-test</artifactId>
<name>Config Tests</name>
<description>Classes to mock the config during tests</description>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>com.powsybl.config-test</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Compilation dependencies -->
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.jimfs</groupId>
<artifactId>jimfs</artifactId>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Loading

0 comments on commit 61a9303

Please sign in to comment.