package org.rzo.yajsw.wrapper;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationUtils;
import org.jboss.netty.logging.SimpleLoggerFactory;
import org.rzo.yajsw.Constants;
import org.rzo.yajsw.boot.WrapperServiceBooter;
import org.rzo.yajsw.cache.Cache;
import org.rzo.yajsw.config.YajswConfigurationImpl;
import org.rzo.yajsw.os.JavaHome;
import org.rzo.yajsw.os.OperatingSystem;
import org.rzo.yajsw.os.Service;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPService;
import org.rzo.yajsw.os.posix.PosixService;
import org.rzo.yajsw.util.Utils;
public class WrappedService
{
/** The _config. */
YajswConfigurationImpl _config;
/** The _debug. */
boolean _debug = false;
/** The Constant PATHSEP. */
static final String PATHSEP = System.getProperty("path.separator");
/** The _log. */
Logger _log = Logger.getLogger(this.getClass().getName());
/** The _local configuration. */
protected Configuration _localConfiguration = new BaseConfiguration();
/** The _use system properties. */
boolean _useSystemProperties = true;
Service _osService;
Cache _cache = null;
volatile boolean _init = false;
private List<String> _confFilesList;
/*
* (non-Javadoc)
*
* @see jnacontrib.win32.Win32Service#init()
*/
public void init()
{
if (_init)
return;
Map utils = new HashMap();
utils.put("util", new Utils(this));
if (_confFilesList != null && !_confFilesList.isEmpty() && _localConfiguration != null && !_localConfiguration.containsKey("wrapper.config"))
_localConfiguration.setProperty("wrapper.config", _confFilesList.get(0));
_config = new YajswConfigurationImpl(_localConfiguration, _useSystemProperties, utils);
if (!_config.isLocalFile())
if (_cache == null)
{
_cache = new Cache();
_cache.load(_config);
}
String dbg = _config.getString("wrapper.debug");
_debug = dbg == null ? false : dbg.equals("true");
_osService = OperatingSystem.instance().serviceManagerInstance().createService();
_osService.setLogger(_log);
_osService.setName(_config.getString("wrapper.ntservice.name"));
String displayName = _config.getString("wrapper.ntservice.displayname");
String description = _config.getString("wrapper.ntservice.description");
Set dependeciesSet = new HashSet();
for (Iterator it = _config.getKeys("wrapper.ntservice.dependency"); it.hasNext();)
{
String value = _config.getString((String) it.next());
if (value != null && value.length() > 0)
dependeciesSet.add(value);
}
String[] dependencies = new String[dependeciesSet.size()];
int i = 0;
for (Iterator it = dependeciesSet.iterator(); it.hasNext(); i++)
dependencies[i] = (String) it.next();
String account = _config.getString("wrapper.ntservice.account");
String password = _config.getString("wrapper.ntservice.password");
String startType = _config.getString("wrapper.ntservice.starttype", Constants.DEFAULT_SERVICE_START_TYPE);
String[] command = getCommand();
_osService.setAccount(account);
_osService.setCommand(command);
_osService.setDependencies(dependencies);
_osService.setDescription(description);
_osService.setDisplayName(displayName);
_osService.setPassword(password);
_osService.setConfig(_config);
_osService.setStartType(startType);
_osService.setFailureActions(OperatingSystem.instance().getServiceFailureActions(_config));
_osService.init();
_init = true;
}
/**
* Install.
*
* @return true, if successful
*/
public boolean install()
{
int i = 0;
return _osService.install();
}
public boolean uninstall()
{
if (_osService == null)
return false;
stop();
return _osService.uninstall();
}
/**
* Adds the classpath from manifest.
*
* @param classpath
* the classpath
* @param f
* the f
*/
protected void addClasspathFromManifest(ArrayList classpath, File f)
{
try
{
Manifest manifest = new JarFile(f).getManifest();
Attributes attr = manifest.getMainAttributes();
String cl = attr.getValue("Class-Path");
if (cl == null)
return;
String[] clArr = cl.split(" ");
for (int i = 0; i < clArr.length; i++)
{
String file = clArr[i];
File myFile = new File(f.getParent(), file).getCanonicalFile();
// System.out.println("adding classpath from manifest "+file);
if (myFile.exists() && !classpath.contains(myFile))
classpath.add(myFile);
else if (!myFile.exists())
System.out.println("file not found " + myFile);
}
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Wrapper options.
*
* @return the string
*/
protected ArrayList wrapperOptions()
{
int additionalCount = 1;
boolean xrsFound = false;
ArrayList result = new ArrayList();
// first add lookup vars eg ${lookup}
if (_config.getBoolean("wrapper.save_interpolated", true))
{
for (Entry<String, String> e : _config.getEnvLookupSet().entrySet())
{
result.add("\"-D" + e.getKey() + "=" + e.getValue()+"\"");
}
for (Iterator it = _config.getLookupSet().iterator(); it.hasNext();)
{
String key = (String) it.next();
if (!"wrapper.working.dir".equals(key))
result.add("\"-D" + key + "=" + _config.getString(key)+"\"");
}
}
for (Iterator it = _config.getSystemConfiguration().getKeys("wrapper"); it.hasNext();)
{
String key = (String) it.next();
if (key.equals("wrapper.config"))
result.add("-D" + key + "=" + _config.getCachedPath());
else
result.add("-D" + key + "=" + _config.getString(key));
if (key.startsWith("wrapper.additional."))
{
additionalCount++;
if (_config.getString(key).equals("-Xrs"))
xrsFound = true;
}
}
// if we have a list of configurations
if (_confFilesList != null && _confFilesList.size() > 1)
{
String confList = "";
// for each configuration
for (int i = 0; i < _confFilesList.size(); i++)
{
// load it
Configuration localConfiguration = ConfigurationUtils.cloneConfiguration(_localConfiguration);
String conf = _confFilesList.get(i);
localConfiguration.setProperty("wrapper.config", conf);
Map utils = new HashMap();
utils.put("util", new Utils(this));
YajswConfigurationImpl config = new YajswConfigurationImpl(localConfiguration, _useSystemProperties, utils);
Cache cache = null;
// check if we need to download files from remote location
if (!config.isLocalFile())
{
cache = new Cache();
cache.load(config);
}
// add configuration file name to list
confList += config.getCachedPath();
if (i < (_confFilesList.size() - 1))
confList += ",";
}
// TODO lookup is currently done only for first configuration
// add list to service parameters
result.add("-D" + "wrapperx.config" + "=" + confList);
}
if (!xrsFound)
{
result.add("-Dwrapper.additional." + (additionalCount) + "x=-Xrs");
}
if (_config.getString("wrapper.stop.conf") != null)
try
{
result.add("-Dwrapper.stop.conf=" + new File(_config.getString("wrapper.stop.conf")).getCanonicalPath());
}
catch (IOException e)
{
e.printStackTrace();
}
if (_config.getString("wrapper.groovy") != null)
try
{
result.add("-Dwrapper.groovy=" + new File(_config.getString("wrapper.groovy")).getCanonicalPath());
}
catch (IOException e)
{
e.printStackTrace();
}
return result;
}
// test main
/**
* The main method.
*
* @param args
* the arguments
*/
public Configuration getLocalConfiguration()
{
return _localConfiguration;
}
public void setLocalConfiguration(Configuration config)
{
_localConfiguration = config;
}
public boolean isInstalled()
{
if (_osService != null)
return _osService.isInstalled(state());
return false;
}
public boolean isRunning()
{
if (_osService != null)
return _osService.isRunning(state());
return false;
}
public boolean isStarting()
{
if (_osService != null)
return _osService.isStarting(state());
return false;
}
public void setUseSystemProperties(boolean useSystem)
{
_useSystemProperties = useSystem;
}
public boolean start()
{
// System.out.println("OsService.start() "+_osService);
if (_osService != null)
return _osService.start();
return false;
}
public boolean stop()
{
if (_osService != null)
return _osService.stop();
return false;
}
/**
* Gets the java command.
*
* @return the java command
*/
String[] getCommand()
{
// interpolate all configuration properties, so that we may evaluate all required environment variables
for (Iterator it = _config.getKeys(); it.hasNext(); )
{
String key = (String) it.next();
if (key.startsWith("wrapper."))
try
{
_config.getList(key);
}
catch (Exception ex)
{
}
}
JavaHome javaHome = OperatingSystem.instance().getJavaHome(_config);
javaHome.setLogger(SimpleLoggerFactory.getInstance(this.getClass().getName()));
String java = javaHome.findJava(_config.getString("wrapper.ntservice.java.command", _config.getString("wrapper.java.command")), _config.getString("wrapper.ntservice.java.customProcName"));
if (java == null)
{
_log.warning("no java exe found. check configuration file. -> using default \"java\"");
java = "java";
}
ArrayList jvmOptions = jvmOptions();
ArrayList wrapperOptions = wrapperOptions();
String mainClass = getServiceMainClass();
String workingDir = _config.getString("wrapper.working.dir");
if (workingDir != null)
{
File wd = new File(workingDir);
if (!wd.exists() || !wd.isDirectory())
_log.warning("working directory " + workingDir + " not found");
}
String[] result = new String[jvmOptions.size() + wrapperOptions.size() + 2];
result[0] = java;
result[result.length - 1] = mainClass;
int i = 1;
for (Iterator it = jvmOptions.listIterator(); it.hasNext(); i++)
result[i] = (String) it.next();
for (Iterator it = wrapperOptions.listIterator(); it.hasNext(); i++)
result[i] = (String) it.next();
return result;
}
private String getServiceMainClass()
{
return WrapperServiceBooter.class.getName();
}
/**
* Jvm options.
*
* @return the string
*/
private ArrayList jvmOptions()
{
ArrayList result = new ArrayList();
result.add("-classpath");
ArrayList classpath = new ArrayList();
String[] files = _config.getString("java.class.path").split(PATHSEP);
for (int i = 0; i < files.length; i++)
{
File f = null;
try
{
f = new File(files[i]).getCanonicalFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (f != null && f.exists() && !classpath.contains(f.getAbsolutePath()))
{
// System.out.println("adding classpath :"+f+":");
classpath.add(f);
//if (f.getName().endsWith(".jar"))
// addClasspathFromManifest(classpath, f);
}
}
StringBuffer sb = new StringBuffer();
for (Iterator it = classpath.iterator(); it.hasNext();)
{
String canonicalFileName = null;
try
{
canonicalFileName = ((File) it.next()).getCanonicalPath();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sb.append(canonicalFileName);
if (it.hasNext())
sb.append(PATHSEP);
}
result.add(sb.toString());
result.add("-Xrs");
result.add("-Dwrapper.service=true");
String wDir = _config.getString("wrapper.working.dir");
if (wDir != null)
{
File f = new File(wDir);
if (f.exists() && f.isDirectory())
try
{
result.add("-Dwrapper.working.dir=" + f.getCanonicalPath());
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (_config.getBoolean("wrapper.ntservice.debug", false))
{
result.add("-Xdebug");
result.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044");
}
for (Iterator it = _config.getKeys("wrapper.ntservice.additional"); it.hasNext();)
{
String key = (String) it.next();
String value = _config.getString(key);
result.add(value);
}
return result;
}
public String getServiceName()
{
return _config.getString("wrapper.ntservice.name");
}
public static void main(String[] args)
{
System.setProperty("wrapper.java.app.mainclass", "test.HelloWorld");
System.setProperty("wrapper.ntservice.name", "JavaServiceWrapper_1207751158998");
System.setProperty("wrapper.filter.trigger.1", "999");
System.setProperty("wrapper.java.additional.1", "-Xrs");
System.setProperty("wrapper.on_exit.default", "RESTART");
WrappedService w = new WrappedService();
System.out.println("init");
w.init();
System.out.println("install");
w.install();
for (int i = 0; i < 10; i++)
{
System.out.println("start");
w.start();
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("stop");
w.stop();
}
System.out.println("uninstall");
w.uninstall();
}
public int state()
{
if (_osService != null)
return _osService.state();
return Service.STATE_UNKNOWN;
}
public boolean isInstalled(int state)
{
if (_osService == null)
return false;
return _osService.isInstalled(state);
}
public boolean isRunning(int state)
{
if (_osService == null)
return false;
return _osService.isRunning(state);
}
public boolean isInteractive(int state)
{
if (_osService == null)
return false;
return _osService.isInteractive(state);
}
public boolean isAutomatic(int state)
{
if (_osService == null)
return false;
return _osService.isAutomatic(state);
}
public boolean isManual(int state)
{
if (_osService == null)
return false;
return _osService.isManual(state);
}
public boolean isDisabled(int state)
{
if (_osService == null)
return false;
return _osService.isDisabled(state);
}
public boolean isPaused(int state)
{
if (_osService == null)
return false;
return _osService.isPaused(state);
}
public boolean isStateUnknown(int state)
{
if (_osService == null)
return false;
return _osService.isStateUnknown(state);
}
public void stopProcess()
{
if (_osService instanceof PosixService)
{
((PosixService) _osService).stopProcess();
}
else
stop();
}
public void startProcess()
{
if (_osService instanceof PosixService)
{
((PosixService) _osService).startProcess();
}
else
start();
}
public String getConfigLocalPath()
{
return _config.getCachedPath(false);
}
public void setConfFilesList(List<String> confFiles)
{
_confFilesList = confFiles;
}
public boolean requiresElevate()
{
if (_osService != null && _osService instanceof WindowsXPService)
return ((WindowsXPService)_osService).requestElevation();
return false;
}
}