All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.satori.composer.runtime.ComposerRuntime Maven / Gradle / Ivy

package com.satori.composer.runtime;

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.*;
import io.vertx.core.impl.*;
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
  
  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;
  }
  
  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(ComposerRuntimeConfig config) throws Exception {
    return start(new Composition(config.mods), config);
  }
  
  public static Vertx start(IMod mod, ComposerRuntimeConfig config) throws Exception {
    final Vertx vertx;
    vertx = createVertx();
    vertx.exceptionHandler(cause -> {
      log.error("terminating framework", cause);
      vertx.close();
    });
    
    vertx.deployVerticle(new ModVerticle(config, mod), ar -> {
      if (!ar.succeeded()) {
        log.error("failed to deploy mod verticle", ar.cause());
        vertx.close();
        return;
      }
      log.info("mod verticle deployed: deploymentId={}", ar.result());
    });
    return vertx;
  }
  
  public static Vertx start(IMod mod) throws Exception {
    ComposerRuntimeConfig config = new ComposerRuntimeConfig();
    config.validate();
    return start(mod, config);
  }
  
  // private methods
  
  private static Vertx createVertx() {
    VertxOptions vertxOpts = new VertxOptions();
    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"
    );
    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);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy