/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.product; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.agent.AgentConfig; import org.hyperic.sigar.win32.Win32; import org.hyperic.util.StringUtil; import org.hyperic.util.exec.Execute; import org.hyperic.util.exec.ExecuteWatchdog; import org.hyperic.util.exec.PumpStreamHandler; public class ExecutableProcess extends Collector { public static final String DOMAIN = "exec"; private static final String AGENT_BUNDLE_HOME = AgentConfig.AGENT_BUNDLE_HOME; public static final String PROP_EXEC = "exec"; public static final String PROP_FILE = "file"; public static final String PROP_ARGS = "args"; private static Log log = LogFactory.getLog(ExecutableProcess.class.getName()); private String[] argv; private File file; private File cwd; private ByteArrayOutputStream output = new ByteArrayOutputStream(); protected int getDefaultTimeout() { return 2 * 60; //2 minutes } protected int getLogLevel(int rc) { switch (rc) { case 0: return LogTrackPlugin.LOGLEVEL_INFO; case 1: return LogTrackPlugin.LOGLEVEL_WARN; case 2: case 3: default: return LogTrackPlugin.LOGLEVEL_ERROR; } } protected double getAvailValue(int rc) { switch (rc) { case 0: return Metric.AVAIL_UP; //green light case 1: return Metric.AVAIL_WARN; //yellow light case 2: return Metric.AVAIL_DOWN; //red light case 3: return Metric.AVAIL_UNKNOWN; //grey light case 4: return Metric.AVAIL_PAUSED; //orange light default: return Metric.AVAIL_UNKNOWN; } } //this method modifies the List argv param (sorry jav) private void addArgv(String value, ArrayList argv) { if ((value != null) && (value.length() != 0)) { String[] add = StringUtil.explodeQuoted(value); for (int i=0; i<add.length; i++) { argv.add(add[i]); } } } protected String getExecProperty() { return getCollectorProperty(PROP_EXEC); } protected String getFileProperty() { return getCollectorProperty(PROP_FILE); } protected String getArgsProperty() { return getCollectorProperty(PROP_ARGS); } // helper method used to resolve the agent // bundle directory for relative paths involving // the pdk directory private String resolveRelativeFile(String file) { if ((file != null) && file.startsWith("pdk/")) { String bundleHome = System.getProperty(AGENT_BUNDLE_HOME); return bundleHome + "/" + file; } else { return file; } } protected void init() { String exec = getExecProperty(); String name = resolveRelativeFile(getFileProperty()); ArrayList argv = new ArrayList(); if (HypericOperatingSystem.IS_WIN32 && (exec == null)) { //Runtime.exec does not handle file associations //such as foo.pl -> perl.exe, foo.py -> python.exe. String exe = Win32.findScriptExecutable(name); if (exe != null) { argv.add(exe); if (exe.endsWith("cscript.exe")) { //surpress banner for .vbs scripts argv.add("//nologo"); } } } addArgv(exec, argv); argv.add(name); addArgv(getArgsProperty(), argv); this.argv = new String[argv.size()]; argv.toArray(this.argv); setSource(name); if (name == null) { String msg = "No file in properties: " + getProperties(); throw new IllegalArgumentException(msg); } this.file = new File(name); if (!this.file.exists()) { String msg = "File '" + this.file + "' does not exist"; throw new IllegalArgumentException(msg); } if (this.file.isAbsolute()) { this.cwd = this.file.getParentFile(); } else { this.cwd = new File("."); } } public boolean isPoolable() { return true; } public void collect() { this.output.reset(); ExecuteWatchdog wdog = new ExecuteWatchdog(getTimeoutMillis()); Execute exec = new Execute(new PumpStreamHandler(this.output), wdog); exec.setCommandline(this.argv); exec.setWorkingDirectory(this.cwd); if (log.isDebugEnabled()) { log.debug(" running: " + this); } int res; try { startTime(); res = exec.execute(); endTime(); String outputMessage = this.output.toString(); if ((outputMessage == null) || (outputMessage.length() == 0)) { outputMessage = "No message, exit value=" + res; } setMessage(outputMessage); parseResults(getMessage()); } catch (Exception e) { if (log.isDebugEnabled()) { log.error(this + ": " + e.getMessage(), e); } setMessage(e.toString()); if (!this.file.exists()) { setMessage("File '" + this.file + "' does not exist"); } res = 2; } if (wdog.killedProcess()) { setMessage("Timeout running " + "[" + exec.getCommandLineString() + "]"); //on posix systems res == 143 (143 & 0x7f == SIGTERM) res = 2; } setLogLevel(getLogLevel(res)); double avail = getAvailValue(res); String msg = this + ": " + getMessage(); switch (getLogLevel()) { case LogTrackPlugin.LOGLEVEL_ERROR: log.error(msg); break; case LogTrackPlugin.LOGLEVEL_WARN: log.warn(msg); break; case LogTrackPlugin.LOGLEVEL_INFO: case LogTrackPlugin.LOGLEVEL_DEBUG: default: log.debug(msg); break; } setAvailability(avail); setResponseCode(res); } public String toString() { return Arrays.asList(this.argv).toString(); } }