/* This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * <p/> * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.rzo.yajsw; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.cli2.Argument; import org.apache.commons.cli2.CommandLine; import org.apache.commons.cli2.Group; import org.apache.commons.cli2.Option; import org.apache.commons.cli2.builder.ArgumentBuilder; import org.apache.commons.cli2.builder.DefaultOptionBuilder; import org.apache.commons.cli2.builder.GroupBuilder; import org.apache.commons.cli2.commandline.Parser; import org.apache.commons.cli2.option.DefaultOption; import org.apache.commons.cli2.util.HelpFormatter; import org.apache.commons.cli2.validation.FileValidator; import org.apache.commons.cli2.validation.InvalidArgumentException; import org.apache.commons.cli2.validation.NumberValidator; import org.apache.commons.cli2.validation.Validator; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.MapConfiguration; import org.rzo.yajsw.boot.WrapperLoader; import org.rzo.yajsw.config.YajswConfiguration; import org.rzo.yajsw.config.YajswConfigurationImpl; import org.rzo.yajsw.os.OperatingSystem; import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess; import org.rzo.yajsw.tools.ConfigGenerator; import org.rzo.yajsw.tray.TrayIconMain; import org.rzo.yajsw.util.VFSFileValidator; import org.rzo.yajsw.wrapper.WrappedProcess; import org.rzo.yajsw.wrapper.WrappedProcessFactory; import org.rzo.yajsw.wrapper.WrappedProcessList; import org.rzo.yajsw.wrapper.WrappedService; import com.sun.jna.Platform; // TODO: Auto-generated Javadoc /** * The Class WrapperExe. */ public class WrapperExe { /** The group. */ static Group group; /** The cl. */ static CommandLine cl; /** The conf file. */ static String confFile; static List confFileList; /** The properties. */ static List properties; /** The cmds. */ static List cmds; /** The pid. */ static int pid; /** The pid. */ static String defaultFile; /** The Constant OPTION_C. */ static final int OPTION_C = 0; /** The Constant OPTION_T. */ static final int OPTION_T = 1; /** The Constant OPTION_P. */ static final int OPTION_P = 2; /** The Constant OPTION_T. */ static final int OPTION_TX = 91; /** The Constant OPTION_P. */ static final int OPTION_PX = 92; /** The Constant OPTION_I. */ static final int OPTION_I = 3; /** The Constant OPTION_R. */ static final int OPTION_R = 4; /** The Constant OPTION_N. */ static final int OPTION_N = 5; /** The Constant OPTION_G. */ static final int OPTION_G = 6; /** The Constant OPTION_D. */ static final int OPTION_D = 7; /** The Constant OPTION_Q. */ static final int OPTION_Q = 8; /** The Constant OPTION_QS. */ static final int OPTION_QS = 9; /** The Constant OPTION_Y. */ static final int OPTION_Y = 10; /** The Constant OPTION_QX. */ static final int OPTION_QX = 11; /** The Constant CONF_FILE. */ static final String CONF_FILE = "confFile"; /** The Constant PROPERTIES. */ static final String PROPERTIES = "properties"; /** The Constant PID. */ static final String PID = "pid"; /** The Constant DEFAULT_FILE. */ static final String DEFAULT_FILE = "default configuration file"; static WrappedService _service = null; static boolean _exitOnTerminate = true; static int _exitCode = 0; static Map<String, String> _properties = new HashMap<String, String>(); private static WrappedService getService() { if (_service != null) return _service; prepareProperties(); _service = new WrappedService(); if (confFileList != null && confFileList.size() > 1) _service.setConfFilesList(confFileList); _service.setLocalConfiguration(new MapConfiguration(_properties)); _service.init(); return _service; } /** * The main method. * * @param args * the arguments */ public static void main(String[] args) { String wrapperJar = WrapperLoader.getWrapperJar(); String homeDir = new File(wrapperJar).getParent(); OperatingSystem.instance().setWorkingDir(homeDir); // System.out.println(System.getProperty("java.class.path")); buildOptions(); parseCommand(args); if (cmds != null && cmds.size() > 0) for (Iterator it = cmds.iterator(); it.hasNext();) { Object cmd = it.next(); if (cmd instanceof DefaultOption) executeCommand((Option) cmd); } else executeCommand(group.findOption("c")); if (_exitOnTerminate) Runtime.getRuntime().halt(_exitCode); } private static File File(String property) { // TODO Auto-generated method stub return null; } /** * Execute command. * * @param cmd * the cmd */ private static void executeCommand(Option cmd) { switch (cmd.getId()) { case OPTION_C: doConsole(); break; case OPTION_T: doStart(); break; case OPTION_P: doStop(); break; case OPTION_TX: doStartPosix(); break; case OPTION_PX: doStopPosix(); break; case OPTION_I: doInstall(); break; case OPTION_R: doRemove(); break; case OPTION_N: pid = ((Long) cl.getValue(cmd)).intValue(); doReconnect(); break; case OPTION_G: pid = ((Long) cl.getValue(cmd)).intValue(); doGenerate(); break; case OPTION_D: break; case OPTION_Q: doState(); break; case OPTION_QS: doStateSilent(); case OPTION_QX: doStatePosix(); break; case OPTION_Y: doStartTrayIcon(); break; default: System.out.println("unimplemented option " + cmd.getPreferredName()); } } /** * Do reconnect. */ private static void doReconnect() { prepareProperties(); Configuration localConf = new MapConfiguration(_properties); YajswConfiguration conf = new YajswConfigurationImpl(localConf, true); WrappedProcess w = WrappedProcessFactory.createProcess(conf); System.out.println("************* RECONNECTING WRAPPER TO PID " + pid + " ***********************"); System.out.println(); if (w.reconnect(pid)) System.out.println("Connected to PID " + pid); else System.out.println("NOT connected to PID " + pid); _exitOnTerminate = false; } /** * Do remove. */ private static void doRemove() { prepareProperties(); WrappedService w = getService(); System.out.println("************* REMOVING " + w.getServiceName() + " ***********************"); System.out.println(); boolean result = w.uninstall(); if (Platform.isWinVista() && w.requiresElevate()) { System.out.println("try uac elevate"); WindowsXPProcess.elevateMe(); return; } if (result) System.out.println("Service " + w.getServiceName() + " removed"); else System.out.println("Service " + w.getServiceName() + " NOT removed"); } /** * Do install. */ private static void doInstall() { WrappedService w = getService(); System.out.println("************* INSTALLING " + w.getServiceName() + " ***********************"); System.out.println(); int i = 0; while (w.isInstalled() && i < 10) { if (Platform.isWinVista() && w.requiresElevate()) { System.out.println("try uac elevate"); WindowsXPProcess.elevateMe(); return; } i++; w.uninstall(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } boolean result = w.install(); if (Platform.isWinVista() && w.requiresElevate()) { System.out.println("try uac elevate"); WindowsXPProcess.elevateMe(); return; } if (result) System.out.println("Service " + w.getServiceName() + " installed"); else System.out.println("Service " + w.getServiceName() + " NOT installed"); } /** * Do stop. */ private static void doStop() { WrappedService w = getService(); System.out.println("************* STOPPING " + w.getServiceName() + " ***********************"); System.out.println(); try { w.stop(); if (Platform.isWinVista() && w.requiresElevate()) { System.out.println("try uac elevate"); WindowsXPProcess.elevateMe(); return; } if (w.isRunning()) System.out.println("Service " + w.getServiceName() + " NOT stopped"); else System.out.println("Service " + w.getServiceName() + " stopped"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void doStopPosix() { WrappedService w = getService(); System.out.println("************* STOPPING " + w.getServiceName() + " ***********************"); System.out.println(); try { w.stopProcess(); } catch (Exception e) { e.printStackTrace(); } if (!w.isRunning()) { System.out.println("Service " + w.getServiceName() + " stopped"); _exitCode = 0; _exitOnTerminate = true; } else { System.out.println("Service" + w.getServiceName() + " NOT stopped"); _exitCode = 1; _exitOnTerminate = true; } } /** * Do start. */ private static void doStart() { WrappedService w = getService(); // w.setDebug(true); w.init(); System.out.println("************* STARTING " + w.getServiceName() + " ***********************"); System.out.println(); w.start(); try { Thread.sleep(1000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } if (Platform.isWinVista() && w.requiresElevate()) { System.out.println("try uac elevate"); WindowsXPProcess.elevateMe(); return; } int i = 0; while (!w.isRunning() && i++ < 30) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); return; } if (!w.isStarting()) break; } if (w.isRunning()) { System.out.println("Service " + w.getServiceName() + " started"); _exitCode = 0; _exitOnTerminate = true; } else { System.out.println("Service " + w.getServiceName() + " NOT started"); _exitCode = 1; _exitOnTerminate = true; } } private static void doStartPosix() { WrappedService w = getService(); System.out.println("************* STARTING " + w.getServiceName() + " ***********************"); System.out.println(); w.startProcess(); int i = 0; while (!w.isRunning() && i < 10) { i++; try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } if (w.isRunning()) System.out.println("Service " + w.getServiceName() + " started"); else System.out.println("Service " + w.getServiceName() + " NOT started"); _exitOnTerminate = true; } /** * Do start. */ private static void doStartTrayIcon() { prepareProperties(); String[] args; if (_service != null) args = new String[] { _service.getConfigLocalPath() }; else args = new String[] { confFile }; try { TrayIconMain.main(args); } catch (Exception e) { e.printStackTrace(); } _exitOnTerminate = true; } private static void doState() { prepareProperties(); WrappedService w = getService(); int state = w.state(); System.out.print("Name : "); System.out.println(w.getServiceName()); System.out.print("Installed : "); System.out.println(w.isInstalled(state)); System.out.print("Running : "); System.out.println(w.isRunning(state)); System.out.print("Interactive : "); System.out.println(w.isInteractive(state)); System.out.print("Automatic : "); System.out.println(w.isAutomatic(state)); System.out.print("Manual : "); System.out.println(w.isManual(state)); System.out.print("Disabled : "); System.out.println(w.isDisabled(state)); System.out.print("Paused : "); System.out.println(w.isPaused(state)); System.out.print("Unkown : "); System.out.println(w.isStateUnknown(state)); } private static void doStateSilent() { prepareProperties(); WrappedService w = getService(); w.init(); int state = w.state(); } private static void doStatePosix() { prepareProperties(); WrappedService w = getService(); int state = w.state(); if (w.isRunning(state)) _exitCode = 0; else _exitCode = 3; _exitOnTerminate = true; } /** * Do console. */ private static void doConsole() { prepareProperties(); final WrappedProcessList list = WrappedProcessFactory.createProcessList(_properties, confFileList, true); list.startAll(); // Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() // { // // public void run() // { // list.onStopWrapper(); // } // // })); _exitOnTerminate = false; } private static void doGenerate() { System.out.println("************* GENERATING YAJSW CONFIGURATION FOR PID " + pid + " ***********************"); System.out.println(); if (defaultFile != null) ConfigGenerator.generate(pid, new File(defaultFile), new File(confFile)); else ConfigGenerator.generate(pid, null, new File(confFile)); } /** * Prepare properties. */ private static void prepareProperties() { if (confFile != null) _properties.put("wrapper.config", confFile); if (defaultFile != null) _properties.put("wrapperx.default.config", defaultFile); if (properties != null) for (Iterator it = properties.iterator(); it.hasNext();) { String prop = (String) it.next(); String key = prop.substring(0, prop.indexOf('=')); String value = prop.substring(prop.indexOf('=') + 1); _properties.put(key, value); } } /** * Parses the command. * * @param args * the args */ private static void parseCommand(String[] args) { Parser parser = new Parser(); // configure a HelpFormatter HelpFormatter hf = new HelpFormatter(); DefaultOptionBuilder oBuilder = new DefaultOptionBuilder(); ; // configure a parser Parser p = new Parser(); p.setGroup(group); p.setHelpFormatter(hf); p.setHelpOption(oBuilder.withLongName("help").withShortName("?").create()); cl = p.parseAndHelp(args); // abort application if no CommandLine was parsed if (cl == null) { System.exit(-1); } cmds = cl.getOptions(); try { confFileList = cl.getValues(CONF_FILE); if (confFileList == null || confFileList.isEmpty()) System.out.println("no wrapper config file found "); else confFile = (String) confFileList.get(0); } catch (Exception ex) { System.out.println("no wrapper config file found "); } try { defaultFile = (String) cl.getValue(cl.getOption("-d")); if (defaultFile != null) defaultFile = new File(defaultFile).getCanonicalPath(); } catch (Exception ex) { // no defaults -> maybe ok } properties = cl.getValues(PROPERTIES); } /** * Builds the options. */ private static void buildOptions() { DefaultOptionBuilder oBuilder = new DefaultOptionBuilder("-", "--", true); ArgumentBuilder aBuilder = new ArgumentBuilder(); GroupBuilder gBuilder = new GroupBuilder(); gBuilder.withOption(oBuilder.reset().withId(OPTION_C).withShortName("c").withLongName("console").withDescription( "run as a Console application").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_T).withShortName("t").withLongName("start").withDescription( "starT an NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_P).withShortName("p").withLongName("stop").withDescription( "stoP a running NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_TX).withShortName("tx").withLongName("startx").withDescription( "starT -internal a Posix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_PX).withShortName("px").withLongName("stopx").withDescription( "stoP -internal- a running Posix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_I).withShortName("i").withLongName("install").withDescription( "Install an NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_R).withShortName("r").withLongName("remove").withDescription( "Remove an NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_Q).withShortName("q").withLongName("query").withDescription( "Query the status of an NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_Y).withShortName("y").withLongName("tray").withDescription("Start System Tray Icon") .create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_QS).withShortName("qs").withLongName("querysilent").withDescription( "Silent Query the status of an NT service or Unix daemon").create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_QX).withShortName("qx").withLongName("queryposix").withDescription( "Query the status of a posix daemon. Return status as exit code").create()); Argument pid = aBuilder.reset().withName(PID).withDescription("PID of process to reconnect to").withMinimum(1).withMaximum(1).withValidator( NumberValidator.getIntegerInstance()).create(); gBuilder.withOption(oBuilder.reset().withId(OPTION_N).withShortName("n").withLongName("reconnect").withDescription( "recoNnect to existing application").withArgument(pid).create()); Argument pid2 = aBuilder.reset().withName(PID).withDescription("PID of process to reconnect to").withMinimum(1).withMaximum(1).withValidator( NumberValidator.getIntegerInstance()).create(); Argument defaultFile = aBuilder.reset().withName(DEFAULT_FILE).withDescription("Default Configuration File").withMinimum(0).withMaximum(1) .withValidator(VFSFileValidator.getExistingFileInstance().setBase(".")).create(); /* * GroupBuilder childGbuilder = new GroupBuilder(); DefaultOptionBuilder * childoObuilder = new DefaultOptionBuilder("-", "--", true); * * childGbuilder.withName(DEFAULT_FILE).withMinimum(0).withMaximum(1). * withOption( * childoObuilder.withId(OPTION_D).withArgument(defaultFile). * withShortName("d").withLongName("defaultConf").withDescription( * "Default Configuration File").create()); * * * * gBuilder.withOption(oBuilder.reset().withId(OPTION_G).withShortName("g" * ).withLongName("genconf").withDescription( * "Generate configuration file from pid" * ).withArgument(pid2).withChildren(childGbuilder.create()).create()); */ gBuilder.withOption(oBuilder.reset().withId(OPTION_D).withShortName("d").withLongName("defaultConf").withDescription( "Default Configuration File").withArgument(defaultFile).create()); gBuilder.withOption(oBuilder.reset().withId(OPTION_G).withShortName("g").withLongName("genconf").withDescription( "Generate configuration file from pid").withArgument(pid2).create()); FileValidator fValidator = VFSFileValidator.getExistingFileInstance().setBase("."); fValidator.setFile(false); // fValidator.setReadable(true); gBuilder.withOption(aBuilder.reset().withName(CONF_FILE).withDescription("is the wrapper.conf to use. Name must be absolute or relative") .withMinimum(0).withMaximum(10).create()); Validator pValidator = new Validator() { public void validate(List values) throws InvalidArgumentException { for (Iterator it = values.iterator(); it.hasNext();) { String p = (String) it.next(); if (!Pattern.matches("wrapper\\..*=.*", p)) { throw new InvalidArgumentException(p); } } } }; gBuilder.withOption(aBuilder.reset().withName(PROPERTIES).withDescription( "are configuration name-value pairs which override values. For example: wrapper.debug=true").withMinimum(0).withValidator(pValidator) .create()); gBuilder.withMaximum(3); group = gBuilder.create(); } }