]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.init/src/org/argeo/api/init/RuntimeManager.java
Improve nested OSGi runtimes
[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 String SHARED = "shared";
20
21 public void startRuntime(String relPath, Consumer<Map<String, String>> configCallback);
22
23 public void closeRuntime(String relPath, boolean async);
24
25 default void startRuntime(String relPath, String props) {
26 startRuntime(relPath, (config) -> {
27 loadProperties(config, props);
28 });
29 }
30
31 static void loadProperties(Map<String, String> config, Properties properties) {
32 for (Object key : properties.keySet()) {
33 config.put(key.toString(), properties.getProperty(key.toString()));
34 }
35 }
36
37 static void loadProperties(Map<String, String> config, String props) {
38 Properties properties = new Properties();
39 try (Reader reader = new StringReader(props)) {
40 properties.load(reader);
41 } catch (IOException e) {
42 throw new IllegalArgumentException("Cannot load properties", e);
43 }
44 loadProperties(config, properties);
45 }
46
47 static void loadProperties(Map<String, String> config, InputStream in) throws IOException {
48 Properties properties = new Properties();
49 properties.load(in);
50 loadProperties(config, properties);
51 }
52
53 static void loadDefaults(Map<String, String> config) {
54 try (InputStream in = RuntimeManager.class.getResourceAsStream("defaults.ini")) {
55 loadProperties(config, in);
56 } catch (IOException e) {
57 throw new IllegalStateException("Could not load runtime defaults", e);
58 }
59 }
60
61 /**
62 * Load configs recursively starting with the parent directories, until a
63 * jvm.args file is found.
64 */
65 @Deprecated
66 static void loadConfig(Path dir, Map<String, String> config) {
67 try {
68 Path jvmArgsPath = dir.resolve(RuntimeManager.JVM_ARGS);
69 if (!Files.exists(jvmArgsPath)) {
70 // load from parent directory
71 loadConfig(dir.getParent(), config);
72 }
73
74 if (Files.exists(dir))
75 for (Path p : Files.newDirectoryStream(dir, "*.ini")) {
76 try (InputStream in = Files.newInputStream(p)) {
77 loadConfig(in, config);
78 }
79 }
80 } catch (IOException e) {
81 throw new UncheckedIOException("Cannot load configuration from " + dir, e);
82 }
83 }
84
85 /**
86 * Load config from a {@link Properties} formatted stream. If a property value
87 * starts with a '+' character, itis expected that the last character is a
88 * separator and it will be prepended to the existing value.
89 */
90 @Deprecated
91 static void loadConfig(InputStream in, Map<String, String> config) throws IOException {
92 Properties props = new Properties();
93 props.load(in);
94 for (Object k : props.keySet()) {
95 String key = k.toString();
96 String value = props.getProperty(key);
97 if (value.length() > 1 && '+' == value.charAt(0)) {
98 String currentValue = config.get(key);
99 if (currentValue == null || "".equals(currentValue)) {
100 // remove the + and the trailing separator
101 value = value.substring(1, value.length() - 1);
102 config.put(key, value);
103 } else {
104 // remove the + but keep the trailing separator
105 value = value.substring(1);
106 config.put(key, value + currentValue);
107 }
108 } else {
109 config.put(key, value);
110 }
111 }
112 }
113 }