package org.myrobotlab.service;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.myrobotlab.codec.CodecUtils;
import org.myrobotlab.framework.Service;
import org.myrobotlab.framework.ServiceType;
import org.myrobotlab.framework.Status;
import org.myrobotlab.framework.repo.Repo;
import org.myrobotlab.io.FileIO;
import org.myrobotlab.logging.Appender;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.logging.Logging;
import org.myrobotlab.logging.LoggingFactory;
import org.myrobotlab.service.interfaces.ServiceInterface;
import org.slf4j.Logger;
/**
* Incubator - This is a sort of testing / example service.
*
*/
public class Incubator extends Service {
private static final long serialVersionUID = 1L;
public final static Logger log = LoggerFactory.getLogger(Incubator.class);
Date now = new Date();
// transient public XMPP xmpp;
// transient public WebGui webgui;
// transient public Python python;
// transient Index<Object> cache = new Index<Object>();
// TODO - take snapshot of threads - compare at
// any other times - find the diff of threads - generated errors
// approprately
// TODO - subscribe to onRegistered --> generates subscription to
// publishState() - filter on Errors
// FIXME NEED TO AD SOME REPO MANAGEMENT ROUTINES TO RUNTIME - LIKE REMOVE
// REPO
public static Status install(String fullType) {
try {
// install everything...
Repo repo = Repo.getLocalInstance();
if (!repo.isServiceTypeInstalled(fullType)) {
repo.install(fullType);
if (repo.hasErrors()) {
log.error("repo had errors");
}
}
} catch (Exception e) {
return Status.error(e);
}
return null;
}
public static void main(String[] args) {
LoggingFactory.init(Level.INFO);
LoggingFactory.getInstance().addAppender(Appender.FILE);
Runtime.start("incubator", "Incubator");
// incubator.servoArduinoOpenCVGUIService();
/*
* incubator.installAll(); // incubator.startTest();
*
* incubator.testPythonScripts();
*
* // Runtime.createAndStart("gui", "GUIService");
*/
}
public Incubator() {
this("incubator");
}
public Incubator(String n) {
super(n);
addRoutes();
}
// very good - dynamicly subscribing to other service's
// published errors
// step 1 subscribe to runtimes onRegistered event
// step 2 in any onRegistered -
// step 3 - fix up - so that state is handled (not just "error")
public void addRoutes() {
Runtime r = Runtime.getInstance();
subscribe(r.getName(), "registered");
// handle my own error the same way too
subscribe(getName(), "publishError");
}
public void onError(Status status) {
try {
// FIXME - remove - only add xmp if onError requires an error
// alert
Xmpp xmpp = (Xmpp) startPeer("xmpp");
// python = (Python) startPeer("python");
/*
* webgui = (WebGui) createPeer("webgui"); webgui.port = 4321;
* webgui.startService();
*/
xmpp.startService();
// webgui.startService();
xmpp.connect("incubator@myrobotlab.org", "hatchMe!");
// FIXME - xmpp.addAuditor("Greg Perry");
// python.startService();
xmpp.sendMessage(CodecUtils.toJson(status), "Greg Perry");
// xmpp.releaseService();
// TODO email
} catch (Exception e) {
Logging.logError(e);
}
}
public void onError(String msg) {
// AHHHH! with just error (vs log.error) - goes in infinite loop
log.error(String.format("cool - all errors are caught here since we register for them - this error is - %s", msg));
}
/**
* install all service
*
* @throws IOException
* @throws ParseException
*/
public void installAll() throws ParseException, IOException {
// Runtime.getInstance();
Repo repo = Repo.getLocalInstance();
repo.install();
}
public List<Status> pythonTest() throws IOException {
ArrayList<Status> ret = new ArrayList<Status>();
Python python = (Python) Runtime.start("python", "Python");
Serial uart99 = (Serial) Runtime.start("uart99", "Serial");
// take inventory of currently running services
HashSet<String> keepMeRunning = new HashSet<String>();
List<ServiceInterface> list = Runtime.getServices();
for (int j = 0; j < list.size(); ++j) {
ServiceInterface si = list.get(j);
keepMeRunning.add(si.getName());
}
String[] serviceTypeNames = Runtime.getInstance().getServiceTypeNames();
ret.add(new Status("subTest"));
ret.add(Status.info("will test %d services", serviceTypeNames.length));
ret.add(new Status("subTest"));
for (int i = 0; i < serviceTypeNames.length; ++i) {
String fullName = serviceTypeNames[i];
String shortName = fullName.substring(fullName.lastIndexOf(".") + 1);
String py = FileIO.resourceToString(String.format("Python/examples/%s.py", shortName));
if (py == null || py.length() == 0) {
ret.add(Status.error("%s.py does not exist", shortName));
} else {
// uart99.connect("UART99");
uart99.recordRX(String.format("%s.rx", shortName)); // FIXME
// FILENAME
// OVERLOAD
python.exec(py);
uart99.stopRecording();
// check rx file against saved data
}
// get python errors !
// clean services
Runtime.releaseAllServicesExcept(keepMeRunning);
}
return null;
}
public void onRegistered(ServiceInterface sw) {
subscribe(sw.getName(), "publishError");
}
// FIXME - 2 sets of services - 1 by serviceData.xml & 1 by all files in
// org.myrobotlab.service
// FIXME - do all types of serialization
// TODO - encode decode test JSON & XML
// final ArrayList<Status>
public ArrayList<Status> serializeTest() {
ArrayList<Status> ret = new ArrayList<Status>();
String[] serviceTypeNames = Runtime.getInstance().getServiceTypeNames();
// Status status = Status.info("serializeTest");
ret.add(Status.info("will test %d services", serviceTypeNames.length));
Set<Thread> originalThreads = Thread.getAllStackTraces().keySet();
for (int i = 0; i < serviceTypeNames.length; ++i) {
ServiceInterface s = null;
String fullType = serviceTypeNames[i];
if ("org.myrobotlab.service.Incubator".equals(fullType) || "org.myrobotlab.service.Runtime".equals(fullType)) {
log.info("skipping Incubator & Runtime");
continue;
}
// fullType = "org.myrobotlab.service.JFugue";
try {
// install it
ret.add(install(fullType));
// create it
log.info("creating {}", fullType);
s = Runtime.create(fullType, fullType);
if (s == null) {
ret.add(Status.error("could not create %s service", fullType));
continue;
}
// start it
log.info("starting {}", fullType);
s.startService();
} catch (Exception e) {
ret.add(Status.error("ERROR - %s", fullType));
ret.add(new Status(e));
continue;
}
try {
log.info("serializing {}", fullType);
// TODO put in encoder
ByteArrayOutputStream fos = null;
ObjectOutputStream out = null;
fos = new ByteArrayOutputStream();
out = new ObjectOutputStream(fos);
out.writeObject(s);
fos.flush();
out.close();
log.info("releasing {}", fullType);
if (s.hasPeers()) {
s.releasePeers();
}
s.releaseService();
sleep(300);
Set<Thread> currentThreads = Thread.getAllStackTraces().keySet();
if (currentThreads.size() > originalThreads.size()) {
for (Thread t : currentThreads) {
if (!originalThreads.contains(t)) {
ret.add(Status.error("%s has added thread %s but not cleanly removed it", fullType, t.getName()));
// resetting original thread count
originalThreads = currentThreads;
}
}
}
log.info("released {}", fullType);
} catch (Exception ex) {
ret.add(new Status(ex));
}
} // end of loop
return ret;
}
public List<Status> serviceTest() {
List<Status> ret = new ArrayList<Status>();
String[] serviceTypeNames = Runtime.getInstance().getServiceTypeNames();
// Status status = Status.info("serviceTest will test %d services",
// serviceTypeNames.length);
// Set<Thread> originalThreads = Thread.getAllStackTraces().keySet();
for (int i = 0; i < serviceTypeNames.length; ++i) {
ServiceInterface s = null;
String fullType = serviceTypeNames[i];
if ("org.myrobotlab.service.Incubator".equals(fullType) || "org.myrobotlab.service.Runtime".equals(fullType)) {
log.info("skipping Incubator & Runtime");
continue;
}
try {
// install it
ret.add(install(fullType));
// create it
log.info("creating {}", fullType);
s = Runtime.create(fullType, fullType);
if (s == null) {
ret.add(Status.error("could not create %s service", fullType));
continue;
}
// start it
log.info("starting {}", fullType);
s.startService();
log.info("starting {}", fullType);
// FIXME - will need to do JUnit !!!!
/*
* Status result = s.test(); if (result != null && result.hasError()) {
* ret.add(result); }
*/
s.releaseService();
if (s.hasPeers()) {
s.releasePeers();
}
} catch (Exception e) {
ret.add(error(e));
continue;
}
}
return ret;
}
@Override
public void startService() {
super.startService();
}
/*
* public Status subTest() {
*
* HashSet<String> keepMeRunning = new HashSet<String>();
* List<ServiceInterface> list = Runtime.getServices(); for (int j = 0; j <
* list.size(); ++j) { ServiceInterface si = list.get(j);
* keepMeRunning.add(si.getName()); }
*
* String[] serviceTypeNames = Runtime.getInstance().getServiceTypeNames();
* Status status = Status.info("subTest");
*
* ret.add(Status.info("will test %d services", serviceTypeNames.length));
*
* for (int i = 0; i < serviceTypeNames.length; ++i) { String fullName =
* serviceTypeNames[i]; String shortName =
* fullName.substring(fullName.lastIndexOf(".") + 1); try { ServiceInterface
* si = Runtime.start(shortName, shortName); ret.add(si.test()); } catch
* (Exception e) { ret.addError(e); }
*
* // clean services Runtime.releaseAllServicesExcept(keepMeRunning); }
*
* return status;
*
* }
*/
/*
* @Override public List<Status> test() { Status status = Status.info(
* "starting %s %s test", getName(), getType());
*
* // ret.add(subTest()); // ret.add(serializeTest()); return
* ret.add(serviceTest());
*
* if (status.hasError()) { onError(status); }
*
* return status; }
*/
public void testInMoovPythonScripts() {
try {
Python python = (Python) Runtime.start("python", "Python");
// String script;
List<File> list = FileIO.listResourceContents("Python/examples");
Runtime.createAndStart("gui", "GUIService");
python = (Python) startPeer("python");
// InMoov i01 = (InMoov) Runtime.createAndStart("i01", "InMoov");
HashSet<String> keepMeRunning = new HashSet<String>(Arrays.asList("i01", "gui", "runtime", "python", getName()));
for (int i = 0; i < list.size(); ++i) {
String r = list.get(i).getName();
if (r.startsWith("InMoov2")) {
warn("testing script %s", r);
String script = FileIO.resourceToString(String.format("Python/examples/%s", r));
python.exec(script);
log.info("here");
// i01.detach();
Runtime.releaseAllServicesExcept(keepMeRunning);
}
}
} catch (Exception e) {
Logging.logError(e);
}
}
public void testPythonScripts() {
try {
Python python = (Python) Runtime.start("python", "Python");
// String script;
List<File> list = FileIO.listResourceContents("Python/examples");
Runtime.createAndStart("gui", "GUIService");
python = (Python) startPeer("python");
// InMoov i01 = (InMoov) Runtime.createAndStart("i01", "InMoov");
HashSet<String> keepMeRunning = new HashSet<String>(Arrays.asList("i01", "gui", "runtime", "python", getName()));
for (int i = 0; i < list.size(); ++i) {
String r = list.get(i).getName();
if (r.startsWith("InMoov2")) {
warn("testing script %s", r);
String script = FileIO.resourceToString(String.format("Python/examples/%s", r));
python.exec(script);
log.info("here");
// i01.detach();
Runtime.releaseAllServicesExcept(keepMeRunning);
}
}
} catch (Exception e) {
Logging.logError(e);
}
}
public void testServiceScripts() {
// get download zip
// uncompress locally
// test - instrumentation for
}
/**
* This static method returns all the details of the class without it having
* to be constructed. It has description, categories, dependencies, and peer
* definitions.
*
* @return ServiceType - returns all the data
*
*/
static public ServiceType getMetaData() {
ServiceType meta = new ServiceType(Incubator.class.getCanonicalName());
meta.addDescription("This connector will connect to an IMAP based email server and crawl the emails");
meta.addCategory("testing", "framework");
meta.addPeer("python", "Python", "shared python instance");
meta.addPeer("xmpp", "Xmpp", "Xmpp service");
return meta;
}
}