/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.ui.gwt.desktop.server.command;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.onecmdb.core.IOneCmdbContext;
import org.onecmdb.core.IRfcResult;
import org.onecmdb.core.utils.bean.CiBean;
import org.onecmdb.core.utils.bean.ValueBean;
import org.onecmdb.core.utils.wsdl.IOneCMDBWebService;
import org.onecmdb.ui.gwt.desktop.client.service.model.AliasFactory;
import org.onecmdb.ui.gwt.desktop.client.service.model.mdr.MDRHistoryState;
import org.onecmdb.ui.gwt.desktop.client.widget.mdr.MDRStartWindow;
import org.onecmdb.ui.gwt.desktop.server.command.exec.ExecResult;
import org.onecmdb.ui.gwt.desktop.server.command.exec.JavaExec;
import org.onecmdb.ui.gwt.desktop.server.command.exec.MDRExecThread;
import org.onecmdb.ui.gwt.desktop.server.command.exec.StreamHandler;
public class ExecCommand extends AbstractOneCMDBCommand {
private String root = null;
Log log = LogFactory.getLog(this.getClass());
private Properties attrMap;
private String config;
private String mdr;
private String verbose;
private String history = MDRHistoryState.getHistoryTemplate();
// Valid commands are [START,LISTEN,STOP]
private String cmd;
private String procid;
private CiBean historyBean;
private Throwable execError;
private static HashMap<String, MDRExecThread> threadMap = new HashMap<String, MDRExecThread>();
/**
* Thread handling...
*
*/
public void unregister(MDRExecThread execThread) {
System.out.println("unregister " + execThread.getCmd().getThreadKey());
synchronized(threadMap) {
threadMap.remove(execThread.getCmd().getThreadKey());
}
}
public void register(MDRExecThread execThread) {
System.out.println("register " + execThread.getCmd().getThreadKey());
synchronized(threadMap) {
threadMap.put(getThreadKey(), execThread);
}
}
// Self test..
public static void main(String argv[]) {
try {
ExecCommand cmd = new ExecCommand();
AbstractOneCMDBCommand.run(cmd, argv);
} catch (Throwable e) {
e.printStackTrace();
}
}
public String getVerbose() {
return verbose;
}
public void setVerbose(String verbose) {
this.verbose = verbose;
}
public void setConfig(String config) {
this.config = config;
}
public String getConfig() {
return(this.config);
}
public String getMdr() {
return mdr;
}
public void setMdr(String mdr) {
this.mdr = mdr;
}
public void setHistory(String history) {
this.history = history;
}
public String getHistory() {
return(this.history);
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getContentType() {
String contentType = "text/plain";
return(contentType);
}
public String getRoot() {
return(this.root);
}
public void setRoot(String root) {
log.info("Set ExecHandler Root to <" + root + ">");
this.root = root;
}
public void transfer(OutputStream out) throws Throwable {
final PrintWriter pw = new PrintWriter(out);
// Initial validation.
if (mdr == null || config == null || mdr.length() == 0 || config.length() == 0) {
throw new IllegalArgumentException("mdr and config arguments must be set!");
}
if (cmd.equalsIgnoreCase("start")) {
// do start a process..
doStart(pw);
return;
} else if (cmd.equalsIgnoreCase("stop")) {
// do stop a process
doStop(pw);
return;
} else if (cmd.equalsIgnoreCase("listen")) {
// do listen on a process.
doListen(pw);
return;
} else if (cmd.equalsIgnoreCase("list")) {
doListRunning(pw);
return;
} else if (cmd.equalsIgnoreCase("status")) {
doStatus(pw);
return;
}
throw new IllegalArgumentException("cmd '" + cmd + "' is not valid, use start|stop|listen|list");
}
private void doListRunning(PrintWriter pw) {
synchronized(threadMap) {
for (String key : threadMap.keySet()) {
MDRExecThread thread = threadMap.get(key);
pw.println(key);
if (isVerbose()) {
pw.println("Started:" + thread.getStart());
pw.println("Runned:" + ((new Date()).getTime() - thread.getStart().getTime()) + "ms");
}
}
}
}
private void doStatus(PrintWriter pw) {
MDRExecThread thread = null;
synchronized(threadMap) {
thread = threadMap.get(getThreadKey());
}
if (thread == null) {
pw.println("NOT_FOUND");
} else {
pw.println("RUNNING");
}
}
private void doListen(PrintWriter pw) {
MDRExecThread thread = null;
synchronized(threadMap) {
thread = threadMap.get(getThreadKey());
}
if (thread == null) {
pw.println(getThreadKey() + " is not running!");
}
thread.addLog(pw);
synchronized(thread) {
try {
thread.join();
} catch (InterruptedException e) {
pw.println("Interuppted....");
e.printStackTrace();
}
}
synchronized(threadMap) {
threadMap.remove(getThreadKey());
}
}
private void doStop(PrintWriter pw) {
MDRExecThread thread = null;
synchronized(threadMap) {
thread = threadMap.get(getThreadKey());
}
if (thread == null) {
pw.println(getThreadKey() + " is not running!");
return;
}
thread.terminate(pw);
}
private String getThreadKey() {
return(mdr + "_" + config);
}
public void doStart(final PrintWriter pw) throws Exception {
pw.println("Starting " + getThreadKey());
pw.flush();
// Check if config is already running.
MDRExecThread thread = null;
synchronized(threadMap) {
thread = threadMap.get(getThreadKey());
}
if (thread != null) {
pw.println(config + "is already running ");
pw.flush();
if (isVerbose()) {
doListen(pw);
}
return;
}
pw.println(getThreadKey() + " starting...");
MDRExecThread start = new MDRExecThread(this);
start.setDaemon(true);
start.setName("OneCMDB-MDR-" + getThreadKey());
register(start);
start.start();
if (isVerbose()) {
doListen(pw);
}
}
private boolean isVerbose() {
if (verbose == null) {
return(false);
}
return(verbose.equals("true"));
}
public IRfcResult update(CiBean local, CiBean base) throws Exception {
List<CiBean> locals = new ArrayList<CiBean>();
List<CiBean> bases = new ArrayList<CiBean>();
locals.add(local);
bases.add(base);
IRfcResult result = getService().update(getToken(), locals.toArray(new CiBean[0]), bases.toArray(new CiBean[0]));
return(result);
}
public void setValue(CiBean local, String alias, String value) {
ValueBean v = local.fetchAttributeValueBean(alias, 0);
if (v == null) {
v = new ValueBean();
v.setAlias(alias);
local.addAttributeValue(v);
}
v.setValue(value);
}
public CiBean getHistoryBean() {
return(historyBean);
}
public CiBean createHistory(CiBean configBean) throws Exception {
CiBean bean = new CiBean();
bean.setDerivedFrom(history);
bean.setAlias(AliasFactory.generateAlias(history));
bean.setTemplate(false);
bean.addAttributeValue(new ValueBean("mdrConfigEntry", configBean.getAlias(), true));
setValue(bean, "status", MDRHistoryState.EXECUTING);
IRfcResult result = getService().update(getToken(), new CiBean[] {bean}, null);
if (result.isRejected()) {
throw new IllegalArgumentException("Can't create history entry <" + history + ">. Reason " + result.getRejectCause());
}
historyBean = getCI(history, bean.getAlias());
return(historyBean);
}
public void setExecError(Throwable t) {
this.execError = t;
}
public Throwable getExecError() {
return(this.execError);
}
}