diff --git a/src/java/com/threerings/crowd/server/CrowdServer.java b/src/java/com/threerings/crowd/server/CrowdServer.java index 21d4b66c3..17115a60a 100644 --- a/src/java/com/threerings/crowd/server/CrowdServer.java +++ b/src/java/com/threerings/crowd/server/CrowdServer.java @@ -27,16 +27,20 @@ import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; +import com.samskivert.util.Invoker; import com.threerings.util.Name; import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.net.AuthRequest; import com.threerings.presents.server.ClientFactory; +import com.threerings.presents.server.ClientManager; import com.threerings.presents.server.ClientResolver; import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.PresentsClient; +import com.threerings.presents.server.PresentsDObjectMgr; import com.threerings.presents.server.PresentsServer; +import com.threerings.presents.server.net.ConnectionManager; import com.threerings.crowd.chat.server.ChatProvider; import com.threerings.crowd.data.BodyObject; @@ -58,18 +62,33 @@ public class CrowdServer extends PresentsServer } } - /** The place registry. */ + /** OBSOLETE! Don't use me. */ public static PlaceRegistry plreg; - /** Our chat provider. */ + /** OBSOLETE! Don't use me. */ public static ChatProvider chatprov; - /** Our body manager. */ + /** OBSOLETE! Don't use me. */ public static BodyManager bodyman; - /** Our location manager. */ + /** OBSOLETE! Don't use me. */ public static LocationManager locman; + /** OBSOLETE! Don't use me. */ + public static ConnectionManager conmgr; + + /** OBSOLETE! Don't use me. */ + public static ClientManager clmgr; + + /** OBSOLETE! Don't use me. */ + public static PresentsDObjectMgr omgr; + + /** OBSOLETE! Don't use me. */ + public static InvocationManager invmgr; + + /** OBSOLETE! Don't use me. */ + public static Invoker invoker; + /** * Initializes all of the server services and prepares for operation. */ @@ -79,18 +98,23 @@ public class CrowdServer extends PresentsServer super.init(injector); // LEGACY: set up our legacy static references + conmgr = _conmgr; + clmgr = _clmgr; + omgr = _omgr; + invmgr = _invmgr; + invoker = _invoker; plreg = _plreg; chatprov = _chatprov; bodyman = _bodyman; locman = _locman; // configure the client manager to use our bits - clmgr.setClientFactory(new ClientFactory() { - public PresentsClient createClient (AuthRequest areq) { - return new CrowdClient(); + _clmgr.setClientFactory(new ClientFactory() { + public Class getClientClass (AuthRequest areq) { + return CrowdClient.class; } - public ClientResolver createClientResolver (Name username) { - return new CrowdClientResolver(); + public Class getClientResolverClass (Name username) { + return CrowdClientResolver.class; } }); @@ -111,21 +135,11 @@ public class CrowdServer extends PresentsServer return new BodyLocator() { public BodyObject get (Name visibleName) { // by default visibleName is username - return (BodyObject)clmgr.getClientObject(visibleName); + return (BodyObject)_clmgr.getClientObject(visibleName); } }; } - /** - * Enumerates the body objects for all active users on the server. This should only be called - * from the dobjmgr thread. The caller had best be certain they know what they're doing, since - * this should only be necessary for use in rather special circumstances. - */ - public static Iterator enumerateBodies () - { - return clmgr.enumerateClientObjects(); - } - /** * Looks up the {@link BodyObject} for the user with the specified visible name, returns null * if they are not online. This should only be called from the dobjmgr thread. diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index b729781b4..33a16fd00 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -194,7 +194,7 @@ public class PlaceManager if (_delegates == null) { _delegates = Lists.newArrayList(); } - delegate.setPlaceManager(this); + delegate.init(this, _omgr, _invmgr); _delegates.add(delegate); } diff --git a/src/java/com/threerings/crowd/server/PlaceManagerDelegate.java b/src/java/com/threerings/crowd/server/PlaceManagerDelegate.java index 05c41aa00..d94f580d1 100644 --- a/src/java/com/threerings/crowd/server/PlaceManagerDelegate.java +++ b/src/java/com/threerings/crowd/server/PlaceManagerDelegate.java @@ -21,6 +21,9 @@ package com.threerings.crowd.server; +import com.threerings.presents.dobj.RootDObjectManager; +import com.threerings.presents.server.InvocationManager; + import com.threerings.crowd.data.OccupantInfo; import com.threerings.crowd.data.PlaceConfig; import com.threerings.crowd.data.PlaceObject; @@ -41,9 +44,11 @@ public class PlaceManagerDelegate * Called by the place manager when this delegate is registered with it. This will happen * before any calls to {@link #didInit}, etc. */ - public void setPlaceManager (PlaceManager plmgr) + public void init (PlaceManager plmgr, RootDObjectManager omgr, InvocationManager invmgr) { _plmgr = plmgr; + _omgr = omgr; + _invmgr = invmgr; } /** @@ -105,4 +110,10 @@ public class PlaceManagerDelegate /** A reference to the manager for which we are delegating. */ protected PlaceManager _plmgr; + + /** A reference to our distributed object manager. */ + protected RootDObjectManager _omgr; + + /** A reference to our invocation manager. */ + protected InvocationManager _invmgr; } diff --git a/src/java/com/threerings/presents/peer/server/PeerClient.java b/src/java/com/threerings/presents/peer/server/PeerClient.java index 8a85e451e..f3d70c043 100644 --- a/src/java/com/threerings/presents/peer/server/PeerClient.java +++ b/src/java/com/threerings/presents/peer/server/PeerClient.java @@ -21,6 +21,7 @@ package com.threerings.presents.peer.server; +import com.google.inject.Inject; import com.samskivert.util.Throttle; import com.threerings.presents.dobj.DObject; @@ -41,7 +42,7 @@ public class PeerClient extends PresentsClient * Creates a peer client and provides it with a reference to the peer * manager. This is only done by the {@link PeerClientFactory}. */ - protected PeerClient (PeerManager peermgr) + @Inject public PeerClient (PeerManager peermgr) { _peermgr = peermgr; } diff --git a/src/java/com/threerings/presents/peer/server/PeerClientFactory.java b/src/java/com/threerings/presents/peer/server/PeerClientFactory.java index a5f46fca1..116774c30 100644 --- a/src/java/com/threerings/presents/peer/server/PeerClientFactory.java +++ b/src/java/com/threerings/presents/peer/server/PeerClientFactory.java @@ -31,37 +31,35 @@ import com.threerings.presents.server.PresentsClient; import com.threerings.presents.peer.net.PeerCreds; /** - * Handles resolution of peer servers and passes non-peer resolution requests - * through to a normal factory. + * Handles resolution of peer servers and passes non-peer resolution requests through to a normal + * factory. */ public class PeerClientFactory implements ClientFactory { - public PeerClientFactory (PeerManager peermgr, ClientFactory delegate) + public PeerClientFactory (ClientFactory delegate) { - _peermgr = peermgr; _delegate = delegate; } // documentation inherited from interface ClientFactory - public PresentsClient createClient (AuthRequest areq) + public Class getClientClass (AuthRequest areq) { if (areq.getCredentials() instanceof PeerCreds) { - return new PeerClient(_peermgr); + return PeerClient.class; } else { - return _delegate.createClient(areq); + return _delegate.getClientClass(areq); } } // documentation inherited from interface ClientFactory - public ClientResolver createClientResolver (Name username) + public Class getClientResolverClass (Name username) { if (username.toString().startsWith(PeerCreds.PEER_PREFIX)) { - return new PeerClientResolver(); + return PeerClientResolver.class; } else { - return _delegate.createClientResolver(username); + return _delegate.getClientResolverClass(username); } } - protected PeerManager _peermgr; protected ClientFactory _delegate; } diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java index 2cb3aa3bf..baf494bd5 100644 --- a/src/java/com/threerings/presents/peer/server/PeerManager.java +++ b/src/java/com/threerings/presents/peer/server/PeerManager.java @@ -220,7 +220,7 @@ public class PeerManager // wire ourselves into the server _conmgr.addChainedAuthenticator(new PeerAuthenticator(this)); - _clmgr.setClientFactory(new PeerClientFactory(this, _clmgr.getClientFactory())); + _clmgr.setClientFactory(new PeerClientFactory(_clmgr.getClientFactory())); // create our node object _nodeobj = _omgr.registerObject(createNodeObject()); diff --git a/src/java/com/threerings/presents/server/ClientFactory.java b/src/java/com/threerings/presents/server/ClientFactory.java index e4d341eae..541bd29d0 100644 --- a/src/java/com/threerings/presents/server/ClientFactory.java +++ b/src/java/com/threerings/presents/server/ClientFactory.java @@ -27,29 +27,30 @@ import com.threerings.presents.data.ClientObject; import com.threerings.presents.net.AuthRequest; /** - * Used to create a {@link PresentsClient} instance to manage an authenticated - * client. + * Used to determine what type of {@link PresentsClient} to use to manage an authenticated client + * as well the type of {@link ClientResolver} to use when resolving clients' runtime data. */ public interface ClientFactory { /** The default client factory. */ public static ClientFactory DEFAULT = new ClientFactory () { - public PresentsClient createClient (AuthRequest areq) { - return new PresentsClient(); + public Class getClientClass (AuthRequest areq) { + return PresentsClient.class; } - public ClientResolver createClientResolver (Name username) { - return new ClientResolver(); + public Class getClientResolverClass (Name username) { + return ClientResolver.class; } }; /** - * Creates an uninitialized client instance for the client that has - * authenticated using the supplied request. + * Returns the {@link PresentsClient} derived class to use for the session that authenticated + * with the supplied request. */ - public PresentsClient createClient (AuthRequest areq); + public Class getClientClass (AuthRequest areq); /** - * Requests a resolver for the client identified by the specified username. + * Returns the {@link ClientResolver} derived class to use to resolve a client with the + * specified username. */ - public ClientResolver createClientResolver (Name username); + public Class getClientResolverClass (Name username); } diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index 7dace047c..00c302b80 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -29,6 +29,7 @@ import java.util.Map; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; +import com.google.inject.Injector; import com.google.inject.Singleton; import com.samskivert.util.Interval; @@ -112,6 +113,15 @@ public class ClientManager }.schedule(CLIENT_FLUSH_INTERVAL, true); } + /** + * Configures the injector we'll use to resolve dependencies for {@link PresentsClient} + * instances. + */ + public void setInjector (Injector injector) + { + _injector = injector; + } + // from interface ShutdownManager.Shutdowner public void shutdown () { @@ -261,7 +271,7 @@ public class ClientManager try { // create a client resolver instance which will create our client object, populate it // and notify the listeners - clr = _factory.createClientResolver(username); + clr = _injector.getInstance(_factory.getClientResolverClass(username)); clr.init(username); clr.addResolutionListener(this); clr.addResolutionListener(listener); @@ -368,8 +378,8 @@ public class ClientManager } else { log.info("Session initiated [username=" + username + ", conn=" + conn + "]."); // create a new client and stick'em in the table - client = _factory.createClient(req); - client.startSession(this, req, conn, rsp.authdata); + client = _injector.getInstance(_factory.getClientClass(req)); + client.startSession(req, conn, rsp.authdata); // map their client instance synchronized (_usermap) { @@ -534,6 +544,9 @@ public class ClientManager protected ClientOp _clop; } + /** Used to resolve dependencies in {@link PresentClient} instances that we create. */ + protected Injector _injector; + /** A mapping from auth username to client instances. */ protected Map _usermap = Maps.newHashMap(); @@ -546,7 +559,7 @@ public class ClientManager /** A mapping of pending client resolvers. */ protected Map _penders = Maps.newHashMap(); - /** The client class in use. */ + /** Lets us know what sort of client classes to use. */ protected ClientFactory _factory = ClientFactory.DEFAULT; /** Tracks registered {@link ClientObserver}s. */ diff --git a/src/java/com/threerings/presents/server/ClientResolver.java b/src/java/com/threerings/presents/server/ClientResolver.java index e894e0b72..708252359 100644 --- a/src/java/com/threerings/presents/server/ClientResolver.java +++ b/src/java/com/threerings/presents/server/ClientResolver.java @@ -21,15 +21,20 @@ package com.threerings.presents.server; -import java.util.ArrayList; +import java.util.List; + +import com.google.common.collect.Lists; +import com.google.inject.Inject; import com.samskivert.util.Invoker; import com.threerings.util.Name; +import com.threerings.presents.annotation.MainInvoker; import com.threerings.presents.data.ClientObject; import com.threerings.presents.data.PermissionPolicy; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.ObjectAccessException; +import com.threerings.presents.dobj.RootDObjectManager; import static com.threerings.presents.Log.log; @@ -84,7 +89,7 @@ public class ClientResolver extends Invoker.Unit // we've got our object, so shunt ourselves over to the invoker thread to perform database // loading _clobj = object; - PresentsServer.invoker.postUnit(this); + _invoker.postUnit(this); } // documentation inherited @@ -128,7 +133,7 @@ public class ClientResolver extends Invoker.Unit } else { // destroy the dangling user object - PresentsServer.omgr.destroyObject(_clobj.getOid()); + _omgr.destroyObject(_clobj.getOid()); // let our listener know that we're hosed reportFailure(_failure); @@ -182,12 +187,14 @@ public class ClientResolver extends Invoker.Unit protected Name _username; /** The entities to notify of success or failure. */ - protected ArrayList _listeners = - new ArrayList(); + protected List _listeners = Lists.newArrayList(); /** The resolving client object. */ protected ClientObject _clobj; /** A place to keep an exception around for a moment. */ protected Exception _failure; + + @Inject @MainInvoker Invoker _invoker; + @Inject RootDObjectManager _omgr; } diff --git a/src/java/com/threerings/presents/server/PresentsClient.java b/src/java/com/threerings/presents/server/PresentsClient.java index f2982979e..642867c2a 100644 --- a/src/java/com/threerings/presents/server/PresentsClient.java +++ b/src/java/com/threerings/presents/server/PresentsClient.java @@ -26,6 +26,7 @@ import java.net.InetAddress; import java.util.HashMap; import java.util.TimeZone; +import com.google.inject.Inject; import com.samskivert.util.HashIntMap; import com.samskivert.util.ResultListener; import com.samskivert.util.Throttle; @@ -60,6 +61,7 @@ import com.threerings.presents.net.PongResponse; import com.threerings.presents.net.UnsubscribeResponse; import com.threerings.presents.server.net.Connection; +import com.threerings.presents.server.net.ConnectionManager; import com.threerings.presents.server.net.MessageHandler; import static com.threerings.presents.Log.log; @@ -196,7 +198,7 @@ public class PresentsClient log.warning("Client disappeared before we could complete the switch to a " + "new client object [ousername=" + _username + ", nusername=" + username + "]."); - _cmgr.releaseClientObject(username); + _clmgr.releaseClientObject(username); Exception error = new Exception("Early withdrawal"); resolutionFailed(username, error); return; @@ -230,7 +232,7 @@ public class PresentsClient _clobj.postMessage(ClientObject.CLOBJ_CHANGED, args); // release our old client object; this will destroy it - _cmgr.releaseClientObject(_username); + _clmgr.releaseClientObject(_username); // update our internal fields _username = username; @@ -257,7 +259,7 @@ public class PresentsClient }; // resolve the new client object - _cmgr.resolveClientObject(username, clr); + _clmgr.resolveClientObject(username, clr); } /** @@ -271,7 +273,7 @@ public class PresentsClient */ public boolean updateUsername (Name username) { - if (_cmgr.renameClientObject(_username, username)) { + if (_clmgr.renameClientObject(_username, username)) { _username = username; return true; } @@ -297,7 +299,7 @@ public class PresentsClient // go ahead and clear out our connection now to prevent funniness setConnection(null); // have the connection manager close our connection when it is next convenient - PresentsServer.conmgr.closeConnection(conn); + _conmgr.closeConnection(conn); } // if we don't have a client object, we failed to resolve in the first place, in which case @@ -311,11 +313,11 @@ public class PresentsClient } // release (and destroy) our client object - _cmgr.releaseClientObject(_username); + _clmgr.releaseClientObject(_username); } // let the client manager know that we're audi 5000 - _cmgr.clientSessionDidEnd(this); + _clmgr.clientSessionDidEnd(this); // clear out the client object so that we know the session is over _clobj = null; @@ -356,7 +358,7 @@ public class PresentsClient sendBootstrap(); // let the client manager know that we're operational - _cmgr.clientSessionDidStart(this); + _clmgr.clientSessionDidStart(this); } // from interface ClientResolutionListener @@ -420,10 +422,8 @@ public class PresentsClient * Initializes this client instance with the specified username, connection instance and client * object and begins a client session. */ - protected void startSession ( - ClientManager cmgr, AuthRequest req, Connection conn, Object authdata) + protected void startSession (AuthRequest req, Connection conn, Object authdata) { - _cmgr = cmgr; _areq = req; _authdata = authdata; setConnection(conn); @@ -432,7 +432,7 @@ public class PresentsClient assignStartingUsername(); // resolve our client object before we get fully underway - cmgr.resolveClientObject(_username, this); + _clmgr.resolveClientObject(_username, this); // make a note of our session start time _sessionStamp = System.currentTimeMillis(); @@ -481,7 +481,7 @@ public class PresentsClient } // we need to get onto the dobj thread so that we can finalize resumption of the session - PresentsServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { // now that we're on the dobjmgr thread we can resume our session resumption finishResumeSession(); @@ -516,7 +516,7 @@ public class PresentsClient */ protected void safeEndSession () { - PresentsServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { endSession(); } @@ -679,7 +679,7 @@ public class PresentsClient log.warning("Client provided no invocation service boot groups? " + this); data.services = new StreamableArrayList(); } else { - data.services = PresentsServer.invmgr.getBootstrapServices(_areq.getBootGroups()); + data.services = _invmgr.getBootstrapServices(_areq.getBootGroups()); } } @@ -699,7 +699,7 @@ public class PresentsClient // that we do this *after* we clear out our connection reference. once the connection ref // is null, no more subscriptions will be processed (even those that were queued up before // the connection went away) - PresentsServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { sessionConnectionClosed(); } @@ -773,7 +773,7 @@ public class PresentsClient * the supplied message to this client. */ protected final void safePostMessage (final DownstreamMessage msg) { - PresentsServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { postMessage(msg); } @@ -851,7 +851,7 @@ public class PresentsClient public void objectAvailable (DObject object) { if (postMessage(new ObjectResponse(object))) { - _firstEventId = PresentsServer.omgr.getNextEventId(false); + _firstEventId = _omgr.getNextEventId(false); this.object = object; synchronized (_subscrips) { // make a note of this new subscription @@ -918,7 +918,7 @@ public class PresentsClient // log.info("Subscribing [client=" + client + ", oid=" + req.getOid() + "]."); // forward the subscribe request to the omgr for processing - PresentsServer.omgr.subscribeToObject(req.getOid(), client.createProxySubscriber()); + client._omgr.subscribeToObject(req.getOid(), client.createProxySubscriber()); } } @@ -965,7 +965,7 @@ public class PresentsClient // log.info("Forwarding event [client=" + client + ", event=" + fevt + "]."); // forward the event to the omgr for processing - PresentsServer.omgr.postEvent(fevt); + client._omgr.postEvent(fevt); } } @@ -994,7 +994,11 @@ public class PresentsClient } } - protected ClientManager _cmgr; + @Inject protected ClientManager _clmgr; + @Inject protected ConnectionManager _conmgr; + @Inject protected PresentsDObjectMgr _omgr; + @Inject protected InvocationManager _invmgr; + protected AuthRequest _areq; protected Object _authdata; protected Name _username; diff --git a/src/java/com/threerings/presents/server/PresentsServer.java b/src/java/com/threerings/presents/server/PresentsServer.java index cb08a1e7a..6f8226adc 100644 --- a/src/java/com/threerings/presents/server/PresentsServer.java +++ b/src/java/com/threerings/presents/server/PresentsServer.java @@ -65,21 +65,6 @@ public class PresentsServer } } - /** OBSOLETE! Don't use me. */ - public static ConnectionManager conmgr; - - /** OBSOLETE! Don't use me. */ - public static ClientManager clmgr; - - /** OBSOLETE! Don't use me. */ - public static PresentsDObjectMgr omgr; - - /** OBSOLETE! Don't use me. */ - public static InvocationManager invmgr; - - /** OBSOLETE! Don't use me. */ - public static Invoker invoker; - /** * The default entry point for the server. */ @@ -120,13 +105,6 @@ public class PresentsServer public void init (Injector injector) throws Exception { - // populate our legacy statics - conmgr = _conmgr; - clmgr = _clmgr; - omgr = _omgr; - invmgr = _invmgr; - invoker = _invoker; - // output general system information SystemInfo si = new SystemInfo(); log.info("Starting up server [os=" + si.osToString() + ", jvm=" + si.jvmToString() + @@ -150,11 +128,14 @@ public class PresentsServer _invoker.start(); _authInvoker.start(); + // provide our client manager with the injector it needs + _clmgr.setInjector(injector); + // configure our connection manager _conmgr.init(getListenPorts(), getDatagramPorts()); // initialize the time base services - TimeBaseProvider.init(invmgr, omgr); + TimeBaseProvider.init(_invmgr, _omgr); } /** @@ -189,14 +170,14 @@ public class PresentsServer { // post a unit that will start up the connection manager when everything else in the // dobjmgr queue is processed - omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { // start up the connection manager _conmgr.start(); } }); // invoke the dobjmgr event loop - omgr.run(); + _omgr.run(); } /** diff --git a/tests/src/java/com/threerings/bureau/server/TestServer.java b/tests/src/java/com/threerings/bureau/server/TestServer.java index 0ba3c438a..5fb3aa891 100644 --- a/tests/src/java/com/threerings/bureau/server/TestServer.java +++ b/tests/src/java/com/threerings/bureau/server/TestServer.java @@ -60,7 +60,7 @@ public class TestServer extends PresentsServer throws Exception { super.init(injector); - breg = new BureauRegistry("localhost:47624", invmgr, omgr, invoker); + breg = new BureauRegistry("localhost:47624", _invmgr, _omgr, _invoker); } public static void setClientTarget (String target) diff --git a/tests/src/java/com/threerings/presents/server/TestServer.java b/tests/src/java/com/threerings/presents/server/TestServer.java index 332b0cc6f..9ab43e23b 100644 --- a/tests/src/java/com/threerings/presents/server/TestServer.java +++ b/tests/src/java/com/threerings/presents/server/TestServer.java @@ -42,7 +42,7 @@ public class TestServer extends PresentsServer _invmgr.registerDispatcher(new TestDispatcher(new TestManager()), "test"); // create a test object - testobj = omgr.registerObject(new TestObject()); + testobj = _omgr.registerObject(new TestObject()); testobj.longs.add(System.currentTimeMillis()); long value = Integer.MAX_VALUE; value++;