package org.kevoree.bootstrap; import com.typesafe.config.Config; import org.kevoree.ContainerNode; import org.kevoree.ContainerRoot; import org.kevoree.NetworkInfo; import org.kevoree.Value; import org.kevoree.annotation.KevoreeInject; import org.kevoree.api.BootstrapService; import org.kevoree.api.KevScriptService; import org.kevoree.api.handler.UpdateCallback; import org.kevoree.api.telemetry.TelemetryEvent; import org.kevoree.api.telemetry.TelemetryListener; import org.kevoree.bootstrap.kernel.KevoreeCLKernel; import org.kevoree.bootstrap.reflect.Injector; import org.kevoree.bootstrap.util.ConfigHelper; import org.kevoree.core.KevoreeCoreBean; import org.kevoree.kevscript.KevScriptEngine; import org.kevoree.log.Log; import org.kevoree.microkernel.KevoreeKernel; import org.kevoree.pmodeling.api.compare.ModelCompare; import org.kevoree.pmodeling.api.json.JSONModelLoader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created with IntelliJ IDEA. * User: duke * Date: 25/11/2013 * Time: 23:47 */ public class Bootstrap { private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static final String defaultNodeName = "node0"; private KevoreeKernel microKernel; private KevoreeCoreBean core; private KevScriptEngine kevScriptEngine; private JSONModelLoader jsonLoader; private int exitId; private static HashMap<String, String> ctxVars = new HashMap<String, String>(); private TelemetryListener telemetryListener; public Bootstrap(KevoreeKernel k, String nodeName, Config config) { //First initiate Security Manager to ensure that no Kill can be called on the JVM this.exitId = new AtomicInteger().incrementAndGet(); System.setSecurityManager(new KevoreeSecurityManager(this.exitId)); //Init all subObjects this.microKernel = k; // init log level String log = System.getProperty("log.level"); if ("DEBUG".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_DEBUG); } else if ("WARN".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_WARN); } else if ("INFO".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_INFO); } else if ("ERROR".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_ERROR); } else if ("TRACE".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_TRACE); } else if ("NONE".equalsIgnoreCase(log)) { Log.set(Log.LEVEL_NONE); } else { log = "INFO"; Log.set(Log.LEVEL_INFO); } Log.info("Log level= {}", log); Injector injector = new Injector(KevoreeInject.class); KevoreeCLKernel kernel = new KevoreeCLKernel(this, injector); String registryUrl = "http://"; if (config.getBoolean("registry.ssl")) { registryUrl = "https://"; } registryUrl += config.getString("registry.host"); if (registryUrl.endsWith("/")) { registryUrl = registryUrl.substring(0, registryUrl.length() - 1); } int port = config.getInt("registry.port"); if (port != 80) { registryUrl += ":" + port; } kevScriptEngine = new KevScriptEngine(registryUrl); core = new KevoreeCoreBean(kevScriptEngine); core.onStop(new KevoreeCoreBean.OnStopHandler() { public void execute() { Runtime.getRuntime().exit(exitId); } }); jsonLoader = core.getFactory().createJSONLoader(); // cross links core.setNodeName(nodeName); kernel.setNodeName(nodeName); kernel.setCore(core); injector.register(BootstrapService.class, kernel); injector.register(KevScriptService.class, kevScriptEngine); core.setBootstrapService(kernel); Log.info("Starting Kevoree using version: {}", core.getFactory().getVersion()); Log.info("Platform node name: {}", nodeName); core.start(); } public KevoreeCoreBean getCore() { return core; } public KevoreeKernel getKernel() { return microKernel; } public KevScriptEngine getKevScriptEngine() { return kevScriptEngine; } protected void registerTelemetryToLogListener() { if (telemetryListener == null) { telemetryListener = new TelemetryListener() { @Override public void notify(TelemetryEvent telemetryEvent) { if (telemetryEvent.type().equals("info")) { Log.info("[{}] {}", telemetryEvent.origin(), telemetryEvent.message()); } else if (telemetryEvent.type().equals("warn")) { Log.warn("[{}] {}", telemetryEvent.origin(), telemetryEvent.message()); } else if (telemetryEvent.type().equals("error")) { Log.error("[{}] {}{}", telemetryEvent.origin(), telemetryEvent.message(), telemetryEvent.stack()); } else { Log.debug("[{}] {}{}", telemetryEvent.origin(), telemetryEvent.message(), telemetryEvent.stack()); } } }; } core.addTelemetryListener(telemetryListener); } protected void unregisterTelemetryToLogListener() { if (telemetryListener != null) { core.removeTelemetryListener(telemetryListener); } } private void checkBootstrap(boolean succeed) { if (succeed) { Log.info("Bootstrap succeed"); } else { Log.info("Bootstrap failed"); System.exit(this.exitId); } } public void bootstrap(ContainerRoot model, UpdateCallback callback) { ContainerRoot emptyModel = initialModel(); core.getFactory().root(emptyModel); ModelCompare compare = core.getFactory().createModelCompare(); compare.merge(emptyModel, model).applyOn(emptyModel); core.update(emptyModel, callback, "/"); } public void bootstrap(ContainerRoot model) { bootstrap(model, new UpdateCallback() { @Override public void run(Boolean applied) { checkBootstrap(applied); } }); } private ContainerRoot initialModel() { return core.getKevoreeFactory().createContainerRoot(); } public void bootstrapFromKevScript(InputStream input, UpdateCallback callback) throws Exception { if (callback == null) { callback = new UpdateCallback() { @Override public void run(Boolean applied) { checkBootstrap(applied); } }; } ContainerRoot emptyModel = initialModel(); core.getFactory().root(emptyModel); for (ClassLoader cl : microKernel.getClassLoaders()) { InputStream is = cl.getResourceAsStream("KEV-INF/kevlib.json"); if (is != null) { try { ContainerRoot CLroot = (ContainerRoot) core.getFactory().createJSONLoader().loadModelFromStream(is).get(0); core.getFactory().root(CLroot); core.getFactory().createModelCompare().merge(emptyModel, CLroot).applyOn(emptyModel); } catch (Exception e) { e.printStackTrace(); } } } kevScriptEngine.executeFromStream(input, emptyModel, ctxVars); //Add network information ContainerNode currentNode = emptyModel.findNodesByID(core.getNodeName()); if (currentNode != null) { if (currentNode.findNetworkInformationByID("ip") == null) { NetworkInfo info = core.getFactory().createNetworkInfo(); info.setName("ip"); currentNode.addNetworkInformation(info); Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); int i = 0; for (NetworkInterface networkInterface : Collections.list(nets)) { if (networkInterface.isUp()) { Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); for (InetAddress inetAddress : Collections.list(inetAddresses)) { if (!inetAddress.isLoopbackAddress()) { Value netprop = core.getFactory().createValue(); netprop.setName(i + "_" + networkInterface.getName()); netprop.setValue(inetAddress.getHostAddress()); info.addValues(netprop); i++; } } } } } } core.update(emptyModel, callback, "/"); } public void bootstrapFromKevScript(InputStream input) throws Exception { this.bootstrapFromKevScript(input, null); } public void bootstrapFromFile(File input, UpdateCallback callback) throws Exception { FileInputStream fin = new FileInputStream(input); if (input.getName().endsWith(".kevs")) { bootstrapFromKevScript(fin, callback); } else { if (input.getName().endsWith(".json")) { bootstrap((ContainerRoot) jsonLoader.loadModelFromStream(fin).get(0), callback); } else { Log.error("Unable to bootstrap from file. Extension should be .kevs or .json (current: {})", input.getName().substring(input.getName().lastIndexOf("."))); } } fin.close(); } public void bootstrapFromFile(File input) throws Exception { this.bootstrapFromFile(input, null); } public void stop() { try { System.out.println(); // give some space if ^C is in the terminal if (core.isStarted()) { core.stop(); } Log.info("Stopped."); } catch (Throwable ex) { System.out.println("Error while stopping kevoree platform: " + ex.getMessage()); } } public static String createBootstrapScript(String nodeName, String version) { StringBuilder buffer = new StringBuilder(); buffer.append("add node0: JavaNode\n".replace("node0", nodeName)); buffer.append("add sync: WSGroup\n"); buffer.append("attach node0 sync\n".replace("node0", nodeName)); return buffer.toString(); } private static String shortId() { final StringBuilder builder = new StringBuilder(); final Random random = new Random(); for (int i = 0; i < 9; i++) { builder.append(CHARS.charAt(random.nextInt(CHARS.length()))); } return builder.toString(); } public static void main(String[] args) throws Exception { String nodeName = System.getProperty("node.name"); if (nodeName == null) { nodeName = defaultNodeName; } Pattern p = Pattern.compile("(%(%([a-zA-Z0-9_]+)%)%)"); Matcher m = p.matcher(nodeName); while (m.find()) { nodeName = shortId(); ctxVars.put(m.group(3), nodeName); } final Bootstrap boot = new Bootstrap(KevoreeKernel.self.get(), nodeName, ConfigHelper.get()); boot.registerTelemetryToLogListener(); if (boot.getKernel() == null) { throw new Exception("Kevoree as not be started from KCL microkernel context"); } final ClassLoader loader = Thread.currentThread().getContextClassLoader(); Runtime.getRuntime().addShutdownHook(new Thread("Shutdown Hook") { public void run() { Thread.currentThread().setContextClassLoader(loader); boot.stop(); } }); String bootstrapModel = System.getProperty("node.bootstrap"); try { if (bootstrapModel != null) { boot.bootstrapFromFile(new File(bootstrapModel)); } else { if (System.getProperty("node.script") != null) { boot.bootstrapFromKevScript(new ByteArrayInputStream(System.getProperty("node.script").getBytes())); } else { String version; if (boot.getCore().getFactory().getVersion().toLowerCase().contains("snapshot")) { version = "latest"; } else { version = "release"; } Log.info("Create minimal system with library in version {}", version); boot.bootstrapFromKevScript(new ByteArrayInputStream(createBootstrapScript(nodeName, version).getBytes())); } } } catch (Exception e) { e.printStackTrace(); } } }