From f8ccff8f23be7c2e15d10f3ee9aa26e10749af84 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Thu, 19 Jul 2001 18:08:20 +0000 Subject: [PATCH] More progress on the invocation services. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@74 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/presents/client/Client.java | 10 ++- .../presents/client/InvocationDirector.java | 13 +++- .../com/threerings/presents/dobj/DEvent.java | 24 +++++- .../presents/server/InvocationManager.java | 23 ++++-- .../presents/server/InvocationProvider.java | 73 +++++++++++++++++++ .../presents/server/PresentsClient.java | 21 +++++- .../presents/client/TestClient.java | 6 +- .../presents/server/TestProvider.java | 7 +- 8 files changed, 157 insertions(+), 20 deletions(-) create mode 100644 src/java/com/threerings/presents/server/InvocationProvider.java 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)); } }