setId(id);
setType(type);
}
+ public Message(int id, Type type, Object payload) {
+ this(id, type);
+ setPayload(payload);
+ }
+
public int getId() {
return id;
import org.opensrf.util.*;
-public class Method implements OSRFSerializable {
+public class Method extends OSRFObject {
private String name;
private List<Object> params;
- /** Register this object */
private static OSRFRegistry registry =
OSRFRegistry.registerObject(
"osrfMethod",
OSRFRegistry.WireProtocol.HASH,
new String[] {"method", "params"});
-
public Method(String name) {
this.name = name;
this.params = new ArrayList<Object>(8);
/**
* Models a single result from a method request.
*/
-public class Result {
+public class Result implements OSRFSerializable {
/** Method result content */
private Object content;
package org.opensrf;
-import org.opensrf.util.JSON;
+import org.opensrf.util.JSONWriter;
import org.opensrf.net.xmpp.*;
+import java.util.Map;
+import java.util.HashMap;
public abstract class Session {
CONNECTED
};
+ /** local cache of existing sessions */
+ private static Map<String, Session>
+ sessionCache = new HashMap<String, Session>();
+
/** the current connection state */
private ConnectState connectState;
XMPPMessage xmsg = new XMPPMessage();
xmsg.setTo(remoteNode);
xmsg.setThread(thread);
- xmsg.setBody(JSON.toJSON(omsg));
+ xmsg.setBody(new JSONWriter(omsg).write());
XMPPSession ses = XMPPSession.getGlobalSession();
try {
XMPPSession.getGlobalSession().send(xmsg);
} catch(XMPPException e) {
- /* XXX log */
+ /* XXX log.. what else? */
connectState = ConnectState.DISCONNECTED;
}
}
+
+ /**
+ * Waits for a message to arrive over the network and passes
+ * all received messages to the stack for processing
+ * @param millis The number of milliseconds to wait for a message to arrive
+ */
+ public static void waitForMessage(long millis) {
+ try {
+ Stack.processXMPPMessage(
+ XMPPSession.getGlobalSession().recv(millis));
+ } catch(XMPPException e) {
+ /* XXX log.. what else? */
+ }
+ }
+
+ /**
+ * Removes this session from the session cache.
+ */
+ public void cleanup() {
+ sessionCache.remove(thread);
+ }
+
+ /**
+ * Searches for the cached session with the given thread.
+ * @param thread The session thread.
+ * @return The found session or null.
+ */
+ public static Session findCachedSession(String thread) {
+ return sessionCache.get(thread);
+ }
}
* timeout is negative, waits potentially forever.
* @return The number of milliseconds in wait
*/
- public synchronized long waitCoreEvent(int timeout) {
+ public synchronized long waitCoreEvent(long timeout) {
if(msgQueue.peek() != null || timeout == 0) return 0;
* If timeout is 0, this method will not block at all, but will return a
* message if there is already a message available.
*/
- public XMPPMessage recv(int timeout) throws XMPPException {
+ public XMPPMessage recv(long timeout) throws XMPPException {
XMPPMessage msg;
public class TestJSON {
- public static void main(String args[]) {
+ public static void main(String args[]) throws Exception {
Map<String,Object> map = new HashMap<String,Object>();
map.put("key1", "value1");
list.add(null);
map.put("key6", list);
- System.out.println(JSON.toJSON(map) + "\n");
+ System.out.println(new JSONWriter(map).write() + "\n");
String[] fields = {"isnew", "name", "shortname", "ill_address"};
OSRFRegistry.registerObject("aou", OSRFRegistry.WireProtocol.ARRAY, fields);
map.put("key7", obj);
list.add(obj);
- System.out.println(JSON.toJSON(map) + "\n");
+ System.out.println(new JSONWriter(map).write() + "\n");
Message m = new Message(1, Message.Type.REQUEST);
method.addParam("app07.dev.gapines.org");
m.setPayload(method);
- System.out.println(JSON.toJSON(m) + "\n");
+ String s = new JSONWriter(m).write();
+ System.out.println(s + "\n");
+
+ Object o = new JSONReader(s).read();
+ System.out.println("Read+Wrote: " + new JSONWriter(o).write());
}
}
+++ /dev/null
-package org.opensrf.util;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * JSON utilities.
- */
-public class JSON {
-
- /** Special OpenSRF serializable object netClass key */
- public static final String JSON_CLASS_KEY = "__c";
-
- /** Special OpenSRF serializable object payload key */
- 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;
- }
-
- /** OpenSRF serializable objects */
- if(obj instanceof OSRFSerializable) {
- encodeOSRFSerializable((OSRFSerializable) 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("}");
- }
-
-
- /**
- * Encodes a network-serializable OpenSRF object
- */
- private static void encodeOSRFSerializable(OSRFSerializable obj, StringBuffer sb) {
-
- OSRFRegistry reg = obj.getRegistry();
- String[] fields = reg.getFields();
- Map<String, Object> map = new HashMap<String, Object>();
- map.put(JSON_CLASS_KEY, reg.getNetClass());
-
- if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) {
-
- List<Object> list = new ArrayList<Object>(fields.length);
- for(String s : fields)
- list.add(obj.get(s));
- map.put(JSON_PAYLOAD_KEY, list);
-
- } else {
- //map.put(JSON_PAYLOAD_KEY, new HashMap<String, Object>(obj));
- Map<String, Object> subMap = new HashMap<String, Object>();
- for(String s : fields)
- map.put(s, obj.get(s));
-
- }
-
- /** now serialize the encoded object */
- toJSON(map, sb);
- }
-}
-
-
-
--- /dev/null
+package org.opensrf.util;
+
+import java.io.*;
+import java.util.*;
+
+import org.json.JSONTokener;
+import org.json.JSONObject;
+import org.json.JSONArray;
+
+
+/**
+ * JSON utilities.
+ */
+public class JSONReader {
+
+ /** Special OpenSRF serializable object netClass key */
+ public static final String JSON_CLASS_KEY = "__c";
+
+ /** Special OpenSRF serializable object payload key */
+ public static final String JSON_PAYLOAD_KEY = "__p";
+
+ private String json;
+
+ public JSONReader(String json) {
+ this.json = json;
+ }
+
+ /**
+ * Parses JSON and creates an object.
+ * @param json The JSON string to parse
+ * @return The resulting object which may be a List,
+ * Map, Number, String, Boolean, or null
+ */
+ public Object read() throws JSONException {
+ JSONTokener tk = new JSONTokener(json);
+ try {
+ return readSubObject(tk.nextValue());
+ } catch(org.json.JSONException e) {
+ throw new JSONException(e.toString());
+ }
+ }
+
+ public List<?> readArray() throws JSONException {
+ Object o = read();
+ try {
+ return (List<?>) o;
+ } catch(Exception e) {
+ throw new JSONException("readArray(): JSON cast exception");
+ }
+ }
+
+ public Map<?,?> readObject() throws JSONException {
+ Object o = read();
+ try {
+ return (Map<?,?>) o;
+ } catch(Exception e) {
+ throw new JSONException("readObject(): JSON cast exception");
+ }
+ }
+
+
+ private Object readSubObject(Object obj) throws JSONException {
+
+ if( obj == null ||
+ obj instanceof String ||
+ obj instanceof Number ||
+ obj instanceof Boolean)
+ return obj;
+
+ try {
+
+ if( obj instanceof JSONObject ) {
+
+ /* read objects */
+ String key;
+ JSONObject jobj = (JSONObject) obj;
+ Map<String, Object> map = new HashMap<String, Object>();
+
+ for( Iterator e = jobj.keys(); e.hasNext(); ) {
+ key = (String) e.next();
+
+ /* we encoutered the special class key */
+ if( JSON_CLASS_KEY.equals(key) )
+ return buildRegisteredObject(
+ (String) jobj.get(key), jobj.get(JSON_PAYLOAD_KEY));
+
+ /* we encountered the data key */
+ if( JSON_PAYLOAD_KEY.equals(key) )
+ return buildRegisteredObject(
+ (String) jobj.get(JSON_CLASS_KEY), jobj.get(key));
+
+ map.put(key, readSubObject(jobj.get(key)));
+ }
+ return map;
+ }
+
+ if ( obj instanceof JSONArray ) {
+
+ JSONArray jarr = (JSONArray) obj;
+ int length = jarr.length();
+ List<Object> list = new ArrayList<Object>(length);
+
+ for( int i = 0; i < length; i++ )
+ list.add(readSubObject(jarr.get(i)));
+ return list;
+
+ }
+
+ } catch(org.json.JSONException e) {
+
+ throw new JSONException(e.toString());
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Builds an OSRFObject map registered OSRFHash object based on the JSON object data.
+ * @param netClass The network class hint for this object.
+ * @param paylaod The actual object on the wire.
+ */
+ private OSRFObject buildRegisteredObject(
+ String netClass, Object payload) throws JSONException {
+
+ OSRFRegistry registry = OSRFRegistry.getRegistry(netClass);
+ OSRFObject obj = new OSRFObject(registry);
+
+ try {
+ if( payload instanceof JSONArray ) {
+ JSONArray jarr = (JSONArray) payload;
+
+ /* for each array item, instert the item into the hash. the hash
+ * key is found by extracting the fields array from the registered
+ * object at the current array index */
+ String fields[] = registry.getFields();
+ for( int i = 0; i < jarr.length(); i++ ) {
+ obj.put(fields[i], readSubObject(jarr.get(i)));
+ }
+
+ } else if( payload instanceof JSONObject ) {
+
+ /* since this is a hash, simply copy the data over */
+ JSONObject jobj = (JSONObject) payload;
+ String key;
+ for( Iterator e = jobj.keys(); e.hasNext(); ) {
+ key = (String) e.next();
+ obj.put(key, readSubObject(jobj.get(key)));
+ }
+ }
+
+ } catch(org.json.JSONException e) {
+ throw new JSONException(e.toString());
+ }
+
+ return obj;
+ }
+}
+
+
+
--- /dev/null
+package org.opensrf.util;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * JSONWriter
+ */
+public class JSONWriter {
+
+ /** The object to serialize to JSON */
+ private Object obj;
+
+ public JSONWriter(Object obj) {
+ this.obj = obj;
+ }
+
+
+ /**
+ * @see write(Object, StringBuffer)
+ */
+ public String write() {
+ StringBuffer sb = new StringBuffer();
+ write(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 void write(StringBuffer sb) {
+ write(obj, sb);
+ }
+
+ public void write(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;
+ }
+
+ /** OpenSRF serializable objects */
+ if(obj instanceof OSRFSerializable) {
+ encodeOSRFSerializable((OSRFSerializable) 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 void encodeJSONArray(Iterable iterable, StringBuffer sb) {
+ Iterator itr = iterable.iterator();
+ sb.append("[");
+ boolean some = false;
+
+ while(itr.hasNext()) {
+ some = true;
+ write(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 as a JSON object
+ */
+ private void encodeJSONObject(Map map, StringBuffer sb) {
+ Iterator itr = map.keySet().iterator();
+ sb.append("{");
+ Object key = null;
+
+ while(itr.hasNext()) {
+ key = itr.next();
+ write(key, sb);
+ sb.append(':');
+ write(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("}");
+ }
+
+
+ /**
+ * Encodes a network-serializable OpenSRF object
+ */
+ private void encodeOSRFSerializable(OSRFSerializable obj, StringBuffer sb) {
+
+ OSRFRegistry reg = obj.getRegistry();
+ String[] fields = reg.getFields();
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put(JSONReader.JSON_CLASS_KEY, reg.getNetClass());
+
+ if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) {
+
+ List<Object> list = new ArrayList<Object>(fields.length);
+ for(String s : fields)
+ list.add(obj.get(s));
+ map.put(JSONReader.JSON_PAYLOAD_KEY, list);
+
+ } else {
+
+ Map<String, Object> subMap = new HashMap<String, Object>();
+ for(String s : fields)
+ subMap.put(s, obj.get(s));
+ map.put(JSONReader.JSON_PAYLOAD_KEY, subMap);
+
+ }
+
+ /** now serialize the encoded object */
+ write(map, sb);
+ }
+}
+
+
+
package org.opensrf.util;
+import java.util.Map;
import java.util.HashMap;
public OSRFObject() {
}
+
+ /*
+ public OSRFObject(String netClass, Map map) {
+ super(map);
+ registry = OSRFRegistry.getRegistry(netClass);
+ }
+ */
+
/**
* Creates a new object with the provided registry
*/
return registry;
}
-
/**
- * Gets the object at the given fields. We override this here
- * as part of the contract with OSRFSerializable
- * @param field the field name to get.
- * @return The object contained at the given field.
+ * Implement get() to fulfill our contract with OSRFSerializable
*/
public Object get(String field) {
return super.get(field);