package javaforce.jbus;
/**
* Created : Apr 9, 2012
*
* @author pquiring
*/
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
import javaforce.*;
public class JBusClient extends Thread {
public String pack;
private Object obj;
private Class<?> cls;
private Socket s;
private InputStream is;
private OutputStream os;
private volatile boolean ready;
private int readyCnt = 0;
private boolean quiet = false;
private int port = 777;
public JBusClient(String pack, Object obj) {
if ((pack == null) || (obj == null)) {
return;
}
this.pack = pack;
this.obj = obj;
cls = obj.getClass();
}
public void setQuiet(boolean state) {
quiet = state;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
try {
JFLog.log("JBusClient:connecting to 127.0.0.1:" + port);
s = new Socket(InetAddress.getByName("127.0.0.1"), port);
is = s.getInputStream();
os = s.getOutputStream();
if (pack != null) {
os.write(("cmd.package=" + pack + "\n").getBytes());
os.flush();
// JFLog.log("JBus Client registered as : " + pack);
}
ready = true;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while (s.isConnected()) {
String cmd = br.readLine();
if (cmd == null) {
break;
}
try {
doCmd(cmd);
} catch (InvocationTargetException ite) {
Throwable cause = ite.getCause();
if (cause == null) {
JFLog.log(ite);
} else {
JFLog.log(cause);
}
} catch (Exception e1) {
JFLog.log(e1);
}
}
} catch (SocketException e2) {
if (!quiet) JFLog.log("JBus Client closed : " + pack);
} catch (Exception e3) {
if (!quiet) JFLog.log(e3);
}
}
private void doCmd(String cmd) throws Exception {
if (cmd.startsWith("cmd.")) {
//unknown cmd
return;
}
//must be a remote function call
//general format : org.package.func(args)
//supported args : "String", int
if (cls == null) {
return; //not accepting calls
}
int b1 = cmd.indexOf("(");
int b2 = cmd.length() - 1;
String argsString = cmd.substring(b1 + 1, b2);
String packFunc = cmd.substring(0, b1);
int idx = packFunc.lastIndexOf('.');
String call_pack = packFunc.substring(0, idx);
if (!call_pack.equals(pack)) {
throw new Exception("package mismatch"); //error : should not happen
}
String call_func = packFunc.substring(idx + 1);
// JFLog.log("call:" + call_pack + "." + call_func + "(" + argsString + ")"); //test
Object args[] = parseArgs(argsString);
int argsLength = args.length;
Class types[] = new Class[argsLength];
for (int a = 0; a < argsLength; a++) {
if (args[a] instanceof Integer) {
types[a] = int.class; //not the same as Integer.class
} else {
types[a] = args[a].getClass(); //String.class
}
}
Method method = cls.getMethod(call_func, types);
method.invoke(obj, args);
}
private Object[] parseArgs(String args) throws Exception {
ArrayList<Object> ret = new ArrayList<Object>();
//"string", int, ...
int pos = 0;
int len = args.length();
while (pos < len) {
if (args.charAt(pos) == '\"') {
//decode String
int q1 = pos;
int q2 = args.indexOf('\"', q1 + 1);
String str = args.substring(q1 + 1, q2);
ret.add(str);
pos = q2 + 1;
} else {
//decode Integer
int nxt = args.indexOf(',', pos);
if (nxt == -1) {
nxt = len;
}
Integer i = Integer.valueOf(args.substring(pos, nxt));
ret.add(i);
pos = nxt;
}
if (pos >= len) {
break;
}
if (args.charAt(pos) != ',') {
throw new Exception("bad args");
}
pos++;
}
return ret.toArray();
}
public boolean call(String pack, String func, String args) {
return call(pack + "." + func + "(" + args + ")\n");
}
public boolean call(String pfa) {
while (!ready) {
readyCnt++;
if (readyCnt == 30) {
return false; //failed
}
JF.sleep(100);
}
try {
os.write(pfa.getBytes());
os.flush();
return true;
} catch (Exception e) {
JFLog.log(e);
return false;
}
}
public boolean broadcast(String pack, String func, String args) {
return call("cmd.broadcast=" + pack + "." + func + "(" + args + ")\n");
}
public boolean ready() {
return ready;
}
public void close() {
try {
s.close();
} catch (Exception e) {
}
s = null;
}
public static String quote(String str) {
return "\"" + str + "\"";
}
public static String encodeString(String in) {
try {
return URLEncoder.encode(in, "UTF-8");
} catch (Exception e) {
return null;
}
}
public static String decodeString(String in) {
try {
return URLDecoder.decode(in, "UTF-8");
} catch (Exception e) {
return null;
}
}
}