/** * */ package jframe.launcher; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jframe.launcher.api.Config; import jframe.launcher.api.DefConfig; import jframe.launcher.api.DefLauncher; import jframe.launcher.util.Program; import jframe.launcher.util.VmargsFile; /** * <p> * daemon运行 * <li>加载config.properties</li> * <li>判断是否daemon执行</li> * <li>写PID到daemon.pid</li> * <li>配置子进程(app.home),调用launcher启动子进程,默認launcher是FrameMain</li> * <li>监听子进程,若异常停止则重启</li> * <li>子进程正常关闭时,自己也关闭</li> * </p> * <p> * normal运行 * <li>加载config.properties</li> * <li>判断是否daemon执行</li> * <li>配置子进程(app.home),调用launcher启动子进程</li> * <li>正常终止自己</li> * </p> * <p> * 父子进程关系 * <li>父进程拷贝所有系统属性给子进程</li> * </p> * * @author dzh * @date Jan 31, 2016 2:16:53 PM * @since 1.0 */ public class MainLauncher extends DefLauncher { private static Logger LOG = LoggerFactory.getLogger(MainLauncher.class); public void launch(Config config) { String daemon = config.getConfig(Config.LAUNCH_MODE); if (Config.LAUNCH_MODE_DAEMON.equalsIgnoreCase(daemon)) { launchDaemon(config); } else { launchNormal(config); } } /** * @param conf */ private void launchNormal(Config config) { LOG.info("Launching normal mode!"); launchInternal(config); } private Process launchInternal(Config config) { String mainClazz = config.getConfig(Config.APP_MAIN); if (mainClazz == null || "".equals(mainClazz)) { mainClazz = Main.class.getName(); // LOG.warn("app.main is nil, use default main class {}", mainClazz); } List<String> list = new VmargsFile().loadVmargs(config.getConfig(Config.FILE_VMARGS)); for (int i = 0; i < list.size(); i++) { String arg = list.get(i); list.set(i, DefConfig.replace(config, arg)); } String conf = System.getProperty(Config.FILE_CONFIG, config.getConfig(Config.FILE_CONFIG)); if (conf != null) { list.add(0, "-Dfile.config=" + conf); } list.add(0, "-Dapp.home=" + config.getConfig(Config.APP_HOME)); list.add(0, "-Dlauncher=" + config.getConfig(Config.APP_LAUNCHER, "jframe.core.FrameLauncher")); list.add(0, "java"); list.add(mainClazz); ProcessBuilder pb = new ProcessBuilder(); pb.command(list); // pb.redirectErrorStream(true); Process p = null; try { p = pb.start(); } catch (IOException e) { LOG.error(e.getMessage()); } return p; } /** * @param conf */ private void launchDaemon(final Config config) { LOG.info("Launching daemon mode! Write pid file: {}", config.getConfig(DefConfig.PID_DAEMON)); try { Program.writePID(Program.getPID(), config.getConfig(DefConfig.PID_DAEMON)); } catch (IOException e) { LOG.error(e.getMessage()); exit(-1); } final String pid_daemon = config.getConfig(Config.PID_DAEMON); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { new File(pid_daemon).deleteOnExit(); } catch (Exception e) { LOG.error("Shutdown Error:" + e.getMessage()); } } }); int exit = 0; do { Process subp = launchInternal(config);// if (subp == null) { LOG.error("Launch MainLauncher Error! Maybe incorrect value in vmargs[-win]"); break; } Thread errT = redirectStream(subp.getErrorStream()); Thread stdT = redirectStream(subp.getInputStream()); LOG.info("Startup sub process successfully!"); try { exit = subp.waitFor(); } catch (Exception e) { LOG.warn(e.getMessage()); break; } finally { if (errT != null) errT.interrupt(); if (stdT != null) stdT.interrupt(); } LOG.info("Shutdown sub process Successfully! exit-{}", exit); } while (exit != 0 && exit != 143); } /** * @param inputStream */ private Thread redirectStream(final InputStream inputStream) { if (inputStream == null) { LOG.error("Main redirectStream null"); return null; } Thread t = new Thread("redirectStream") { public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(inputStream, config(Config.FILE_CONFIG, Config.UTF8))); while (!Thread.interrupted()) { try { String str = br.readLine(); if (str == null) Thread.sleep(1000); else LOG.info(str); } catch (IOException e) { LOG.error(e.getMessage()); break; } } } catch (Exception e) { LOG.warn(e.getMessage()); } finally { if (br != null) try { br.close(); } catch (Exception e) { } } } }; t.setDaemon(true); t.start(); return t; } }