]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.init/src/org/argeo/api/init/RuntimeManager.java
Improve init launch
[lgpl/argeo-commons.git] / org.argeo.init / src / org / argeo / api / init / RuntimeManager.java
1 package org.argeo.api.init;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.Reader;
6 import java.io.StringReader;
7 import java.io.UncheckedIOException;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.util.Map;
11 import java.util.Properties;
12 import java.util.function.Consumer;
13
14 /** Dynamically manages multiple runtimes within a single JVM. */
15 public interface RuntimeManager {
16 String JVM_ARGS = "jvm.args";
17 String STATE = "state";
18 String DATA = "data";
19
20 public void startRuntime(String relPath, Consumer<Map<String, String>> configCallback);
21
22 public void closeRuntime(String relPath, boolean async);
23
24 default void startRuntime(String relPath, String props) {
25 Properties properties = new Properties();
26 try (Reader reader = new StringReader(props)) {
27 properties.load(reader);
28 } catch (IOException e) {
29 throw new IllegalArgumentException("Cannot load properties", e);
30 }
31 startRuntime(relPath, (config) -> {
32 for (Object key : properties.keySet()) {
33 config.put(key.toString(), properties.getProperty(key.toString()));
34 }
35 });
36 }
37
38 /**
39 * Load configs recursively starting with the parent directories, until a
40 * jvm.args file is found.
41 */
42 static void loadConfig(Path dir, Map<String, String> config) {
43 try {
44 Path jvmArgsPath = dir.resolve(RuntimeManager.JVM_ARGS);
45 if (!Files.exists(jvmArgsPath)) {
46 // load from parent directory
47 loadConfig(dir.getParent(), config);
48 }
49
50 if (Files.exists(dir))
51 for (Path p : Files.newDirectoryStream(dir, "*.ini")) {
52 try (InputStream in = Files.newInputStream(p)) {
53 loadConfig(in, config);
54 }
55 }
56 } catch (IOException e) {
57 throw new UncheckedIOException("Cannot load configuration from " + dir, e);
58 }
59 }
60
61 /**
62 * Load config from a {@link Properties} formatted stream. If a property value
63 * starts with a '+' character, itis expected that the last character is a
64 * separator and it will be prepended to the existing value.
65 */
66 static void loadConfig(InputStream in, Map<String, String> config) throws IOException {
67 Properties props = new Properties();
68 props.load(in);
69 for (Object k : props.keySet()) {
70 String key = k.toString();
71 String value = props.getProperty(key);
72 if (value.length() > 1 && '+' == value.charAt(0)) {
73 String currentValue = config.get(key);
74 if (currentValue == null || "".equals(currentValue)) {
75 // remove the + and the trailing separator
76 value = value.substring(1, value.length() - 1);
77 config.put(key, value);
78 } else {
79 // remove the + but keep the trailing separator
80 value = value.substring(1);
81 config.put(key, value + currentValue);
82 }
83 } else {
84 config.put(key, value);
85 }
86 }
87 }
88 }