/**
*
*/
package org.squidy.manager;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.basex.server.EventNotifier;
import org.mvel2.MVEL;
import org.squidy.database.BaseXSession;
import org.squidy.database.Session;
import org.squidy.database.SessionFactoryProvider;
import org.squidy.manager.model.ModelData;
import org.squidy.manager.model.Pipe;
import org.squidy.manager.model.Piping;
import org.squidy.manager.model.Processable;
import org.squidy.manager.model.Workspace;
import org.squidy.manager.parser.ModelHandler;
import org.squidy.resource.MessageResourceBundle;
/**
* <code>Manager</code>.
*
* <pre>
* Date: Aug 6, 2010
* Time: 8:00:23 AM
* </pre>
*
* @author Roman Rädle, <a
* href="mailto:Roman.Raedle@uni-konstanz.de">Roman.
* Raedle@uni-konstanz.de</a>, University of Konstanz
* @version $Id$
* @since 1.5.0
*/
public class Manager {
// Logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(Manager.class);
public static final String TRIGGER_PROCESSING = "processing";
public static final String TRIGGER_PROPERTY = "property";
public static void main(String[] args) throws Exception {
switch (args.length) {
case 0:
new Manager();
break;
case 1:
new Manager(args[0]);
break;
case 2:
new Manager(args[0], Boolean.parseBoolean(args[1]));
break;
default:
help(null);
break;
}
}
private static final Map<Command, Method> COMMANDS = getCommands(Manager.class);
private String file;
private ModelData data;
private static MessageResourceBundle bundle;
static {
bundle = MessageResourceBundle.getBundle("manager");
}
private static Manager instance;
/**
*
*/
public static Manager get() {
if (instance == null)
instance = new Manager();
return instance;
}
/**
*
*/
public static Manager get(ModelData data) {
if (instance == null)
instance = new Manager(data);
return instance;
}
private Manager() {
Thread cmdThread = new Thread() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
String cmd = null;
try {
while ((cmd = br.readLine()) != null) {
String[] cmdParams = cmd.split(" ");
String cmdName = cmdParams[0];
Object[] params = new String[cmdParams.length - 1];
System.arraycopy(cmdParams, 1, params, 0, params.length);
Method method = getMethodForCommandName(cmdName);
if (method == null) {
System.out.println(bundle.getMessage(
"manager.unknown_command", cmdName));
help(null);
consoleInput();
continue;
}
try {
method.invoke(Manager.this, params);
} catch (IllegalArgumentException e) {
System.out.println("Illegal arguments:");
System.out.println(bundle
.getMessage(getCommandForCommandName(
cmdName).help()));
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
consoleInput();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
};
cmdThread.start();
if (LOG.isInfoEnabled()) {
LOG.info("Manager started");
}
consoleInput();
}
public Manager(ModelData data) {
this();
this.data = data;
Session session = SessionFactoryProvider.getProvider().getSession();
if (!(session instanceof BaseXSession))
return;
BaseXSession basexSession = (BaseXSession)session;
if (session != null)
try {
basexSession.execute("create event " + TRIGGER_PROPERTY);
basexSession.watch(TRIGGER_PROPERTY, new EventNotifier() {
@Override
public void notify(final String value) {
String[] a = value.split(",");
String[] a0 = a[0].split("=");
String[] a1 = a[1].split("=");
Processable p = getProcessableWithId(
Manager.this.data.getWorkspace(), a0[1]);
setProperty(p, a1[0], a1[1]);
}
});
basexSession.execute("create event " + TRIGGER_PROCESSING);
basexSession.watch(TRIGGER_PROCESSING,
new EventNotifier() {
@Override
public void notify(final String value) {
String[] a = value.split(",");
String[] a0 = a[0].split("=");
String[] a1 = a[1].split("=");
Processable p = getProcessableWithId(
Manager.this.data.getWorkspace(), a0[1]);
if (p != null)
switch (Processable.Action.valueOf(a1[1])) {
case START:
p.start();
break;
case STOP:
p.stop();
break;
case DUPLICATE:
break;
case DELETE:
p.delete();
break;
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param file
*/
public Manager(String file) {
this();
load(file);
}
/**
* @param file
* @param autostart
*/
public Manager(String file, boolean autostart) {
this(file);
if (autostart) {
start("*");
}
}
/**
*
*/
private static void consoleInput() {
System.out.print("> ");
}
/**
* @param cmdName
* @return
*/
private static Command getCommandForCommandName(String cmdName) {
for (Command cmd : COMMANDS.keySet()) {
if (cmd.name().equals(cmdName)) {
return cmd;
}
}
return null;
}
/**
* @param cmdName
* @return
*/
private static Method getMethodForCommandName(String cmdName) {
for (Command cmd : COMMANDS.keySet()) {
if (cmd.name().equals(cmdName)) {
return COMMANDS.get(cmd);
}
}
return null;
}
/**
* @param file
*/
@Command(name = "load", description = "manager.load.description", help = "manager.load.help", order = 1)
private void load(String file) {
this.file = file;
ModelHandler modelHandler = ModelHandler.getModelHandler();
InputStream inputStream = null;
try {
inputStream = new FileInputStream(new File(file));
} catch (FileNotFoundException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Could not load workspace: " + e.getMessage());
}
}
if (inputStream != null) {
data = modelHandler.load(inputStream);
if (LOG.isInfoEnabled()) {
LOG.info("Workspace loaded");
}
}
}
/**
* @throws IOException
*/
@Command(name = "start", description = "manager.start.description", help = "manager.start.help", order = 2)
public void start(String id) throws ProcessException {
if (data != null) {
Workspace workspace = data.getWorkspace();
if ("*".equals(id)) {
workspace.start();
} else {
Processable processable = getProcessableWithId(workspace, id);
if (processable != null) {
processable.start();
} else {
System.out.println("No node with this id has been found");
}
}
}
}
/**
* @throws IOException
*/
@Command(name = "stop", description = "manager.stop.description", help = "manager.stop.help", order = 3)
public void stop(String id) throws ProcessException {
if (data != null) {
Workspace workspace = data.getWorkspace();
if ("*".equals(id)) {
workspace.stop();
} else {
Processable processable = getProcessableWithId(workspace, id);
if (processable != null) {
processable.stop();
} else {
System.out.println("No node with this id has been found");
}
}
}
}
/**
*
*/
@Command(name = "info", description = "manager.info.description", help = "manager.info.help", order = 4)
private void info() {
PrintStream console = System.out;
if (data != null) {
console.println("file:\t\t" + file);
console.println("processing:\t"
+ data.getWorkspace().isProcessing());
} else {
console.println("-");
}
}
@Command(name = "list", description = "manager.list.description", help = "manager.list.help", order = 5)
private void list(String type) {
if ("nodes".equals(type)) {
if (data != null) {
Workspace workspace = data.getWorkspace();
workspace0(workspace, 0);
}
}
}
private void workspace0(Processable processable, int tab) {
PrintStream console = System.out;
for (int i = 0; i < tab; i++) {
console.print("\t");
}
console.println("id={" + processable.getId() + "},type={"
+ processable.getClass().getSimpleName() + "}");
for (Processable subProcessable : processable.getSubProcessables()) {
workspace0(subProcessable, tab + 1);
}
}
@Command(name = "help", description = "manager.help.description", help = "manager.help.help", order = 888)
private static void help(String cmdName) {
PrintStream console = System.out;
if (cmdName != null) {
String helpBundle = getCommandForCommandName(cmdName).help();
console.println(bundle.getMessage(helpBundle));
} else {
for (Command cmd : COMMANDS.keySet()) {
console.print(cmd.name());
console.print("\t\t");
console.print(bundle.getMessage(cmd.description()));
console.println();
}
}
}
/**
*
*/
@Command(name = "exit", description = "manager.exit.description", help = "manager.exit.help", order = 999)
private void exit() {
stop("*");
if (LOG.isInfoEnabled()) {
LOG.info("Manager exit");
}
System.exit(0);
}
/**
* @param type
* @return
*/
private static Map<Command, Method> getCommands(Class<?> type) {
Map<Command, Method> commands = new TreeMap<Command, Method>(
new Comparator<Command>() {
/**
* @param o1
* @param o2
* @return
*/
public int compare(Command o1, Command o2) {
return ((Integer) o1.order()).compareTo((Integer) o2
.order());
}
});
for (Method method : type.getDeclaredMethods()) {
if (method.isAnnotationPresent(Command.class)) {
method.setAccessible(true);
commands.put(method.getAnnotation(Command.class), method);
}
}
return commands;
}
private static final Processable getProcessableWithId(
Processable processable, String id) {
if (id.equals(processable.getId())) {
return processable;
}
for (Processable subProcessable : processable.getSubProcessables()) {
Processable res = getProcessableWithId(subProcessable, id);
if (res != null)
return res;
}
if (processable instanceof Piping) {
Piping piping = (Piping) processable;
for (Pipe pipe : piping.getPipes()) {
if (id.equals(pipe.getId()))
return pipe;
}
}
return null;
}
public void propertyChanged(Processable processable, String name,
Object value) {
try {
setProperty(processable, name, value);
SessionFactoryProvider
.getProvider()
.getSession()
.execute("db:event(" + TRIGGER_PROPERTY + ",processable=" + processable.getId() + "," + name + "=" + value + ")");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void setProperty(Processable processable, String name, Object value) {
Object oldValue = MVEL.getProperty(name, processable);
MVEL.setProperty(processable, name, value);
Object newValue = MVEL.getProperty(name, processable);
processable.fireStatusChange(name, oldValue, newValue);
}
public void notify(Processable processable, Processable.Action action) {
try {
SessionFactoryProvider
.getProvider()
.getSession()
.execute("db:event(" + TRIGGER_PROCESSING + ",processable=" + processable.getId() + ",action=" + action + ")");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* <code>Command</code>.
*
* <pre>
* Date: Aug 8, 2010
* Time: 10:24:30 PM
* </pre>
*
* @author Roman Rädle, <a
* href="mailto:Roman.Raedle@uni-konstanz.de">Roman
* .Raedle@uni-konstanz.de</a>, University of Konstanz
* @version $Id$
* @since 1.5.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Command {
String name();
String description();
String help();
int order() default 0;
}
}