/*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* FlowRunner.java
* Copyright (C) 2008 Pentaho Corporation
*
*/
package weka.gui.beans;
import java.util.Vector;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import weka.gui.Logger;
import weka.gui.beans.xml.*;
/**
* Small utility class for executing KnowledgeFlow
* flows outside of the KnowledgeFlow application
*
* @author Mark Hall (mhall{[at]}pentaho{[dot]}org
* @version $Revision: 1.9 $
*/
public class FlowRunner {
/** The potential flow(s) to execute */
protected Vector m_beans;
protected int m_runningCount = 0;
protected transient Logger m_log = null;
/**
* Constructor
*/
public FlowRunner() {
// make sure that properties and plugins are loaded
KnowledgeFlowApp.loadProperties();
}
public void setLog(Logger log) {
m_log = log;
}
protected synchronized void launchThread(final Startable s, final int flowNum) {
Thread t = new Thread() {
private int m_num = flowNum;
public void run() {
try {
s.start();
} catch (Exception ex) {
ex.printStackTrace();
if (m_log != null) {
m_log.logMessage(ex.getMessage());
} else {
System.err.println(ex.getMessage());
}
} finally {
if (m_log != null) {
m_log.logMessage("[FlowRunner] flow " + m_num + " finished.");
} else {
System.out.println("[FlowRunner] Flow " + m_num + " finished.");
}
decreaseCount();
}
}
};
m_runningCount++;
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
protected synchronized void decreaseCount() {
m_runningCount--;
}
public synchronized void stopAllFlows() {
for (int i = 0; i < m_beans.size(); i++) {
BeanInstance temp = (BeanInstance)m_beans.elementAt(i);
if (temp.getBean() instanceof BeanCommon) {
// try to stop any execution
((BeanCommon)temp.getBean()).stop();
}
}
}
/**
* Waits until all flows have finished executing before returning
*
*/
public void waitUntilFinished() {
try {
while (m_runningCount > 0) {
Thread.sleep(200);
}
} catch (Exception ex) {
if (m_log != null) {
m_log.logMessage("[FlowRunner] Attempting to stop all flows...");
} else {
System.err.println("[FlowRunner] Attempting to stop all flows...");
}
stopAllFlows();
// ex.printStackTrace();
}
}
/**
* Load a serialized KnowledgeFlow (either binary or xml)
*
* @param fileName the name of the file to load from
* @throws Exception if something goes wrong
*/
public void load(String fileName) throws Exception {
if (!fileName.endsWith(".kf") && !fileName.endsWith(".kfml")) {
throw new Exception("Can only load and run binary or xml serialized KnowledgeFlows "
+ "(*.kf | *.kfml)");
}
if (fileName.endsWith(".kf")) {
loadBinary(fileName);
} else if (fileName.endsWith(".kfml")) {
loadXML(fileName);
}
}
/**
* Load a binary serialized KnowledgeFlow
*
* @param fileName the name of the file to load from
* @throws Exception if something goes wrong
*/
public void loadBinary(String fileName) throws Exception {
if (!fileName.endsWith(".kf")) {
throw new Exception("File must be a binary flow (*.kf)");
}
InputStream is = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(is);
m_beans = (Vector)ois.readObject();
// don't need the graphical connections
ois.close();
}
/**
* Load an XML serialized KnowledgeFlow
*
* @param fileName the name of the file to load from
* @throws Exception if something goes wrong
*/
public void loadXML(String fileName) throws Exception {
if (!fileName.endsWith(".kfml")) {
throw new Exception("File must be an XML flow (*.kfml)");
}
XMLBeans xml = new XMLBeans(null, null);
Vector v = (Vector) xml.read(new File(fileName));
m_beans = (Vector) v.get(XMLBeans.INDEX_BEANINSTANCES);
}
/**
* Get the vector holding the flow(s)
*
* @return the Vector holding the flow(s)
*/
public Vector getFlows() {
return m_beans;
}
/**
* Set the vector holding the flows(s) to run
*
* @param beans the Vector holding the flows to run
*/
public void setFlows(Vector beans) {
m_beans = beans;
}
/**
* Launch all loaded KnowledgeFlow
*
* @throws Exception if something goes wrong during execution
*/
public void run() throws Exception {
if (m_beans == null) {
throw new Exception("Don't seem to have any beans I can execute.");
}
int numFlows = 1;
// look for a Startable bean...
for (int i = 0; i < m_beans.size(); i++) {
BeanInstance tempB = (BeanInstance)m_beans.elementAt(i);
if (tempB.getBean() instanceof Startable) {
Startable s = (Startable)tempB.getBean();
// start that sucker...
if (m_log != null) {
m_log.logMessage("[FlowRunner] Launching flow "+numFlows+"...");
} else {
System.out.println("[FlowRunner] Launching flow "+numFlows+"...");
}
launchThread(s, numFlows);
numFlows++;
}
}
}
/**
* Main method for testing this class. <p>
* <br>Usage:<br><br>
* <pre>Usage:\n\nFlowRunner <serialized kf file></pre>
*
* @param args command line arguments
*/
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage:\n\nFlowRunner <serialized kf file>");
} else {
try {
FlowRunner fr = new FlowRunner();
String fileName = args[0];
fr.load(fileName);
fr.run();
fr.waitUntilFinished();
System.out.println("Finished all flows.");
} catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex.getMessage());
}
}
}
}