From 483ac086b098c554a7bb9557f5867271de960423 Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Wed, 19 Jul 2017 14:09:26 -0700 Subject: [PATCH 1/8] config-loader --- build.gradle | 2 +- composer/build.gradle | 10 +- .../config/loader/CompositeConfigLoader.java | 68 ++++++++++ .../composer/config/loader/ConfigLoader.java | 38 ++++++ .../config/loader/ConfigLoaderUtils.java | 23 ++++ .../config/loader/ConfigParsingException.java | 28 +++++ .../config/loader/FileConfigLoader.java | 35 ++++++ .../loader/ModResourceConfigLoader.java | 35 ++++++ .../config/loader/ResourceConfigLoader.java | 51 ++++++++ .../composer/runtime/ComposerRuntime.java | 116 ++++-------------- .../satori/composer/runtime/ModFactory.java | 49 ++++++++ .../com/satori/mods/suite/Composition.java | 2 +- mods-examples/big-blue-bus/build.gradle | 6 - .../com/satori/mods/examples/BigBlueBus.java | 6 +- mods-examples/clock/build.gradle | 8 +- .../com/satori/mods/examples/ClockApp.java | 6 +- mods-examples/clock2/build.gradle | 6 - mods-examples/hello-world/build.gradle | 6 - mods-examples/nws-usa-alerts/build.gradle | 6 - .../satori/mods/examples/NwsUsaAlerts.java | 6 +- mods-examples/rtm-filter/build.gradle | 2 +- .../satori/mods/examples/RtmFilterApp.java | 15 ++- .../com/satori/mods/core/config/Config.java | 7 ++ .../mods/resources/ModResourceLoader.java | 24 ++-- 24 files changed, 407 insertions(+), 148 deletions(-) create mode 100644 composer/src/com/satori/composer/config/loader/CompositeConfigLoader.java create mode 100644 composer/src/com/satori/composer/config/loader/ConfigLoader.java create mode 100644 composer/src/com/satori/composer/config/loader/ConfigLoaderUtils.java create mode 100644 composer/src/com/satori/composer/config/loader/ConfigParsingException.java create mode 100644 composer/src/com/satori/composer/config/loader/FileConfigLoader.java create mode 100644 composer/src/com/satori/composer/config/loader/ModResourceConfigLoader.java create mode 100644 composer/src/com/satori/composer/config/loader/ResourceConfigLoader.java create mode 100644 composer/src/com/satori/composer/runtime/ModFactory.java diff --git a/build.gradle b/build.gradle index a837f67..cdddd1a 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ idea { subprojects { group 'com.satori' - version '0.1.3' + version '0.1.4-SNAPSHOT' apply plugin: 'java' diff --git a/composer/build.gradle b/composer/build.gradle index a4ff18e..3f78686 100644 --- a/composer/build.gradle +++ b/composer/build.gradle @@ -2,17 +2,19 @@ dependencies { compile project(':mods') compile 'com.google.protobuf:protobuf-java:3.3.1' + compile 'org.freemarker:freemarker:2.3.26-incubating' - compile 'net.sf.saxon:Saxon-HE:9.6.0-10' + compile 'net.sf.saxon:Saxon-HE:9.8.0-3' compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0.pr4' - compile 'org.slf4j:slf4j-api:1.7.25' + compile 'org.slf4j:slf4j-api:1.8.0-alpha2' + compile 'io.vertx:vertx-core:3.4.2' compile 'io.vertx:vertx-web:3.4.2' - compile 'org.javassist:javassist:3.21.0-GA' + compile 'org.javassist:javassist:3.22.0-CR2' testCompile 'junit:junit:4.+' - testCompile 'org.apache.commons:commons-jexl3:+' + testCompile 'org.mockito:mockito-core:2.+' } diff --git a/composer/src/com/satori/composer/config/loader/CompositeConfigLoader.java b/composer/src/com/satori/composer/config/loader/CompositeConfigLoader.java new file mode 100644 index 0000000..c920eec --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/CompositeConfigLoader.java @@ -0,0 +1,68 @@ +package com.satori.composer.config.loader; + +import java.util.*; + +import com.fasterxml.jackson.databind.*; + +/** + * Load Mod configuration, looking at a few places. + */ +public class CompositeConfigLoader implements ConfigLoader { + + private final Iterable loaders; + + public CompositeConfigLoader(Iterable loaders) { + this.loaders = loaders; + } + + public CompositeConfigLoader(ConfigLoader... loaders) { + this.loaders = Arrays.stream(loaders)::iterator; + } + + @Override + public JsonNode tryLoad() throws ConfigParsingException { + return tryLoad(loaders); + } + + /** + * Load configuration trying all supplied configuration sources in turn. + */ + public static JsonNode tryLoad(ConfigLoader... loaders) throws ConfigParsingException { + if(loaders == null){ + return null; + } + return tryLoad(Arrays.stream(loaders)::iterator); + } + + public static JsonNode tryLoad(Iterable loaders) throws ConfigParsingException { + if(loaders == null){ + return null; + } + for (ConfigLoader l : loaders) { + if (l == null) { + continue; + } + JsonNode result = l.tryLoad(); + if (result != null) { + return result; + } + } + return null; + } + + public static JsonNode load(ConfigLoader... loaders) throws Exception { + JsonNode result = tryLoad(loaders); + if(result != null){ + return result; + } + throw new Exception("not found"); + } + + public static JsonNode load(Iterable loaders) throws Exception { + JsonNode result = tryLoad(loaders); + if(result != null){ + return result; + } + throw new Exception("not found"); + } +} diff --git a/composer/src/com/satori/composer/config/loader/ConfigLoader.java b/composer/src/com/satori/composer/config/loader/ConfigLoader.java new file mode 100644 index 0000000..e73df84 --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/ConfigLoader.java @@ -0,0 +1,38 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.core.config.*; + +import java.io.*; +import java.nio.file.*; + +import com.fasterxml.jackson.databind.*; + +public interface ConfigLoader { + + JsonNode tryLoad() throws ConfigParsingException; + + default JsonNode load() throws Exception{ + JsonNode result = tryLoad(); + if(result != null){ + return result; + } + throw new Exception("not found"); + } + + static ConfigLoader fromFile(Path path){ + return ()->{ + if (path == null) { + return null; + } + try (final Reader reader = Files.newBufferedReader(path)) { + return Config.mapper.readTree(reader); + } catch (FileNotFoundException e) { + return null; + } catch (Exception e) { + throw new ConfigParsingException(e); + } + }; + } + + +} diff --git a/composer/src/com/satori/composer/config/loader/ConfigLoaderUtils.java b/composer/src/com/satori/composer/config/loader/ConfigLoaderUtils.java new file mode 100644 index 0000000..ade387e --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/ConfigLoaderUtils.java @@ -0,0 +1,23 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.core.config.*; + +import java.io.*; + +import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.databind.*; + +public class ConfigLoaderUtils { + + public static JsonNode parseConfigString(String config) throws ConfigParsingException { + try { + return Config.mapper.readTree(config); + } catch (JsonParseException e) { + throw new ConfigParsingException( + String.format("Can't parse configuration: '%s'", config), e + ); + } catch (IOException e) { + throw new IllegalStateException("IOException while parsing JSON from a String"); + } + } +} diff --git a/composer/src/com/satori/composer/config/loader/ConfigParsingException.java b/composer/src/com/satori/composer/config/loader/ConfigParsingException.java new file mode 100644 index 0000000..bf2aaf2 --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/ConfigParsingException.java @@ -0,0 +1,28 @@ +package com.satori.composer.config.loader; + +public class ConfigParsingException extends Exception { + + ConfigParsingException() { + super(createErrorMessage(null)); + } + + ConfigParsingException(String config) { + super(createErrorMessage(config)); + } + + public ConfigParsingException(String config, Throwable cause) { + super(createErrorMessage(config), cause); + } + + public ConfigParsingException(Throwable cause) { + super(createErrorMessage(null), cause); + } + + private static String createErrorMessage(String config){ + if(config != null){ + return String.format("Can't parse configuration: '%s'", config); + } + + return "Can't parse configuration"; + } +} diff --git a/composer/src/com/satori/composer/config/loader/FileConfigLoader.java b/composer/src/com/satori/composer/config/loader/FileConfigLoader.java new file mode 100644 index 0000000..4ae27ae --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/FileConfigLoader.java @@ -0,0 +1,35 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.core.config.*; + +import java.io.*; +import java.nio.file.*; + +import com.fasterxml.jackson.databind.*; + +public class FileConfigLoader implements ConfigLoader { + + private final Path path; + + public FileConfigLoader(Path path) { + this.path = path; + } + + @Override + public JsonNode tryLoad() throws ConfigParsingException { + if (path == null) { + return null; + } + File file = path.toFile(); + if(!file.exists() || !file.isFile()){ + return null; + } + try (final Reader reader = Files.newBufferedReader(path)) { + return Config.mapper.readTree(reader); + } catch (FileNotFoundException e) { + return null; + } catch (Exception e) { + throw new ConfigParsingException(e); + } + } +} diff --git a/composer/src/com/satori/composer/config/loader/ModResourceConfigLoader.java b/composer/src/com/satori/composer/config/loader/ModResourceConfigLoader.java new file mode 100644 index 0000000..0993d90 --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/ModResourceConfigLoader.java @@ -0,0 +1,35 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.resources.*; + +import java.util.function.*; + +import com.fasterxml.jackson.databind.*; + +/** + * Get Mod configuration from a resource file bundled in the JAR. + */ +public class ModResourceConfigLoader implements ConfigLoader { + + private final String resourceName; + + public ModResourceConfigLoader(String resourceName) { + this.resourceName = resourceName; + } + + public ModResourceConfigLoader(Supplier resourceName) { + this.resourceName = resourceName != null ? resourceName.get() : null; + } + + @Override + public JsonNode tryLoad() throws ConfigParsingException { + if(resourceName == null || resourceName.isEmpty()){ + return null; + } + try { + return ModResourceLoader.tryLoadAsJson(resourceName); + } catch (Exception e) { + throw new ConfigParsingException(e); + } + } +} diff --git a/composer/src/com/satori/composer/config/loader/ResourceConfigLoader.java b/composer/src/com/satori/composer/config/loader/ResourceConfigLoader.java new file mode 100644 index 0000000..014a086 --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/ResourceConfigLoader.java @@ -0,0 +1,51 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.core.config.*; +import com.satori.mods.resources.*; + +import java.io.*; +import java.util.function.*; + +import com.fasterxml.jackson.databind.*; + +/** + * Get Mod configuration from a resource file bundled in the JAR. + */ +public class ResourceConfigLoader implements ConfigLoader { + + private final String resourceName; + private final ClassLoader classLoader; + + public ResourceConfigLoader(String resourceName) { + this(ModResourceLoader.class.getClassLoader(), resourceName); + } + + public ResourceConfigLoader(Supplier resourceName) { + this(resourceName.get()); + } + + public ResourceConfigLoader(ClassLoader classLoader, String resourceName) { + this.resourceName = resourceName; + this.classLoader = classLoader; + } + + public ResourceConfigLoader(ClassLoader classLoader, Supplier resourceName) { + this(classLoader, resourceName.get()); + } + + @Override + public JsonNode tryLoad() throws ConfigParsingException { + if(resourceName == null || resourceName.isEmpty()){ + return null; + } + + try (final InputStream inputStream = classLoader.getResourceAsStream(resourceName)) { + if (inputStream == null) { + return null; + } + return Config.mapper.readTree(inputStream); + } catch (Exception e){ + throw new ConfigParsingException(e); + } + } +} diff --git a/composer/src/com/satori/composer/runtime/ComposerRuntime.java b/composer/src/com/satori/composer/runtime/ComposerRuntime.java index 247c0fc..f8da57b 100644 --- a/composer/src/com/satori/composer/runtime/ComposerRuntime.java +++ b/composer/src/com/satori/composer/runtime/ComposerRuntime.java @@ -1,14 +1,10 @@ package com.satori.composer.runtime; +import com.satori.composer.config.loader.*; import com.satori.mods.api.*; import com.satori.mods.core.config.*; -import com.satori.mods.resources.*; import com.satori.mods.suite.*; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; - import com.fasterxml.jackson.databind.*; import io.netty.util.*; import io.vertx.core.*; @@ -16,87 +12,32 @@ import org.slf4j.*; public class ComposerRuntime { - public static final Logger log = LoggerFactory.getLogger(ComposerRuntime.class); - public static final String defaultRuntimeConfigPath = "config.json"; - public static final String CONFIG_PATH_PROP = "mod.config"; - public static final String CONFIG_PATH_ENV = "MOD_CONFIG"; - - // public methods + private static final Logger log = LoggerFactory.getLogger(ComposerRuntime.class); - public static String resolveConfigPath(/*CommandLine cmd*/) { - String result; - - // TODO: add option to specify mod config path in command line arguments? - /*result = cmd.getOptionValue("modConfigPath", null); - if (result != null && !result.isEmpty()) { - return result; - }*/ - - result = System.getProperty(CONFIG_PATH_PROP); - if (result != null && !result.isEmpty()) { - return result; - } - - result = System.getenv(CONFIG_PATH_ENV); - if (result != null && !result.isEmpty()) { - return result; - } - - return defaultRuntimeConfigPath; + /** + * Starts composer with specified config loader. + */ + public static Vertx start(ConfigLoader configLoader) throws Exception { + return start(configLoader.load()); } - public static ComposerRuntimeConfig loadConfig(String configPath) throws Exception { - try (InputStream stream = ModResourceLoader.loadAsStream(configPath)) { - return Config.parse(stream, ComposerRuntimeConfig.class); - } - } - - public static ComposerRuntimeConfig loadConfig() throws Exception { - String configPath = resolveConfigPath(); - return loadConfig(configPath); - } - - public static IMod createMod(String className, JsonNode config) { - - final Class modClass; - try { - modClass = Class.forName(className).asSubclass(IMod.class); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - - Constructor[] ctors = modClass.getDeclaredConstructors(); - Class[] configParams = new Class[]{JsonNode.class}; - Constructor defaultCtor = null; - - for (Constructor ctor : ctors) { - Class[] params = ctor.getParameterTypes(); - if (params.length == 0) { - defaultCtor = ctor; - } else if (Arrays.equals(params, configParams)) { - try { - return (IMod) ctor.newInstance(config); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - } - if (defaultCtor == null) { - throw new RuntimeException("matching constructors for mod not found"); - } - - try { - return (IMod) defaultCtor.newInstance(); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } + public static Vertx start(JsonNode config) throws Exception { + return start(Config.parseAndValidate(config, ComposerRuntimeConfig.class)); } public static Vertx start(ComposerRuntimeConfig config) throws Exception { + prepare(); + if (config == null) { + throw new InvalidConfigException("Config must not be null"); + } + config.validate(); return start(new Composition(config.mods), config); } - public static Vertx start(IMod mod, ComposerRuntimeConfig config) throws Exception { + /** + * Main entry point to start composer. + */ + private static Vertx start(IMod mod, ComposerRuntimeConfig config) throws Exception { final Vertx vertx; vertx = createVertx(); vertx.exceptionHandler(cause -> { @@ -116,34 +57,27 @@ public static Vertx start(IMod mod, ComposerRuntimeConfig config) throws Excepti } public static Vertx start(IMod mod) throws Exception { + prepare(); + ComposerRuntimeConfig config = new ComposerRuntimeConfig(); config.validate(); return start(mod, config); } - // private methods - private static Vertx createVertx() { - VertxOptions vertxOpts = new VertxOptions(); + VertxOptions vertxOpts = new VertxOptions() + .setEventLoopPoolSize(1); return Vertx.vertx(vertxOpts); } - // entry point - public static void prepare() throws Exception { System.setProperty( - io.vertx.core.logging.LoggerFactory.LOGGER_DELEGATE_FACTORY_CLASS_NAME, "io.vertx.core.logging.SLF4JLogDelegateFactory" + io.vertx.core.logging.LoggerFactory.LOGGER_DELEGATE_FACTORY_CLASS_NAME, + "io.vertx.core.logging.SLF4JLogDelegateFactory" ); System.setProperty( FileResolver.DISABLE_CP_RESOLVING_PROP_NAME, "true" ); ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID); } - - public static void main(String... args) throws Exception { - prepare(); - ComposerRuntimeConfig config = loadConfig(); - config.validate(); - start(config); - } -} +} \ No newline at end of file diff --git a/composer/src/com/satori/composer/runtime/ModFactory.java b/composer/src/com/satori/composer/runtime/ModFactory.java new file mode 100644 index 0000000..553d6b0 --- /dev/null +++ b/composer/src/com/satori/composer/runtime/ModFactory.java @@ -0,0 +1,49 @@ +package com.satori.composer.runtime; + +import com.satori.mods.api.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.fasterxml.jackson.databind.*; +import org.slf4j.*; + +public class ModFactory { + private static final Logger log = LoggerFactory.getLogger(ModFactory.class); + + public static IMod create(String className, JsonNode config) { + + final Class modClass; + try { + modClass = Class.forName(className).asSubclass(IMod.class); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + Constructor[] ctors = modClass.getDeclaredConstructors(); + Class[] configParams = new Class[]{JsonNode.class}; + Constructor defaultCtor = null; + + for (Constructor ctor : ctors) { + Class[] params = ctor.getParameterTypes(); + if (params.length == 0) { + defaultCtor = ctor; + } else if (Arrays.equals(params, configParams)) { + try { + return (IMod) ctor.newInstance(config); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + } + if (defaultCtor == null) { + throw new RuntimeException("matching constructors for mod not found"); + } + + try { + return (IMod) defaultCtor.newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/composer/src/com/satori/mods/suite/Composition.java b/composer/src/com/satori/mods/suite/Composition.java index 1e25e92..a8aeac3 100644 --- a/composer/src/com/satori/mods/suite/Composition.java +++ b/composer/src/com/satori/mods/suite/Composition.java @@ -32,7 +32,7 @@ public Composition(CompositionSettings config) throws Exception { public Composition(HashMap mods) { mods.forEach((modName, modConf) -> { - IMod mod = ComposerRuntime.createMod(modConf.type, modConf.settings); + IMod mod = ModFactory.create(modConf.type, modConf.settings); addMod(modName, mod, modConf.connectors); }); } diff --git a/mods-examples/big-blue-bus/build.gradle b/mods-examples/big-blue-bus/build.gradle index 8f9e1bc..2c4107b 100644 --- a/mods-examples/big-blue-bus/build.gradle +++ b/mods-examples/big-blue-bus/build.gradle @@ -7,14 +7,8 @@ applicationName = projectDir.name dependencies { compile project(':composer') - compile 'org.slf4j:slf4j-api:1.8.+' compile 'org.slf4j:slf4j-jdk14:1.8.+' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.+' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+' - compile 'com.fasterxml.jackson.module:jackson-module-afterburner:2.9.+' - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.+' - testCompile 'junit:junit:4.+' } diff --git a/mods-examples/big-blue-bus/src/com/satori/mods/examples/BigBlueBus.java b/mods-examples/big-blue-bus/src/com/satori/mods/examples/BigBlueBus.java index 26721e9..8ee22ce 100644 --- a/mods-examples/big-blue-bus/src/com/satori/mods/examples/BigBlueBus.java +++ b/mods-examples/big-blue-bus/src/com/satori/mods/examples/BigBlueBus.java @@ -15,9 +15,9 @@ public static void main(String... args) throws Exception { try (final InputStream is = ModResourceLoader.loadAsStream("log.properties")) { LogManager.getLogManager().readConfiguration(is); } - ComposerRuntimeConfig config = ComposerRuntime.loadConfig("config.json"); - config.validate(); - ComposerRuntime.start(config); + ComposerRuntime.start(ModResourceLoader.loadAsConfigAndValidate( + "config.json", ComposerRuntimeConfig.class + )); } } diff --git a/mods-examples/clock/build.gradle b/mods-examples/clock/build.gradle index 59cd1cf..0b0e180 100644 --- a/mods-examples/clock/build.gradle +++ b/mods-examples/clock/build.gradle @@ -1,20 +1,14 @@ apply plugin: 'application' apply from: '../examples.gradle' -mainClassName = 'com.satori.mods.examples.ClocksApp' +mainClassName = 'com.satori.mods.examples.ClockApp' applicationName = projectDir.name dependencies { compile project(':composer') - compile 'org.slf4j:slf4j-api:1.8.+' compile 'org.slf4j:slf4j-jdk14:1.8.+' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.+' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+' - compile 'com.fasterxml.jackson.module:jackson-module-afterburner:2.9.+' - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.+' - testCompile 'junit:junit:4.+' } diff --git a/mods-examples/clock/src/com/satori/mods/examples/ClockApp.java b/mods-examples/clock/src/com/satori/mods/examples/ClockApp.java index f63b149..330cee9 100644 --- a/mods-examples/clock/src/com/satori/mods/examples/ClockApp.java +++ b/mods-examples/clock/src/com/satori/mods/examples/ClockApp.java @@ -15,9 +15,9 @@ public static void main(String... args) throws Exception { try (final InputStream is = ModResourceLoader.loadAsStream("log.properties")) { LogManager.getLogManager().readConfiguration(is); } - ComposerRuntimeConfig config = ComposerRuntime.loadConfig("config.json"); - config.validate(); - ComposerRuntime.start(config); + ComposerRuntime.start(ModResourceLoader.loadAsConfigAndValidate( + "config.json", ComposerRuntimeConfig.class + )); } } diff --git a/mods-examples/clock2/build.gradle b/mods-examples/clock2/build.gradle index a0b306d..5479cb1 100644 --- a/mods-examples/clock2/build.gradle +++ b/mods-examples/clock2/build.gradle @@ -7,14 +7,8 @@ applicationName = projectDir.name dependencies { compile project(':composer') - compile 'org.slf4j:slf4j-api:1.8.+' compile 'org.slf4j:slf4j-jdk14:1.8.+' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.+' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+' - compile 'com.fasterxml.jackson.module:jackson-module-afterburner:2.9.+' - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.+' - testCompile 'junit:junit:4.+' } diff --git a/mods-examples/hello-world/build.gradle b/mods-examples/hello-world/build.gradle index 68f9165..663903d 100644 --- a/mods-examples/hello-world/build.gradle +++ b/mods-examples/hello-world/build.gradle @@ -7,14 +7,8 @@ applicationName = projectDir.name dependencies { compile project(':composer') - compile 'org.slf4j:slf4j-api:1.8.+' compile 'org.slf4j:slf4j-jdk14:1.8.+' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.+' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+' - compile 'com.fasterxml.jackson.module:jackson-module-afterburner:2.9.+' - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.+' - testCompile 'junit:junit:4.+' } diff --git a/mods-examples/nws-usa-alerts/build.gradle b/mods-examples/nws-usa-alerts/build.gradle index 8359c8c..9c4c63a 100644 --- a/mods-examples/nws-usa-alerts/build.gradle +++ b/mods-examples/nws-usa-alerts/build.gradle @@ -7,13 +7,7 @@ applicationName = projectDir.name dependencies { compile project(':composer') - compile 'org.slf4j:slf4j-api:1.8.+' compile 'org.slf4j:slf4j-jdk14:1.8.+' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.+' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.+' - compile 'com.fasterxml.jackson.module:jackson-module-afterburner:2.9.+' - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.+' - testCompile 'junit:junit:4.+' } \ No newline at end of file diff --git a/mods-examples/nws-usa-alerts/src/com/satori/mods/examples/NwsUsaAlerts.java b/mods-examples/nws-usa-alerts/src/com/satori/mods/examples/NwsUsaAlerts.java index 162247a..63537f1 100644 --- a/mods-examples/nws-usa-alerts/src/com/satori/mods/examples/NwsUsaAlerts.java +++ b/mods-examples/nws-usa-alerts/src/com/satori/mods/examples/NwsUsaAlerts.java @@ -15,8 +15,8 @@ public static void main(String... args) throws Exception { try (final InputStream is = ModResourceLoader.loadAsStream("log.properties")) { LogManager.getLogManager().readConfiguration(is); } - ComposerRuntimeConfig config = ComposerRuntime.loadConfig("config.json"); - config.validate(); - ComposerRuntime.start(config); + ComposerRuntime.start(ModResourceLoader.loadAsConfigAndValidate( + "config.json", ComposerRuntimeConfig.class + )); } } diff --git a/mods-examples/rtm-filter/build.gradle b/mods-examples/rtm-filter/build.gradle index d4b4973..9c4c63a 100644 --- a/mods-examples/rtm-filter/build.gradle +++ b/mods-examples/rtm-filter/build.gradle @@ -7,7 +7,7 @@ applicationName = projectDir.name dependencies { compile project(':composer') - compileOnly 'org.slf4j:slf4j-api:1.8.+' + compile 'org.slf4j:slf4j-jdk14:1.8.+' testCompile 'junit:junit:4.+' } \ No newline at end of file diff --git a/mods-examples/rtm-filter/src/com/satori/mods/examples/RtmFilterApp.java b/mods-examples/rtm-filter/src/com/satori/mods/examples/RtmFilterApp.java index 4360074..148c602 100644 --- a/mods-examples/rtm-filter/src/com/satori/mods/examples/RtmFilterApp.java +++ b/mods-examples/rtm-filter/src/com/satori/mods/examples/RtmFilterApp.java @@ -1,14 +1,23 @@ package com.satori.mods.examples; import com.satori.composer.runtime.*; +import com.satori.mods.resources.*; + +import java.io.*; +import java.util.logging.*; public class RtmFilterApp { // entry point public static void main(String... args) throws Exception { - ComposerRuntimeConfig config = ComposerRuntime.loadConfig("config.json"); - config.validate(); - new ComposerRuntime().start(config); + ComposerRuntime.prepare(); + try (final InputStream is = ModResourceLoader.loadAsStream("log.properties")) { + LogManager.getLogManager().readConfiguration(is); + } + ComposerRuntime.start(ModResourceLoader.loadAsConfigAndValidate( + "config.json", ComposerRuntimeConfig.class + )); + } } diff --git a/mods/src/com/satori/mods/core/config/Config.java b/mods/src/com/satori/mods/core/config/Config.java index c984ab4..0d170be 100644 --- a/mods/src/com/satori/mods/core/config/Config.java +++ b/mods/src/com/satori/mods/core/config/Config.java @@ -24,17 +24,24 @@ public static T parse(InputStream stream, Class cls) throw } public static T parseAndValidate(InputStream stream, Class cls) throws Exception { + if(stream == null){ + return null; + } T result = parse(stream, cls); result.validate(); return result; } public static T parseAndValidate(JsonNode tree, Class cls) throws Exception { + if(tree == null){ + return null; + } T result = mapper.treeToValue(tree, cls); result.validate(); return result; } + @Override public String toString() { try { diff --git a/mods/src/com/satori/mods/resources/ModResourceLoader.java b/mods/src/com/satori/mods/resources/ModResourceLoader.java index 6e1a909..f8d8976 100644 --- a/mods/src/com/satori/mods/resources/ModResourceLoader.java +++ b/mods/src/com/satori/mods/resources/ModResourceLoader.java @@ -10,7 +10,11 @@ public class ModResourceLoader { - public static InputStream tryLoadAsStream(String resourceName) throws ModResourceNotFoundException { + public static InputStream tryLoadAsStream(String resourceName) { + + if (resourceName == null || resourceName.trim().isEmpty()) { + return null; + } // first try to get specified resource using file system @@ -54,7 +58,7 @@ public static JsonNode tryLoadAsJson(String resourceName) throws Exception { } } - public static T tryLoadConfig(String resourceName, Class cls) throws Exception { + public static T tryLoadAsConfig(String resourceName, Class cls) throws Exception { try (final InputStream inputStream = loadAsStream(resourceName)) { if (inputStream == null) { return null; @@ -72,7 +76,7 @@ public static InputStream loadAsStream(String resourceName) throws ModResourceNo } public static String loadAsString(String resourceName) throws Exception { - final String res = loadAsString(resourceName); + final String res = tryLoadAsString(resourceName); if (res == null) { throw new ModResourceNotFoundException(resourceName); } @@ -81,18 +85,24 @@ public static String loadAsString(String resourceName) throws Exception { public static JsonNode loadAsJson(String resourceName) throws Exception { - final JsonNode res = loadAsJson(resourceName); + final JsonNode res = tryLoadAsJson(resourceName); if (res == null) { throw new ModResourceNotFoundException(resourceName); } return res; } - public static T loadConfig(String resourceName, Class cls) throws Exception { - final T res = loadConfig(resourceName, cls); + public static T loadAsConfig(String resourceName, Class cls) throws Exception { + final T res = tryLoadAsConfig(resourceName, cls); if (res == null) { throw new ModResourceNotFoundException(resourceName); } return res; } -} + + public static T loadAsConfigAndValidate(String resourceName, Class cls) throws Exception { + final T res = loadAsConfig(resourceName, cls); + res.validate(); + return res; + } +} \ No newline at end of file From 2b9541454b371b11c2819805b5fe8008b4f50ce7 Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Wed, 19 Jul 2017 16:20:04 -0700 Subject: [PATCH 2/8] config-loader: +StringConfigLoader --- build.gradle | 2 +- .../config/loader/StringConfigLoader.java | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 composer/src/com/satori/composer/config/loader/StringConfigLoader.java diff --git a/build.gradle b/build.gradle index cdddd1a..100ccaa 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ idea { subprojects { group 'com.satori' - version '0.1.4-SNAPSHOT' + version '0.1.5-SNAPSHOT' apply plugin: 'java' diff --git a/composer/src/com/satori/composer/config/loader/StringConfigLoader.java b/composer/src/com/satori/composer/config/loader/StringConfigLoader.java new file mode 100644 index 0000000..5866d2f --- /dev/null +++ b/composer/src/com/satori/composer/config/loader/StringConfigLoader.java @@ -0,0 +1,45 @@ +package com.satori.composer.config.loader; + +import com.satori.mods.core.config.*; + +import java.util.function.*; + +import com.fasterxml.jackson.databind.*; + +public class StringConfigLoader implements ConfigLoader { + + private final String string; + + public StringConfigLoader(String string) { + this.string = string; + } + + public StringConfigLoader(Supplier string) { + this.string = string != null ? string.get() : null; + } + + @Override + public JsonNode tryLoad() throws ConfigParsingException { + return tryLoad(string); + } + + public static JsonNode tryLoad(String string) throws ConfigParsingException { + if (string == null || string.isEmpty()) { + return null; + } + try { + return Config.mapper.readTree(string); + } catch (Exception e) { + throw new ConfigParsingException(e); + } + } + + public static JsonNode load(String string) throws Exception { + JsonNode result = tryLoad(string); + if (result != null) { + return result; + } + throw new Exception("not found"); + } + +} From 1ba4a202dceb25643ad0d309976cb4a53aa0edcd Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Wed, 19 Jul 2017 16:36:12 -0700 Subject: [PATCH 3/8] update maven dependencies in readme --- readme.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 233b3f1..c4d6e49 100644 --- a/readme.md +++ b/readme.md @@ -73,13 +73,28 @@ - [Async support library](docs/async/readme.md) ### Maven +##### releases: ```xml com.satori satori-composer - 0.0.6+ + 0.1.+ ``` +##### snapshots: +```xml + + https://oss.sonatype.org/content/repositories/snapshots/ + +``` +```xml + + com.satori + satori-composer + 0.1.+-SNAPSHOT + +``` + ### Download [Latest release](https://github.com/satori-com/satori-composer/releases/latest) From 0b6be6f0365eab4c8cf9fcad631e08505fb6f37c Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Wed, 19 Jul 2017 17:48:00 -0700 Subject: [PATCH 4/8] use org.slf4j v1.7.25 by default --- build.gradle | 2 +- composer/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 100ccaa..8c6f6a5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ idea { subprojects { group 'com.satori' - version '0.1.5-SNAPSHOT' + version '0.1.6-SNAPSHOT' apply plugin: 'java' diff --git a/composer/build.gradle b/composer/build.gradle index 3f78686..8c5a7ee 100644 --- a/composer/build.gradle +++ b/composer/build.gradle @@ -7,7 +7,7 @@ dependencies { compile 'net.sf.saxon:Saxon-HE:9.8.0-3' compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0.pr4' - compile 'org.slf4j:slf4j-api:1.8.0-alpha2' + compile 'org.slf4j:slf4j-api:1.7.25' compile 'io.vertx:vertx-core:3.4.2' compile 'io.vertx:vertx-web:3.4.2' From de546d24bc47ee53e35482e96afa38f991a79ee3 Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Mon, 31 Jul 2017 16:01:33 -0700 Subject: [PATCH 5/8] examples: remove APP-KEYS --- .../res/com/satori/mods/resources/publisher.json | 9 +++++---- .../res/com/satori/mods/resources/config.json | 9 +++++---- .../res/com/satori/mods/resources/config.json | 10 +++++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/mods-examples/hello-world/res/com/satori/mods/resources/publisher.json b/mods-examples/hello-world/res/com/satori/mods/resources/publisher.json index ddf7f21..7fd19b5 100644 --- a/mods-examples/hello-world/res/com/satori/mods/resources/publisher.json +++ b/mods-examples/hello-world/res/com/satori/mods/resources/publisher.json @@ -1,7 +1,8 @@ { - "channel": "hello-world", - "host": "he3rv0pp.api.satori.com", + "channel": "YOUR_CHANNEL", + "host": "YOU_HOST", //no wss scheme, just host: x.satori.com "ssl": true, - "args": {"appkey": "dFDa4104a3913EE4DbdDedd257ea54F1"}, - "auth": {"role": "demo", "secret": "dBdaE8021926Ac602EdD4c184e25d09E"} + "args": {"appkey": "YOU_APPKEY"} //, + // enable if your permission needs auth + //"auth": {"role": "YOUR_ROLE","secret": "YOUR_SECRET"} } diff --git a/mods-examples/nws-usa-alerts/res/com/satori/mods/resources/config.json b/mods-examples/nws-usa-alerts/res/com/satori/mods/resources/config.json index 14b005a..23a3ddb 100644 --- a/mods-examples/nws-usa-alerts/res/com/satori/mods/resources/config.json +++ b/mods-examples/nws-usa-alerts/res/com/satori/mods/resources/config.json @@ -35,11 +35,12 @@ "type": "com.satori.mods.suite.RtmPublishMod", "connectors": "filter", "settings": { - "channel": "nws-usa-alerts", - "host": "he3rv0pp.api.satori.com", //just host, no wss scheme + "channel": "YOUR_CHANNEL", + "host": "YOU_HOST", //no wss scheme, just host: x.satori.com "ssl": true, - "args": {"appkey": "dFDa4104a3913EE4DbdDedd257ea54F1"}, - "auth": {"role": "demo", "secret": "dBdaE8021926Ac602EdD4c184e25d09E"} + "args": {"appkey": "YOU_APPKEY"} //, + // enable if your publish permission needs auth + //"auth": {"role": "YOUR_ROLE","secret": "YOUR_SECRET"} } } } diff --git a/mods-examples/rtm-filter/res/com/satori/mods/resources/config.json b/mods-examples/rtm-filter/res/com/satori/mods/resources/config.json index d4f2e6f..af8f8bc 100644 --- a/mods-examples/rtm-filter/res/com/satori/mods/resources/config.json +++ b/mods-examples/rtm-filter/res/com/satori/mods/resources/config.json @@ -3,12 +3,12 @@ "subscriber": { "type": "com.satori.mods.suite.RtmSubscribeMod", "settings": { - "channel": "vehicles", - "filter": "SELECT * FROM `stream.vehicles` WHERE vehicle.agency = \"ritchies\"", - "host": "xe9k0020.api.satori.com", + "channel": "YOUR_CHANNEL", + "host": "YOU_HOST", //no wss scheme, just host: x.satori.com "ssl": true, - "args": {"appkey": "Fdcc4a0d84cE75314B069F20E787d6f8"}, - "auth": {"role": "client", "secret": "ADa6EbC63A9e7B73bFEdffBCC4C5B6e0"} + "args": {"appkey": "YOU_APPKEY"} //, + // enable if your permission needs auth + //"auth": {"role": "YOUR_ROLE","secret": "YOUR_SECRET"} } }, "printer": { From f58d60e4fe30bd71beea4955f566fd41c70e6ab3 Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Mon, 31 Jul 2017 16:32:29 -0700 Subject: [PATCH 6/8] update dependencies --- composer/build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/composer/build.gradle b/composer/build.gradle index 8c5a7ee..4ea406f 100644 --- a/composer/build.gradle +++ b/composer/build.gradle @@ -5,16 +5,15 @@ dependencies { compile 'org.freemarker:freemarker:2.3.26-incubating' compile 'net.sf.saxon:Saxon-HE:9.8.0-3' - compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0.pr4' + compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0' compile 'org.slf4j:slf4j-api:1.7.25' compile 'io.vertx:vertx-core:3.4.2' compile 'io.vertx:vertx-web:3.4.2' - compile 'org.javassist:javassist:3.22.0-CR2' + compile 'org.javassist:javassist:3.21.0-GA' testCompile 'junit:junit:4.+' - testCompile 'org.mockito:mockito-core:2.+' } From 48a3567f49623d3b1e096c99f85b383a22b3c55e Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Mon, 31 Jul 2017 16:35:35 -0700 Subject: [PATCH 7/8] version: 0.1.7-SNAPSHOT --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8c6f6a5..8deaeda 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ idea { subprojects { group 'com.satori' - version '0.1.6-SNAPSHOT' + version '0.1.7-SNAPSHOT' apply plugin: 'java' From 7c985ca98f5d6713154dd967f6ed5502732cd626 Mon Sep 17 00:00:00 2001 From: akolomentsev Date: Mon, 31 Jul 2017 16:38:42 -0700 Subject: [PATCH 8/8] version: 0.1.7 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8deaeda..09868a0 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ idea { subprojects { group 'com.satori' - version '0.1.7-SNAPSHOT' + version '0.1.7' apply plugin: 'java'