--- /dev/null
+package org.opensrf;
+
+
+public class Message {
+
+ /** Message types */
+ public enum Type {
+ REQUEST,
+ STATUS,
+ RESULT,
+ CONNECT,
+ DISCONNECT,
+ };
+
+ /** Message ID. This number is used to relate requests to responses */
+ private int id;
+ /** Type of message. */
+ private Type type;
+ /** message payload */
+ private Object payload;
+
+ /**
+ * @param id This message's ID
+ * @param type The type of message
+ */
+ public Message(int id, Type type) {
+ setId(id);
+ setType(type);
+ }
+ public int getId() {
+ return id;
+ }
+ public Type getType() {
+ return type;
+ }
+ public Object getPayload() {
+ return payload;
+ }
+ public void setId(int id) {
+ this.id = id;
+ }
+ public void setType(Type type) {
+ this.type = type;
+ }
+ public void setPayload(Object p) {
+ payload = p;
+ }
+}
+
+
--- /dev/null
+package org.opensrf;
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class Method {
+
+ private String name;
+ private List<Object> params;
+
+ public Method(String name) {
+ this.name = name;
+ this.params = new ArrayList<Object>(8);
+ }
+
+ public Method(String name, List<Object> params) {
+ this.name = name;
+ this.params = params;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public List<Object> getParams() {
+ return params;
+ }
+
+ /**
+ * Pushes a new param object onto the set of params
+ * @param p The new param to add to the method.
+ */
+ public void pushParam(Object p) {
+ this.params.add(p);
+ }
+}
+
--- /dev/null
+package org.opensrf;
+
+/**
+ * Thrown when the server responds with a method exception.
+ */
+public class MethodException extends Exception {
+ public MethodException(String info) {
+ super(info);
+ }
+}
+
--- /dev/null
+package org.opensrf;
+
+
+/**
+ * Models a single result from a method request.
+ */
+public class Result {
+
+ /** Method result content */
+ private Object content;
+ /** Name of the status */
+ private String status;
+ /** Status code number */
+ private int statusCode;
+
+ public Result(String status, int statusCode, Object content) {
+ this.status = status;
+ this.statusCode = statusCode;
+ this.content = content;
+ }
+
+ /**
+ * Get status.
+ * @return status as String.
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * Set status.
+ * @param status the value to set.
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ /**
+ * Get statusCode.
+ * @return statusCode as int.
+ */
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Set statusCode.
+ * @param statusCode the value to set.
+ */
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ /**
+ * Get content.
+ * @return content as Object.
+ */
+ public Object getContent() {
+ return content;
+ }
+
+ /**
+ * Set content.
+ * @param content the value to set.
+ */
+ public void setContent(Object content) {
+ this.content = content;
+ }
+}
+
--- /dev/null
+package org.opensrf;
+import org.opensrf.util.JSON;
+import org.opensrf.net.xmpp.*;
+
+public abstract class Session {
+
+ /** Represents the different connection states for a session */
+ public enum ConnectState {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED
+ };
+
+ /** the current connection state */
+ private ConnectState connectState;
+
+ /** The (jabber) address of the remote party we are communicating with */
+ private String remoteNode;
+
+ /**
+ * The thread is used to link messages to a given session.
+ * In other words, each session has a unique thread, and all messages
+ * in that session will carry this thread around as an indicator.
+ */
+ private String thread;
+
+ public Session() {
+ connectState = ConnectState.DISCONNECTED;
+ }
+
+ /**
+ * Sends a Message to our remoteNode.
+ */
+ public void send(Message omsg) throws XMPPException {
+
+ /** construct the XMPP message */
+ XMPPMessage xmsg = new XMPPMessage();
+ xmsg.setTo(remoteNode);
+ xmsg.setThread(thread);
+ xmsg.setBody(JSON.toJSON(omsg));
+ XMPPSession ses = XMPPSession.getGlobalSession();
+
+ try {
+ XMPPSession.getGlobalSession().send(xmsg);
+ } catch(XMPPException e) {
+ /* XXX log */
+ connectState = ConnectState.DISCONNECTED;
+ }
+ }
+}
* Used for XMPP stream/authentication errors
*/
public class XMPPException extends Exception {
- private String info;
-
- /**
- * @param info Runtime exception information.
- */
public XMPPException(String info) {
- this.info = info;
- }
- public String toString() {
- return this.info;
+ super(info);
}
}
}
} catch(javax.xml.stream.XMLStreamException se) {
- /* XXX log an error, set a state, and notify */
+ /* XXX log an error */
+ xmlState = XMLState.IN_NOTHING;
+ streamState = XMPPStreamState.DISCONNECTED;
+ notifyCoreEvent();
}
}
/** Raw socket output stream */
OutputStream outStream;
+ /** The process-wide session. All communication occurs
+ * accross this single connection */
+ private static XMPPSession globalSession;
/**
this.port = port;
}
+ public static XMPPSession getGlobalSession() {
+ return globalSession;
+ }
+
+ public static void setGlobalSession(XMPPSession ses) {
+ globalSession = ses;
+ }
+
/** true if this session is connected to the server */
public boolean connected() {
return (
reader != null &&
- reader.getXMPPStreamState() == XMPPReader.XMPPStreamState.CONNECTED);
+ reader.getXMPPStreamState() ==
+ XMPPReader.XMPPStreamState.CONNECTED);
}
* Sends an XMPPMessage.
* @param msg The message to send.
*/
- public void send(XMPPMessage msg) throws XMPPException {
+ public synchronized void send(XMPPMessage msg) throws XMPPException {
checkConnected();
try {
outStream.write(msg.toXML().getBytes());
--- /dev/null
+package org.opensrf.test;
+
+import org.opensrf.util.JSON;
+import java.util.*;
+
+public class TestJSON {
+
+ public static void main(String args[]) {
+
+ Map<String,Object> map = new HashMap<String,Object>();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ map.put("key3", "value3");
+ map.put("key4", "athe\u0301s");
+ map.put("key5", null);
+
+ List<Object> list = new ArrayList<Object>(16);
+ list.add(new Integer(1));
+ list.add(new Boolean(true));
+ list.add("WATER");
+ list.add(null);
+ map.put("key6", list);
+
+ System.out.println(JSON.toJSON(map));
+ }
+}
--- /dev/null
+package org.opensrf.util;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * JSON utilities.
+ */
+public class JSON {
+
+ public static final String JSON_CLASS_KEY = "__c";
+ public static final String JSON_PAYLOAD_KEY = "__p";
+
+
+ /**
+ * @see toJSON(Object, StringBuffer)
+ */
+ public static String toJSON(Object obj) {
+ StringBuffer sb = new StringBuffer();
+ toJSON(obj, sb);
+ return sb.toString();
+ }
+
+
+ /**
+ * Encodes a java object to JSON.
+ * Maps (HashMaps, etc.) are encoded as JSON objects.
+ * Iterable's (Lists, etc.) are encoded as JSON arrays
+ */
+ public static void toJSON(Object obj, StringBuffer sb) {
+
+ /** JSON null */
+ if(obj == null) {
+ sb.append("null");
+ return;
+ }
+
+ /** JSON string */
+ if(obj instanceof String) {
+ sb.append('"');
+ Utils.escape((String) obj, sb);
+ sb.append('"');
+ return;
+ }
+
+ /** JSON number */
+ if(obj instanceof Number) {
+ sb.append(obj.toString());
+ return;
+ }
+
+ /** JSON array */
+ if(obj instanceof Iterable) {
+ encodeJSONArray((Iterable) obj, sb);
+ return;
+ }
+
+ /** JSON object */
+ if(obj instanceof Map) {
+ encodeJSONObject((Map) obj, sb);
+ return;
+ }
+
+ /** JSON boolean */
+ if(obj instanceof Boolean) {
+ sb.append((((Boolean) obj).booleanValue() ? "true" : "false"));
+ return;
+ }
+ }
+
+
+ /**
+ * Encodes a List as a JSON array
+ */
+ private static void encodeJSONArray(Iterable iterable, StringBuffer sb) {
+ Iterator itr = iterable.iterator();
+ sb.append("[");
+ boolean some = false;
+
+ while(itr.hasNext()) {
+ some = true;
+ toJSON(itr.next(), sb);
+ sb.append(',');
+ }
+
+ /* remove the trailing comma if the array has any items*/
+ if(some)
+ sb.deleteCharAt(sb.length()-1);
+ sb.append("]");
+ }
+
+
+ /**
+ * Encodes a Map to a JSON object
+ */
+ private static void encodeJSONObject(Map map, StringBuffer sb) {
+ Iterator itr = map.keySet().iterator();
+ sb.append("{");
+ Object key = null;
+
+ while(itr.hasNext()) {
+ key = itr.next();
+ toJSON(key, sb);
+ sb.append(':');
+ toJSON(map.get(key), sb);
+ sb.append(',');
+ }
+
+ /* remove the trailing comma if the object has any items*/
+ if(key != null)
+ sb.deleteCharAt(sb.length()-1);
+ sb.append("}");
+ }
+}
+
+
+
--- /dev/null
+package org.opensrf.util;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Collection of general, static utility methods
+ */
+public class Utils {
+
+ /**
+ * Returns the string representation of a given file.
+ * @param filename The file to turn into a string
+ */
+ public static String fileToString(String filename)
+ throws FileNotFoundException, IOException {
+
+ StringBuffer sb = new StringBuffer();
+ BufferedReader in = new BufferedReader(new FileReader(filename));
+ String str;
+ while ((str = in.readLine()) != null)
+ sb.append(str);
+ in.close();
+ return sb.toString();
+ }
+
+
+ /**
+ * @see escape(String, StringBuffer)
+ */
+ public static String escape(String string) {
+ StringBuffer sb = new StringBuffer();
+ escape(string, sb);
+ return sb.toString();
+ }
+
+ /**
+ * Escapes a string. Turns bare newlines into \n, etc.
+ * Escapes \n, \r, \t, ", \f
+ * Encodes non-ascii characters as UTF-8: \u0000
+ * @param string The string to escape
+ * @param sb The string buffer to write the escaped string into
+ */
+ public static void escape(String string, StringBuffer sb) {
+ int len = string.length();
+ String utf;
+ char c;
+ for( int i = 0; i < len; i++ ) {
+ c = string.charAt(i);
+ switch (c) {
+ case '\\':
+ sb.append("\\\\");
+ break;
+ case '"':
+ sb.append("\\\"");
+ break;
+ case '\b':
+ sb.append("\\b");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\f':
+ sb.append("\\f");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ default:
+ if (c < 32 || c > 126 ) {
+ /* escape all non-ascii or control characters as UTF-8 */
+ utf = "000" + Integer.toHexString(c);
+ sb.append("\\u" + utf.substring(utf.length() - 4));
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+ }
+}
+
+
+