Modified invocation request procedure to provide a reference to the client

object that initiated the request. Implemented the invocation notification
side of things.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@76 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-07-19 19:18:07 +00:00
parent 359af834ae
commit 41488822dc
10 changed files with 238 additions and 30 deletions
@@ -1,11 +1,13 @@
//
// $Id: InvocationDirector.java,v 1.3 2001/07/19 18:08:20 mdb Exp $
// $Id: InvocationDirector.java,v 1.4 2001/07/19 19:18:06 mdb Exp $
package com.threerings.cocktail.cher.client;
import java.lang.reflect.Method;
import java.util.HashMap;
import com.samskivert.util.StringUtil;
import com.threerings.cocktail.cher.Log;
import com.threerings.cocktail.cher.data.*;
import com.threerings.cocktail.cher.dobj.*;
@@ -84,7 +86,7 @@ public class InvocationManager
// create a message event on the invocation manager object
MessageEvent event = new MessageEvent(
_imoid, InvocationObject.MESSAGE_NAME, iargs);
_imoid, InvocationObject.REQUEST_NAME, iargs);
// if we have a response target, register that for later receipt
// of the response
@@ -96,6 +98,15 @@ public class InvocationManager
_omgr.postEvent(event);
}
/**
* Registers the supplied invocation receiver instance as the handler
* for all invocation notifications for the specified module.
*/
public void registerReceiver (String module, InvocationReceiver receiver)
{
_receivers.put(module, receiver);
}
public void objectAvailable (DObject object)
{
// let the client know that we're ready to go now that we've got
@@ -123,21 +134,29 @@ public class InvocationManager
// and only those of proper name
MessageEvent mevt = (MessageEvent)event;
if (!mevt.getName().equals(InvocationObject.MESSAGE_NAME)) {
return true;
String name = mevt.getName();
if (name.equals(InvocationObject.RESPONSE_NAME)) {
handleInvocationResponse(mevt.getArgs());
} else if (name.equals(InvocationObject.NOTIFICATION_NAME)) {
handleInvocationNotification(mevt.getArgs());
}
// we've got an invocation response, so we extract the args and
// process it
Object[] args = mevt.getArgs();
return true;
}
/**
* Processes an invocation response message.
*/
protected void handleInvocationResponse (Object[] args)
{
String name = (String)args[0];
int invid = ((Integer)args[1]).intValue();
Object rsptarg = _targets.get(invid);
if (rsptarg == null) {
Log.warning("No target for invocation response " +
"[rsp=" + mevt + "].");
return true;
"[args=" + StringUtil.toString(args) + "].");
return;
}
// prune the method arguments from the full message arguments
@@ -151,7 +170,7 @@ public class InvocationManager
Log.warning("Unable to resolve response method " +
"[target=" + rsptarg.getClass().getName() +
", method=" + mname + "].");
return true;
return;
}
// and invoke it
@@ -162,8 +181,46 @@ public class InvocationManager
"[target=" + rsptarg + ", method=" + rspmeth +
", error=" + e + "].");
}
}
return true;
/**
* Processes an invocation notification message.
*/
protected void handleInvocationNotification (Object[] args)
{
String module = (String)args[0];
String proc = (String)args[1];
InvocationReceiver receiver =
(InvocationReceiver)_receivers.get(module);
if (receiver == null) {
Log.warning("No receiver registered for notification " +
"[args=" + StringUtil.toString(args) + "].");
return;
}
// prune the method arguments from the full message arguments
Object[] nargs = new Object[args.length-2];
System.arraycopy(args, 2, nargs, 0, nargs.length);
// and invoke the receiver method
String mname = "handle" + proc + "Notification";
Method rspmeth = ClassUtil.getMethod(mname, receiver, _methcache);
if (rspmeth == null) {
Log.warning("Unable to resolve receiver method " +
"[target=" + receiver.getClass().getName() +
", method=" + mname + "].");
return;
}
// and invoke it
try {
rspmeth.invoke(receiver, nargs);
} catch (Exception e) {
Log.warning("Error invoking receiver method " +
"[receiver=" + receiver + ", method=" + rspmeth +
", error=" + e + "].");
}
}
protected synchronized int nextInvocationId ()
@@ -189,5 +246,6 @@ public class InvocationManager
protected int _invocationId;
protected IntMap _targets = new IntMap();
protected HashMap _receivers = new HashMap();
protected HashMap _methcache = new HashMap();
}
@@ -0,0 +1,34 @@
//
// $Id: InvocationReceiver.java,v 1.1 2001/07/19 19:18:06 mdb Exp $
package com.threerings.cocktail.cher.client;
/**
* Classes registered to process invocation notifications should extend
* the invocation receiver class and register themselves with the
* invocation manager. Because the invocation notification procedures are
* looked up using reflection, there are no methods to override in the
* receiver class, but it serves as a useful point for documentation and
* as a useful indicator that the derived class in question is actually
* serving as an invocation receiver.
*
* <p> Invocation notifications are identified by a module name and a
* procedure name. The module name identifies which invocation receiver
* instance will receive the notification. Receivers are registered with
* the invocation manager as handling all notification procedures for a
* particular module. The notification procedure name is used to construct
* a method name which is then reflected and invoked. The name
* construction is as follows: a notification message requesting the
* invocation of a procedure named <code>Tell</code> will result in a
* method named <code>handleTellNotification</code> being invoked on the
* invocation receiver instance. The signature of that method is defined
* by the arguments supplied with the invocation notification message.
* These arguments must always be of the same type and must exactly match
* the signature of the implementing method (with the standard reflection
* argument type conversion process taken into account).
*
* @see InvocationManager#registerReceiver
*/
public class InvocationReceiver
{
}