diff --git a/src/java/com/threerings/presents/client/Client.java b/src/java/com/threerings/presents/client/Client.java
index 9ee5a3e63..911ce972f 100644
--- a/src/java/com/threerings/presents/client/Client.java
+++ b/src/java/com/threerings/presents/client/Client.java
@@ -1,5 +1,5 @@
//
-// $Id: Client.java,v 1.9 2001/07/19 07:48:25 mdb Exp $
+// $Id: Client.java,v 1.10 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.client;
@@ -254,6 +254,14 @@ public class Client
// create our invocation manager
_invmgr = new InvocationManager(this, data.invOid);
+ // we can't quite call initialization completed at this point
+ // because we need for the invocation manager to fully initialize
+ // (which requires a round trip to the server) before turning the
+ // client loose to do things like request invocation services
+ }
+
+ void invocationManagerReady ()
+ {
// let the client know that logon has now fully succeeded
notifyObservers(Client.CLIENT_DID_LOGON, null);
}
diff --git a/src/java/com/threerings/presents/client/InvocationDirector.java b/src/java/com/threerings/presents/client/InvocationDirector.java
index 2e3528a2b..74078fc91 100644
--- a/src/java/com/threerings/presents/client/InvocationDirector.java
+++ b/src/java/com/threerings/presents/client/InvocationDirector.java
@@ -1,5 +1,5 @@
//
-// $Id: InvocationDirector.java,v 1.2 2001/07/19 07:09:16 mdb Exp $
+// $Id: InvocationDirector.java,v 1.3 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.client;
@@ -44,6 +44,7 @@ public class InvocationManager
*/
public InvocationManager (Client client, int imoid)
{
+ _client = client;
_omgr = client.getDObjectManager();
_imoid = imoid;
@@ -97,12 +98,17 @@ public class InvocationManager
public void objectAvailable (DObject object)
{
- // nothing doing
+ // let the client know that we're ready to go now that we've got
+ // our subscription to the client object
+ _client.invocationManagerReady();
}
public void requestFailed (int oid, ObjectAccessException cause)
{
- // nothing doing
+ // aiya! we were unable to subscribe to the client object. we're
+ // hosed, hosed, hosed
+ Log.warning("Invocation manager unable to subscribe to client " +
+ "object. All is wrong in the universe.");
}
/**
@@ -176,6 +182,7 @@ public class InvocationManager
}
}
+ protected Client _client;
protected DObjectManager _omgr;
protected int _imoid;
protected ClientObject _clobj;
diff --git a/src/java/com/threerings/presents/dobj/DEvent.java b/src/java/com/threerings/presents/dobj/DEvent.java
index c77097b36..4ba5e5d81 100644
--- a/src/java/com/threerings/presents/dobj/DEvent.java
+++ b/src/java/com/threerings/presents/dobj/DEvent.java
@@ -1,5 +1,5 @@
//
-// $Id: DEvent.java,v 1.3 2001/06/01 19:56:13 mdb Exp $
+// $Id: DEvent.java,v 1.4 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.dobj;
@@ -35,6 +35,25 @@ public abstract class DEvent
public abstract boolean applyToObject (DObject target)
throws ObjectAccessException;
+ /**
+ * Returns the object id of the client that generated this event. This
+ * will only be valid on the server, it will return -1 otherwise.
+ */
+ public int getSourceOid ()
+ {
+ return _soid;
+ }
+
+ /**
+ * Do not call this method. Sets the source oid of the client that
+ * generated this event. It is automatically called by the client
+ * management code when a client forwards an event to the server.
+ */
+ public void setSourceOid (int sourceOid)
+ {
+ _soid = sourceOid;
+ }
+
/**
* Constructs a new distributed object event that pertains to the
* specified distributed object.
@@ -46,4 +65,7 @@ public abstract class DEvent
/** The oid of the object that is the target of this event. */
protected int _toid;
+
+ /** The oid of the client that generated this event. */
+ protected int _soid;
}
diff --git a/src/java/com/threerings/presents/server/InvocationManager.java b/src/java/com/threerings/presents/server/InvocationManager.java
index e6f93427d..9d2f02611 100644
--- a/src/java/com/threerings/presents/server/InvocationManager.java
+++ b/src/java/com/threerings/presents/server/InvocationManager.java
@@ -1,5 +1,5 @@
//
-// $Id: InvocationManager.java,v 1.3 2001/07/19 07:48:25 mdb Exp $
+// $Id: InvocationManager.java,v 1.4 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.server;
@@ -51,7 +51,7 @@ public class InvocationManager
* Registers the supplied invocation provider instance as the handler
* for all invocation requests for the specified module.
*/
- public void registerProvider (String module, Object provider)
+ public void registerProvider (String module, InvocationProvider provider)
{
_providers.put(module, provider);
}
@@ -90,10 +90,11 @@ public class InvocationManager
Object[] args = mevt.getArgs();
String module = (String)args[0];
String procedure = (String)args[1];
- int invid = ((Integer)args[2]).intValue();
+ Integer invid = (Integer)args[2];
// locate a provider for this module
- Object provider = _providers.get(module);
+ InvocationProvider provider =
+ (InvocationProvider)_providers.get(module);
if (provider == null) {
Log.warning("No provider registered for invocation request " +
"[evt=" + mevt + "].");
@@ -115,14 +116,26 @@ public class InvocationManager
}
// and invoke it
+ Object[] rargs = null;
try {
- procmeth.invoke(provider, margs);
+ rargs = (Object[])procmeth.invoke(provider, margs);
} catch (Exception e) {
Log.warning("Error invoking invocation procedure " +
"[provider=" + provider + ", method=" + procmeth +
", error=" + e + "].");
}
+ // if there is a response to be delivered, do so
+ if (rargs != null) {
+ // fill in the invocation id
+ rargs[1] = invid;
+ // and create a message event for delivery to the client
+ MessageEvent revt = new MessageEvent(
+ mevt.getSourceOid(), InvocationObject.MESSAGE_NAME, rargs);
+ // and ship it off
+ CherServer.omgr.postEvent(revt);
+ }
+
return true;
}
diff --git a/src/java/com/threerings/presents/server/InvocationProvider.java b/src/java/com/threerings/presents/server/InvocationProvider.java
new file mode 100644
index 000000000..29fee2056
--- /dev/null
+++ b/src/java/com/threerings/presents/server/InvocationProvider.java
@@ -0,0 +1,73 @@
+//
+// $Id: InvocationProvider.java,v 1.1 2001/07/19 18:08:20 mdb Exp $
+
+package com.threerings.cocktail.cher.server;
+
+/**
+ * Invocation providers should extend this class when implementing
+ * invocation services. Because the service procedures are identified by
+ * strings and the methods that are invoked are looked up via reflection,
+ * the derived class doesn't override or implement any particular method.
+ * However, the procedure names are still restricted. For example, a
+ * procedure identified by the name Tell would result in the
+ * invocation of a method named handleTellRequest. The
+ * arguments to that method would be defined by the arguments that
+ * accompanied the Tell invocation request. If the arguments
+ * do not match, a reflection error will happen when trying to invoke the
+ * method and the whole request will fail.
+ *
+ *
Invocation procedures must also package up their response in a
+ * particular way which is through the use of the
+ * createResponse methods. These take a response identifier
+ * (which determines the name of the method that will be invoked on the
+ * response target object provided in the client) and a variable number of
+ * arguments. If a response was created with the identifier
+ * TellFailed, that would result in the method
+ * handleTellFailed being invoked on the response target
+ * object in the client. Again the arguments much match exactly and follow
+ * the reflection rules for automatic conversion of primitive types
+ * (supply an Integer object for int params,
+ * etc.).
+ */
+public class InvocationProvider
+{
+ /**
+ * Creates a response array properly configured with the supplied name
+ * and single argument.
+ */
+ protected Object[] createResponse (String name, Object arg)
+ {
+ return new Object[] { name, null, arg };
+ }
+
+ /**
+ * Creates a response array properly configured with the supplied name
+ * and two arguments.
+ */
+ protected Object[] createResponse (String name, Object arg1, Object arg2)
+ {
+ return new Object[] { name, null, arg1, arg2 };
+ }
+
+ /**
+ * Creates a response array properly configured with the supplied name
+ * and three arguments.
+ */
+ protected Object[] createResponse (String name, Object arg1, Object arg2,
+ Object arg3)
+ {
+ return new Object[] { name, null, arg1, arg2, arg3 };
+ }
+
+ /**
+ * Creates a response array properly configured with the supplied name
+ * and varying number of arguments.
+ */
+ protected Object[] createResponse (String name, Object[] args)
+ {
+ Object[] rsp = new Object[args.length+2];
+ rsp[0] = name;
+ System.arraycopy(args, 0, rsp, 2, args.length);
+ return rsp;
+ }
+}
diff --git a/src/java/com/threerings/presents/server/PresentsClient.java b/src/java/com/threerings/presents/server/PresentsClient.java
index c4edc3f01..c025c96f6 100644
--- a/src/java/com/threerings/presents/server/PresentsClient.java
+++ b/src/java/com/threerings/presents/server/PresentsClient.java
@@ -1,5 +1,5 @@
//
-// $Id: PresentsClient.java,v 1.7 2001/07/19 07:48:25 mdb Exp $
+// $Id: PresentsClient.java,v 1.8 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.server;
@@ -71,6 +71,14 @@ public class Client implements Subscriber, MessageHandler
return _username;
}
+ /**
+ * Returns the client object that is associated with this client.
+ */
+ public ClientObject getClientObject ()
+ {
+ return _clobj;
+ }
+
/**
* Called by the client manager when a new connection arrives that
* authenticates as this already established client. This must only be
@@ -289,10 +297,15 @@ public class Client implements Subscriber, MessageHandler
public void dispatch (Client client, UpstreamMessage msg)
{
ForwardEventRequest req = (ForwardEventRequest)msg;
- Log.info("Forwarding event [client=" + client +
- ", event=" + req.getEvent() + "].");
+ DEvent fevt = req.getEvent();
+
+ // fill in the proper source oid
+ fevt.setSourceOid(client.getClientObject().getOid());
+
// forward the event to the omgr for processing
- CherServer.omgr.postEvent(req.getEvent());
+ Log.info("Forwarding event [client=" + client +
+ ", event=" + fevt + "].");
+ CherServer.omgr.postEvent(fevt);
}
}
diff --git a/tests/src/java/com/threerings/presents/client/TestClient.java b/tests/src/java/com/threerings/presents/client/TestClient.java
index f64498e89..a13311ada 100644
--- a/tests/src/java/com/threerings/presents/client/TestClient.java
+++ b/tests/src/java/com/threerings/presents/client/TestClient.java
@@ -1,5 +1,5 @@
//
-// $Id: TestClient.java,v 1.5 2001/07/19 07:48:25 mdb Exp $
+// $Id: TestClient.java,v 1.6 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.client.test;
@@ -87,9 +87,9 @@ public class TestClient
return false;
}
- public void handleTestSucceeded (String response)
+ public void handleTestSucceeded (String one, int two)
{
- Log.info("Got test response [rsp=" + response + "].");
+ Log.info("Got test response [one=" + one + ", two=" + two + "].");
}
public static void main (String[] args)
diff --git a/tests/src/java/com/threerings/presents/server/TestProvider.java b/tests/src/java/com/threerings/presents/server/TestProvider.java
index d8b67bdcc..d8d3bbb44 100644
--- a/tests/src/java/com/threerings/presents/server/TestProvider.java
+++ b/tests/src/java/com/threerings/presents/server/TestProvider.java
@@ -1,18 +1,19 @@
//
-// $Id: TestProvider.java,v 1.2 2001/07/19 07:48:58 mdb Exp $
+// $Id: TestProvider.java,v 1.3 2001/07/19 18:08:20 mdb Exp $
package com.threerings.cocktail.cher.server.test;
import com.threerings.cocktail.cher.Log;
+import com.threerings.cocktail.cher.server.InvocationProvider;
/**
* A test of the invocation services.
*/
-public class TestProvider
+public class TestProvider extends InvocationProvider
{
public Object[] handleTestRequest (String one, int two)
{
Log.info("Test request [one=" + one + ", two=" + two + "].");
- return null;
+ return createResponse("TestSucceeded", one, new Integer(two));
}
}