From: kenstir Date: Wed, 18 Nov 2015 17:23:47 +0000 (-0500) Subject: moved opensrf sources to fit android library project structure X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=6d68300e6f80821f3ce877191bda0f98850a9db5;p=working%2FEvergreen.git moved opensrf sources to fit android library project structure --- diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/ClientSession.java b/Open-ILS/src/Android/opensrf/org/opensrf/ClientSession.java deleted file mode 100644 index 3ed4908296..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/ClientSession.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.opensrf; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.Random; -import java.util.Arrays; - -import org.opensrf.util.*; -import org.opensrf.net.xmpp.*; - - -/** - * Models an OpenSRF client session. - */ -public class ClientSession extends Session { - - /** The remote service to communicate with */ - private String service; - /** OpenSRF domain */ - private String domain; - /** Router name */ - private String router; - - /** - * original remote node. The current remote node will change based - * on server responses. This is used to reset the remote node to - * its original state. - */ - private String origRemoteNode; - /** The next request id */ - private int nextId; - /** The requests this session has sent */ - private Map requests; - - /** - * Creates a new client session. Initializes the - * @param service The remote service. - */ - public ClientSession(String service) throws ConfigException { - this(service, null); - } - - /** - * Creates a new client session. Initializes the - * @param service The remote service. - * @param locale The locale for this session. - */ - public ClientSession(String service, String locale) throws ConfigException { - this.service = service; - if(locale != null) - setLocale(locale); - - /** generate the remote node string */ - domain = (String) Config.global().getFirst("/domain"); - router = Config.global().getString("/router_name"); - setRemoteNode(router + "@" + domain + "/" + service); - origRemoteNode = getRemoteNode(); - - - /** create a random thread */ - long time = new Date().getTime(); - Random rand = new Random(time); - setThread(rand.nextInt()+""+rand.nextInt()+""+time+Thread.currentThread().getId()); - - nextId = 0; - requests = new HashMap(); - cacheSession(); - } - - /** - * Creates a new request to send to our remote service. - * @param method The method API name - * @param params The list of method parameters - * @return The request object. - */ - public Request request(String method, List params) throws SessionException { - return request(new Request(this, nextId++, method, params)); - } - - /** - * Creates a new request to send to our remote service. - * @param method The method API name - * @param params The list of method parameters - * @return The request object. - */ - public Request request(String method, Object[] params) throws SessionException { - return request(new Request(this, nextId++, method, Arrays.asList(params))); - } - - - /** - * Creates a new request to send to our remote service. - * @param method The method API name - * @return The request object. - */ - public Request request(String method) throws SessionException { - return request(new Request(this, nextId++, method)); - } - - - private Request request(Request req) throws SessionException { - if(getConnectState() != ConnectState.CONNECTED) - resetRemoteId(); - requests.put(new Integer(req.getId()), req); - req.send(); - return req; - } - - - /** - * Resets the remoteNode to its original state. - */ - public void resetRemoteId() { - setRemoteNode(origRemoteNode); - } - - - /** - * Pushes a response onto the result queue of the appropriate request. - * @param msg The received RESULT Message - */ - public void pushResponse(Message msg) { - - Request req = findRequest(msg.getId()); - if(req == null) { - /** LOG that we've received a result to a non-existant request */ - System.err.println(msg.getId() +" has no corresponding request"); - return; - } - OSRFObject payload = (OSRFObject) msg.get("payload"); - - /** build a result and push it onto the request's result queue */ - req.pushResponse( - new Result( - payload.getString("status"), - payload.getInt("statusCode"), - payload.get("content") - ) - ); - } - - public Request findRequest(int reqId) { - return requests.get(new Integer(reqId)); - } - - /** - * Removes a request for this session's request set - */ - public void cleanupRequest(int reqId) { - requests.remove(new Integer(reqId)); - } - - public void setRequestComplete(int reqId) { - Request req = findRequest(reqId); - if(req == null) return; - req.setComplete(); - } - - public static Object atomicRequest(String service, String method, Object[] params) throws MethodException { - try { - ClientSession session = new ClientSession(service); - Request osrfRequest = session.request(method, params); - Result result = osrfRequest.recv(600000); - if(result.getStatusCode() != 200) - throw new MethodException( - "Request "+service+":"+method+":"+" failed with status code " + result.getStatusCode()); - return result.getContent(); - } catch(Exception e) { - throw new MethodException(e); - } - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Message.java b/Open-ILS/src/Android/opensrf/org/opensrf/Message.java deleted file mode 100644 index 6bfe1eaaa7..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Message.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.opensrf; -import org.opensrf.util.*; - - -public class Message implements OSRFSerializable { - - /** Message types */ - public static final String REQUEST = "REQUEST"; - public static final String STATUS = "STATUS"; - public static final String RESULT = "RESULT"; - public static final String CONNECT = "CONNECT"; - public static final String DISCONNECT = "DISCONNECT"; - - /** Message ID. This number is used to relate requests to responses */ - private int id; - /** type of message. */ - private String type; - /** message payload */ - private Object payload; - /** message locale */ - private String locale; - - /** Create a registry for the osrfMessage object */ - private static OSRFRegistry registry = - OSRFRegistry.registerObject( - "osrfMessage", - OSRFRegistry.WireProtocol.HASH, - new String[] {"threadTrace", "type", "payload", "locale"}); - - /** - * @param id This message's ID - * @param type The type of message - */ - public Message(int id, String type) { - setId(id); - setString(type); - } - - /** - * @param id This message's ID - * @param type The type of message - * @param payload The message payload - */ - public Message(int id, String type, Object payload) { - this(id, type); - setPayload(payload); - } - - /** - * @param id This message's ID - * @param type The type of message - * @param payload The message payload - * @param locale The message locale - */ - public Message(int id, String type, Object payload, String locale) { - this(id, type, payload); - setPayload(payload); - setLocale(locale); - } - - - public int getId() { - return id; - } - public String getType() { - return type; - } - public Object getPayload() { - return payload; - } - public String getLocale() { - return locale; - } - public void setId(int id) { - this.id = id; - } - public void setString(String type) { - this.type = type; - } - public void setPayload(Object p) { - payload = p; - } - public void setLocale(String l) { - locale = l; - } - - /** - * Implements the generic get() API required by OSRFSerializable - */ - public Object get(String field) { - if("threadTrace".equals(field)) - return getId(); - if("type".equals(field)) - return getType().toString(); - if("payload".equals(field)) - return getPayload(); - if("locale".equals(field)) - return getLocale(); - return null; - } - - /** - * @return The osrfMessage registry. - */ - public OSRFRegistry getRegistry() { - return registry; - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Method.java b/Open-ILS/src/Android/opensrf/org/opensrf/Method.java deleted file mode 100644 index b708d4fa39..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Method.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.opensrf; -import java.util.List; -import java.util.ArrayList; -import org.opensrf.util.*; - - -public class Method extends OSRFObject { - - /** The method API name */ - private String name; - /** The ordered list of method params */ - private List params; - - /** Create a registry for the osrfMethod object */ - private static OSRFRegistry registry = - OSRFRegistry.registerObject( - "osrfMethod", - OSRFRegistry.WireProtocol.HASH, - new String[] {"method", "params"}); - - /** - * @param name The method API name - */ - public Method(String name) { - this.name = name; - this.params = new ArrayList(8); - } - - /** - * @param name The method API name - * @param params The ordered list of params - */ - public Method(String name, List params) { - this.name = name; - this.params = params; - } - - /** - * @return The method API name - */ - public String getName() { - return name; - } - /** - * @return The ordered list of params - */ - public List 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 addParam(Object p) { - this.params.add(p); - } - - /** - * Implements the generic get() API required by OSRFSerializable - */ - public Object get(String field) { - if("method".equals(field)) - return getName(); - if("params".equals(field)) - return getParams(); - return null; - } - - /** - * @return The osrfMethod registry. - */ - public OSRFRegistry getRegistry() { - return registry; - } - -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/MethodException.java b/Open-ILS/src/Android/opensrf/org/opensrf/MethodException.java deleted file mode 100644 index f87e638cf2..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/MethodException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.opensrf; - -/** - * Thrown when the server responds with a method exception. - */ -public class MethodException extends Exception { - public MethodException(String info) { - super(info); - } - public MethodException(Throwable cause) { - super(cause); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/MultiSession.java b/Open-ILS/src/Android/opensrf/org/opensrf/MultiSession.java deleted file mode 100644 index a312aff9b8..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/MultiSession.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.opensrf; -import java.util.List; -import java.util.ArrayList; -import org.opensrf.util.ConfigException; - -public class MultiSession { - - class RequestContainer { - Request request; - int id; - RequestContainer(Request r) { - request = r; - } - } - - private boolean complete; - private List requests; - private int lastId; - - public MultiSession() { - requests = new ArrayList(); - } - - public boolean isComplete() { - return complete; - } - - public int lastId() { - return lastId; - } - - /** - * Adds a new request to the set of requests. - * @param service The OpenSRF service - * @param method The OpenSRF method - * @param params The array of method params - * @return The request ID, which is used to map results from recv() to the original request. - */ - public int request(String service, String method, Object[] params) throws SessionException, ConfigException { - ClientSession ses = new ClientSession(service); - return request(ses.request(method, params)); - } - - - public int request(String service, String method) throws SessionException, ConfigException { - ClientSession ses = new ClientSession(service); - return request(ses.request(method)); - } - - private int request(Request req) { - RequestContainer c = new RequestContainer(req); - c.id = requests.size(); - requests.add(c); - return c.id; - } - - - /** - * Calls recv on all pending requests until there is data to return. The ID which - * maps the received object to the request can be retrieved by calling lastId(). - * @param millis Number of milliseconds to wait for some data to arrive. - * @return The object result or null if all requests are complete - * @throws MethodException Thrown if no response is received within - * the given timeout or the method fails. - */ - public Object recv(int millis) throws MethodException { - if(complete) return null; - - Request req = null; - Result res = null; - RequestContainer cont = null; - - long duration = 0; - long blockTime = 100; - - /* if there is only 1 outstanding request, don't poll */ - if(requests.size() == 1) - blockTime = millis; - - while(true) { - for(int i = 0; i < requests.size(); i++) { - - cont = requests.get(i); - req = cont.request; - - try { - if(i == 0) { - res = req.recv(blockTime); - } else { - res = req.recv(0); - } - } catch(SessionException e) { - throw new MethodException(e); - } - - if(res != null) break; - } - - if(res != null) break; - duration += blockTime; - - if(duration >= millis) { - System.out.println("duration = " + duration + " millis = " + millis); - throw new MethodException("No request received within " + millis + " milliseconds"); - } - } - - if(res.getStatusCode() != 200) { - throw new MethodException("Request " + cont.id + " failed with status code " + - res.getStatusCode() + " and status message " + res.getStatus()); - } - - if(req.isComplete()) - requests.remove(requests.indexOf(cont)); - - if(requests.size() == 0) - complete = true; - - lastId = cont.id; - return res.getContent(); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Request.java b/Open-ILS/src/Android/opensrf/org/opensrf/Request.java deleted file mode 100644 index 2d72e2df65..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Request.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.opensrf; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.List; -import java.util.Date; -import org.opensrf.net.xmpp.XMPPException; -import org.opensrf.util.Logger; - -public class Request { - - /** This request's controlling session */ - private ClientSession session; - /** The method */ - private Method method; - /** The ID of this request */ - private int id; - /** Queue of Results */ - private Queue resultQueue; - /** If true, the receive timeout for this request should be reset */ - private boolean resetTimeout; - - /** If true, the server has indicated that this request is complete. */ - private boolean complete; - - /** - * @param ses The controlling session for this request. - * @param id This request's ID. - * @param method The requested method. - */ - public Request(ClientSession ses, int id, Method method) { - this.session = ses; - this.id = id; - this.method = method; - resultQueue = new ConcurrentLinkedQueue(); - complete = false; - resetTimeout = false; - } - - /** - * @param ses The controlling session for this request. - * @param id This request's ID. - * @param methodName The requested method's API name. - */ - public Request(ClientSession ses, int id, String methodName) { - this(ses, id, new Method(methodName)); - } - - /** - * @param ses The controlling session for this request. - * @param id This request's ID. - * @param methodName The requested method's API name. - * @param params The list of request params - */ - public Request(ClientSession ses, int id, String methodName, List params) { - this(ses, id, new Method(methodName, params)); - } - - /** - * Sends the request to the server. - */ - public void send() throws SessionException { - session.send(new Message(id, Message.REQUEST, method, session.getLocale())); - } - - /** - * Receives the next result for this request. This method - * will wait up to the specified number of milliseconds for - * a response. - * @param millis Number of milliseconds to wait for a result. If - * negative, this method will wait indefinitely. - * @return The result or null if none arrives in time - */ - public Result recv(long millis) throws SessionException, MethodException { - - Result result = null; - - if((result = resultQueue.poll()) != null) - return result; - - if(millis < 0 && !complete) { - /** wait potentially forever for a result to arrive */ - while(!complete) { - session.waitForMessage(millis); - if((result = resultQueue.poll()) != null) - return result; - } - - } else { - - while(millis >= 0 && !complete) { - - /** wait up to millis milliseconds for a result. waitForMessage() - * will return if a response to any request arrives, so we keep track - * of how long we've been waiting in total for a response to - * this request */ - - long start = new Date().getTime(); - session.waitForMessage(millis); - millis -= new Date().getTime() - start; - if((result = resultQueue.poll()) != null) - return result; - } - } - - return null; - } - - /** - * Pushes a result onto the result queue - * @param result The result to push - */ - public void pushResponse(Result result) { - resultQueue.offer(result); - } - - /** - * @return This request's ID - */ - public int getId() { - return id; - } - - /** - * Removes this request from the controlling session's request set - */ - public void cleanup() { - session.cleanupRequest(id); - } - - /** Sets this request as complete */ - public void setComplete() { - complete = true; - } - - public boolean isComplete() { - return complete; - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Result.java b/Open-ILS/src/Android/opensrf/org/opensrf/Result.java deleted file mode 100644 index 80b71dd138..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Result.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.opensrf; -import org.opensrf.util.*; - - -/** - * Models a single result from a method request. - */ -public class Result implements OSRFSerializable { - - /** Method result content */ - private Object content; - /** Name of the status */ - private String status; - /** Status code number */ - private int statusCode; - - - /** Register this object */ - private static OSRFRegistry registry = - OSRFRegistry.registerObject( - "osrfResult", - OSRFRegistry.WireProtocol.HASH, - new String[] {"status", "statusCode", "content"}); - - - /** - * @param status The status message for this result - * @param statusCode The status code - * @param content The content of the result - */ - 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; - } - - /** - * Implements the generic get() API required by OSRFSerializable - */ - public Object get(String field) { - if("status".equals(field)) - return getStatus(); - if("statusCode".equals(field)) - return getStatusCode(); - if("content".equals(field)) - return getContent(); - return null; - } - - /** - * @return The osrfMethod registry. - */ - public OSRFRegistry getRegistry() { - return registry; - } - -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/ServerSession.java b/Open-ILS/src/Android/opensrf/org/opensrf/ServerSession.java deleted file mode 100644 index 62e5133058..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/ServerSession.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.opensrf; - -/** - * Models an OpenSRF server session. - */ -public class ServerSession extends Session { -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Session.java b/Open-ILS/src/Android/opensrf/org/opensrf/Session.java deleted file mode 100644 index 15fd352d5f..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Session.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.opensrf; -import org.opensrf.util.JSONWriter; -import org.opensrf.net.xmpp.*; -import java.util.Map; -import java.util.HashMap; -import java.util.Arrays; - -public abstract class Session { - - /** Represents the different connection states for a session */ - public enum ConnectState { - DISCONNECTED, - CONNECTING, - CONNECTED - }; - - /** local cache of existing sessions */ - private static Map - sessionCache = new HashMap(); - - /** the current connection state */ - private ConnectState connectState; - - /** The address of the remote party we are communicating with */ - private String remoteNode; - - /** Session locale */ - protected String locale; - /** Default session locale */ - protected static String defaultLocale = "en-US"; - - /** - * 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 SessionException { - - /** construct the XMPP message */ - XMPPMessage xmsg = new XMPPMessage(); - xmsg.setTo(remoteNode); - xmsg.setThread(thread); - xmsg.setBody(new JSONWriter(Arrays.asList(new Message[] {omsg})).write()); - - try { - XMPPSession.getThreadSession().send(xmsg); - } catch(XMPPException e) { - connectState = ConnectState.DISCONNECTED; - throw new SessionException("Error sending message to " + remoteNode, e); - } - } - - /** - * 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) throws SessionException, MethodException { - try { - Stack.processXMPPMessage( - XMPPSession.getThreadSession().recv(millis)); - } catch(XMPPException e) { - throw new SessionException("Error waiting for message", e); - } - } - - /** - * 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); - } - - /** - * Puts this session into session cache. - */ - protected void cacheSession() { - sessionCache.put(thread, this); - } - - /** - * Sets the remote address - * @param nodeName The name of the remote node. - */ - public void setRemoteNode(String nodeName) { - remoteNode = nodeName; - } - /** - * @return The remote node - */ - public String getRemoteNode() { - return remoteNode; - } - - - /** - * Get thread. - * @return thread as String. - */ - public String getThread() { - return thread; - } - - /** - * Set thread. - * @param thread the value to set. - */ - public void setThread(String thread) { - this.thread = thread; - } - - /** - * Get locale. - * @return locale as String. - */ - public String getLocale() { - if(locale == null) - return defaultLocale; - return locale; - } - - /** - * Set locale. - * @param locale the value to set. - */ - public void setLocale(String locale) { - this.locale = locale; - } - - /** - * Get defaultLocale. - * @return defaultLocale as String. - */ - public String getDefaultLocale() { - return defaultLocale; - } - - /** - * Set defaultLocale. - * @param defaultLocale the value to set. - */ - public void setDefaultLocale(String defaultLocale) { - this.defaultLocale = defaultLocale; - } - - - /** - * Get connectState. - * @return connectState as ConnectState. - */ - public ConnectState getConnectState() { - return connectState; - } - - /** - * Set connectState. - * @param connectState the value to set. - */ - public void setConnectState(ConnectState connectState) { - this.connectState = connectState; - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/SessionException.java b/Open-ILS/src/Android/opensrf/org/opensrf/SessionException.java deleted file mode 100644 index bd90a7610d..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/SessionException.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.opensrf; -/** - * Used by sessions to indicate communication errors - */ -public class SessionException extends Exception { - public SessionException(String info) { - super(info); - } - public SessionException(String info, Throwable cause) { - super(info, cause); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Stack.java b/Open-ILS/src/Android/opensrf/org/opensrf/Stack.java deleted file mode 100644 index 3e7e6061fb..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Stack.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.opensrf; -import org.opensrf.net.xmpp.XMPPMessage; -import org.opensrf.util.*; -import java.util.Date; -import java.util.List; -import java.util.Iterator; - - -public class Stack { - - public static void processXMPPMessage(XMPPMessage msg) throws MethodException { - - if(msg == null) return; - - //System.out.println(msg.getBody()); - - /** fetch this session from the cache */ - Session ses = Session.findCachedSession(msg.getThread()); - - if(ses == null) { - /** inbound client request, create a new server session */ - return; - } - - /** parse the JSON message body, which should result in a list of OpenSRF messages */ - List msgList; - - try { - msgList = new JSONReader(msg.getBody()).readArray(); - } catch(JSONException e) { - /** XXX LOG error */ - e.printStackTrace(); - return; - } - - Iterator itr = msgList.iterator(); - - OSRFObject obj = null; - long start = new Date().getTime(); - - /** cycle through the messages and push them up the stack */ - while(itr.hasNext()) { - - /** Construct a Message object from the parsed generic OSRFObject */ - obj = (OSRFObject) itr.next(); - - processOSRFMessage( - ses, - new Message( - obj.getInt("threadTrace"), - obj.getString("type"), - obj.get("payload") - ) - ); - } - - /** LOG the duration */ - } - - private static void processOSRFMessage(Session ses, Message msg) throws MethodException { - - Logger.debug("received id=" + msg.getId() + - " type=" + msg.getType() + " payload=" + msg.getPayload()); - - if( ses instanceof ClientSession ) - processResponse((ClientSession) ses, msg); - else - processRequest((ServerSession) ses, msg); - } - - /** - * Process a server response - */ - private static void processResponse(ClientSession session, Message msg) throws MethodException { - String type = msg.getType(); - - if(msg.RESULT.equals(type)) { - session.pushResponse(msg); - return; - } - - if(msg.STATUS.equals(type)) { - - OSRFObject obj = (OSRFObject) msg.getPayload(); - Status stat = new Status(obj.getString("status"), obj.getInt("statusCode")); - int statusCode = stat.getStatusCode(); - String status = stat.getStatus(); - - switch(statusCode) { - case Status.COMPLETE: - session.setRequestComplete(msg.getId()); - break; - case Status.NOTFOUND: - session.setRequestComplete(msg.getId()); - throw new MethodException(status); - } - } - } - - /** - * Process a client request - */ - private static void processRequest(ServerSession session, Message msg) { - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Status.java b/Open-ILS/src/Android/opensrf/org/opensrf/Status.java deleted file mode 100644 index 8026c7b8cd..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Status.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.opensrf; -import org.opensrf.util.*; - -public class Status { - - public static final int CONTINUE = 100; - public static final int OK = 200; - public static final int ACCEPTED = 202; - public static final int COMPLETE = 205; - public static final int REDIRECTED = 307; - public static final int EST = 400; - public static final int STATUS_UNAUTHORIZED = 401; - public static final int FORBIDDEN = 403; - public static final int NOTFOUND = 404; - public static final int NOTALLOWED = 405; - public static final int TIMEOUT = 408; - public static final int EXPFAILED = 417; - public static final int INTERNALSERVERERROR = 500; - public static final int NOTIMPLEMENTED = 501; - public static final int VERSIONNOTSUPPORTED = 505; - - private OSRFRegistry registry = OSRFRegistry.registerObject( - "osrfConnectStatus", - OSRFRegistry.WireProtocol.HASH, - new String[] {"status", "statusCode"}); - - /** The name of the status */ - String status; - /** The status code */ - int statusCode; - - public Status(String status, int statusCode) { - this.status = status; - this.statusCode = statusCode; - } - - public int getStatusCode() { - return statusCode; - } - public String getStatus() { - return status; - } - - /** - * Implements the generic get() API required by OSRFSerializable - */ - public Object get(String field) { - if("status".equals(field)) - return getStatus(); - if("statusCode".equals(field)) - return new Integer(getStatusCode()); - return null; - } - - /** - * @return The osrfMessage registry. - */ - public OSRFRegistry getRegistry() { - return registry; - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/Sys.java b/Open-ILS/src/Android/opensrf/org/opensrf/Sys.java deleted file mode 100644 index d65f8a4ffa..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/Sys.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.opensrf; - -import org.opensrf.util.*; -import org.opensrf.net.xmpp.*; -import java.util.Random; -import java.util.Date; -import java.net.InetAddress; - - -public class Sys { - - private static void initLogger(Config config) { - if(Logger.instance() == null) { - try { - String logFile = config.getString("/logfile"); - int logLevel = config.getInt("/loglevel"); - Logger.init( (short) config.getInt("/loglevel"), new FileLogger(logFile)); - /** add syslog support... */ - } catch(Exception e) { - /* by default, log to stderr at WARN level */ - Logger.init(Logger.WARN, new Logger()); - } - } - } - - /** - * Connects to the OpenSRF network so that client sessions may communicate. - * @param configFile The OpenSRF config file - * @param configContext Where in the XML document the config chunk lives. This - * allows an OpenSRF client config chunk to live in XML files where other config - * information lives. - */ - public static void bootstrapClient(String configFile, String configContext) - throws ConfigException, SessionException { - - - /** see if the current thread already has a connection */ - XMPPSession existing = XMPPSession.getThreadSession(); - if(existing != null && existing.connected()) - return; - - /** create the config parser */ - Config config = new Config(configContext); - config.parse(configFile); - Config.setConfig(config); /* set this as the global config */ - - initLogger(config); - - /** Collect the network connection info from the config */ - String username = config.getString("/username"); - String passwd = config.getString("/passwd"); - String host = (String) config.getFirst("/domain"); - int port = config.getInt("/port"); - - - /** Create a random login resource string */ - String res = "java_"; - try { - res += InetAddress.getLocalHost().getHostAddress(); - } catch(java.net.UnknownHostException e) {} - res += "_"+Math.abs(new Random(new Date().getTime()).nextInt()) - + "_t"+ Thread.currentThread().getId(); - - - - try { - - /** Connect to the Jabber network */ - Logger.info("attempting to create XMPP session "+username+"@"+host+"/"+res); - XMPPSession xses = new XMPPSession(host, port); - xses.connect(username, passwd, res); - XMPPSession.setThreadSession(xses); - - } catch(XMPPException e) { - throw new SessionException("Unable to bootstrap client", e); - } - } - - /** - * Shuts down the connection to the opensrf network - */ - public static void shutdown() { - XMPPSession.getThreadSession().disconnect(); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/GatewayRequest.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/http/GatewayRequest.java deleted file mode 100644 index 61d7306baf..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/GatewayRequest.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.opensrf.net.http; - -import android.util.Log; -import org.json.JSONObject; -import org.opensrf.*; -import org.opensrf.util.*; - -import java.io.IOException; -import java.io.BufferedInputStream; -import java.io.OutputStreamWriter; -import java.io.InputStream; -import java.io.IOException; -import java.net.URL; -import java.net.URI; -import java.net.HttpURLConnection; -import java.lang.StringBuffer; -import java.util.List; -import java.util.Iterator; -import java.util.Map; -import java.util.HashMap; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -public class GatewayRequest extends HttpRequest { - - private boolean readComplete; - private String TAG = GatewayRequest.class.getName(); - - public GatewayRequest(HttpConnection conn, String service, Method method) { - super(conn, service, method); - readComplete = false; - } - - public GatewayRequest send() { - try { - - String postData = compilePostData(service, method); - - urlConn = (HttpURLConnection) httpConn.url.openConnection(); - urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - urlConn.setDoInput(true); - urlConn.setDoOutput(true); - - - - OutputStreamWriter wr = new OutputStreamWriter(urlConn.getOutputStream()); - wr.write(postData); - wr.flush(); - wr.close(); - - } catch (java.io.IOException ex) { - failed = true; - failure = ex; - } - - return this; - } - - public Object recv() { - - if (readComplete) - return nextResponse(); - - try { - - InputStream netStream = new BufferedInputStream(urlConn.getInputStream()); - StringBuffer readBuf = new StringBuffer(); - - int bytesRead = 0; - byte[] buffer = new byte[1024]; - - while ((bytesRead = netStream.read(buffer)) != -1) { - readBuf.append(new String(buffer, 0, bytesRead)); - } - - netStream.close(); - urlConn = null; - - Map result = null; - - //System.out.println("osrf: Received " + readBuf.toString()); - //Log.d(TAG, "received:" + readBuf.toString()); - try { - result = (Map) new JSONReader(readBuf.toString()).readObject(); - } catch (org.opensrf.util.JSONException ex) { - ex.printStackTrace(); - return null; - } - //System.out.println("osrf: Converted object " + result); - Log.d(TAG, "service:" + this.service - + " method:" + this.method.getName() - + " result:" + new JSONObject(result).toString()); - String status = result.get("status").toString(); - if (!"200".equals(status)) { - failed = true; - // failure = - } - - // gateway always returns a wrapper array with the full results set - responseList = (List) result.get("payload"); - - // System.out.println("Response list : " + responseList); - } catch (java.io.IOException ex) { - failed = true; - failure = ex; - } - - readComplete = true; - return nextResponse(); - } - - private String compilePostData(String service, Method method) { - URI uri = null; - StringBuffer postData = new StringBuffer(); - - postData.append("service="); - postData.append(service); - postData.append("&method="); - postData.append(method.getName()); - - List params = method.getParams(); - Iterator itr = params.iterator(); - - while (itr.hasNext()) { - postData.append("¶m="); - postData.append(new JSONWriter(itr.next()).write()); - } - - try { - // not using URLEncoder because it replaces ' ' with '+'. - uri = new URI("http", "", null, postData.toString(), null); - } catch (java.net.URISyntaxException ex) { - ex.printStackTrace(); - } - - return uri.getRawQuery(); - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpConnection.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpConnection.java deleted file mode 100644 index 32fdebc212..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpConnection.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.opensrf.net.http; - -import java.net.URL; -import java.net.MalformedURLException; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import org.opensrf.*; -import org.opensrf.util.*; - - -/** - * Manages connection parameters and thread limiting for opensrf json gateway connections. - */ - -public class HttpConnection { - - /** Compiled URL object */ - protected URL url; - /** Number of threads currently communicating with the server */ - protected int activeThreads; - /** Queue of pending async requests */ - protected Queue pendingThreadQueue; - /** maximum number of actively communicating threads allowed */ - protected int maxThreads = 10; - - public HttpConnection(String fullUrl) throws java.net.MalformedURLException { - activeThreads = 0; - pendingThreadQueue = new ConcurrentLinkedQueue(); - url = new URL(fullUrl); - } - - public int getMaxThreads() { - return maxThreads; - } - - /** - * Set the maximum number of actively communicating threads allowed - */ - public void setMaxThreads(int max) { - maxThreads = max; - } - - /** - * Launches or queues an asynchronous request. - * - * If the maximum active thread count has not been reached, - * start a new thread and use it to send and receive the request. - * The response is passed to the request's HttpRequestHandler - * onComplete(). After complete, if the number of active threads - * is still lower than the max, one request will be pulled (if - * present) from the async queue and fired. - * - * If there are too many active threads, the main request is - * pushed onto the async queue for later processing - */ - protected void manageAsyncRequest(final HttpRequest request) { - - if (activeThreads >= maxThreads) { - pendingThreadQueue.offer(request); - return; - } - - activeThreads++; - - //Send the request receive the response, fire off the next - //thread if necessary, then pass the result to the handler - Runnable r = new Runnable() { - public void run() { - - Object response; - request.send(); - - while ((response = request.recv()) != null) { - if (request.handler != null) - request.handler.onResponse(request, response); - } - - if (request.handler != null) - request.handler.onComplete(request); - - activeThreads--; - - if (activeThreads < maxThreads) { - try { - manageAsyncRequest(pendingThreadQueue.remove()); - } catch (java.util.NoSuchElementException ex) { - // may have been gobbled by another thread - } - } - } - }; - - new Thread(r).start(); - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequest.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequest.java deleted file mode 100644 index 8af4623451..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequest.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.opensrf.net.http; -import org.opensrf.*; -import org.opensrf.util.*; - -import java.util.List; -import java.util.LinkedList; -import java.net.HttpURLConnection; - -public abstract class HttpRequest { - - protected String service; - protected Method method; - protected HttpURLConnection urlConn; - protected HttpConnection httpConn; - protected HttpRequestHandler handler; - protected List responseList; - protected Exception failure; - protected boolean failed; - protected boolean complete; - - public HttpRequest() { - failed = false; - complete = false; - handler = null; - urlConn = null; - } - - public HttpRequest(HttpConnection conn, String service, Method method) { - this(); - this.httpConn = conn; - this.service = service; - this.method = method; - } - - public void sendAsync(final HttpRequestHandler handler) { - this.handler = handler; - httpConn.manageAsyncRequest(this); - } - - protected void pushResponse(Object response) { - if (responseList == null) - responseList = new LinkedList(); - responseList.add(response); - } - - protected List responses() { - return responseList; - } - - protected Object nextResponse() { - if (complete || failed) return null; - if (responseList.size() > 0) - return responseList.remove(0); - return null; - } - - public Exception getFailure() { - return failure; - } - - public abstract HttpRequest send(); - - public abstract Object recv(); - - public boolean failed(){ - return failed; - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequestHandler.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequestHandler.java deleted file mode 100644 index 9c0f9e5043..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/http/HttpRequestHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.opensrf.net.http; - -import java.util.List; - -/* - * Handler for async gateway responses. - */ -public abstract class HttpRequestHandler { - - /** - * Called when all responses have been received. - * - * If discardResponses() returns true, will be passed null. - */ - public void onComplete(HttpRequest request) { - } - - /** - * Called with each response received from the server. - * - * @param payload the value returned from the server. - */ - public void onResponse(HttpRequest request, Object response) { - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPException.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPException.java deleted file mode 100644 index 8c20ab7aee..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.opensrf.net.xmpp; - -/** - * Used for XMPP stream/authentication errors - */ -public class XMPPException extends Exception { - public XMPPException(String info) { - super(info); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPMessage.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPMessage.java deleted file mode 100644 index b6e2c76346..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPMessage.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.opensrf.net.xmpp; - -import java.io.*; - -/** - * Models a single XMPP message. - */ -public class XMPPMessage { - - /** Message body */ - private String body; - /** Message recipient */ - private String to; - /** Message sender */ - private String from; - /** Message thread */ - private String thread; - /** Message xid */ - private String xid; - - public XMPPMessage() { - } - - public String getBody() { - return body; - } - public String getTo() { - return to; - } - public String getFrom() { - return from; - } - public String getThread() { - return thread; - } - public String getXid() { - return xid; - } - public void setBody(String body) { - this.body = body; - } - public void setTo(String to) { - this.to = to; - } - public void setFrom(String from) { - this.from = from; - } - public void setThread(String thread) { - this.thread = thread; - } - public void setXid(String xid) { - this.xid = xid; - } - - - /** - * Generates the XML representation of this message. - */ - public String toXML() { - StringBuffer sb = new StringBuffer(""); - escapeXML(thread, sb); - sb.append(""); - escapeXML(body, sb); - sb.append(""); - return sb.toString(); - } - - - /** - * Escapes non-valid XML characters. - * @param s The string to escape. - * @param sb The StringBuffer to append new data to. - */ - private void escapeXML(String s, StringBuffer sb) { - if( s == null ) return; - char c; - int l = s.length(); - for( int i = 0; i < l; i++ ) { - c = s.charAt(i); - switch(c) { - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '&': - sb.append("&"); - break; - default: - sb.append(c); - } - } - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPReader.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPReader.java deleted file mode 100644 index 406298a730..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPReader.java +++ /dev/null @@ -1,293 +0,0 @@ -package org.opensrf.net.xmpp; - -import javax.xml.stream.*; -import javax.xml.stream.events.* ; -import javax.xml.namespace.QName; -import java.util.Queue; -import java.io.InputStream; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.Date; -import org.opensrf.util.Logger; - -/** - * Slim XMPP Stream reader. This reader only understands enough XMPP - * to handle logins and recv messages. It's implemented as a StAX parser. - * @author Bill Erickson, Georgia Public Library Systems - */ -public class XMPPReader implements Runnable { - - /** Queue of received messages. */ - private Queue msgQueue; - /** Incoming XMPP XML stream */ - private InputStream inStream; - /** Current message body */ - private StringBuffer msgBody; - /** Current message thread */ - private StringBuffer msgThread; - /** Current message status */ - private StringBuffer msgStatus; - /** Current message error type */ - private StringBuffer msgErrType; - /** Current message sender */ - private String msgFrom; - /** Current message recipient */ - private String msgTo; - /** Current message error code */ - private int msgErrCode; - - /** Where this reader currently is in the document */ - private XMLState xmlState; - - /** The current connect state to the XMPP server */ - private XMPPStreamState streamState; - - - /** Used to represent out connection state to the XMPP server */ - public static enum XMPPStreamState { - DISCONNECTED, /* not connected to the server */ - CONNECT_SENT, /* we've sent the initial connect message */ - CONNECT_RECV, /* we've received a response to our connect message */ - AUTH_SENT, /* we've sent an authentication request */ - CONNECTED /* authentication is complete */ - }; - - - /** Used to represents where we are in the XML document stream. */ - public static enum XMLState { - IN_NOTHING, - IN_BODY, - IN_THREAD, - IN_STATUS - }; - - - /** - * Creates a new reader. Initializes the message queue. - * Sets the stream state to disconnected, and the xml - * state to in_nothing. - * @param inStream the inbound XML stream - */ - public XMPPReader(InputStream inStream) { - msgQueue = new ConcurrentLinkedQueue(); - this.inStream = inStream; - resetBuffers(); - xmlState = XMLState.IN_NOTHING; - streamState = XMPPStreamState.DISCONNECTED; - } - - /** - * Change the connect state and notify that a core - * event has occurred. - */ - protected void setXMPPStreamState(XMPPStreamState state) { - streamState = state; - notifyCoreEvent(); - } - - /** - * @return The current stream state of the reader - */ - public XMPPStreamState getXMPPStreamState() { - return streamState; - } - - - /** - * @return The next message in the queue, or null - */ - public XMPPMessage popMessageQueue() { - return (XMPPMessage) msgQueue.poll(); - } - - - /** - * Initializes the message buffers - */ - private void resetBuffers() { - msgBody = new StringBuffer(); - msgThread = new StringBuffer(); - msgStatus = new StringBuffer(); - msgErrType = new StringBuffer(); - msgFrom = ""; - msgTo = ""; - } - - - /** - * Notifies the waiting thread that a core event has occurred. - * Each reader should have exactly one dependent session thread. - */ - private synchronized void notifyCoreEvent() { - notifyAll(); - } - - - /** - * Waits up to timeout milliseconds for a core event to occur. - * Also, having a message already waiting in the queue - * constitutes a core event. - * @param timeout The number of milliseconds to wait. If - * timeout is negative, waits potentially forever. - * @return The number of milliseconds in wait - */ - public synchronized long waitCoreEvent(long timeout) { - - if(msgQueue.peek() != null || timeout == 0) return 0; - long start = new Date().getTime(); - - try{ - if(timeout < 0) - wait(); - else - wait(timeout); - } catch(InterruptedException ie) {} - - return new Date().getTime() - start; - } - - - - /** Kickoff the thread */ - public void run() { - read(); - } - - - /** - * Parses XML data from the provided XMPP stream. - */ - public void read() { - - try { - - XMLInputFactory factory = XMLInputFactory.newInstance(); - - /** disable as many unused features as possible to speed up the parsing */ - factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE); - factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); - factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); - factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); - factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); - - /** create the stream reader */ - XMLStreamReader reader = factory.createXMLStreamReader(inStream); - int eventType; - - while(reader.hasNext()) { - /** cycle through the XML events */ - - eventType = reader.next(); - - switch(eventType) { - - case XMLEvent.START_ELEMENT: - handleStartElement(reader); - break; - - case XMLEvent.CHARACTERS: - switch(xmlState) { - case IN_BODY: - msgBody.append(reader.getText()); - break; - case IN_THREAD: - msgThread.append(reader.getText()); - break; - case IN_STATUS: - msgStatus.append(reader.getText()); - break; - } - break; - - case XMLEvent.END_ELEMENT: - xmlState = XMLState.IN_NOTHING; - if("message".equals(reader.getName().toString())) { - - /** build a message and add it to the message queue */ - XMPPMessage msg = new XMPPMessage(); - msg.setFrom(msgFrom); - msg.setTo(msgTo); - msg.setBody(msgBody.toString()); - msg.setThread(msgThread.toString()); - - Logger.internal("xmpp message from="+msgFrom+" " + msg.getBody()); - - msgQueue.offer(msg); - resetBuffers(); - notifyCoreEvent(); - } - break; - } - } - - } catch(javax.xml.stream.XMLStreamException se) { - /* XXX log an error */ - xmlState = XMLState.IN_NOTHING; - streamState = XMPPStreamState.DISCONNECTED; - notifyCoreEvent(); - } - } - - - /** - * Handles the start_element event. - */ - private void handleStartElement(XMLStreamReader reader) { - - String name = reader.getName().toString(); - - if("message".equals(name)) { - xmlState = XMLState.IN_BODY; - - /** add a special case for the opensrf "router_from" attribute */ - String rf = reader.getAttributeValue(null, "router_from"); - if( rf != null ) - msgFrom = rf; - else - msgFrom = reader.getAttributeValue(null, "from"); - msgTo = reader.getAttributeValue(null, "to"); - return; - } - - if("body".equals(name)) { - xmlState = XMLState.IN_BODY; - return; - } - - if("thread".equals(name)) { - xmlState = XMLState.IN_THREAD; - return; - } - - if("stream:stream".equals(name)) { - setXMPPStreamState(XMPPStreamState.CONNECT_RECV); - return; - } - - if("iq".equals(name)) { - if("result".equals(reader.getAttributeValue(null, "type"))) - setXMPPStreamState(XMPPStreamState.CONNECTED); - return; - } - - if("status".equals(name)) { - xmlState = XMLState.IN_STATUS; - return; - } - - if("stream:error".equals(name)) { - setXMPPStreamState(XMPPStreamState.DISCONNECTED); - return; - } - - if("error".equals(name)) { - msgErrType.append(reader.getAttributeValue(null, "type")); - msgErrCode = Integer.parseInt(reader.getAttributeValue(null, "code")); - setXMPPStreamState(XMPPStreamState.DISCONNECTED); - return; - } - } -} - - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPSession.java b/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPSession.java deleted file mode 100644 index f9be7d2a63..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/net/xmpp/XMPPSession.java +++ /dev/null @@ -1,263 +0,0 @@ -package org.opensrf.net.xmpp; - -import java.io.*; -import java.net.Socket; -import java.util.Map; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; - - -/** - * Represents a single XMPP session. Sessions are responsible for writing to - * the stream and for managing a stream reader. - */ -public class XMPPSession { - - /** Initial jabber message */ - public static final String JABBER_CONNECT = - ""; - - /** Basic auth message */ - public static final String JABBER_BASIC_AUTH = - "" + - "%s%s%s"; - - public static final String JABBER_DISCONNECT = ""; - - private static Map threadConnections = new ConcurrentHashMap(); - - /** jabber domain */ - private String host; - /** jabber port */ - private int port; - /** jabber username */ - private String username; - /** jabber password */ - private String password; - /** jabber resource */ - private String resource; - - /** XMPP stream reader */ - XMPPReader reader; - /** Fprint-capable socket writer */ - PrintWriter writer; - /** Raw socket output stream */ - OutputStream outStream; - /** The raw socket */ - Socket socket; - - /** The process-wide session. All communication occurs - * accross this single connection */ - private static XMPPSession globalSession; - - - /** - * Creates a new session. - * @param host The jabber domain - * @param port The jabber port - */ - public XMPPSession( String host, int port ) { - this.host = host; - this.port = port; - } - - /** - * Returns the global, process-wide session - */ - /* - public static XMPPSession getGlobalSession() { - return globalSession; - } - */ - - public static XMPPSession getThreadSession() { - return (XMPPSession) threadConnections.get(new Long(Thread.currentThread().getId())); - } - - /** - * Sets the given session as the global session for the current thread - * @param ses The session - */ - public static void setThreadSession(XMPPSession ses) { - /* every time we create a new connection, clean up any dead threads. - * this is cheaper than cleaning up the dead threads at every access. */ - cleanupThreadSessions(); - threadConnections.put(new Long(Thread.currentThread().getId()), ses); - } - - /** - * Analyzes the threadSession data to see if there are any sessions - * whose controlling thread has gone away. - */ - private static void cleanupThreadSessions() { - Thread threads[] = new Thread[Thread.activeCount()]; - Thread.enumerate(threads); - for(Iterator i = threadConnections.keySet().iterator(); i.hasNext(); ) { - boolean found = false; - Long id = (Long) i.next(); - for(Thread t : threads) { - if(t.getId() == id.longValue()) { - found = true; - break; - } - } - if(!found) - threadConnections.remove(id); - } - } - - /** - * Sets the global, process-wide section - */ - /* - 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 && - !socket.isClosed() - ); - } - - - /** - * Connects to the network. - * @param username The jabber username - * @param password The jabber password - * @param resource The Jabber resource - */ - public void connect(String username, String password, String resource) throws XMPPException { - - this.username = username; - this.password = password; - this.resource = resource; - - try { - /* open the socket and associated streams */ - socket = new Socket(host, port); - - /** the session maintains control over the output stream */ - outStream = socket.getOutputStream(); - writer = new PrintWriter(outStream, true); - - /** pass the input stream to the reader */ - reader = new XMPPReader(socket.getInputStream()); - - } catch(IOException ioe) { - throw new - XMPPException("unable to communicate with host " + host + " on port " + port); - } - - /* build the reader thread */ - Thread thread = new Thread(reader); - thread.setDaemon(true); - thread.start(); - - synchronized(reader) { - /* send the initial jabber message */ - sendConnect(); - reader.waitCoreEvent(10000); - } - if( reader.getXMPPStreamState() != XMPPReader.XMPPStreamState.CONNECT_RECV ) - throw new XMPPException("unable to connect to jabber server"); - - synchronized(reader) { - /* send the basic auth message */ - sendBasicAuth(); - reader.waitCoreEvent(10000); - } - if(!connected()) - throw new XMPPException("Authentication failed"); - } - - /** Sends the initial jabber message */ - private void sendConnect() { - reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT); - writer.printf(JABBER_CONNECT, host); - } - - /** Send the basic auth message */ - private void sendBasicAuth() { - reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT); - writer.printf(JABBER_BASIC_AUTH, username, password, resource); - } - - - /** - * Sends an XMPPMessage. - * @param msg The message to send. - */ - public synchronized void send(XMPPMessage msg) throws XMPPException { - checkConnected(); - try { - String xml = msg.toXML(); - outStream.write(xml.getBytes()); - } catch (Exception e) { - throw new XMPPException(e.toString()); - } - } - - - /** - * @throws XMPPException if we are no longer connected. - */ - private void checkConnected() throws XMPPException { - if(!connected()) - throw new XMPPException("Disconnected stream"); - } - - - /** - * Receives messages from the network. - * @param timeout Maximum number of milliseconds to wait for a message to arrive. - * If timeout is negative, this method will wait indefinitely. - * 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(long timeout) throws XMPPException { - - XMPPMessage msg; - - if(timeout < 0) { - - while(true) { /* wait indefinitely for a message to arrive */ - reader.waitCoreEvent(timeout); - msg = reader.popMessageQueue(); - if( msg != null ) return msg; - checkConnected(); - } - - } else { - - while(timeout >= 0) { /* wait at most 'timeout' milleseconds for a message to arrive */ - msg = reader.popMessageQueue(); - if( msg != null ) return msg; - timeout -= reader.waitCoreEvent(timeout); - msg = reader.popMessageQueue(); - if( msg != null ) return msg; - checkConnected(); - if(timeout == 0) break; - } - } - - return reader.popMessageQueue(); - } - - - /** - * Disconnects from the jabber server and closes the socket - */ - public void disconnect() { - try { - outStream.write(JABBER_DISCONNECT.getBytes()); - socket.close(); - } catch(Exception e) {} - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/MathBench.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/MathBench.java deleted file mode 100644 index b6e67f953c..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/MathBench.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; -import java.util.Date; -import java.util.List; -import java.util.ArrayList; -import java.io.PrintStream; - - -public class MathBench { - - public static void main(String args[]) throws Exception { - - PrintStream out = System.out; - - if(args.length < 2) { - out.println("usage: java org.opensrf.test.MathBench "); - return; - } - - /** connect to the opensrf network */ - Sys.bootstrapClient(args[0], "/config/opensrf"); - - /** how many iterations */ - int count = Integer.parseInt(args[1]); - - /** create the client session */ - ClientSession session = new ClientSession("opensrf.math"); - - /** params are 1,2 */ - List params = new ArrayList(); - params.add(new Integer(1)); - params.add(new Integer(2)); - - Request request; - Result result; - long start; - double total = 0; - - for(int i = 0; i < count; i++) { - - start = new Date().getTime(); - - /** create (and send) the request */ - request = session.request("add", params); - - /** wait up to 3 seconds for a response */ - result = request.recv(3000); - - /** collect the round-trip time */ - total += new Date().getTime() - start; - - if(result.getStatusCode() == Status.OK) { - out.print("+"); - } else { - out.println("\nrequest failed"); - out.println("status = " + result.getStatus()); - out.println("status code = " + result.getStatusCode()); - } - - /** remove this request from the session's request set */ - request.cleanup(); - - if((i+1) % 100 == 0) /** print 100 responses per line */ - out.println(" [" + (i+1) + "]"); - } - - out.println("\nAverage request time is " + (total/count) + " ms"); - - /** remove this session from the global session cache */ - session.cleanup(); - - /** disconnect from the opensrf network */ - Sys.shutdown(); - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestCache.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestCache.java deleted file mode 100644 index d555444ccf..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestCache.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.opensrf.test; -import org.opensrf.util.Cache; - -public class TestCache { - public static void main(String args[]) throws Exception { - - /** - * args is a list of string like so: server:port server2:port server3:port ... - */ - - Cache.initCache(args); - Cache cache = new Cache(); - - cache.set("key1", "HI, MA!"); - cache.set("key2", "HI, MA! 2"); - cache.set("key3", "HI, MA! 3"); - - System.out.println("got key1 = " + (String) cache.get("key1")); - System.out.println("got key2 = " + (String) cache.get("key2")); - System.out.println("got key3 = " + (String) cache.get("key3")); - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestClient.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestClient.java deleted file mode 100644 index a1136cd719..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestClient.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; -import java.util.Map; -import java.util.Date; -import java.util.List; -import java.util.ArrayList; -import java.io.PrintStream; - -public class TestClient { - - public static void main(String args[]) throws Exception { - - /** which opensrf service are we sending our request to */ - String service; - /** which opensrf method we're calling */ - String method; - /** method params, captures from command-line args */ - List params; - /** knows how to read JSON */ - JSONReader reader; - /** opensrf request */ - Request request; - /** request result */ - Result result; - /** start time for the request */ - long start; - /** for brevity */ - PrintStream out = System.out; - - if(args.length < 3) { - out.println( "usage: org.opensrf.test.TestClient "+ - " [, ]"); - return; - } - - /** connect to the opensrf network, default config context - * for opensrf_core.xml is /config/opensrf */ - Sys.bootstrapClient(args[0], "/config/opensrf"); - - /* grab the server, method, and any params from the command line */ - service = args[1]; - method = args[2]; - params = new ArrayList(); - for(int i = 3; i < args.length; i++) - params.add(new JSONReader(args[i]).read()); - - - /** build the client session */ - ClientSession session = new ClientSession(service); - - /** kick off the timer */ - start = new Date().getTime(); - - /** Create the request object from the session, method and params */ - request = session.request(method, params); - - while( (result = request.recv(60000)) != null ) { - /** loop over the results and print the JSON version of the content */ - - if(result.getStatusCode() != 200) { - /** make sure the request succeeded */ - out.println("status = " + result.getStatus()); - out.println("status code = " + result.getStatusCode()); - continue; - } - - /** JSON-ify the resulting object and print it */ - out.println("\nresult JSON: " + new JSONWriter(result.getContent()).write()); - } - - /** How long did the request take? */ - out.println("Request round trip took: " + (new Date().getTime() - start) + " ms."); - - Sys.shutdown(); - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestConfig.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestConfig.java deleted file mode 100644 index f65a84f701..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; - -public class TestConfig { - public static void main(String args[]) throws Exception { - Config config = new Config(""); - config.parse(args[0]); - Config.setConfig(config); - System.out.println(config); - System.out.println(""); - - for(int i = 1; i < args.length; i++) - System.out.println("Found config value: " + args[i] + ": " + Config.global().get(args[i])); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestJSON.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestJSON.java deleted file mode 100644 index b19d4088aa..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestJSON.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.opensrf.test; - -import org.opensrf.*; -import org.opensrf.util.*; -import java.util.*; - -public class TestJSON { - - public static void main(String args[]) throws Exception { - - Map map = new HashMap(); - map.put("key1", "value1"); - map.put("key2", "value2"); - map.put("key3", "value3"); - map.put("key4", "athe\u0301s"); - map.put("key5", null); - - List list = new ArrayList(16); - list.add(new Integer(1)); - list.add(new Boolean(true)); - list.add("WATER"); - list.add(null); - map.put("key6", list); - - System.out.println(new JSONWriter(map).write() + "\n"); - - String[] fields = {"isnew", "name", "shortname", "ill_address"}; - OSRFRegistry.registerObject("aou", OSRFRegistry.WireProtocol.ARRAY, fields); - - OSRFObject obj = new OSRFObject(OSRFRegistry.getRegistry("aou")); - obj.put("name", "athens clarke county"); - obj.put("ill_address", new Integer(1)); - obj.put("shortname", "ARL-ATH"); - - map.put("key7", obj); - list.add(obj); - System.out.println(new JSONWriter(map).write() + "\n"); - - - Message m = new Message(1, Message.REQUEST); - Method method = new Method("opensrf.settings.host_config.get"); - method.addParam("app07.dev.gapines.org"); - m.setPayload(method); - - 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()); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestLog.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestLog.java deleted file mode 100644 index 1d60242969..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestLog.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.opensrf.test; -import org.opensrf.util.Logger; -import org.opensrf.util.FileLogger; - - -/** Simple test class for tesing the logging functionality */ -public class TestLog { - public static void main(String args[]) { - Logger.init(Logger.DEBUG, new FileLogger("test.log")); - Logger.error("Hello, world"); - Logger.warn("Hello, world"); - Logger.info("Hello, world"); - Logger.debug("Hello, world"); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestMultiSession.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestMultiSession.java deleted file mode 100644 index bb0f1a1c09..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestMultiSession.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; - -public class TestMultiSession { - public static void main(String[] args) { - try { - String config = args[0]; - - Sys.bootstrapClient(config, "/config/opensrf"); - MultiSession ses = new MultiSession(); - - for(int i = 0; i < 40; i++) { - ses.request("opensrf.settings", "opensrf.system.time"); - } - - while(!ses.isComplete()) - System.out.println("result = " + ses.recv(5000) + " and id = " + ses.lastId()); - - System.out.println("done"); - Sys.shutdown(); - } catch(Exception e) { - e.printStackTrace(); - } - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestSettings.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestSettings.java deleted file mode 100644 index 116bbe1683..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestSettings.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; - -public class TestSettings { - public static void main(String args[]) throws Exception { - Sys.bootstrapClient(args[0], "/config/opensrf"); - SettingsClient client = SettingsClient.instance(); - String lang = client.getString("/apps/opensrf.settings/language"); - String impl = client.getString("/apps/opensrf.settings/implementation"); - System.out.println("opensrf.settings language = " + lang); - System.out.println("opensrf.settings implementation = " + impl); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestThread.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestThread.java deleted file mode 100644 index bb4cf067e9..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestThread.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.opensrf.test; -import org.opensrf.*; -import org.opensrf.util.*; -import java.util.Map; -import java.util.Date; -import java.util.List; -import java.util.ArrayList; -import java.io.PrintStream; - -/** - * Connects to the opensrf network once per thread and runs - * and runs a series of request acccross all launched threads. - * The purpose is to verify that the java threaded client api - * is functioning as expected - */ -public class TestThread implements Runnable { - - String args[]; - - public TestThread(String args[]) { - this.args = args; - } - - public void run() { - - try { - - Sys.bootstrapClient(args[0], "/config/opensrf"); - ClientSession session = new ClientSession(args[3]); - - List params = new ArrayList(); - for(int i = 5; i < args.length; i++) - params.add(new JSONReader(args[3]).read()); - - for(int i = 0; i < Integer.parseInt(args[2]); i++) { - System.out.println("thread " + Thread.currentThread().getId()+" sending request " + i); - Request request = session.request(args[4], params); - Result result = request.recv(3000); - if(result != null) { - System.out.println("thread " + Thread.currentThread().getId()+ - " got result JSON: " + new JSONWriter(result.getContent()).write()); - } else { - System.out.println("* thread " + Thread.currentThread().getId()+ " got NO result"); - } - } - - Sys.shutdown(); - } catch(Exception e) { - System.err.println(e); - } - } - - public static void main(String args[]) throws Exception { - - if(args.length < 5) { - System.out.println( "usage: org.opensrf.test.TestClient "+ - " [, ]"); - return; - } - - int numThreads = Integer.parseInt(args[1]); - for(int i = 0; i < numThreads; i++) - new Thread(new TestThread(args)).start(); - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLFlattener.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLFlattener.java deleted file mode 100644 index c1fa394fef..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLFlattener.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.opensrf.test; -import org.opensrf.util.XMLFlattener; -import java.io.FileInputStream; - -public class TestXMLFlattener { - public static void main(String args[]) throws Exception { - FileInputStream fis = new FileInputStream(args[0]); - XMLFlattener f = new XMLFlattener(fis); - System.out.println(f.read()); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLTransformer.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLTransformer.java deleted file mode 100644 index 9768372f11..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMLTransformer.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.opensrf.test; -import org.opensrf.util.XMLTransformer; -import java.io.File; - -public class TestXMLTransformer { - /** - * arg[0] path to an XML file - * arg[1] path to the XSL file to apply - */ - public static void main(String[] args) { - try { - File xmlFile = new File(args[0]); - File xslFile = new File(args[1]); - XMLTransformer t = new XMLTransformer(xmlFile, xslFile); - System.out.println(t.apply()); - } catch(Exception e) { - e.printStackTrace(); - } - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMPP.java b/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMPP.java deleted file mode 100644 index 2fba67fb8b..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/test/TestXMPP.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.opensrf.test; - -import org.opensrf.net.xmpp.XMPPReader; -import org.opensrf.net.xmpp.XMPPMessage; -import org.opensrf.net.xmpp.XMPPSession; - -public class TestXMPP { - - /** - * Connects to the jabber server and waits for inbound messages. - * If a recipient is provided, a small message is sent to the recipient. - */ - public static void main(String args[]) throws Exception { - - String host; - int port; - String username; - String password; - String resource; - String recipient; - - try { - host = args[0]; - port = Integer.parseInt(args[1]); - username = args[2]; - password = args[3]; - resource = args[4]; - - } catch(ArrayIndexOutOfBoundsException e) { - System.err.println("usage: org.opensrf.test.TestXMPP []"); - return; - } - - XMPPSession session = new XMPPSession(host, port); - session.connect(username, password, resource); - - XMPPMessage msg; - - if( args.length == 6 ) { - - /** they specified a recipient */ - - recipient = args[5]; - msg = new XMPPMessage(); - msg.setTo(recipient); - msg.setThread("test-thread"); - msg.setBody("Hello, from java-xmpp"); - System.out.println("Sending message to " + recipient); - session.send(msg); - } - - while(true) { - System.out.println("waiting for message..."); - msg = session.recv(-1); /* wait forever for a message to arrive */ - System.out.println("got message: " + msg.toXML()); - } - } -} - - - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/Cache.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/Cache.java deleted file mode 100644 index 53036886cc..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/Cache.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.opensrf.util; -import com.danga.MemCached.*; -import java.util.List; - -/** - * Memcache client - */ -public class Cache extends MemCachedClient { - - public Cache() { - super(); - setCompressThreshold(4096); /* ?? */ - } - - /** - * Initializes the cache client - * @param serverList Array of server:port strings specifying the - * set of memcache servers this client will talk to - */ - public static void initCache(String[] serverList) { - SockIOPool pool = SockIOPool.getInstance(); - pool.setServers(serverList); - pool.initialize(); - com.danga.MemCached.Logger logger = - com.danga.MemCached.Logger.getLogger(MemCachedClient.class.getName()); - logger.setLevel(logger.LEVEL_ERROR); - } - - /** - * Initializes the cache client - * @param serverList List of server:port strings specifying the - * set of memcache servers this client will talk to - */ - public static void initCache(List serverList) { - initCache(serverList.toArray(new String[]{})); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/Config.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/Config.java deleted file mode 100644 index ddac9c0b71..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/Config.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.opensrf.util; - -import org.json.*; -import java.util.Map; -import java.util.List; - - -/** - * Config reader and accesor module. This module reads an XML config file, - * then loads the file into an internal config, whose values may be accessed - * by xpath-style lookup paths. - */ -public class Config { - - /** The globl config instance */ - private static Config config; - /** The object form of the parsed config */ - private Map configObject; - /** - * The log parsing context. This is used as a prefix to the - * config item search path. This allows config XML chunks to - * be inserted into arbitrary XML files. - */ - private String context; - - public static Config global() { - return config; - } - - - /** - * @param context The config context - */ - public Config(String context) { - this.context = context; - } - - /** - * Sets the global config object. - * @param c The config object to use. - */ - public static void setGlobalConfig(Config c) { - config = c; - } - - /** - * Parses an XML config file. - * @param filename The path to the file to parse. - */ - public void parse(String filename) throws ConfigException { - try { - String xml = Utils.fileToString(filename); - JSONObject jobj = XML.toJSONObject(xml); - configObject = (Map) new JSONReader(jobj.toString()).readObject(); - } catch(Exception e) { - throw new ConfigException("Error parsing config", e); - } - } - - public static void setConfig(Config conf) { - config = conf; - } - - public void setConfigObject(Map config) { - this.configObject = config; - } - - protected Map getConfigObject() { - return this.configObject; - } - - - /** - * Returns the configuration value found at the requested path. - * @param path The search path - * @return The config value, or null if no value exists at the given path. - * @throws ConfigException thrown if nothing is found at the path - */ - public String getString(String path) throws ConfigException { - try { - return (String) get(path); - } catch(Exception e) { - throw new - ConfigException("No config string found at " + path); - } - } - - /** - * Gets the int value at the given path - * @param path The search path - */ - public int getInt(String path) throws ConfigException { - try { - return Integer.parseInt(getString(path)); - } catch(Exception e) { - throw new - ConfigException("No config int found at " + path); - } - } - - /** - * Returns the configuration object found at the requested path. - * @param path The search path - * @return The config value - * @throws ConfigException thrown if nothing is found at the path - */ - public Object get(String path) throws ConfigException { - try { - Object obj = Utils.findPath(configObject, context + path); - if(obj == null) - throw new ConfigException(""); - return obj; - } catch(Exception e) { - e.printStackTrace(); - throw new ConfigException("No config object found at " + path); - } - } - - /** - * Returns the first item in the list found at the given path. If - * no list is found, ConfigException is thrown. - * @param path The search path - */ - public Object getFirst(String path) throws ConfigException { - Object obj = get(path); - if(obj instanceof List) - return ((List) obj).get(0); - return obj; - } - - - /** - * Returns the config as a JSON string - */ - public String toString() { - return new JSONWriter(configObject).write(); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/ConfigException.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/ConfigException.java deleted file mode 100644 index c1c491ec8d..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/ConfigException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.opensrf.util; - -/** - * Thrown by the Config module when a user requests a configuration - * item that does not exist - */ -public class ConfigException extends Exception { - public ConfigException(String info) { - super(info); - } - public ConfigException(String info, Throwable t) { - super(info, t); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/FileLogger.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/FileLogger.java deleted file mode 100644 index 9eb838df0c..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/FileLogger.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.opensrf.util; -import java.io.BufferedWriter; -import java.io.FileWriter; - - -public class FileLogger extends Logger { - - /** File to log to */ - private String filename; - - /** - * FileLogger constructor - * @param filename The path to the log file - */ - public FileLogger(String filename) { - this.filename = filename; - } - - /** - * Logs the mesage to a file. - * @param level The log level - * @param msg The mesage to log - */ - protected synchronized void log(short level, String msg) { - if(level > logLevel) return; - - BufferedWriter out = null; - try { - out = new BufferedWriter(new FileWriter(this.filename, true)); - out.write(formatMessage(level, msg) + "\n"); - - } catch(Exception e) { - /** If we are unable to write our log message, go ahead and - * fall back to the default (stdout) logger */ - Logger.init(logLevel, new Logger()); - Logger.logByLevel(ERROR, "Unable to write to log file " + this.filename); - Logger.logByLevel(level, msg); - } - - try { - out.close(); - } catch(Exception e) {} - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONException.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONException.java deleted file mode 100644 index ec28e1d86d..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.opensrf.util; -/** - * Used to indicate JSON parsing errors - */ -public class JSONException extends Exception { - public JSONException(String s) { - super(s); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONReader.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONReader.java deleted file mode 100644 index 55eb5c03b4..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONReader.java +++ /dev/null @@ -1,176 +0,0 @@ -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"; - - /** The JSON string to parser */ - private String json; - - /** - * @param json The JSON to parse - */ - public JSONReader(String json) { - this.json = json; - } - - /** - * Parses JSON and creates an object. - * @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()); - } - } - - /** - * Assumes that a JSON array will be read. Returns - * the resulting array as a list. - */ - public List readArray() throws JSONException { - Object o = read(); - try { - return (List) o; - } catch(Exception e) { - throw new JSONException("readArray(): JSON cast exception"); - } - } - - /** - * Assumes that a JSON object will be read. Returns - * the resulting object as a map. - */ - public Map readObject() throws JSONException { - Object o = read(); - try { - return (Map) o; - } catch(Exception e) { - throw new JSONException("readObject(): JSON cast exception"); - } - } - - - /** - * Recurse through the object and turn items into maps, lists, etc. - */ - 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 map = new HashMap(); - - 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 list = new ArrayList(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; - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONWriter.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONWriter.java deleted file mode 100644 index 7cb2cca02d..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/JSONWriter.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.opensrf.util; - -import java.io.*; -import java.util.*; - - -/** - * JSONWriter - */ -public class JSONWriter { - - /** The object to serialize to JSON */ - private Object obj; - - /** - * @param obj The object to encode - */ - public JSONWriter(Object obj) { - this.obj = obj; - } - - - /** - * Encodes a java object to JSON. - */ - 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); - } - - /** - * Encodes the object as JSON into the provided buffer - */ - 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 map = new HashMap(); - map.put(JSONReader.JSON_CLASS_KEY, reg.getNetClass()); - - if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) { - - /** encode arrays as lists */ - List list = new ArrayList(fields.length); - for(String s : fields) - list.add(obj.get(s)); - map.put(JSONReader.JSON_PAYLOAD_KEY, list); - - } else { - - /** encode hashes as maps */ - Map subMap = new HashMap(); - 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); - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/Logger.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/Logger.java deleted file mode 100644 index 2923c23b9e..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/Logger.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.opensrf.util; -import java.text.SimpleDateFormat; -import java.text.FieldPosition; -import java.util.Date; - -/** - * Basic OpenSRF logging API. This default implementation - * logs to stderr. - */ -public class Logger { - - /** Log levels */ - public static final short ERROR = 1; - public static final short WARN = 2; - public static final short INFO = 3; - public static final short DEBUG = 4; - public static final short INTERNAL = 5; - - /** The global log instance */ - private static Logger instance; - /** The global log level */ - protected static short logLevel; - - public Logger() {} - - /** Sets the global Logger instance - * @param level The global log level. - * @param l The Logger instance to use - */ - public static void init(short level, Logger l) { - instance = l; - logLevel = level; - } - - /** - * @return The global Logger instance - */ - public static Logger instance() { - return instance; - } - - /** - * Logs an error message - * @param msg The message to log - */ - public static void error(String msg) { - instance.log(ERROR, msg); - } - - /** - * Logs an warning message - * @param msg The message to log - */ - public static void warn(String msg) { - instance.log(WARN, msg); - } - - /** - * Logs an info message - * @param msg The message to log - */ - public static void info(String msg) { - instance.log(INFO, msg); - } - - /** - * Logs an debug message - * @param msg The message to log - */ - public static void debug(String msg) { - instance.log(DEBUG, msg); - } - - /** - * Logs an internal message - * @param msg The message to log - */ - public static void internal(String msg) { - instance.log(INTERNAL, msg); - } - - - /** - * Appends the text representation of the log level - * @param sb The stringbuffer to append to - * @param level The log level - */ - protected static void appendLevelString(StringBuffer sb, short level) { - switch(level) { - case DEBUG: - sb.append("DEBG"); break; - case INFO: - sb.append("INFO"); break; - case INTERNAL: - sb.append("INT "); break; - case WARN: - sb.append("WARN"); break; - case ERROR: - sb.append("ERR "); break; - } - } - - /** - * Formats a message for logging. Appends the current date+time - * and the log level string. - * @param level The log level - * @param msg The message to log - */ - protected static String formatMessage(short level, String msg) { - - StringBuffer sb = new StringBuffer(); - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format( - new Date(), sb, new FieldPosition(0)); - - sb.append(" ["); - appendLevelString(sb, level); - sb.append(":"); - sb.append(Thread.currentThread().getId()); - sb.append("] "); - sb.append(msg); - return sb.toString(); - } - - /** - * Logs a message by passing the log level explicitly - * @param level The log level - * @param msg The message to log - */ - public static void logByLevel(short level, String msg) { - instance.log(level, msg); - } - - /** - * Performs the actual logging. Subclasses should override - * this method. - * @param level The log level - * @param msg The message to log - */ - protected synchronized void log(short level, String msg) { - if(level > logLevel) return; - System.err.println(formatMessage(level, msg)); - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFObject.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFObject.java deleted file mode 100644 index af28f4a860..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFObject.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.opensrf.util; - -import java.util.Map; -import java.util.HashMap; - - -/** - * Generic OpenSRF network-serializable object. This allows - * access to object fields. - */ -public class OSRFObject extends HashMap implements OSRFSerializable { - - /** This objects registry */ - private OSRFRegistry registry; - - public OSRFObject() { - } - - - /** - * Creates a new object with the provided registry - */ - public OSRFObject(OSRFRegistry reg) { - this(); - registry = reg; - } - - - /** - * Creates a new OpenSRF object based on the net class string - * */ - public OSRFObject(String netClass) { - this(OSRFRegistry.getRegistry(netClass)); - } - - - /** - * @return This object's registry - */ - public OSRFRegistry getRegistry() { - return registry; - } - - /** - * Implement get() to fulfill our contract with OSRFSerializable - */ - public Object get(String field) { - return super.get(field); - } - - /** Returns the string value found at the given field */ - public String getString(String field) { - return (String) get(field); - } - - /** Returns the int value found at the given field */ - public int getInt(String field) { - Object o = get(field); - if(o instanceof String) - return Integer.parseInt((String) o); - return ((Integer) get(field)).intValue(); - } -} diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFRegistry.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFRegistry.java deleted file mode 100644 index c6e6bc6540..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFRegistry.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.opensrf.util; - -import java.io.Serializable; -import java.util.Map; -import java.util.HashMap; - - -/** - * Manages the registration of OpenSRF network-serializable objects. - * A serializable object has a class "hint" (called netClass within) which - * describes the type of object. Each object also has a set of field names - * for accessing/mutating object properties. Finally, objects have a - * serialization wire protocol. Currently supported protocols are HASH - * and ARRAY. - */ -public class OSRFRegistry implements Serializable{ - - - /** - * - */ - private static final long serialVersionUID = 1L; - /** - * Global collection of registered net objects. - * Maps netClass names to registries. - */ - private static HashMap - registry = new HashMap(); - - - /** Serialization types for registered objects */ - public enum WireProtocol { - ARRAY, HASH - }; - - - /** Array of field names for this registered object */ - String fields[]; - /** The wire protocol for this object */ - WireProtocol wireProtocol; - /** The network class for this object */ - String netClass; - - /** - * Returns the array of field names - */ - public String[] getFields() { - return this.fields; - } - - - /** - * Registers a new object. - * @param netClass The net class for this object - * @param wireProtocol The object's wire protocol - * @param fields An array of field names. For objects whose - * wire protocol is ARRAY, the positions of the field names - * will be used as the array indices for the fields at serialization time - */ - public static OSRFRegistry registerObject(String netClass, WireProtocol wireProtocol, String fields[]) { - OSRFRegistry r = new OSRFRegistry(netClass, wireProtocol, fields); - registry.put(netClass, r); - return r; - } - - /** - * Returns the registry for the given netclass - * @param netClass The network class to lookup - */ - public static OSRFRegistry getRegistry(String netClass) { - if( netClass == null ) return null; - return (OSRFRegistry) registry.get(netClass); - } - - - /** - * @param field The name of the field to lookup - * @return the index into the fields array of the given field name. - */ - public int getFieldIndex(String field) { - for( int i = 0; i < fields.length; i++ ) - if( fields[i].equals(field) ) - return i; - return -1; - } - - /** Returns the wire protocol of this object */ - public WireProtocol getWireProtocol() { - return this.wireProtocol; - } - - /** Returns the netClass ("hint") of this object */ - public String getNetClass() { - return this.netClass; - } - - /** - * Creates a new registry object. - * @param netClass The network class/hint - * @param wireProtocol The wire protocol - * @param fields The array of field names. For array-based objects, - * the fields array must be sorted in accordance with the sorting - * of the objects in the array. - */ - public OSRFRegistry(String netClass, WireProtocol wireProtocol, String fields[]) { - this.netClass = netClass; - this.wireProtocol = wireProtocol; - this.fields = fields; - } -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFSerializable.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFSerializable.java deleted file mode 100644 index 64b5d6f4e5..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/OSRFSerializable.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.opensrf.util; - -/** - * All network-serializable OpenSRF object must implement this interface. - */ -public interface OSRFSerializable { - - /** - * Returns the object registry object for the implementing class. - */ - public abstract OSRFRegistry getRegistry(); - - /** - * Returns the object found at the given field - */ - public abstract Object get(String field); -} - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/SettingsClient.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/SettingsClient.java deleted file mode 100644 index 71e570a410..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/SettingsClient.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.opensrf.util; -import org.opensrf.*; -import java.util.Map; - -/** - * Connects to the OpenSRF Settings server to fetch the settings config. - * Provides a Config interface for fetching settings via path - */ -public class SettingsClient extends Config { - - /** Singleton SettingsClient instance */ - private static SettingsClient client = new SettingsClient(); - - public SettingsClient() { - super(""); - } - - /** - * @return The global settings client instance - */ - public static SettingsClient instance() throws ConfigException { - if(client.getConfigObject() == null) - client.fetchConfig(); - return client; - } - - /** - * Fetches the settings object from the settings server - */ - private void fetchConfig() throws ConfigException { - - ClientSession ses = new ClientSession("opensrf.settings"); - try { - - Request req = ses.request( - "opensrf.settings.host_config.get", - new String[]{(String)Config.global().getFirst("/domain")}); - - Result res = req.recv(12000); - if(res == null) { - /** throw exception */ - } - setConfigObject((Map) res.getContent()); - - } catch(Exception e) { - throw new ConfigException("Error fetching settings config", e); - - } finally { - ses.cleanup(); - } - } -} - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/Utils.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/Utils.java deleted file mode 100644 index 159d254706..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/Utils.java +++ /dev/null @@ -1,106 +0,0 @@ -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(); - } - - - /** - * Escapes a string. - */ - 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); - } - } - } - } - - - /** - * Descends into the map along the given XPATH-style path - * and returns the object found there. - * @param path The XPATH-style path to search. Path - * components are separated by '/' characters. - * Example: /opensrf/loglevel - * @return The found object. - */ - - public static Object findPath(Map map, String path) { - String keys[] = path.split("/", -1); - int i = 0; - if(path.charAt(0) == '/') i++; - for(; i < keys.length - 1; i++ ) - map = (Map) map.get(keys[i]); - - return map.get(keys[i]); - } -} - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLFlattener.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLFlattener.java deleted file mode 100644 index 7abefe09fd..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLFlattener.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.opensrf.util; - -import javax.xml.stream.*; -import javax.xml.stream.events.* ; -import javax.xml.namespace.QName; -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.ListIterator; -import java.io.InputStream; -import org.opensrf.util.JSONWriter; -import org.opensrf.util.JSONReader; - -/** - * Flattens an XML file into a properties map. Values are stored as JSON strings or arrays. - * An array is created if more than one value resides at the same key. - * e.g. html.head.script = "alert('hello');" - */ -public class XMLFlattener { - - /** Flattened properties map */ - private Map props; - /** Incoming XML stream */ - private InputStream inStream; - /** Runtime list of encountered elements */ - private List elementList; - - /** - * Creates a new reader. Initializes the message queue. - * Sets the stream state to disconnected, and the xml - * state to in_nothing. - * @param inStream the inbound XML stream - */ - public XMLFlattener(InputStream inStream) { - props = new HashMap(); - this.inStream = inStream; - elementList = new ArrayList(); - } - - /** Turns an array of strings into a dot-separated key string */ - private String listToString() { - ListIterator itr = elementList.listIterator(); - StringBuffer sb = new StringBuffer(); - while(itr.hasNext()) { - sb.append(itr.next()); - if(itr.hasNext()) - sb.append("."); - } - return sb.toString(); - } - - /** - * Parses XML data from the provided stream. - */ - public Map read() throws javax.xml.stream.XMLStreamException { - - XMLInputFactory factory = XMLInputFactory.newInstance(); - - /** disable as many unused features as possible to speed up the parsing */ - factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE); - factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); - factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); - factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); - factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); - - /** create the stream reader */ - XMLStreamReader reader = factory.createXMLStreamReader(inStream); - int eventType; - - while(reader.hasNext()) { - /** cycle through the XML events */ - - eventType = reader.next(); - if(reader.isWhiteSpace()) continue; - - switch(eventType) { - - case XMLEvent.START_ELEMENT: - elementList.add(reader.getName().toString()); - break; - - case XMLEvent.CHARACTERS: - String text = reader.getText(); - String key = listToString(); - - if(props.containsKey(key)) { - - /* something in the map already has this key */ - - Object o = null; - try { - o = new JSONReader(props.get(key)).read(); - } catch(org.opensrf.util.JSONException e){} - - if(o instanceof List) { - /* if the map contains a list, append to the list and re-encode */ - ((List) o).add(text); - - } else { - /* if the map just contains a string, start building a new list - * with the old string and append the new string */ - List arr = new ArrayList(); - arr.add((String) o); - arr.add(text); - o = arr; - } - - props.put(key, new JSONWriter(o).write()); - - } else { - props.put(key, new JSONWriter(text).write()); - } - break; - - case XMLEvent.END_ELEMENT: - elementList.remove(elementList.size()-1); - break; - } - } - - return props; - } -} - - - - diff --git a/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLTransformer.java b/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLTransformer.java deleted file mode 100644 index f8bc0d3fac..0000000000 --- a/Open-ILS/src/Android/opensrf/org/opensrf/util/XMLTransformer.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.opensrf.util; -import javax.xml.transform.*; -import javax.xml.transform.stream.*; -import javax.xml.parsers.*; -import java.io.File; -import java.io.ByteArrayInputStream; -import java.io.OutputStream; -import java.io.ByteArrayOutputStream; - - -/** - * Performs XSL transformations. - * TODO: Add ability to pass in XSL variables - */ -public class XMLTransformer { - - /** The XML to transform */ - private Source xmlSource; - /** The stylesheet to apply */ - private Source xslSource; - - public XMLTransformer(Source xmlSource, Source xslSource) { - this.xmlSource = xmlSource; - this.xslSource = xslSource; - } - - public XMLTransformer(String xmlString, File xslFile) { - this( - new StreamSource(new ByteArrayInputStream(xmlString.getBytes())), - new StreamSource(xslFile)); - } - - public XMLTransformer(File xmlFile, File xslFile) { - this( - new StreamSource(xmlFile), - new StreamSource(xslFile)); - } - - /** - * Applies the transformation and puts the result into the provided output stream - */ - public void apply(OutputStream outStream) throws TransformerException, TransformerConfigurationException { - Result result = new StreamResult(outStream); - Transformer trans = TransformerFactory.newInstance().newTransformer(xslSource); - trans.transform(xmlSource, result); - } - - /** - * Applies the transformation and return the resulting string - * @return The String created by the XSL transformation - */ - public String apply() throws TransformerException, TransformerConfigurationException { - OutputStream outStream = new ByteArrayOutputStream(); - this.apply(outStream); - return outStream.toString(); - } -} - - diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/ClientSession.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/ClientSession.java new file mode 100644 index 0000000000..3ed4908296 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/ClientSession.java @@ -0,0 +1,175 @@ +package org.opensrf; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Random; +import java.util.Arrays; + +import org.opensrf.util.*; +import org.opensrf.net.xmpp.*; + + +/** + * Models an OpenSRF client session. + */ +public class ClientSession extends Session { + + /** The remote service to communicate with */ + private String service; + /** OpenSRF domain */ + private String domain; + /** Router name */ + private String router; + + /** + * original remote node. The current remote node will change based + * on server responses. This is used to reset the remote node to + * its original state. + */ + private String origRemoteNode; + /** The next request id */ + private int nextId; + /** The requests this session has sent */ + private Map requests; + + /** + * Creates a new client session. Initializes the + * @param service The remote service. + */ + public ClientSession(String service) throws ConfigException { + this(service, null); + } + + /** + * Creates a new client session. Initializes the + * @param service The remote service. + * @param locale The locale for this session. + */ + public ClientSession(String service, String locale) throws ConfigException { + this.service = service; + if(locale != null) + setLocale(locale); + + /** generate the remote node string */ + domain = (String) Config.global().getFirst("/domain"); + router = Config.global().getString("/router_name"); + setRemoteNode(router + "@" + domain + "/" + service); + origRemoteNode = getRemoteNode(); + + + /** create a random thread */ + long time = new Date().getTime(); + Random rand = new Random(time); + setThread(rand.nextInt()+""+rand.nextInt()+""+time+Thread.currentThread().getId()); + + nextId = 0; + requests = new HashMap(); + cacheSession(); + } + + /** + * Creates a new request to send to our remote service. + * @param method The method API name + * @param params The list of method parameters + * @return The request object. + */ + public Request request(String method, List params) throws SessionException { + return request(new Request(this, nextId++, method, params)); + } + + /** + * Creates a new request to send to our remote service. + * @param method The method API name + * @param params The list of method parameters + * @return The request object. + */ + public Request request(String method, Object[] params) throws SessionException { + return request(new Request(this, nextId++, method, Arrays.asList(params))); + } + + + /** + * Creates a new request to send to our remote service. + * @param method The method API name + * @return The request object. + */ + public Request request(String method) throws SessionException { + return request(new Request(this, nextId++, method)); + } + + + private Request request(Request req) throws SessionException { + if(getConnectState() != ConnectState.CONNECTED) + resetRemoteId(); + requests.put(new Integer(req.getId()), req); + req.send(); + return req; + } + + + /** + * Resets the remoteNode to its original state. + */ + public void resetRemoteId() { + setRemoteNode(origRemoteNode); + } + + + /** + * Pushes a response onto the result queue of the appropriate request. + * @param msg The received RESULT Message + */ + public void pushResponse(Message msg) { + + Request req = findRequest(msg.getId()); + if(req == null) { + /** LOG that we've received a result to a non-existant request */ + System.err.println(msg.getId() +" has no corresponding request"); + return; + } + OSRFObject payload = (OSRFObject) msg.get("payload"); + + /** build a result and push it onto the request's result queue */ + req.pushResponse( + new Result( + payload.getString("status"), + payload.getInt("statusCode"), + payload.get("content") + ) + ); + } + + public Request findRequest(int reqId) { + return requests.get(new Integer(reqId)); + } + + /** + * Removes a request for this session's request set + */ + public void cleanupRequest(int reqId) { + requests.remove(new Integer(reqId)); + } + + public void setRequestComplete(int reqId) { + Request req = findRequest(reqId); + if(req == null) return; + req.setComplete(); + } + + public static Object atomicRequest(String service, String method, Object[] params) throws MethodException { + try { + ClientSession session = new ClientSession(service); + Request osrfRequest = session.request(method, params); + Result result = osrfRequest.recv(600000); + if(result.getStatusCode() != 200) + throw new MethodException( + "Request "+service+":"+method+":"+" failed with status code " + result.getStatusCode()); + return result.getContent(); + } catch(Exception e) { + throw new MethodException(e); + } + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Message.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Message.java new file mode 100644 index 0000000000..6bfe1eaaa7 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Message.java @@ -0,0 +1,110 @@ +package org.opensrf; +import org.opensrf.util.*; + + +public class Message implements OSRFSerializable { + + /** Message types */ + public static final String REQUEST = "REQUEST"; + public static final String STATUS = "STATUS"; + public static final String RESULT = "RESULT"; + public static final String CONNECT = "CONNECT"; + public static final String DISCONNECT = "DISCONNECT"; + + /** Message ID. This number is used to relate requests to responses */ + private int id; + /** type of message. */ + private String type; + /** message payload */ + private Object payload; + /** message locale */ + private String locale; + + /** Create a registry for the osrfMessage object */ + private static OSRFRegistry registry = + OSRFRegistry.registerObject( + "osrfMessage", + OSRFRegistry.WireProtocol.HASH, + new String[] {"threadTrace", "type", "payload", "locale"}); + + /** + * @param id This message's ID + * @param type The type of message + */ + public Message(int id, String type) { + setId(id); + setString(type); + } + + /** + * @param id This message's ID + * @param type The type of message + * @param payload The message payload + */ + public Message(int id, String type, Object payload) { + this(id, type); + setPayload(payload); + } + + /** + * @param id This message's ID + * @param type The type of message + * @param payload The message payload + * @param locale The message locale + */ + public Message(int id, String type, Object payload, String locale) { + this(id, type, payload); + setPayload(payload); + setLocale(locale); + } + + + public int getId() { + return id; + } + public String getType() { + return type; + } + public Object getPayload() { + return payload; + } + public String getLocale() { + return locale; + } + public void setId(int id) { + this.id = id; + } + public void setString(String type) { + this.type = type; + } + public void setPayload(Object p) { + payload = p; + } + public void setLocale(String l) { + locale = l; + } + + /** + * Implements the generic get() API required by OSRFSerializable + */ + public Object get(String field) { + if("threadTrace".equals(field)) + return getId(); + if("type".equals(field)) + return getType().toString(); + if("payload".equals(field)) + return getPayload(); + if("locale".equals(field)) + return getLocale(); + return null; + } + + /** + * @return The osrfMessage registry. + */ + public OSRFRegistry getRegistry() { + return registry; + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Method.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Method.java new file mode 100644 index 0000000000..b708d4fa39 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Method.java @@ -0,0 +1,78 @@ +package org.opensrf; +import java.util.List; +import java.util.ArrayList; +import org.opensrf.util.*; + + +public class Method extends OSRFObject { + + /** The method API name */ + private String name; + /** The ordered list of method params */ + private List params; + + /** Create a registry for the osrfMethod object */ + private static OSRFRegistry registry = + OSRFRegistry.registerObject( + "osrfMethod", + OSRFRegistry.WireProtocol.HASH, + new String[] {"method", "params"}); + + /** + * @param name The method API name + */ + public Method(String name) { + this.name = name; + this.params = new ArrayList(8); + } + + /** + * @param name The method API name + * @param params The ordered list of params + */ + public Method(String name, List params) { + this.name = name; + this.params = params; + } + + /** + * @return The method API name + */ + public String getName() { + return name; + } + /** + * @return The ordered list of params + */ + public List 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 addParam(Object p) { + this.params.add(p); + } + + /** + * Implements the generic get() API required by OSRFSerializable + */ + public Object get(String field) { + if("method".equals(field)) + return getName(); + if("params".equals(field)) + return getParams(); + return null; + } + + /** + * @return The osrfMethod registry. + */ + public OSRFRegistry getRegistry() { + return registry; + } + +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/MethodException.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/MethodException.java new file mode 100644 index 0000000000..f87e638cf2 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/MethodException.java @@ -0,0 +1,14 @@ +package org.opensrf; + +/** + * Thrown when the server responds with a method exception. + */ +public class MethodException extends Exception { + public MethodException(String info) { + super(info); + } + public MethodException(Throwable cause) { + super(cause); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/MultiSession.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/MultiSession.java new file mode 100644 index 0000000000..a312aff9b8 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/MultiSession.java @@ -0,0 +1,123 @@ +package org.opensrf; +import java.util.List; +import java.util.ArrayList; +import org.opensrf.util.ConfigException; + +public class MultiSession { + + class RequestContainer { + Request request; + int id; + RequestContainer(Request r) { + request = r; + } + } + + private boolean complete; + private List requests; + private int lastId; + + public MultiSession() { + requests = new ArrayList(); + } + + public boolean isComplete() { + return complete; + } + + public int lastId() { + return lastId; + } + + /** + * Adds a new request to the set of requests. + * @param service The OpenSRF service + * @param method The OpenSRF method + * @param params The array of method params + * @return The request ID, which is used to map results from recv() to the original request. + */ + public int request(String service, String method, Object[] params) throws SessionException, ConfigException { + ClientSession ses = new ClientSession(service); + return request(ses.request(method, params)); + } + + + public int request(String service, String method) throws SessionException, ConfigException { + ClientSession ses = new ClientSession(service); + return request(ses.request(method)); + } + + private int request(Request req) { + RequestContainer c = new RequestContainer(req); + c.id = requests.size(); + requests.add(c); + return c.id; + } + + + /** + * Calls recv on all pending requests until there is data to return. The ID which + * maps the received object to the request can be retrieved by calling lastId(). + * @param millis Number of milliseconds to wait for some data to arrive. + * @return The object result or null if all requests are complete + * @throws MethodException Thrown if no response is received within + * the given timeout or the method fails. + */ + public Object recv(int millis) throws MethodException { + if(complete) return null; + + Request req = null; + Result res = null; + RequestContainer cont = null; + + long duration = 0; + long blockTime = 100; + + /* if there is only 1 outstanding request, don't poll */ + if(requests.size() == 1) + blockTime = millis; + + while(true) { + for(int i = 0; i < requests.size(); i++) { + + cont = requests.get(i); + req = cont.request; + + try { + if(i == 0) { + res = req.recv(blockTime); + } else { + res = req.recv(0); + } + } catch(SessionException e) { + throw new MethodException(e); + } + + if(res != null) break; + } + + if(res != null) break; + duration += blockTime; + + if(duration >= millis) { + System.out.println("duration = " + duration + " millis = " + millis); + throw new MethodException("No request received within " + millis + " milliseconds"); + } + } + + if(res.getStatusCode() != 200) { + throw new MethodException("Request " + cont.id + " failed with status code " + + res.getStatusCode() + " and status message " + res.getStatus()); + } + + if(req.isComplete()) + requests.remove(requests.indexOf(cont)); + + if(requests.size() == 0) + complete = true; + + lastId = cont.id; + return res.getContent(); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Request.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Request.java new file mode 100644 index 0000000000..2d72e2df65 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Request.java @@ -0,0 +1,138 @@ +package org.opensrf; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.List; +import java.util.Date; +import org.opensrf.net.xmpp.XMPPException; +import org.opensrf.util.Logger; + +public class Request { + + /** This request's controlling session */ + private ClientSession session; + /** The method */ + private Method method; + /** The ID of this request */ + private int id; + /** Queue of Results */ + private Queue resultQueue; + /** If true, the receive timeout for this request should be reset */ + private boolean resetTimeout; + + /** If true, the server has indicated that this request is complete. */ + private boolean complete; + + /** + * @param ses The controlling session for this request. + * @param id This request's ID. + * @param method The requested method. + */ + public Request(ClientSession ses, int id, Method method) { + this.session = ses; + this.id = id; + this.method = method; + resultQueue = new ConcurrentLinkedQueue(); + complete = false; + resetTimeout = false; + } + + /** + * @param ses The controlling session for this request. + * @param id This request's ID. + * @param methodName The requested method's API name. + */ + public Request(ClientSession ses, int id, String methodName) { + this(ses, id, new Method(methodName)); + } + + /** + * @param ses The controlling session for this request. + * @param id This request's ID. + * @param methodName The requested method's API name. + * @param params The list of request params + */ + public Request(ClientSession ses, int id, String methodName, List params) { + this(ses, id, new Method(methodName, params)); + } + + /** + * Sends the request to the server. + */ + public void send() throws SessionException { + session.send(new Message(id, Message.REQUEST, method, session.getLocale())); + } + + /** + * Receives the next result for this request. This method + * will wait up to the specified number of milliseconds for + * a response. + * @param millis Number of milliseconds to wait for a result. If + * negative, this method will wait indefinitely. + * @return The result or null if none arrives in time + */ + public Result recv(long millis) throws SessionException, MethodException { + + Result result = null; + + if((result = resultQueue.poll()) != null) + return result; + + if(millis < 0 && !complete) { + /** wait potentially forever for a result to arrive */ + while(!complete) { + session.waitForMessage(millis); + if((result = resultQueue.poll()) != null) + return result; + } + + } else { + + while(millis >= 0 && !complete) { + + /** wait up to millis milliseconds for a result. waitForMessage() + * will return if a response to any request arrives, so we keep track + * of how long we've been waiting in total for a response to + * this request */ + + long start = new Date().getTime(); + session.waitForMessage(millis); + millis -= new Date().getTime() - start; + if((result = resultQueue.poll()) != null) + return result; + } + } + + return null; + } + + /** + * Pushes a result onto the result queue + * @param result The result to push + */ + public void pushResponse(Result result) { + resultQueue.offer(result); + } + + /** + * @return This request's ID + */ + public int getId() { + return id; + } + + /** + * Removes this request from the controlling session's request set + */ + public void cleanup() { + session.cleanupRequest(id); + } + + /** Sets this request as complete */ + public void setComplete() { + complete = true; + } + + public boolean isComplete() { + return complete; + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Result.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Result.java new file mode 100644 index 0000000000..80b71dd138 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Result.java @@ -0,0 +1,106 @@ +package org.opensrf; +import org.opensrf.util.*; + + +/** + * Models a single result from a method request. + */ +public class Result implements OSRFSerializable { + + /** Method result content */ + private Object content; + /** Name of the status */ + private String status; + /** Status code number */ + private int statusCode; + + + /** Register this object */ + private static OSRFRegistry registry = + OSRFRegistry.registerObject( + "osrfResult", + OSRFRegistry.WireProtocol.HASH, + new String[] {"status", "statusCode", "content"}); + + + /** + * @param status The status message for this result + * @param statusCode The status code + * @param content The content of the result + */ + 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; + } + + /** + * Implements the generic get() API required by OSRFSerializable + */ + public Object get(String field) { + if("status".equals(field)) + return getStatus(); + if("statusCode".equals(field)) + return getStatusCode(); + if("content".equals(field)) + return getContent(); + return null; + } + + /** + * @return The osrfMethod registry. + */ + public OSRFRegistry getRegistry() { + return registry; + } + +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/ServerSession.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/ServerSession.java new file mode 100644 index 0000000000..62e5133058 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/ServerSession.java @@ -0,0 +1,8 @@ +package org.opensrf; + +/** + * Models an OpenSRF server session. + */ +public class ServerSession extends Session { +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Session.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Session.java new file mode 100644 index 0000000000..15fd352d5f --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Session.java @@ -0,0 +1,180 @@ +package org.opensrf; +import org.opensrf.util.JSONWriter; +import org.opensrf.net.xmpp.*; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; + +public abstract class Session { + + /** Represents the different connection states for a session */ + public enum ConnectState { + DISCONNECTED, + CONNECTING, + CONNECTED + }; + + /** local cache of existing sessions */ + private static Map + sessionCache = new HashMap(); + + /** the current connection state */ + private ConnectState connectState; + + /** The address of the remote party we are communicating with */ + private String remoteNode; + + /** Session locale */ + protected String locale; + /** Default session locale */ + protected static String defaultLocale = "en-US"; + + /** + * 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 SessionException { + + /** construct the XMPP message */ + XMPPMessage xmsg = new XMPPMessage(); + xmsg.setTo(remoteNode); + xmsg.setThread(thread); + xmsg.setBody(new JSONWriter(Arrays.asList(new Message[] {omsg})).write()); + + try { + XMPPSession.getThreadSession().send(xmsg); + } catch(XMPPException e) { + connectState = ConnectState.DISCONNECTED; + throw new SessionException("Error sending message to " + remoteNode, e); + } + } + + /** + * 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) throws SessionException, MethodException { + try { + Stack.processXMPPMessage( + XMPPSession.getThreadSession().recv(millis)); + } catch(XMPPException e) { + throw new SessionException("Error waiting for message", e); + } + } + + /** + * 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); + } + + /** + * Puts this session into session cache. + */ + protected void cacheSession() { + sessionCache.put(thread, this); + } + + /** + * Sets the remote address + * @param nodeName The name of the remote node. + */ + public void setRemoteNode(String nodeName) { + remoteNode = nodeName; + } + /** + * @return The remote node + */ + public String getRemoteNode() { + return remoteNode; + } + + + /** + * Get thread. + * @return thread as String. + */ + public String getThread() { + return thread; + } + + /** + * Set thread. + * @param thread the value to set. + */ + public void setThread(String thread) { + this.thread = thread; + } + + /** + * Get locale. + * @return locale as String. + */ + public String getLocale() { + if(locale == null) + return defaultLocale; + return locale; + } + + /** + * Set locale. + * @param locale the value to set. + */ + public void setLocale(String locale) { + this.locale = locale; + } + + /** + * Get defaultLocale. + * @return defaultLocale as String. + */ + public String getDefaultLocale() { + return defaultLocale; + } + + /** + * Set defaultLocale. + * @param defaultLocale the value to set. + */ + public void setDefaultLocale(String defaultLocale) { + this.defaultLocale = defaultLocale; + } + + + /** + * Get connectState. + * @return connectState as ConnectState. + */ + public ConnectState getConnectState() { + return connectState; + } + + /** + * Set connectState. + * @param connectState the value to set. + */ + public void setConnectState(ConnectState connectState) { + this.connectState = connectState; + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/SessionException.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/SessionException.java new file mode 100644 index 0000000000..bd90a7610d --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/SessionException.java @@ -0,0 +1,13 @@ +package org.opensrf; +/** + * Used by sessions to indicate communication errors + */ +public class SessionException extends Exception { + public SessionException(String info) { + super(info); + } + public SessionException(String info, Throwable cause) { + super(info, cause); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Stack.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Stack.java new file mode 100644 index 0000000000..3e7e6061fb --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Stack.java @@ -0,0 +1,105 @@ +package org.opensrf; +import org.opensrf.net.xmpp.XMPPMessage; +import org.opensrf.util.*; +import java.util.Date; +import java.util.List; +import java.util.Iterator; + + +public class Stack { + + public static void processXMPPMessage(XMPPMessage msg) throws MethodException { + + if(msg == null) return; + + //System.out.println(msg.getBody()); + + /** fetch this session from the cache */ + Session ses = Session.findCachedSession(msg.getThread()); + + if(ses == null) { + /** inbound client request, create a new server session */ + return; + } + + /** parse the JSON message body, which should result in a list of OpenSRF messages */ + List msgList; + + try { + msgList = new JSONReader(msg.getBody()).readArray(); + } catch(JSONException e) { + /** XXX LOG error */ + e.printStackTrace(); + return; + } + + Iterator itr = msgList.iterator(); + + OSRFObject obj = null; + long start = new Date().getTime(); + + /** cycle through the messages and push them up the stack */ + while(itr.hasNext()) { + + /** Construct a Message object from the parsed generic OSRFObject */ + obj = (OSRFObject) itr.next(); + + processOSRFMessage( + ses, + new Message( + obj.getInt("threadTrace"), + obj.getString("type"), + obj.get("payload") + ) + ); + } + + /** LOG the duration */ + } + + private static void processOSRFMessage(Session ses, Message msg) throws MethodException { + + Logger.debug("received id=" + msg.getId() + + " type=" + msg.getType() + " payload=" + msg.getPayload()); + + if( ses instanceof ClientSession ) + processResponse((ClientSession) ses, msg); + else + processRequest((ServerSession) ses, msg); + } + + /** + * Process a server response + */ + private static void processResponse(ClientSession session, Message msg) throws MethodException { + String type = msg.getType(); + + if(msg.RESULT.equals(type)) { + session.pushResponse(msg); + return; + } + + if(msg.STATUS.equals(type)) { + + OSRFObject obj = (OSRFObject) msg.getPayload(); + Status stat = new Status(obj.getString("status"), obj.getInt("statusCode")); + int statusCode = stat.getStatusCode(); + String status = stat.getStatus(); + + switch(statusCode) { + case Status.COMPLETE: + session.setRequestComplete(msg.getId()); + break; + case Status.NOTFOUND: + session.setRequestComplete(msg.getId()); + throw new MethodException(status); + } + } + } + + /** + * Process a client request + */ + private static void processRequest(ServerSession session, Message msg) { + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Status.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Status.java new file mode 100644 index 0000000000..8026c7b8cd --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Status.java @@ -0,0 +1,63 @@ +package org.opensrf; +import org.opensrf.util.*; + +public class Status { + + public static final int CONTINUE = 100; + public static final int OK = 200; + public static final int ACCEPTED = 202; + public static final int COMPLETE = 205; + public static final int REDIRECTED = 307; + public static final int EST = 400; + public static final int STATUS_UNAUTHORIZED = 401; + public static final int FORBIDDEN = 403; + public static final int NOTFOUND = 404; + public static final int NOTALLOWED = 405; + public static final int TIMEOUT = 408; + public static final int EXPFAILED = 417; + public static final int INTERNALSERVERERROR = 500; + public static final int NOTIMPLEMENTED = 501; + public static final int VERSIONNOTSUPPORTED = 505; + + private OSRFRegistry registry = OSRFRegistry.registerObject( + "osrfConnectStatus", + OSRFRegistry.WireProtocol.HASH, + new String[] {"status", "statusCode"}); + + /** The name of the status */ + String status; + /** The status code */ + int statusCode; + + public Status(String status, int statusCode) { + this.status = status; + this.statusCode = statusCode; + } + + public int getStatusCode() { + return statusCode; + } + public String getStatus() { + return status; + } + + /** + * Implements the generic get() API required by OSRFSerializable + */ + public Object get(String field) { + if("status".equals(field)) + return getStatus(); + if("statusCode".equals(field)) + return new Integer(getStatusCode()); + return null; + } + + /** + * @return The osrfMessage registry. + */ + public OSRFRegistry getRegistry() { + return registry; + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/Sys.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/Sys.java new file mode 100644 index 0000000000..d65f8a4ffa --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/Sys.java @@ -0,0 +1,86 @@ +package org.opensrf; + +import org.opensrf.util.*; +import org.opensrf.net.xmpp.*; +import java.util.Random; +import java.util.Date; +import java.net.InetAddress; + + +public class Sys { + + private static void initLogger(Config config) { + if(Logger.instance() == null) { + try { + String logFile = config.getString("/logfile"); + int logLevel = config.getInt("/loglevel"); + Logger.init( (short) config.getInt("/loglevel"), new FileLogger(logFile)); + /** add syslog support... */ + } catch(Exception e) { + /* by default, log to stderr at WARN level */ + Logger.init(Logger.WARN, new Logger()); + } + } + } + + /** + * Connects to the OpenSRF network so that client sessions may communicate. + * @param configFile The OpenSRF config file + * @param configContext Where in the XML document the config chunk lives. This + * allows an OpenSRF client config chunk to live in XML files where other config + * information lives. + */ + public static void bootstrapClient(String configFile, String configContext) + throws ConfigException, SessionException { + + + /** see if the current thread already has a connection */ + XMPPSession existing = XMPPSession.getThreadSession(); + if(existing != null && existing.connected()) + return; + + /** create the config parser */ + Config config = new Config(configContext); + config.parse(configFile); + Config.setConfig(config); /* set this as the global config */ + + initLogger(config); + + /** Collect the network connection info from the config */ + String username = config.getString("/username"); + String passwd = config.getString("/passwd"); + String host = (String) config.getFirst("/domain"); + int port = config.getInt("/port"); + + + /** Create a random login resource string */ + String res = "java_"; + try { + res += InetAddress.getLocalHost().getHostAddress(); + } catch(java.net.UnknownHostException e) {} + res += "_"+Math.abs(new Random(new Date().getTime()).nextInt()) + + "_t"+ Thread.currentThread().getId(); + + + + try { + + /** Connect to the Jabber network */ + Logger.info("attempting to create XMPP session "+username+"@"+host+"/"+res); + XMPPSession xses = new XMPPSession(host, port); + xses.connect(username, passwd, res); + XMPPSession.setThreadSession(xses); + + } catch(XMPPException e) { + throw new SessionException("Unable to bootstrap client", e); + } + } + + /** + * Shuts down the connection to the opensrf network + */ + public static void shutdown() { + XMPPSession.getThreadSession().disconnect(); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/GatewayRequest.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/GatewayRequest.java new file mode 100644 index 0000000000..61d7306baf --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/GatewayRequest.java @@ -0,0 +1,140 @@ +package org.opensrf.net.http; + +import android.util.Log; +import org.json.JSONObject; +import org.opensrf.*; +import org.opensrf.util.*; + +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.OutputStreamWriter; +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URI; +import java.net.HttpURLConnection; +import java.lang.StringBuffer; +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class GatewayRequest extends HttpRequest { + + private boolean readComplete; + private String TAG = GatewayRequest.class.getName(); + + public GatewayRequest(HttpConnection conn, String service, Method method) { + super(conn, service, method); + readComplete = false; + } + + public GatewayRequest send() { + try { + + String postData = compilePostData(service, method); + + urlConn = (HttpURLConnection) httpConn.url.openConnection(); + urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + urlConn.setDoInput(true); + urlConn.setDoOutput(true); + + + + OutputStreamWriter wr = new OutputStreamWriter(urlConn.getOutputStream()); + wr.write(postData); + wr.flush(); + wr.close(); + + } catch (java.io.IOException ex) { + failed = true; + failure = ex; + } + + return this; + } + + public Object recv() { + + if (readComplete) + return nextResponse(); + + try { + + InputStream netStream = new BufferedInputStream(urlConn.getInputStream()); + StringBuffer readBuf = new StringBuffer(); + + int bytesRead = 0; + byte[] buffer = new byte[1024]; + + while ((bytesRead = netStream.read(buffer)) != -1) { + readBuf.append(new String(buffer, 0, bytesRead)); + } + + netStream.close(); + urlConn = null; + + Map result = null; + + //System.out.println("osrf: Received " + readBuf.toString()); + //Log.d(TAG, "received:" + readBuf.toString()); + try { + result = (Map) new JSONReader(readBuf.toString()).readObject(); + } catch (org.opensrf.util.JSONException ex) { + ex.printStackTrace(); + return null; + } + //System.out.println("osrf: Converted object " + result); + Log.d(TAG, "service:" + this.service + + " method:" + this.method.getName() + + " result:" + new JSONObject(result).toString()); + String status = result.get("status").toString(); + if (!"200".equals(status)) { + failed = true; + // failure = + } + + // gateway always returns a wrapper array with the full results set + responseList = (List) result.get("payload"); + + // System.out.println("Response list : " + responseList); + } catch (java.io.IOException ex) { + failed = true; + failure = ex; + } + + readComplete = true; + return nextResponse(); + } + + private String compilePostData(String service, Method method) { + URI uri = null; + StringBuffer postData = new StringBuffer(); + + postData.append("service="); + postData.append(service); + postData.append("&method="); + postData.append(method.getName()); + + List params = method.getParams(); + Iterator itr = params.iterator(); + + while (itr.hasNext()) { + postData.append("¶m="); + postData.append(new JSONWriter(itr.next()).write()); + } + + try { + // not using URLEncoder because it replaces ' ' with '+'. + uri = new URI("http", "", null, postData.toString(), null); + } catch (java.net.URISyntaxException ex) { + ex.printStackTrace(); + } + + return uri.getRawQuery(); + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpConnection.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpConnection.java new file mode 100644 index 0000000000..32fdebc212 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpConnection.java @@ -0,0 +1,97 @@ +package org.opensrf.net.http; + +import java.net.URL; +import java.net.MalformedURLException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import org.opensrf.*; +import org.opensrf.util.*; + + +/** + * Manages connection parameters and thread limiting for opensrf json gateway connections. + */ + +public class HttpConnection { + + /** Compiled URL object */ + protected URL url; + /** Number of threads currently communicating with the server */ + protected int activeThreads; + /** Queue of pending async requests */ + protected Queue pendingThreadQueue; + /** maximum number of actively communicating threads allowed */ + protected int maxThreads = 10; + + public HttpConnection(String fullUrl) throws java.net.MalformedURLException { + activeThreads = 0; + pendingThreadQueue = new ConcurrentLinkedQueue(); + url = new URL(fullUrl); + } + + public int getMaxThreads() { + return maxThreads; + } + + /** + * Set the maximum number of actively communicating threads allowed + */ + public void setMaxThreads(int max) { + maxThreads = max; + } + + /** + * Launches or queues an asynchronous request. + * + * If the maximum active thread count has not been reached, + * start a new thread and use it to send and receive the request. + * The response is passed to the request's HttpRequestHandler + * onComplete(). After complete, if the number of active threads + * is still lower than the max, one request will be pulled (if + * present) from the async queue and fired. + * + * If there are too many active threads, the main request is + * pushed onto the async queue for later processing + */ + protected void manageAsyncRequest(final HttpRequest request) { + + if (activeThreads >= maxThreads) { + pendingThreadQueue.offer(request); + return; + } + + activeThreads++; + + //Send the request receive the response, fire off the next + //thread if necessary, then pass the result to the handler + Runnable r = new Runnable() { + public void run() { + + Object response; + request.send(); + + while ((response = request.recv()) != null) { + if (request.handler != null) + request.handler.onResponse(request, response); + } + + if (request.handler != null) + request.handler.onComplete(request); + + activeThreads--; + + if (activeThreads < maxThreads) { + try { + manageAsyncRequest(pendingThreadQueue.remove()); + } catch (java.util.NoSuchElementException ex) { + // may have been gobbled by another thread + } + } + } + }; + + new Thread(r).start(); + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequest.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequest.java new file mode 100644 index 0000000000..8af4623451 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequest.java @@ -0,0 +1,70 @@ +package org.opensrf.net.http; +import org.opensrf.*; +import org.opensrf.util.*; + +import java.util.List; +import java.util.LinkedList; +import java.net.HttpURLConnection; + +public abstract class HttpRequest { + + protected String service; + protected Method method; + protected HttpURLConnection urlConn; + protected HttpConnection httpConn; + protected HttpRequestHandler handler; + protected List responseList; + protected Exception failure; + protected boolean failed; + protected boolean complete; + + public HttpRequest() { + failed = false; + complete = false; + handler = null; + urlConn = null; + } + + public HttpRequest(HttpConnection conn, String service, Method method) { + this(); + this.httpConn = conn; + this.service = service; + this.method = method; + } + + public void sendAsync(final HttpRequestHandler handler) { + this.handler = handler; + httpConn.manageAsyncRequest(this); + } + + protected void pushResponse(Object response) { + if (responseList == null) + responseList = new LinkedList(); + responseList.add(response); + } + + protected List responses() { + return responseList; + } + + protected Object nextResponse() { + if (complete || failed) return null; + if (responseList.size() > 0) + return responseList.remove(0); + return null; + } + + public Exception getFailure() { + return failure; + } + + public abstract HttpRequest send(); + + public abstract Object recv(); + + public boolean failed(){ + return failed; + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequestHandler.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequestHandler.java new file mode 100644 index 0000000000..9c0f9e5043 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/http/HttpRequestHandler.java @@ -0,0 +1,25 @@ +package org.opensrf.net.http; + +import java.util.List; + +/* + * Handler for async gateway responses. + */ +public abstract class HttpRequestHandler { + + /** + * Called when all responses have been received. + * + * If discardResponses() returns true, will be passed null. + */ + public void onComplete(HttpRequest request) { + } + + /** + * Called with each response received from the server. + * + * @param payload the value returned from the server. + */ + public void onResponse(HttpRequest request, Object response) { + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPException.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPException.java new file mode 100644 index 0000000000..8c20ab7aee --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPException.java @@ -0,0 +1,10 @@ +package org.opensrf.net.xmpp; + +/** + * Used for XMPP stream/authentication errors + */ +public class XMPPException extends Exception { + public XMPPException(String info) { + super(info); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPMessage.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPMessage.java new file mode 100644 index 0000000000..b6e2c76346 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPMessage.java @@ -0,0 +1,101 @@ +package org.opensrf.net.xmpp; + +import java.io.*; + +/** + * Models a single XMPP message. + */ +public class XMPPMessage { + + /** Message body */ + private String body; + /** Message recipient */ + private String to; + /** Message sender */ + private String from; + /** Message thread */ + private String thread; + /** Message xid */ + private String xid; + + public XMPPMessage() { + } + + public String getBody() { + return body; + } + public String getTo() { + return to; + } + public String getFrom() { + return from; + } + public String getThread() { + return thread; + } + public String getXid() { + return xid; + } + public void setBody(String body) { + this.body = body; + } + public void setTo(String to) { + this.to = to; + } + public void setFrom(String from) { + this.from = from; + } + public void setThread(String thread) { + this.thread = thread; + } + public void setXid(String xid) { + this.xid = xid; + } + + + /** + * Generates the XML representation of this message. + */ + public String toXML() { + StringBuffer sb = new StringBuffer(""); + escapeXML(thread, sb); + sb.append(""); + escapeXML(body, sb); + sb.append(""); + return sb.toString(); + } + + + /** + * Escapes non-valid XML characters. + * @param s The string to escape. + * @param sb The StringBuffer to append new data to. + */ + private void escapeXML(String s, StringBuffer sb) { + if( s == null ) return; + char c; + int l = s.length(); + for( int i = 0; i < l; i++ ) { + c = s.charAt(i); + switch(c) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + default: + sb.append(c); + } + } + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPReader.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPReader.java new file mode 100644 index 0000000000..406298a730 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPReader.java @@ -0,0 +1,293 @@ +package org.opensrf.net.xmpp; + +import javax.xml.stream.*; +import javax.xml.stream.events.* ; +import javax.xml.namespace.QName; +import java.util.Queue; +import java.io.InputStream; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Date; +import org.opensrf.util.Logger; + +/** + * Slim XMPP Stream reader. This reader only understands enough XMPP + * to handle logins and recv messages. It's implemented as a StAX parser. + * @author Bill Erickson, Georgia Public Library Systems + */ +public class XMPPReader implements Runnable { + + /** Queue of received messages. */ + private Queue msgQueue; + /** Incoming XMPP XML stream */ + private InputStream inStream; + /** Current message body */ + private StringBuffer msgBody; + /** Current message thread */ + private StringBuffer msgThread; + /** Current message status */ + private StringBuffer msgStatus; + /** Current message error type */ + private StringBuffer msgErrType; + /** Current message sender */ + private String msgFrom; + /** Current message recipient */ + private String msgTo; + /** Current message error code */ + private int msgErrCode; + + /** Where this reader currently is in the document */ + private XMLState xmlState; + + /** The current connect state to the XMPP server */ + private XMPPStreamState streamState; + + + /** Used to represent out connection state to the XMPP server */ + public static enum XMPPStreamState { + DISCONNECTED, /* not connected to the server */ + CONNECT_SENT, /* we've sent the initial connect message */ + CONNECT_RECV, /* we've received a response to our connect message */ + AUTH_SENT, /* we've sent an authentication request */ + CONNECTED /* authentication is complete */ + }; + + + /** Used to represents where we are in the XML document stream. */ + public static enum XMLState { + IN_NOTHING, + IN_BODY, + IN_THREAD, + IN_STATUS + }; + + + /** + * Creates a new reader. Initializes the message queue. + * Sets the stream state to disconnected, and the xml + * state to in_nothing. + * @param inStream the inbound XML stream + */ + public XMPPReader(InputStream inStream) { + msgQueue = new ConcurrentLinkedQueue(); + this.inStream = inStream; + resetBuffers(); + xmlState = XMLState.IN_NOTHING; + streamState = XMPPStreamState.DISCONNECTED; + } + + /** + * Change the connect state and notify that a core + * event has occurred. + */ + protected void setXMPPStreamState(XMPPStreamState state) { + streamState = state; + notifyCoreEvent(); + } + + /** + * @return The current stream state of the reader + */ + public XMPPStreamState getXMPPStreamState() { + return streamState; + } + + + /** + * @return The next message in the queue, or null + */ + public XMPPMessage popMessageQueue() { + return (XMPPMessage) msgQueue.poll(); + } + + + /** + * Initializes the message buffers + */ + private void resetBuffers() { + msgBody = new StringBuffer(); + msgThread = new StringBuffer(); + msgStatus = new StringBuffer(); + msgErrType = new StringBuffer(); + msgFrom = ""; + msgTo = ""; + } + + + /** + * Notifies the waiting thread that a core event has occurred. + * Each reader should have exactly one dependent session thread. + */ + private synchronized void notifyCoreEvent() { + notifyAll(); + } + + + /** + * Waits up to timeout milliseconds for a core event to occur. + * Also, having a message already waiting in the queue + * constitutes a core event. + * @param timeout The number of milliseconds to wait. If + * timeout is negative, waits potentially forever. + * @return The number of milliseconds in wait + */ + public synchronized long waitCoreEvent(long timeout) { + + if(msgQueue.peek() != null || timeout == 0) return 0; + long start = new Date().getTime(); + + try{ + if(timeout < 0) + wait(); + else + wait(timeout); + } catch(InterruptedException ie) {} + + return new Date().getTime() - start; + } + + + + /** Kickoff the thread */ + public void run() { + read(); + } + + + /** + * Parses XML data from the provided XMPP stream. + */ + public void read() { + + try { + + XMLInputFactory factory = XMLInputFactory.newInstance(); + + /** disable as many unused features as possible to speed up the parsing */ + factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE); + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); + factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); + factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); + + /** create the stream reader */ + XMLStreamReader reader = factory.createXMLStreamReader(inStream); + int eventType; + + while(reader.hasNext()) { + /** cycle through the XML events */ + + eventType = reader.next(); + + switch(eventType) { + + case XMLEvent.START_ELEMENT: + handleStartElement(reader); + break; + + case XMLEvent.CHARACTERS: + switch(xmlState) { + case IN_BODY: + msgBody.append(reader.getText()); + break; + case IN_THREAD: + msgThread.append(reader.getText()); + break; + case IN_STATUS: + msgStatus.append(reader.getText()); + break; + } + break; + + case XMLEvent.END_ELEMENT: + xmlState = XMLState.IN_NOTHING; + if("message".equals(reader.getName().toString())) { + + /** build a message and add it to the message queue */ + XMPPMessage msg = new XMPPMessage(); + msg.setFrom(msgFrom); + msg.setTo(msgTo); + msg.setBody(msgBody.toString()); + msg.setThread(msgThread.toString()); + + Logger.internal("xmpp message from="+msgFrom+" " + msg.getBody()); + + msgQueue.offer(msg); + resetBuffers(); + notifyCoreEvent(); + } + break; + } + } + + } catch(javax.xml.stream.XMLStreamException se) { + /* XXX log an error */ + xmlState = XMLState.IN_NOTHING; + streamState = XMPPStreamState.DISCONNECTED; + notifyCoreEvent(); + } + } + + + /** + * Handles the start_element event. + */ + private void handleStartElement(XMLStreamReader reader) { + + String name = reader.getName().toString(); + + if("message".equals(name)) { + xmlState = XMLState.IN_BODY; + + /** add a special case for the opensrf "router_from" attribute */ + String rf = reader.getAttributeValue(null, "router_from"); + if( rf != null ) + msgFrom = rf; + else + msgFrom = reader.getAttributeValue(null, "from"); + msgTo = reader.getAttributeValue(null, "to"); + return; + } + + if("body".equals(name)) { + xmlState = XMLState.IN_BODY; + return; + } + + if("thread".equals(name)) { + xmlState = XMLState.IN_THREAD; + return; + } + + if("stream:stream".equals(name)) { + setXMPPStreamState(XMPPStreamState.CONNECT_RECV); + return; + } + + if("iq".equals(name)) { + if("result".equals(reader.getAttributeValue(null, "type"))) + setXMPPStreamState(XMPPStreamState.CONNECTED); + return; + } + + if("status".equals(name)) { + xmlState = XMLState.IN_STATUS; + return; + } + + if("stream:error".equals(name)) { + setXMPPStreamState(XMPPStreamState.DISCONNECTED); + return; + } + + if("error".equals(name)) { + msgErrType.append(reader.getAttributeValue(null, "type")); + msgErrCode = Integer.parseInt(reader.getAttributeValue(null, "code")); + setXMPPStreamState(XMPPStreamState.DISCONNECTED); + return; + } + } +} + + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPSession.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPSession.java new file mode 100644 index 0000000000..f9be7d2a63 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/net/xmpp/XMPPSession.java @@ -0,0 +1,263 @@ +package org.opensrf.net.xmpp; + +import java.io.*; +import java.net.Socket; +import java.util.Map; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Represents a single XMPP session. Sessions are responsible for writing to + * the stream and for managing a stream reader. + */ +public class XMPPSession { + + /** Initial jabber message */ + public static final String JABBER_CONNECT = + ""; + + /** Basic auth message */ + public static final String JABBER_BASIC_AUTH = + "" + + "%s%s%s"; + + public static final String JABBER_DISCONNECT = ""; + + private static Map threadConnections = new ConcurrentHashMap(); + + /** jabber domain */ + private String host; + /** jabber port */ + private int port; + /** jabber username */ + private String username; + /** jabber password */ + private String password; + /** jabber resource */ + private String resource; + + /** XMPP stream reader */ + XMPPReader reader; + /** Fprint-capable socket writer */ + PrintWriter writer; + /** Raw socket output stream */ + OutputStream outStream; + /** The raw socket */ + Socket socket; + + /** The process-wide session. All communication occurs + * accross this single connection */ + private static XMPPSession globalSession; + + + /** + * Creates a new session. + * @param host The jabber domain + * @param port The jabber port + */ + public XMPPSession( String host, int port ) { + this.host = host; + this.port = port; + } + + /** + * Returns the global, process-wide session + */ + /* + public static XMPPSession getGlobalSession() { + return globalSession; + } + */ + + public static XMPPSession getThreadSession() { + return (XMPPSession) threadConnections.get(new Long(Thread.currentThread().getId())); + } + + /** + * Sets the given session as the global session for the current thread + * @param ses The session + */ + public static void setThreadSession(XMPPSession ses) { + /* every time we create a new connection, clean up any dead threads. + * this is cheaper than cleaning up the dead threads at every access. */ + cleanupThreadSessions(); + threadConnections.put(new Long(Thread.currentThread().getId()), ses); + } + + /** + * Analyzes the threadSession data to see if there are any sessions + * whose controlling thread has gone away. + */ + private static void cleanupThreadSessions() { + Thread threads[] = new Thread[Thread.activeCount()]; + Thread.enumerate(threads); + for(Iterator i = threadConnections.keySet().iterator(); i.hasNext(); ) { + boolean found = false; + Long id = (Long) i.next(); + for(Thread t : threads) { + if(t.getId() == id.longValue()) { + found = true; + break; + } + } + if(!found) + threadConnections.remove(id); + } + } + + /** + * Sets the global, process-wide section + */ + /* + 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 && + !socket.isClosed() + ); + } + + + /** + * Connects to the network. + * @param username The jabber username + * @param password The jabber password + * @param resource The Jabber resource + */ + public void connect(String username, String password, String resource) throws XMPPException { + + this.username = username; + this.password = password; + this.resource = resource; + + try { + /* open the socket and associated streams */ + socket = new Socket(host, port); + + /** the session maintains control over the output stream */ + outStream = socket.getOutputStream(); + writer = new PrintWriter(outStream, true); + + /** pass the input stream to the reader */ + reader = new XMPPReader(socket.getInputStream()); + + } catch(IOException ioe) { + throw new + XMPPException("unable to communicate with host " + host + " on port " + port); + } + + /* build the reader thread */ + Thread thread = new Thread(reader); + thread.setDaemon(true); + thread.start(); + + synchronized(reader) { + /* send the initial jabber message */ + sendConnect(); + reader.waitCoreEvent(10000); + } + if( reader.getXMPPStreamState() != XMPPReader.XMPPStreamState.CONNECT_RECV ) + throw new XMPPException("unable to connect to jabber server"); + + synchronized(reader) { + /* send the basic auth message */ + sendBasicAuth(); + reader.waitCoreEvent(10000); + } + if(!connected()) + throw new XMPPException("Authentication failed"); + } + + /** Sends the initial jabber message */ + private void sendConnect() { + reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT); + writer.printf(JABBER_CONNECT, host); + } + + /** Send the basic auth message */ + private void sendBasicAuth() { + reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT); + writer.printf(JABBER_BASIC_AUTH, username, password, resource); + } + + + /** + * Sends an XMPPMessage. + * @param msg The message to send. + */ + public synchronized void send(XMPPMessage msg) throws XMPPException { + checkConnected(); + try { + String xml = msg.toXML(); + outStream.write(xml.getBytes()); + } catch (Exception e) { + throw new XMPPException(e.toString()); + } + } + + + /** + * @throws XMPPException if we are no longer connected. + */ + private void checkConnected() throws XMPPException { + if(!connected()) + throw new XMPPException("Disconnected stream"); + } + + + /** + * Receives messages from the network. + * @param timeout Maximum number of milliseconds to wait for a message to arrive. + * If timeout is negative, this method will wait indefinitely. + * 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(long timeout) throws XMPPException { + + XMPPMessage msg; + + if(timeout < 0) { + + while(true) { /* wait indefinitely for a message to arrive */ + reader.waitCoreEvent(timeout); + msg = reader.popMessageQueue(); + if( msg != null ) return msg; + checkConnected(); + } + + } else { + + while(timeout >= 0) { /* wait at most 'timeout' milleseconds for a message to arrive */ + msg = reader.popMessageQueue(); + if( msg != null ) return msg; + timeout -= reader.waitCoreEvent(timeout); + msg = reader.popMessageQueue(); + if( msg != null ) return msg; + checkConnected(); + if(timeout == 0) break; + } + } + + return reader.popMessageQueue(); + } + + + /** + * Disconnects from the jabber server and closes the socket + */ + public void disconnect() { + try { + outStream.write(JABBER_DISCONNECT.getBytes()); + socket.close(); + } catch(Exception e) {} + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/MathBench.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/MathBench.java new file mode 100644 index 0000000000..b6e67f953c --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/MathBench.java @@ -0,0 +1,79 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; +import java.util.Date; +import java.util.List; +import java.util.ArrayList; +import java.io.PrintStream; + + +public class MathBench { + + public static void main(String args[]) throws Exception { + + PrintStream out = System.out; + + if(args.length < 2) { + out.println("usage: java org.opensrf.test.MathBench "); + return; + } + + /** connect to the opensrf network */ + Sys.bootstrapClient(args[0], "/config/opensrf"); + + /** how many iterations */ + int count = Integer.parseInt(args[1]); + + /** create the client session */ + ClientSession session = new ClientSession("opensrf.math"); + + /** params are 1,2 */ + List params = new ArrayList(); + params.add(new Integer(1)); + params.add(new Integer(2)); + + Request request; + Result result; + long start; + double total = 0; + + for(int i = 0; i < count; i++) { + + start = new Date().getTime(); + + /** create (and send) the request */ + request = session.request("add", params); + + /** wait up to 3 seconds for a response */ + result = request.recv(3000); + + /** collect the round-trip time */ + total += new Date().getTime() - start; + + if(result.getStatusCode() == Status.OK) { + out.print("+"); + } else { + out.println("\nrequest failed"); + out.println("status = " + result.getStatus()); + out.println("status code = " + result.getStatusCode()); + } + + /** remove this request from the session's request set */ + request.cleanup(); + + if((i+1) % 100 == 0) /** print 100 responses per line */ + out.println(" [" + (i+1) + "]"); + } + + out.println("\nAverage request time is " + (total/count) + " ms"); + + /** remove this session from the global session cache */ + session.cleanup(); + + /** disconnect from the opensrf network */ + Sys.shutdown(); + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestCache.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestCache.java new file mode 100644 index 0000000000..d555444ccf --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestCache.java @@ -0,0 +1,24 @@ +package org.opensrf.test; +import org.opensrf.util.Cache; + +public class TestCache { + public static void main(String args[]) throws Exception { + + /** + * args is a list of string like so: server:port server2:port server3:port ... + */ + + Cache.initCache(args); + Cache cache = new Cache(); + + cache.set("key1", "HI, MA!"); + cache.set("key2", "HI, MA! 2"); + cache.set("key3", "HI, MA! 3"); + + System.out.println("got key1 = " + (String) cache.get("key1")); + System.out.println("got key2 = " + (String) cache.get("key2")); + System.out.println("got key3 = " + (String) cache.get("key3")); + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestClient.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestClient.java new file mode 100644 index 0000000000..a1136cd719 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestClient.java @@ -0,0 +1,80 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; +import java.util.Map; +import java.util.Date; +import java.util.List; +import java.util.ArrayList; +import java.io.PrintStream; + +public class TestClient { + + public static void main(String args[]) throws Exception { + + /** which opensrf service are we sending our request to */ + String service; + /** which opensrf method we're calling */ + String method; + /** method params, captures from command-line args */ + List params; + /** knows how to read JSON */ + JSONReader reader; + /** opensrf request */ + Request request; + /** request result */ + Result result; + /** start time for the request */ + long start; + /** for brevity */ + PrintStream out = System.out; + + if(args.length < 3) { + out.println( "usage: org.opensrf.test.TestClient "+ + " [, ]"); + return; + } + + /** connect to the opensrf network, default config context + * for opensrf_core.xml is /config/opensrf */ + Sys.bootstrapClient(args[0], "/config/opensrf"); + + /* grab the server, method, and any params from the command line */ + service = args[1]; + method = args[2]; + params = new ArrayList(); + for(int i = 3; i < args.length; i++) + params.add(new JSONReader(args[i]).read()); + + + /** build the client session */ + ClientSession session = new ClientSession(service); + + /** kick off the timer */ + start = new Date().getTime(); + + /** Create the request object from the session, method and params */ + request = session.request(method, params); + + while( (result = request.recv(60000)) != null ) { + /** loop over the results and print the JSON version of the content */ + + if(result.getStatusCode() != 200) { + /** make sure the request succeeded */ + out.println("status = " + result.getStatus()); + out.println("status code = " + result.getStatusCode()); + continue; + } + + /** JSON-ify the resulting object and print it */ + out.println("\nresult JSON: " + new JSONWriter(result.getContent()).write()); + } + + /** How long did the request take? */ + out.println("Request round trip took: " + (new Date().getTime() - start) + " ms."); + + Sys.shutdown(); + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestConfig.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestConfig.java new file mode 100644 index 0000000000..f65a84f701 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestConfig.java @@ -0,0 +1,16 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; + +public class TestConfig { + public static void main(String args[]) throws Exception { + Config config = new Config(""); + config.parse(args[0]); + Config.setConfig(config); + System.out.println(config); + System.out.println(""); + + for(int i = 1; i < args.length; i++) + System.out.println("Found config value: " + args[i] + ": " + Config.global().get(args[i])); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestJSON.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestJSON.java new file mode 100644 index 0000000000..b19d4088aa --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestJSON.java @@ -0,0 +1,51 @@ +package org.opensrf.test; + +import org.opensrf.*; +import org.opensrf.util.*; +import java.util.*; + +public class TestJSON { + + public static void main(String args[]) throws Exception { + + Map map = new HashMap(); + map.put("key1", "value1"); + map.put("key2", "value2"); + map.put("key3", "value3"); + map.put("key4", "athe\u0301s"); + map.put("key5", null); + + List list = new ArrayList(16); + list.add(new Integer(1)); + list.add(new Boolean(true)); + list.add("WATER"); + list.add(null); + map.put("key6", list); + + System.out.println(new JSONWriter(map).write() + "\n"); + + String[] fields = {"isnew", "name", "shortname", "ill_address"}; + OSRFRegistry.registerObject("aou", OSRFRegistry.WireProtocol.ARRAY, fields); + + OSRFObject obj = new OSRFObject(OSRFRegistry.getRegistry("aou")); + obj.put("name", "athens clarke county"); + obj.put("ill_address", new Integer(1)); + obj.put("shortname", "ARL-ATH"); + + map.put("key7", obj); + list.add(obj); + System.out.println(new JSONWriter(map).write() + "\n"); + + + Message m = new Message(1, Message.REQUEST); + Method method = new Method("opensrf.settings.host_config.get"); + method.addParam("app07.dev.gapines.org"); + m.setPayload(method); + + 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()); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestLog.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestLog.java new file mode 100644 index 0000000000..1d60242969 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestLog.java @@ -0,0 +1,15 @@ +package org.opensrf.test; +import org.opensrf.util.Logger; +import org.opensrf.util.FileLogger; + + +/** Simple test class for tesing the logging functionality */ +public class TestLog { + public static void main(String args[]) { + Logger.init(Logger.DEBUG, new FileLogger("test.log")); + Logger.error("Hello, world"); + Logger.warn("Hello, world"); + Logger.info("Hello, world"); + Logger.debug("Hello, world"); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestMultiSession.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestMultiSession.java new file mode 100644 index 0000000000..bb0f1a1c09 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestMultiSession.java @@ -0,0 +1,26 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; + +public class TestMultiSession { + public static void main(String[] args) { + try { + String config = args[0]; + + Sys.bootstrapClient(config, "/config/opensrf"); + MultiSession ses = new MultiSession(); + + for(int i = 0; i < 40; i++) { + ses.request("opensrf.settings", "opensrf.system.time"); + } + + while(!ses.isComplete()) + System.out.println("result = " + ses.recv(5000) + " and id = " + ses.lastId()); + + System.out.println("done"); + Sys.shutdown(); + } catch(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestSettings.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestSettings.java new file mode 100644 index 0000000000..116bbe1683 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestSettings.java @@ -0,0 +1,14 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; + +public class TestSettings { + public static void main(String args[]) throws Exception { + Sys.bootstrapClient(args[0], "/config/opensrf"); + SettingsClient client = SettingsClient.instance(); + String lang = client.getString("/apps/opensrf.settings/language"); + String impl = client.getString("/apps/opensrf.settings/implementation"); + System.out.println("opensrf.settings language = " + lang); + System.out.println("opensrf.settings implementation = " + impl); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestThread.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestThread.java new file mode 100644 index 0000000000..bb4cf067e9 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestThread.java @@ -0,0 +1,68 @@ +package org.opensrf.test; +import org.opensrf.*; +import org.opensrf.util.*; +import java.util.Map; +import java.util.Date; +import java.util.List; +import java.util.ArrayList; +import java.io.PrintStream; + +/** + * Connects to the opensrf network once per thread and runs + * and runs a series of request acccross all launched threads. + * The purpose is to verify that the java threaded client api + * is functioning as expected + */ +public class TestThread implements Runnable { + + String args[]; + + public TestThread(String args[]) { + this.args = args; + } + + public void run() { + + try { + + Sys.bootstrapClient(args[0], "/config/opensrf"); + ClientSession session = new ClientSession(args[3]); + + List params = new ArrayList(); + for(int i = 5; i < args.length; i++) + params.add(new JSONReader(args[3]).read()); + + for(int i = 0; i < Integer.parseInt(args[2]); i++) { + System.out.println("thread " + Thread.currentThread().getId()+" sending request " + i); + Request request = session.request(args[4], params); + Result result = request.recv(3000); + if(result != null) { + System.out.println("thread " + Thread.currentThread().getId()+ + " got result JSON: " + new JSONWriter(result.getContent()).write()); + } else { + System.out.println("* thread " + Thread.currentThread().getId()+ " got NO result"); + } + } + + Sys.shutdown(); + } catch(Exception e) { + System.err.println(e); + } + } + + public static void main(String args[]) throws Exception { + + if(args.length < 5) { + System.out.println( "usage: org.opensrf.test.TestClient "+ + " [, ]"); + return; + } + + int numThreads = Integer.parseInt(args[1]); + for(int i = 0; i < numThreads; i++) + new Thread(new TestThread(args)).start(); + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLFlattener.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLFlattener.java new file mode 100644 index 0000000000..c1fa394fef --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLFlattener.java @@ -0,0 +1,11 @@ +package org.opensrf.test; +import org.opensrf.util.XMLFlattener; +import java.io.FileInputStream; + +public class TestXMLFlattener { + public static void main(String args[]) throws Exception { + FileInputStream fis = new FileInputStream(args[0]); + XMLFlattener f = new XMLFlattener(fis); + System.out.println(f.read()); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLTransformer.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLTransformer.java new file mode 100644 index 0000000000..9768372f11 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMLTransformer.java @@ -0,0 +1,22 @@ +package org.opensrf.test; +import org.opensrf.util.XMLTransformer; +import java.io.File; + +public class TestXMLTransformer { + /** + * arg[0] path to an XML file + * arg[1] path to the XSL file to apply + */ + public static void main(String[] args) { + try { + File xmlFile = new File(args[0]); + File xslFile = new File(args[1]); + XMLTransformer t = new XMLTransformer(xmlFile, xslFile); + System.out.println(t.apply()); + } catch(Exception e) { + e.printStackTrace(); + } + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMPP.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMPP.java new file mode 100644 index 0000000000..2fba67fb8b --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/test/TestXMPP.java @@ -0,0 +1,63 @@ +package org.opensrf.test; + +import org.opensrf.net.xmpp.XMPPReader; +import org.opensrf.net.xmpp.XMPPMessage; +import org.opensrf.net.xmpp.XMPPSession; + +public class TestXMPP { + + /** + * Connects to the jabber server and waits for inbound messages. + * If a recipient is provided, a small message is sent to the recipient. + */ + public static void main(String args[]) throws Exception { + + String host; + int port; + String username; + String password; + String resource; + String recipient; + + try { + host = args[0]; + port = Integer.parseInt(args[1]); + username = args[2]; + password = args[3]; + resource = args[4]; + + } catch(ArrayIndexOutOfBoundsException e) { + System.err.println("usage: org.opensrf.test.TestXMPP []"); + return; + } + + XMPPSession session = new XMPPSession(host, port); + session.connect(username, password, resource); + + XMPPMessage msg; + + if( args.length == 6 ) { + + /** they specified a recipient */ + + recipient = args[5]; + msg = new XMPPMessage(); + msg.setTo(recipient); + msg.setThread("test-thread"); + msg.setBody("Hello, from java-xmpp"); + System.out.println("Sending message to " + recipient); + session.send(msg); + } + + while(true) { + System.out.println("waiting for message..."); + msg = session.recv(-1); /* wait forever for a message to arrive */ + System.out.println("got message: " + msg.toXML()); + } + } +} + + + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Cache.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Cache.java new file mode 100644 index 0000000000..53036886cc --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Cache.java @@ -0,0 +1,38 @@ +package org.opensrf.util; +import com.danga.MemCached.*; +import java.util.List; + +/** + * Memcache client + */ +public class Cache extends MemCachedClient { + + public Cache() { + super(); + setCompressThreshold(4096); /* ?? */ + } + + /** + * Initializes the cache client + * @param serverList Array of server:port strings specifying the + * set of memcache servers this client will talk to + */ + public static void initCache(String[] serverList) { + SockIOPool pool = SockIOPool.getInstance(); + pool.setServers(serverList); + pool.initialize(); + com.danga.MemCached.Logger logger = + com.danga.MemCached.Logger.getLogger(MemCachedClient.class.getName()); + logger.setLevel(logger.LEVEL_ERROR); + } + + /** + * Initializes the cache client + * @param serverList List of server:port strings specifying the + * set of memcache servers this client will talk to + */ + public static void initCache(List serverList) { + initCache(serverList.toArray(new String[]{})); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Config.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Config.java new file mode 100644 index 0000000000..ddac9c0b71 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Config.java @@ -0,0 +1,139 @@ +package org.opensrf.util; + +import org.json.*; +import java.util.Map; +import java.util.List; + + +/** + * Config reader and accesor module. This module reads an XML config file, + * then loads the file into an internal config, whose values may be accessed + * by xpath-style lookup paths. + */ +public class Config { + + /** The globl config instance */ + private static Config config; + /** The object form of the parsed config */ + private Map configObject; + /** + * The log parsing context. This is used as a prefix to the + * config item search path. This allows config XML chunks to + * be inserted into arbitrary XML files. + */ + private String context; + + public static Config global() { + return config; + } + + + /** + * @param context The config context + */ + public Config(String context) { + this.context = context; + } + + /** + * Sets the global config object. + * @param c The config object to use. + */ + public static void setGlobalConfig(Config c) { + config = c; + } + + /** + * Parses an XML config file. + * @param filename The path to the file to parse. + */ + public void parse(String filename) throws ConfigException { + try { + String xml = Utils.fileToString(filename); + JSONObject jobj = XML.toJSONObject(xml); + configObject = (Map) new JSONReader(jobj.toString()).readObject(); + } catch(Exception e) { + throw new ConfigException("Error parsing config", e); + } + } + + public static void setConfig(Config conf) { + config = conf; + } + + public void setConfigObject(Map config) { + this.configObject = config; + } + + protected Map getConfigObject() { + return this.configObject; + } + + + /** + * Returns the configuration value found at the requested path. + * @param path The search path + * @return The config value, or null if no value exists at the given path. + * @throws ConfigException thrown if nothing is found at the path + */ + public String getString(String path) throws ConfigException { + try { + return (String) get(path); + } catch(Exception e) { + throw new + ConfigException("No config string found at " + path); + } + } + + /** + * Gets the int value at the given path + * @param path The search path + */ + public int getInt(String path) throws ConfigException { + try { + return Integer.parseInt(getString(path)); + } catch(Exception e) { + throw new + ConfigException("No config int found at " + path); + } + } + + /** + * Returns the configuration object found at the requested path. + * @param path The search path + * @return The config value + * @throws ConfigException thrown if nothing is found at the path + */ + public Object get(String path) throws ConfigException { + try { + Object obj = Utils.findPath(configObject, context + path); + if(obj == null) + throw new ConfigException(""); + return obj; + } catch(Exception e) { + e.printStackTrace(); + throw new ConfigException("No config object found at " + path); + } + } + + /** + * Returns the first item in the list found at the given path. If + * no list is found, ConfigException is thrown. + * @param path The search path + */ + public Object getFirst(String path) throws ConfigException { + Object obj = get(path); + if(obj instanceof List) + return ((List) obj).get(0); + return obj; + } + + + /** + * Returns the config as a JSON string + */ + public String toString() { + return new JSONWriter(configObject).write(); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/ConfigException.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/ConfigException.java new file mode 100644 index 0000000000..c1c491ec8d --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/ConfigException.java @@ -0,0 +1,14 @@ +package org.opensrf.util; + +/** + * Thrown by the Config module when a user requests a configuration + * item that does not exist + */ +public class ConfigException extends Exception { + public ConfigException(String info) { + super(info); + } + public ConfigException(String info, Throwable t) { + super(info, t); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/FileLogger.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/FileLogger.java new file mode 100644 index 0000000000..9eb838df0c --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/FileLogger.java @@ -0,0 +1,44 @@ +package org.opensrf.util; +import java.io.BufferedWriter; +import java.io.FileWriter; + + +public class FileLogger extends Logger { + + /** File to log to */ + private String filename; + + /** + * FileLogger constructor + * @param filename The path to the log file + */ + public FileLogger(String filename) { + this.filename = filename; + } + + /** + * Logs the mesage to a file. + * @param level The log level + * @param msg The mesage to log + */ + protected synchronized void log(short level, String msg) { + if(level > logLevel) return; + + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(this.filename, true)); + out.write(formatMessage(level, msg) + "\n"); + + } catch(Exception e) { + /** If we are unable to write our log message, go ahead and + * fall back to the default (stdout) logger */ + Logger.init(logLevel, new Logger()); + Logger.logByLevel(ERROR, "Unable to write to log file " + this.filename); + Logger.logByLevel(level, msg); + } + + try { + out.close(); + } catch(Exception e) {} + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONException.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONException.java new file mode 100644 index 0000000000..ec28e1d86d --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONException.java @@ -0,0 +1,9 @@ +package org.opensrf.util; +/** + * Used to indicate JSON parsing errors + */ +public class JSONException extends Exception { + public JSONException(String s) { + super(s); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONReader.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONReader.java new file mode 100644 index 0000000000..55eb5c03b4 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONReader.java @@ -0,0 +1,176 @@ +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"; + + /** The JSON string to parser */ + private String json; + + /** + * @param json The JSON to parse + */ + public JSONReader(String json) { + this.json = json; + } + + /** + * Parses JSON and creates an object. + * @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()); + } + } + + /** + * Assumes that a JSON array will be read. Returns + * the resulting array as a list. + */ + public List readArray() throws JSONException { + Object o = read(); + try { + return (List) o; + } catch(Exception e) { + throw new JSONException("readArray(): JSON cast exception"); + } + } + + /** + * Assumes that a JSON object will be read. Returns + * the resulting object as a map. + */ + public Map readObject() throws JSONException { + Object o = read(); + try { + return (Map) o; + } catch(Exception e) { + throw new JSONException("readObject(): JSON cast exception"); + } + } + + + /** + * Recurse through the object and turn items into maps, lists, etc. + */ + 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 map = new HashMap(); + + 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 list = new ArrayList(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; + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONWriter.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONWriter.java new file mode 100644 index 0000000000..7cb2cca02d --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/JSONWriter.java @@ -0,0 +1,172 @@ +package org.opensrf.util; + +import java.io.*; +import java.util.*; + + +/** + * JSONWriter + */ +public class JSONWriter { + + /** The object to serialize to JSON */ + private Object obj; + + /** + * @param obj The object to encode + */ + public JSONWriter(Object obj) { + this.obj = obj; + } + + + /** + * Encodes a java object to JSON. + */ + 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); + } + + /** + * Encodes the object as JSON into the provided buffer + */ + 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 map = new HashMap(); + map.put(JSONReader.JSON_CLASS_KEY, reg.getNetClass()); + + if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) { + + /** encode arrays as lists */ + List list = new ArrayList(fields.length); + for(String s : fields) + list.add(obj.get(s)); + map.put(JSONReader.JSON_PAYLOAD_KEY, list); + + } else { + + /** encode hashes as maps */ + Map subMap = new HashMap(); + 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); + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Logger.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Logger.java new file mode 100644 index 0000000000..2923c23b9e --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Logger.java @@ -0,0 +1,144 @@ +package org.opensrf.util; +import java.text.SimpleDateFormat; +import java.text.FieldPosition; +import java.util.Date; + +/** + * Basic OpenSRF logging API. This default implementation + * logs to stderr. + */ +public class Logger { + + /** Log levels */ + public static final short ERROR = 1; + public static final short WARN = 2; + public static final short INFO = 3; + public static final short DEBUG = 4; + public static final short INTERNAL = 5; + + /** The global log instance */ + private static Logger instance; + /** The global log level */ + protected static short logLevel; + + public Logger() {} + + /** Sets the global Logger instance + * @param level The global log level. + * @param l The Logger instance to use + */ + public static void init(short level, Logger l) { + instance = l; + logLevel = level; + } + + /** + * @return The global Logger instance + */ + public static Logger instance() { + return instance; + } + + /** + * Logs an error message + * @param msg The message to log + */ + public static void error(String msg) { + instance.log(ERROR, msg); + } + + /** + * Logs an warning message + * @param msg The message to log + */ + public static void warn(String msg) { + instance.log(WARN, msg); + } + + /** + * Logs an info message + * @param msg The message to log + */ + public static void info(String msg) { + instance.log(INFO, msg); + } + + /** + * Logs an debug message + * @param msg The message to log + */ + public static void debug(String msg) { + instance.log(DEBUG, msg); + } + + /** + * Logs an internal message + * @param msg The message to log + */ + public static void internal(String msg) { + instance.log(INTERNAL, msg); + } + + + /** + * Appends the text representation of the log level + * @param sb The stringbuffer to append to + * @param level The log level + */ + protected static void appendLevelString(StringBuffer sb, short level) { + switch(level) { + case DEBUG: + sb.append("DEBG"); break; + case INFO: + sb.append("INFO"); break; + case INTERNAL: + sb.append("INT "); break; + case WARN: + sb.append("WARN"); break; + case ERROR: + sb.append("ERR "); break; + } + } + + /** + * Formats a message for logging. Appends the current date+time + * and the log level string. + * @param level The log level + * @param msg The message to log + */ + protected static String formatMessage(short level, String msg) { + + StringBuffer sb = new StringBuffer(); + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format( + new Date(), sb, new FieldPosition(0)); + + sb.append(" ["); + appendLevelString(sb, level); + sb.append(":"); + sb.append(Thread.currentThread().getId()); + sb.append("] "); + sb.append(msg); + return sb.toString(); + } + + /** + * Logs a message by passing the log level explicitly + * @param level The log level + * @param msg The message to log + */ + public static void logByLevel(short level, String msg) { + instance.log(level, msg); + } + + /** + * Performs the actual logging. Subclasses should override + * this method. + * @param level The log level + * @param msg The message to log + */ + protected synchronized void log(short level, String msg) { + if(level > logLevel) return; + System.err.println(formatMessage(level, msg)); + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFObject.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFObject.java new file mode 100644 index 0000000000..af28f4a860 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFObject.java @@ -0,0 +1,63 @@ +package org.opensrf.util; + +import java.util.Map; +import java.util.HashMap; + + +/** + * Generic OpenSRF network-serializable object. This allows + * access to object fields. + */ +public class OSRFObject extends HashMap implements OSRFSerializable { + + /** This objects registry */ + private OSRFRegistry registry; + + public OSRFObject() { + } + + + /** + * Creates a new object with the provided registry + */ + public OSRFObject(OSRFRegistry reg) { + this(); + registry = reg; + } + + + /** + * Creates a new OpenSRF object based on the net class string + * */ + public OSRFObject(String netClass) { + this(OSRFRegistry.getRegistry(netClass)); + } + + + /** + * @return This object's registry + */ + public OSRFRegistry getRegistry() { + return registry; + } + + /** + * Implement get() to fulfill our contract with OSRFSerializable + */ + public Object get(String field) { + return super.get(field); + } + + /** Returns the string value found at the given field */ + public String getString(String field) { + return (String) get(field); + } + + /** Returns the int value found at the given field */ + public int getInt(String field) { + Object o = get(field); + if(o instanceof String) + return Integer.parseInt((String) o); + return ((Integer) get(field)).intValue(); + } +} diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFRegistry.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFRegistry.java new file mode 100644 index 0000000000..c6e6bc6540 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFRegistry.java @@ -0,0 +1,112 @@ +package org.opensrf.util; + +import java.io.Serializable; +import java.util.Map; +import java.util.HashMap; + + +/** + * Manages the registration of OpenSRF network-serializable objects. + * A serializable object has a class "hint" (called netClass within) which + * describes the type of object. Each object also has a set of field names + * for accessing/mutating object properties. Finally, objects have a + * serialization wire protocol. Currently supported protocols are HASH + * and ARRAY. + */ +public class OSRFRegistry implements Serializable{ + + + /** + * + */ + private static final long serialVersionUID = 1L; + /** + * Global collection of registered net objects. + * Maps netClass names to registries. + */ + private static HashMap + registry = new HashMap(); + + + /** Serialization types for registered objects */ + public enum WireProtocol { + ARRAY, HASH + }; + + + /** Array of field names for this registered object */ + String fields[]; + /** The wire protocol for this object */ + WireProtocol wireProtocol; + /** The network class for this object */ + String netClass; + + /** + * Returns the array of field names + */ + public String[] getFields() { + return this.fields; + } + + + /** + * Registers a new object. + * @param netClass The net class for this object + * @param wireProtocol The object's wire protocol + * @param fields An array of field names. For objects whose + * wire protocol is ARRAY, the positions of the field names + * will be used as the array indices for the fields at serialization time + */ + public static OSRFRegistry registerObject(String netClass, WireProtocol wireProtocol, String fields[]) { + OSRFRegistry r = new OSRFRegistry(netClass, wireProtocol, fields); + registry.put(netClass, r); + return r; + } + + /** + * Returns the registry for the given netclass + * @param netClass The network class to lookup + */ + public static OSRFRegistry getRegistry(String netClass) { + if( netClass == null ) return null; + return (OSRFRegistry) registry.get(netClass); + } + + + /** + * @param field The name of the field to lookup + * @return the index into the fields array of the given field name. + */ + public int getFieldIndex(String field) { + for( int i = 0; i < fields.length; i++ ) + if( fields[i].equals(field) ) + return i; + return -1; + } + + /** Returns the wire protocol of this object */ + public WireProtocol getWireProtocol() { + return this.wireProtocol; + } + + /** Returns the netClass ("hint") of this object */ + public String getNetClass() { + return this.netClass; + } + + /** + * Creates a new registry object. + * @param netClass The network class/hint + * @param wireProtocol The wire protocol + * @param fields The array of field names. For array-based objects, + * the fields array must be sorted in accordance with the sorting + * of the objects in the array. + */ + public OSRFRegistry(String netClass, WireProtocol wireProtocol, String fields[]) { + this.netClass = netClass; + this.wireProtocol = wireProtocol; + this.fields = fields; + } +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFSerializable.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFSerializable.java new file mode 100644 index 0000000000..64b5d6f4e5 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/OSRFSerializable.java @@ -0,0 +1,19 @@ +package org.opensrf.util; + +/** + * All network-serializable OpenSRF object must implement this interface. + */ +public interface OSRFSerializable { + + /** + * Returns the object registry object for the implementing class. + */ + public abstract OSRFRegistry getRegistry(); + + /** + * Returns the object found at the given field + */ + public abstract Object get(String field); +} + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/SettingsClient.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/SettingsClient.java new file mode 100644 index 0000000000..71e570a410 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/SettingsClient.java @@ -0,0 +1,53 @@ +package org.opensrf.util; +import org.opensrf.*; +import java.util.Map; + +/** + * Connects to the OpenSRF Settings server to fetch the settings config. + * Provides a Config interface for fetching settings via path + */ +public class SettingsClient extends Config { + + /** Singleton SettingsClient instance */ + private static SettingsClient client = new SettingsClient(); + + public SettingsClient() { + super(""); + } + + /** + * @return The global settings client instance + */ + public static SettingsClient instance() throws ConfigException { + if(client.getConfigObject() == null) + client.fetchConfig(); + return client; + } + + /** + * Fetches the settings object from the settings server + */ + private void fetchConfig() throws ConfigException { + + ClientSession ses = new ClientSession("opensrf.settings"); + try { + + Request req = ses.request( + "opensrf.settings.host_config.get", + new String[]{(String)Config.global().getFirst("/domain")}); + + Result res = req.recv(12000); + if(res == null) { + /** throw exception */ + } + setConfigObject((Map) res.getContent()); + + } catch(Exception e) { + throw new ConfigException("Error fetching settings config", e); + + } finally { + ses.cleanup(); + } + } +} + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Utils.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Utils.java new file mode 100644 index 0000000000..159d254706 --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/Utils.java @@ -0,0 +1,106 @@ +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(); + } + + + /** + * Escapes a string. + */ + 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); + } + } + } + } + + + /** + * Descends into the map along the given XPATH-style path + * and returns the object found there. + * @param path The XPATH-style path to search. Path + * components are separated by '/' characters. + * Example: /opensrf/loglevel + * @return The found object. + */ + + public static Object findPath(Map map, String path) { + String keys[] = path.split("/", -1); + int i = 0; + if(path.charAt(0) == '/') i++; + for(; i < keys.length - 1; i++ ) + map = (Map) map.get(keys[i]); + + return map.get(keys[i]); + } +} + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLFlattener.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLFlattener.java new file mode 100644 index 0000000000..7abefe09fd --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLFlattener.java @@ -0,0 +1,128 @@ +package org.opensrf.util; + +import javax.xml.stream.*; +import javax.xml.stream.events.* ; +import javax.xml.namespace.QName; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.ListIterator; +import java.io.InputStream; +import org.opensrf.util.JSONWriter; +import org.opensrf.util.JSONReader; + +/** + * Flattens an XML file into a properties map. Values are stored as JSON strings or arrays. + * An array is created if more than one value resides at the same key. + * e.g. html.head.script = "alert('hello');" + */ +public class XMLFlattener { + + /** Flattened properties map */ + private Map props; + /** Incoming XML stream */ + private InputStream inStream; + /** Runtime list of encountered elements */ + private List elementList; + + /** + * Creates a new reader. Initializes the message queue. + * Sets the stream state to disconnected, and the xml + * state to in_nothing. + * @param inStream the inbound XML stream + */ + public XMLFlattener(InputStream inStream) { + props = new HashMap(); + this.inStream = inStream; + elementList = new ArrayList(); + } + + /** Turns an array of strings into a dot-separated key string */ + private String listToString() { + ListIterator itr = elementList.listIterator(); + StringBuffer sb = new StringBuffer(); + while(itr.hasNext()) { + sb.append(itr.next()); + if(itr.hasNext()) + sb.append("."); + } + return sb.toString(); + } + + /** + * Parses XML data from the provided stream. + */ + public Map read() throws javax.xml.stream.XMLStreamException { + + XMLInputFactory factory = XMLInputFactory.newInstance(); + + /** disable as many unused features as possible to speed up the parsing */ + factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE); + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); + factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); + factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); + + /** create the stream reader */ + XMLStreamReader reader = factory.createXMLStreamReader(inStream); + int eventType; + + while(reader.hasNext()) { + /** cycle through the XML events */ + + eventType = reader.next(); + if(reader.isWhiteSpace()) continue; + + switch(eventType) { + + case XMLEvent.START_ELEMENT: + elementList.add(reader.getName().toString()); + break; + + case XMLEvent.CHARACTERS: + String text = reader.getText(); + String key = listToString(); + + if(props.containsKey(key)) { + + /* something in the map already has this key */ + + Object o = null; + try { + o = new JSONReader(props.get(key)).read(); + } catch(org.opensrf.util.JSONException e){} + + if(o instanceof List) { + /* if the map contains a list, append to the list and re-encode */ + ((List) o).add(text); + + } else { + /* if the map just contains a string, start building a new list + * with the old string and append the new string */ + List arr = new ArrayList(); + arr.add((String) o); + arr.add(text); + o = arr; + } + + props.put(key, new JSONWriter(o).write()); + + } else { + props.put(key, new JSONWriter(text).write()); + } + break; + + case XMLEvent.END_ELEMENT: + elementList.remove(elementList.size()-1); + break; + } + } + + return props; + } +} + + + + diff --git a/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLTransformer.java b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLTransformer.java new file mode 100644 index 0000000000..f8bc0d3fac --- /dev/null +++ b/Open-ILS/src/Android/opensrf/src/org/opensrf/util/XMLTransformer.java @@ -0,0 +1,59 @@ +package org.opensrf.util; +import javax.xml.transform.*; +import javax.xml.transform.stream.*; +import javax.xml.parsers.*; +import java.io.File; +import java.io.ByteArrayInputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; + + +/** + * Performs XSL transformations. + * TODO: Add ability to pass in XSL variables + */ +public class XMLTransformer { + + /** The XML to transform */ + private Source xmlSource; + /** The stylesheet to apply */ + private Source xslSource; + + public XMLTransformer(Source xmlSource, Source xslSource) { + this.xmlSource = xmlSource; + this.xslSource = xslSource; + } + + public XMLTransformer(String xmlString, File xslFile) { + this( + new StreamSource(new ByteArrayInputStream(xmlString.getBytes())), + new StreamSource(xslFile)); + } + + public XMLTransformer(File xmlFile, File xslFile) { + this( + new StreamSource(xmlFile), + new StreamSource(xslFile)); + } + + /** + * Applies the transformation and puts the result into the provided output stream + */ + public void apply(OutputStream outStream) throws TransformerException, TransformerConfigurationException { + Result result = new StreamResult(outStream); + Transformer trans = TransformerFactory.newInstance().newTransformer(xslSource); + trans.transform(xmlSource, result); + } + + /** + * Applies the transformation and return the resulting string + * @return The String created by the XSL transformation + */ + public String apply() throws TransformerException, TransformerConfigurationException { + OutputStream outStream = new ByteArrayOutputStream(); + this.apply(outStream); + return outStream.toString(); + } +} + +