From bf77cb1520e6aae81c5c54b69e5ded0b15498b09 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Sun, 8 Jun 2008 17:18:26 +0000 Subject: [PATCH] Moved location services implementation into LocationManager so that LocationProvider can be an interface like its brothers and sisters. Modified the place registry to create PlaceManager instances using the injector so that we can inject dependencies into managers. Also modified the custom classloader functionality so that it can/will circumvent this process entirely. It's not possible to inject using a custom classloader and one certainly would not want to do so. Unfortunately this means we can't inject some basic managers into PlaceManager because it needs to work for games loaded into a sandboxed classloader, but the big win is that in everything other than GameManager and PlaceManager, we can inject to our heart's content. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5168 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- build.xml | 1 - .../threerings/crowd/server/CrowdClient.java | 2 +- .../threerings/crowd/server/CrowdServer.java | 10 + .../crowd/server/LocationManager.java | 223 ++++++++++++++++++ .../crowd/server/LocationProvider.java | 216 +---------------- .../threerings/crowd/server/PlaceManager.java | 16 +- .../crowd/server/PlaceRegistry.java | 75 +++--- .../bureau/server/RegistryTester.java | 11 +- 8 files changed, 296 insertions(+), 258 deletions(-) create mode 100644 src/java/com/threerings/crowd/server/LocationManager.java diff --git a/build.xml b/build.xml index a54bfd4af..e77907a04 100644 --- a/build.xml +++ b/build.xml @@ -71,7 +71,6 @@ - diff --git a/src/java/com/threerings/crowd/server/CrowdClient.java b/src/java/com/threerings/crowd/server/CrowdClient.java index 6785d2011..7b0e26981 100644 --- a/src/java/com/threerings/crowd/server/CrowdClient.java +++ b/src/java/com/threerings/crowd/server/CrowdClient.java @@ -84,6 +84,6 @@ public class CrowdClient extends PresentsClient */ protected void clearLocation (BodyObject bobj) { - CrowdServer.plreg.locprov.leaveOccupiedPlace(bobj); + CrowdServer.locman.leaveOccupiedPlace(bobj); } } diff --git a/src/java/com/threerings/crowd/server/CrowdServer.java b/src/java/com/threerings/crowd/server/CrowdServer.java index 584422075..21d4b66c3 100644 --- a/src/java/com/threerings/crowd/server/CrowdServer.java +++ b/src/java/com/threerings/crowd/server/CrowdServer.java @@ -67,6 +67,9 @@ public class CrowdServer extends PresentsServer /** Our body manager. */ public static BodyManager bodyman; + /** Our location manager. */ + public static LocationManager locman; + /** * Initializes all of the server services and prepares for operation. */ @@ -79,6 +82,7 @@ public class CrowdServer extends PresentsServer plreg = _plreg; chatprov = _chatprov; bodyman = _bodyman; + locman = _locman; // configure the client manager to use our bits clmgr.setClientFactory(new ClientFactory() { @@ -90,6 +94,9 @@ public class CrowdServer extends PresentsServer } }); + // configure the place registry with the injector + _plreg.setInjector(injector); + // create our body locator _lookup = createBodyLocator(); } @@ -155,6 +162,9 @@ public class CrowdServer extends PresentsServer /** Handles body-related invocation services. */ @Inject protected BodyManager _bodyman; + /** Handles location-related invocation services. */ + @Inject protected LocationManager _locman; + /** Provides chat-related invocation services. */ @Inject protected ChatProvider _chatprov; diff --git a/src/java/com/threerings/crowd/server/LocationManager.java b/src/java/com/threerings/crowd/server/LocationManager.java new file mode 100644 index 000000000..78ce16a98 --- /dev/null +++ b/src/java/com/threerings/crowd/server/LocationManager.java @@ -0,0 +1,223 @@ +// +// $Id$ +// +// Narya library - tools for developing networked games +// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/narya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.threerings.crowd.server; + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.dobj.RootDObjectManager; + +import com.threerings.presents.server.ClientManager; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationManager; +import com.threerings.presents.server.InvocationProvider; +import com.threerings.presents.server.PresentsClient; + +import com.threerings.crowd.client.LocationService; +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.CrowdCodes; +import com.threerings.crowd.data.LocationCodes; +import com.threerings.crowd.data.Place; +import com.threerings.crowd.data.PlaceConfig; +import com.threerings.crowd.data.PlaceObject; +import com.threerings.crowd.server.CrowdServer; + +import static com.threerings.crowd.Log.log; + +/** + * Handles location-related services. + */ +@Singleton +public class LocationManager + implements LocationProvider, LocationCodes +{ + @Inject public LocationManager (InvocationManager invmgr) + { + invmgr.registerDispatcher(new LocationDispatcher(this), CrowdCodes.CROWD_GROUP); + } + + // from interface LocationProvider + public void moveTo (ClientObject caller, int placeOid, LocationService.MoveListener listener) + throws InvocationException + { + // do the move and send the response + listener.moveSucceeded(moveTo((BodyObject)caller, placeOid)); + } + + // from interface LocationProvider + public void leavePlace (ClientObject caller) + { + leaveOccupiedPlace((BodyObject)caller); + } + + /** + * Moves the specified body from whatever location they currently occupy to the location + * identified by the supplied place oid. + * + * @return the config object for the new location. + * + * @exception ServiceFaildException thrown if the move was not successful for some reason + * (which will be communicated as an error code in the exception's message data). + */ + public PlaceConfig moveTo (BodyObject source, int placeOid) + throws InvocationException + { + int bodoid = source.getOid(); + + // make sure the place in question actually exists + PlaceManager pmgr = _plreg.getPlaceManager(placeOid); + if (pmgr == null) { + log.info("Requested to move to non-existent place [who=" + source.who() + + ", placeOid=" + placeOid + "]."); + throw new InvocationException(NO_SUCH_PLACE); + } + + // if they're already in the location they're asking to move to, just give them the config + // because we don't need to update anything in distributed object world + Place place = pmgr.getLocation(); + if (place.equals(source.location)) { + log.debug("Going along with client request to move to where they already are " + + "[source=" + source.who() + ", place=" + place + "]."); + return pmgr.getConfig(); + } + + // make sure they have access to the specified place + String errmsg; + if ((errmsg = pmgr.ratifyBodyEntry(source)) != null) { + throw new InvocationException(errmsg); + } + + // acquire a lock on the body object to avoid breakage by rapid fire moveTo requests + if (!source.acquireLock("moveToLock")) { + // if we're still locked, a previous moveTo request hasn't been fully processed + throw new InvocationException(MOVE_IN_PROGRESS); + } + + // configure the client accordingly if the place uses a custom class loader + PresentsClient client = _clmgr.getClient(source.username); + if (client != null) { + client.setClassLoader(pmgr.getClass().getClassLoader()); + } + + try { + PlaceObject plobj = pmgr.getPlaceObject(); + + // the doubly nested try catch is to prevent failure if one or the other of the + // transactions fails to start + plobj.startTransaction(); + try { + source.startTransaction(); + try { + // remove them from any previous location + leaveOccupiedPlace(source); + + // generate a new occinfo record (which will add it to the target location) + pmgr.buildOccupantInfo(source); + + // set the body's new location + source.willEnterPlace(place, plobj); + + // add the body oid to the place object's occupant list + plobj.addToOccupants(bodoid); + + } finally { + source.commitTransaction(); + } + } finally { + plobj.commitTransaction(); + } + + } finally { + // and finally queue up an event to release the lock once these events are processed + source.releaseLock("moveToLock"); + } + + return pmgr.getConfig(); + } + + /** + * Removes the specified body from the place object they currently occupy. Does nothing if the + * body is not currently in a place. + */ + public void leaveOccupiedPlace (BodyObject source) + { + Place oldloc = source.location; + int bodoid = source.getOid(); + + // nothing to do if they weren't previously in some location + if (oldloc == null) { + return; + } + + // remove them from the occupant list + PlaceObject plobj = null; + try { + plobj = (PlaceObject)_omgr.getObject(oldloc.placeOid); + if (plobj != null) { + Integer key = Integer.valueOf(bodoid); + plobj.startTransaction(); + try { + // remove their occupant info (which is keyed on oid) + plobj.removeFromOccupantInfo(key); + // and remove them from the occupant list + plobj.removeFromOccupants(bodoid); + + } finally { + plobj.commitTransaction(); + } + + } else { + log.info("Body's prior location no longer around? [boid=" + bodoid + + ", place=" + oldloc + "]."); + } + + } catch (ClassCastException cce) { + log.warning("Body claims to occupy non-PlaceObject!? [boid=" + bodoid + + ", place=" + oldloc + ", error=" + cce + "]."); + } + + // clear out their location + source.didLeavePlace(plobj); + } + + /** + * Forcibly moves the specified body object to the new place. This is accomplished by first + * removing the client from their old location and then sending the client a notification, + * instructing it to move to the new location (which it does using the normal moveTo service). + * This has the benefit that the client is removed from their old place regardless of whether + * or not they are cooperating. If they choose to ignore the forced move request, they will + * remain in limbo, unable to do much of anything. + */ + public void moveBody (BodyObject source, Place place) + { + // first remove them from their old place + leaveOccupiedPlace(source); + + // then send a forced move notification + LocationSender.forcedMove(source, place.placeOid); + } + + @Inject protected RootDObjectManager _omgr; + @Inject protected PlaceRegistry _plreg; + @Inject protected ClientManager _clmgr; +} diff --git a/src/java/com/threerings/crowd/server/LocationProvider.java b/src/java/com/threerings/crowd/server/LocationProvider.java index e91acd649..ec04bd4fd 100644 --- a/src/java/com/threerings/crowd/server/LocationProvider.java +++ b/src/java/com/threerings/crowd/server/LocationProvider.java @@ -2,7 +2,7 @@ // $Id$ // // Narya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved +// Copyright (C) 2002-2008 Three Rings Design, Inc., All Rights Reserved // http://www.threerings.net/code/narya/ // // This library is free software; you can redistribute it and/or modify it @@ -21,218 +21,24 @@ package com.threerings.crowd.server; -import com.threerings.presents.dobj.RootDObjectManager; - -import com.threerings.presents.data.ClientObject; - -import com.threerings.presents.server.InvocationException; -import com.threerings.presents.server.InvocationManager; -import com.threerings.presents.server.InvocationProvider; -import com.threerings.presents.server.PresentsClient; - import com.threerings.crowd.client.LocationService; -import com.threerings.crowd.data.BodyObject; -import com.threerings.crowd.data.LocationCodes; -import com.threerings.crowd.data.Place; -import com.threerings.crowd.data.PlaceConfig; -import com.threerings.crowd.data.PlaceObject; -import com.threerings.crowd.server.CrowdServer; - -import static com.threerings.crowd.Log.log; +import com.threerings.presents.data.ClientObject; +import com.threerings.presents.server.InvocationException; +import com.threerings.presents.server.InvocationProvider; /** - * This class provides the server end of the location services. + * Defines the server-side of the {@link LocationService}. */ -public class LocationProvider - implements LocationCodes, InvocationProvider +public interface LocationProvider extends InvocationProvider { /** - * Creates a location provider and prepares it for operation. + * Handles a {@link LocationService#leavePlace} request. */ - public LocationProvider (InvocationManager invmgr, RootDObjectManager omgr, PlaceRegistry plreg) - { - // we'll need these later - _invmgr = invmgr; - _omgr = omgr; - _plreg = plreg; - } + public void leavePlace (ClientObject caller); /** - * Requests that this client's body be moved to the specified location. - * - * @param caller the client object of the client that invoked this remotely callable method. - * @param place the oid of the place to which the body should be moved. - * @param listener the listener that will be informed of success or failure. + * Handles a {@link LocationService#moveTo} request. */ - public void moveTo (ClientObject caller, int placeOid, LocationService.MoveListener listener) - throws InvocationException - { - // do the move and send the response - listener.moveSucceeded(moveTo((BodyObject)caller, placeOid)); - } - - /** - * Requests that we leave our current place and move to nowhere land. - */ - public void leavePlace (ClientObject caller) - throws InvocationException - { - leaveOccupiedPlace((BodyObject)caller); - } - - /** - * Moves the specified body from whatever location they currently occupy to the location - * identified by the supplied place oid. - * - * @return the config object for the new location. - * - * @exception ServiceFaildException thrown if the move was not successful for some reason - * (which will be communicated as an error code in the exception's message data). - */ - public PlaceConfig moveTo (BodyObject source, int placeOid) - throws InvocationException - { - int bodoid = source.getOid(); - - // make sure the place in question actually exists - PlaceManager pmgr = _plreg.getPlaceManager(placeOid); - if (pmgr == null) { - log.info("Requested to move to non-existent place [who=" + source.who() + - ", placeOid=" + placeOid + "]."); - throw new InvocationException(NO_SUCH_PLACE); - } - - // if they're already in the location they're asking to move to, just give them the config - // because we don't need to update anything in distributed object world - Place place = pmgr.getLocation(); - if (place.equals(source.location)) { - log.debug("Going along with client request to move to where they already are " + - "[source=" + source.who() + ", place=" + place + "]."); - return pmgr.getConfig(); - } - - // make sure they have access to the specified place - String errmsg; - if ((errmsg = pmgr.ratifyBodyEntry(source)) != null) { - throw new InvocationException(errmsg); - } - - // acquire a lock on the body object to avoid breakage by rapid fire moveTo requests - if (!source.acquireLock("moveToLock")) { - // if we're still locked, a previous moveTo request hasn't been fully processed - throw new InvocationException(MOVE_IN_PROGRESS); - } - - // configure the client accordingly if the place uses a custom class loader - PresentsClient client = CrowdServer.clmgr.getClient(source.username); - if (client != null) { - client.setClassLoader(_plreg.getClassLoader(pmgr.getConfig())); - } - - try { - PlaceObject plobj = pmgr.getPlaceObject(); - - // the doubly nested try catch is to prevent failure if one or the other of the - // transactions fails to start - plobj.startTransaction(); - try { - source.startTransaction(); - try { - // remove them from any previous location - leaveOccupiedPlace(source); - - // generate a new occinfo record (which will add it to the target location) - pmgr.buildOccupantInfo(source); - - // set the body's new location - source.willEnterPlace(place, plobj); - - // add the body oid to the place object's occupant list - plobj.addToOccupants(bodoid); - - } finally { - source.commitTransaction(); - } - } finally { - plobj.commitTransaction(); - } - - } finally { - // and finally queue up an event to release the lock once these events are processed - source.releaseLock("moveToLock"); - } - - return pmgr.getConfig(); - } - - /** - * Removes the specified body from the place object they currently occupy. Does nothing if the - * body is not currently in a place. - */ - public void leaveOccupiedPlace (BodyObject source) - { - Place oldloc = source.location; - int bodoid = source.getOid(); - - // nothing to do if they weren't previously in some location - if (oldloc == null) { - return; - } - - // remove them from the occupant list - PlaceObject plobj = null; - try { - plobj = (PlaceObject)_omgr.getObject(oldloc.placeOid); - if (plobj != null) { - Integer key = Integer.valueOf(bodoid); - plobj.startTransaction(); - try { - // remove their occupant info (which is keyed on oid) - plobj.removeFromOccupantInfo(key); - // and remove them from the occupant list - plobj.removeFromOccupants(bodoid); - - } finally { - plobj.commitTransaction(); - } - - } else { - log.info("Body's prior location no longer around? [boid=" + bodoid + - ", place=" + oldloc + "]."); - } - - } catch (ClassCastException cce) { - log.warning("Body claims to occupy non-PlaceObject!? [boid=" + bodoid + - ", place=" + oldloc + ", error=" + cce + "]."); - } - - // clear out their location - source.didLeavePlace(plobj); - } - - /** - * Forcibly moves the specified body object to the new place. This is accomplished by first - * removing the client from their old location and then sending the client a notification, - * instructing it to move to the new location (which it does using the normal moveTo service). - * This has the benefit that the client is removed from their old place regardless of whether - * or not they are cooperating. If they choose to ignore the forced move request, they will - * remain in limbo, unable to do much of anything. - */ - public void moveBody (BodyObject source, Place place) - { - // first remove them from their old place - leaveOccupiedPlace(source); - - // then send a forced move notification - LocationSender.forcedMove(source, place.placeOid); - } - - /** The invocation manager with which we interoperate. */ - protected InvocationManager _invmgr; - - /** The distributed object manager with which we interoperate. */ - protected RootDObjectManager _omgr; - - /** The place registry with which we interoperate. */ - protected PlaceRegistry _plreg; + public void moveTo (ClientObject caller, int arg1, LocationService.MoveListener arg2) + throws InvocationException; } diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index 651fcbfdc..b729781b4 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -36,7 +36,6 @@ import com.samskivert.util.StringUtil; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.AccessController; import com.threerings.presents.dobj.DObject; -import com.threerings.presents.dobj.DObjectManager; import com.threerings.presents.dobj.DynamicListener; import com.threerings.presents.dobj.EntryUpdatedEvent; import com.threerings.presents.dobj.MessageEvent; @@ -46,9 +45,9 @@ import com.threerings.presents.dobj.ObjectDeathListener; import com.threerings.presents.dobj.ObjectDestroyedEvent; import com.threerings.presents.dobj.ObjectRemovedEvent; import com.threerings.presents.dobj.OidListListener; +import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.dobj.SetAdapter; import com.threerings.presents.server.InvocationManager; -import com.threerings.presents.server.PresentsDObjectMgr; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.data.OccupantInfo; @@ -168,8 +167,7 @@ public class PlaceManager { // update the canonical copy _occInfo.put(occInfo.getBodyOid(), occInfo); - // clone the canonical copy and send out an event updating the distributed set with that - // clone + // clone the canonical copy and send an event updating the distributed set with that clone _plobj.updateOccupantInfo((OccupantInfo)occInfo.clone()); } @@ -177,7 +175,7 @@ public class PlaceManager * Called by the place registry after creating this place manager. */ public void init (PlaceRegistry registry, InvocationManager invmgr, - DObjectManager omgr, PlaceConfig config) + RootDObjectManager omgr, PlaceConfig config) { _registry = registry; _invmgr = invmgr; @@ -263,7 +261,7 @@ public class PlaceManager public void shutdown () { // destroy the object and everything will follow from that - CrowdServer.omgr.destroyObject(_plobj.getOid()); + _omgr.destroyObject(_plobj.getOid()); // clear out our services if (_plobj.speakService != null) { @@ -349,7 +347,7 @@ public class PlaceManager // the first argument should be the client object of the caller or null if it is // a server-originated event int srcoid = event.getSourceOid(); - DObject source = (srcoid <= 0) ? null : CrowdServer.omgr.getObject(srcoid); + DObject source = (srcoid <= 0) ? null : _omgr.getObject(srcoid); Object[] args = event.getArgs(), nargs; if (args == null) { nargs = new Object[] { source }; @@ -636,7 +634,7 @@ public class PlaceManager // queue up a shutdown interval, unless we've already got one. long idlePeriod = idleUnloadPeriod(); if (idlePeriod > 0L && _shutdownInterval == null) { - _shutdownInterval = new Interval((PresentsDObjectMgr)_omgr) { + _shutdownInterval = new Interval(_omgr) { public void expired () { log.debug("Unloading idle place '" + where () + "'."); shutdown(); @@ -693,7 +691,7 @@ public class PlaceManager protected InvocationManager _invmgr; /** A distributed object manager for doing dobj stuff. */ - protected DObjectManager _omgr; + protected RootDObjectManager _omgr; /** A reference to the place object that we manage. */ protected PlaceObject _plobj; diff --git a/src/java/com/threerings/crowd/server/PlaceRegistry.java b/src/java/com/threerings/crowd/server/PlaceRegistry.java index c261fa9ff..4eec0f31b 100644 --- a/src/java/com/threerings/crowd/server/PlaceRegistry.java +++ b/src/java/com/threerings/crowd/server/PlaceRegistry.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import com.google.inject.Inject; +import com.google.inject.Injector; import com.google.inject.Singleton; import com.samskivert.util.IntMap; @@ -57,39 +58,32 @@ public class PlaceRegistry public void invoke (PlaceManager plmgr); } - /** The location provider used by the place registry to provide location-related invocation - * services. */ - public LocationProvider locprov; - /** * Creates and initializes the place registry. This is called by the server during its * initialization phase. */ - @Inject public PlaceRegistry (ShutdownManager shutmgr, InvocationManager invmgr, - RootDObjectManager omgr) + @Inject public PlaceRegistry (ShutdownManager shutmgr) { shutmgr.registerShutdowner(this); - - // create and register our location provider - locprov = new LocationProvider(invmgr, omgr, this); - invmgr.registerDispatcher(new LocationDispatcher(locprov), CrowdCodes.CROWD_GROUP); - - // we'll need these later - _omgr = omgr; - _invmgr = invmgr; } /** - * By overriding this method, it is possible to customize the place registry to cause it to - * load the classes associated with a particular place via a custom class loader. That loader - * may enforce restricted privileges or obtain the classes from some special source. - * - * @return the class loader to use when instantiating the {@link PlaceManager} associated with - * the supplied {@link PlaceConfig}. This method must not return null. + * Provides the place registry with access to an injector that it can use to create {@link + * PlaceManager} instances with all dependencies resolved. This is called by the {@link + * CrowdServer} during the server initialization phase. */ - public ClassLoader getClassLoader (PlaceConfig config) + public void setInjector (Injector injector) { - return getClass().getClassLoader(); + _injector = injector; + } + + /** + * Returns the place manager associated with the specified place object id or null if no such + * place exists. + */ + public PlaceManager getPlaceManager (int placeOid) + { + return _pmgrs.get(placeOid); } /** @@ -142,15 +136,6 @@ public class PlaceRegistry return createPlace(config, null, hook); } - /** - * Returns the place manager associated with the specified place object id or null if no such - * place exists. - */ - public PlaceManager getPlaceManager (int placeOid) - { - return _pmgrs.get(placeOid); - } - /** * Returns an enumeration of all of the registered place objects. This should only be accessed * on the dobjmgr thread and shouldn't be kept around across event dispatches. @@ -204,12 +189,10 @@ public class PlaceRegistry throws InstantiationException, InvocationException { PlaceManager pmgr = null; - ClassLoader loader = getClassLoader(config); try { // create a place manager using the class supplied in the place config - pmgr = (PlaceManager)Class.forName( - config.getManagerClassName(), true, loader).newInstance(); + pmgr = createPlaceManager(config); // if we have delegates, add them if (delegates != null) { @@ -226,8 +209,7 @@ public class PlaceRegistry throw new InstantiationException("Error creating PlaceManager for " + config); } - // give the manager an opportunity to abort the whole process if it fails any permissions - // checks + // let the manager abort the whole process if it fails any permissions checks String errmsg = pmgr.checkPermissions(); if (errmsg != null) { // give the place manager a chance to clean up after its early initialization process @@ -256,6 +238,20 @@ public class PlaceRegistry return pmgr; } + /** + * Creates an instance of a {@link PlaceManager} using the information in the supplied place + * config. Derived classes may wish to specialize this process for certain places for example + * loading user supplied place management code from a special class loader that sandboxes their + * code. + */ + protected PlaceManager createPlaceManager (PlaceConfig config) + throws Exception + { + @SuppressWarnings("unchecked") Class clazz = + (Class) Class.forName(config.getManagerClassName()); + return _injector.getInstance(clazz); + } + /** * Called by the place manager when it has been shut down. */ @@ -273,10 +269,13 @@ public class PlaceRegistry } /** The invocation manager with which we operate. */ - protected InvocationManager _invmgr; + @Inject protected InvocationManager _invmgr; /** The distributed object manager with which we operate. */ - protected RootDObjectManager _omgr; + @Inject protected RootDObjectManager _omgr; + + /** We use this to inject dependencies into place managers that we create. */ + protected Injector _injector; /** A mapping from place object id to place manager. */ protected IntMap _pmgrs = IntMaps.newHashIntMap(); diff --git a/tests/src/java/com/threerings/bureau/server/RegistryTester.java b/tests/src/java/com/threerings/bureau/server/RegistryTester.java index 884a58918..55bb605ee 100644 --- a/tests/src/java/com/threerings/bureau/server/RegistryTester.java +++ b/tests/src/java/com/threerings/bureau/server/RegistryTester.java @@ -30,10 +30,11 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Singleton; -import com.threerings.bureau.data.AgentObject; - +import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.server.ShutdownManager; +import com.threerings.bureau.data.AgentObject; + import static com.threerings.bureau.Log.log; /** @@ -173,11 +174,11 @@ public class RegistryTester } // create or destroy some agents - TestServer.omgr.postRunnable(createOrDestroyAgents); + _omgr.postRunnable(createOrDestroyAgents); } // clean up - TestServer.omgr.postRunnable(new Runnable() { + _omgr.postRunnable(new Runnable() { public void run () { for (AgentObject obj : _agents) { TestServer.breg.destroyAgent(obj); @@ -217,6 +218,8 @@ public class RegistryTester return obj; } + @Inject protected RootDObjectManager _omgr; + protected TestServer _server; protected boolean _stop; protected Random _rng1;