Bureaucracy review updates and hello world test
* Fleshed out client-side Agent class, made abstract * Delegate the creation of the bureau director to subclasses of BureauClient * Moved BureauDirector's BureauReceiver and Subscriber implementations to anonymous classes that delegate to protected methods. * Use SafeSubscriber * Added new service method for notiyfing the server when the creation of an agent fails so that the registry is not perpetually waiting * Made BureauCredentials more conformant * Made BureauRegistry respond properly to client logging off * Got rid of superfluous uses of safeToString * Changed Launcher to CommandGenerator and now use ProcessBuilder and copyMergedOutput * Changed bureau process parameters to server name and port instead of URL git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5030 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -26,10 +26,28 @@ import com.threerings.bureau.data.AgentObject;
|
|||||||
/**
|
/**
|
||||||
* Represents an agent running within a bureau client.
|
* Represents an agent running within a bureau client.
|
||||||
*/
|
*/
|
||||||
public class Agent
|
public abstract class Agent
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Initializes the Agent with the distributed agent object.
|
||||||
|
*/
|
||||||
|
public void init (AgentObject agentObj)
|
||||||
|
{
|
||||||
|
_agentObj = agentObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the code running in the agent.
|
||||||
|
*/
|
||||||
|
public abstract void start ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the code running in the agent.
|
||||||
|
*/
|
||||||
|
public abstract void stop ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shared agent object.
|
* The shared agent object.
|
||||||
*/
|
*/
|
||||||
public AgentObject agentObject;
|
protected AgentObject _agentObj;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import com.samskivert.util.Config;
|
|||||||
/**
|
/**
|
||||||
* Represents a client embedded in a bureau.
|
* Represents a client embedded in a bureau.
|
||||||
*/
|
*/
|
||||||
public class BureauClient extends Client
|
public abstract class BureauClient extends Client
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new client.
|
* Creates a new client.
|
||||||
@@ -45,14 +45,16 @@ public class BureauClient extends Client
|
|||||||
|
|
||||||
_bureauId = bureauId;
|
_bureauId = bureauId;
|
||||||
|
|
||||||
BureauCredentials creds = new BureauCredentials();
|
BureauCredentials creds = new BureauCredentials(_bureauId);
|
||||||
creds.sessionToken = token;
|
creds.sessionToken = token;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
|
|
||||||
_ctx = createContext();
|
_ctx = createContext();
|
||||||
_director = new BureauDirector(_ctx);
|
_director = createDirector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract BureauDirector createDirector ();
|
||||||
|
|
||||||
protected BureauContext createContext ()
|
protected BureauContext createContext ()
|
||||||
{
|
{
|
||||||
return new BureauContext () {
|
return new BureauContext () {
|
||||||
|
|||||||
@@ -3,81 +3,31 @@ package com.threerings.bureau.client;
|
|||||||
import com.threerings.presents.client.BasicDirector;
|
import com.threerings.presents.client.BasicDirector;
|
||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
import com.threerings.bureau.data.BureauCodes;
|
import com.threerings.bureau.data.BureauCodes;
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.IntMap;
|
||||||
|
import com.samskivert.util.IntMaps;
|
||||||
import com.threerings.bureau.data.AgentObject;
|
import com.threerings.bureau.data.AgentObject;
|
||||||
import com.threerings.bureau.Log;
|
import com.threerings.bureau.Log;
|
||||||
import com.threerings.bureau.util.BureauContext;
|
import com.threerings.bureau.util.BureauContext;
|
||||||
import com.threerings.presents.client.Client;
|
import com.threerings.presents.client.Client;
|
||||||
import com.threerings.presents.dobj.Subscriber;
|
import com.threerings.presents.dobj.Subscriber;
|
||||||
|
import com.threerings.presents.util.SafeSubscriber;
|
||||||
import com.threerings.presents.dobj.ObjectAccessException;
|
import com.threerings.presents.dobj.ObjectAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows the server to create and destroy agents on a client.
|
* Allows the server to create and destroy agents on a client.
|
||||||
* @see BureauRegistry
|
* @see BureauRegistry
|
||||||
*/
|
*/
|
||||||
public class BureauDirector extends BasicDirector
|
public abstract class BureauDirector extends BasicDirector
|
||||||
implements BureauReceiver, Subscriber<AgentObject>
|
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new BureauDirector.
|
||||||
|
*/
|
||||||
public BureauDirector (BureauContext ctx)
|
public BureauDirector (BureauContext ctx)
|
||||||
{
|
{
|
||||||
super(ctx);
|
super(ctx);
|
||||||
_ctx = ctx;
|
_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from BureauReceiver
|
|
||||||
public synchronized void createAgent (int agentId)
|
|
||||||
{
|
|
||||||
_ctx.getDObjectManager().subscribeToObject(agentId, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// from BureauReceiver
|
|
||||||
public synchronized void destroyAgent (int agentId)
|
|
||||||
{
|
|
||||||
Agent agent = null;
|
|
||||||
try {
|
|
||||||
agent = _agents.remove(agentId);
|
|
||||||
// TODO: stop the agent somehow
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
Log.warning("Could not create agent [id=" + agentId + "]");
|
|
||||||
Log.logStackTrace(t);
|
|
||||||
// TODO: failure notification?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ctx.getDObjectManager().unsubscribeFromObject(agentId, this);
|
|
||||||
doStopAgent(agent);
|
|
||||||
_bureauService.agentDestroyed(_ctx.getClient(), agentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// from Subscriber
|
|
||||||
public synchronized void objectAvailable (AgentObject agentObject)
|
|
||||||
{
|
|
||||||
int oid = agentObject.getOid();
|
|
||||||
try {
|
|
||||||
Agent agent = new Agent();
|
|
||||||
agent.agentObject = agentObject;
|
|
||||||
doStartAgent(agent);
|
|
||||||
_agents.put(oid, agent);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
Log.warning("Could not create agent [obj=" + agentObject + "]");
|
|
||||||
Log.logStackTrace(e);
|
|
||||||
// TODO: failure notification?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: post to runqueue?
|
|
||||||
_bureauService.agentCreated(_ctx.getClient(), oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// from Subscriber
|
|
||||||
public synchronized void requestFailed (int oid, ObjectAccessException cause)
|
|
||||||
{
|
|
||||||
Log.warning("Could not subscribe to agent [oid=" + oid + "]");
|
|
||||||
Log.logStackTrace(cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override // from BasicDirector
|
@Override // from BasicDirector
|
||||||
public void clientDidLogon (Client client)
|
public void clientDidLogon (Client client)
|
||||||
{
|
{
|
||||||
@@ -85,6 +35,79 @@ public class BureauDirector extends BasicDirector
|
|||||||
_bureauService.bureauInitialized(_ctx.getClient(), _ctx.getBureauId());
|
_bureauService.bureauInitialized(_ctx.getClient(), _ctx.getBureauId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new agent when the server requests it.
|
||||||
|
*/
|
||||||
|
protected synchronized void createAgent (int agentId)
|
||||||
|
{
|
||||||
|
Subscriber<AgentObject> delegator = new Subscriber<AgentObject>() {
|
||||||
|
public void objectAvailable (AgentObject agentObject) {
|
||||||
|
BureauDirector.this.objectAvailable(agentObject);
|
||||||
|
}
|
||||||
|
public void requestFailed (int oid, ObjectAccessException cause) {
|
||||||
|
BureauDirector.this.requestFailed(oid, cause);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_subscriber = new SafeSubscriber<AgentObject>(agentId, delegator);
|
||||||
|
_subscriber.subscribe(_ctx.getDObjectManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys an agent at the server's request.
|
||||||
|
*/
|
||||||
|
protected synchronized void destroyAgent (int agentId)
|
||||||
|
{
|
||||||
|
Agent agent = null;
|
||||||
|
agent = _agents.remove(agentId);
|
||||||
|
|
||||||
|
if (agent == null) {
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
agent.stop();
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
Log.warning("Stopping an agent caused an exception");
|
||||||
|
Log.logStackTrace(t);
|
||||||
|
}
|
||||||
|
_subscriber.unsubscribe(_ctx.getDObjectManager());
|
||||||
|
_bureauService.agentDestroyed(_ctx.getClient(), agentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the a request to subscribe to an object finishes and the object is available.
|
||||||
|
*/
|
||||||
|
protected synchronized void objectAvailable (AgentObject agentObject)
|
||||||
|
{
|
||||||
|
int oid = agentObject.getOid();
|
||||||
|
Agent agent;
|
||||||
|
try {
|
||||||
|
agent = createAgent(agentObject);
|
||||||
|
agent.init(agentObject);
|
||||||
|
agent.start();
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
Log.warning("Could not create agent [obj=" + agentObject + "]");
|
||||||
|
Log.logStackTrace(t);
|
||||||
|
_bureauService.agentCreationFailed(_ctx.getClient(), oid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_agents.put(oid, agent);
|
||||||
|
_bureauService.agentCreated(_ctx.getClient(), oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the a request to subscribe to an object fails.
|
||||||
|
*/
|
||||||
|
protected synchronized void requestFailed (int oid, ObjectAccessException cause)
|
||||||
|
{
|
||||||
|
Log.warning("Could not subscribe to agent [oid=" + oid + "]");
|
||||||
|
Log.logStackTrace(cause);
|
||||||
|
}
|
||||||
|
|
||||||
@Override // from BasicDirector
|
@Override // from BasicDirector
|
||||||
protected void registerServices (Client client)
|
protected void registerServices (Client client)
|
||||||
{
|
{
|
||||||
@@ -95,8 +118,17 @@ public class BureauDirector extends BasicDirector
|
|||||||
|
|
||||||
// Set up our decoder so we can receive method calls
|
// Set up our decoder so we can receive method calls
|
||||||
// from the server
|
// from the server
|
||||||
|
BureauReceiver receiver = new BureauReceiver () {
|
||||||
|
public void createAgent (int agentId) {
|
||||||
|
BureauDirector.this.createAgent(agentId);
|
||||||
|
}
|
||||||
|
public void destroyAgent (int agentId) {
|
||||||
|
BureauDirector.this.destroyAgent(agentId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
client.getInvocationDirector().
|
client.getInvocationDirector().
|
||||||
registerReceiver(new BureauDecoder(this));
|
registerReceiver(new BureauDecoder(receiver));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // from BasicDirector
|
@Override // from BasicDirector
|
||||||
@@ -108,21 +140,16 @@ public class BureauDirector extends BasicDirector
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the agent object is ready and it is time to run his code.
|
* Called when it is time to create an Agent. Subclasses should read the
|
||||||
|
* <code>agentObject</code>'s type and/or properties to determine what kind of Agent to
|
||||||
|
* create.
|
||||||
|
* @param agentObj the distributed and object
|
||||||
|
* @return a new Agent that will govern the distributed object
|
||||||
*/
|
*/
|
||||||
protected void doStartAgent (Agent agent)
|
protected abstract Agent createAgent (AgentObject agentObj);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the agent object is being destroyed and the client code should stop
|
|
||||||
* processing.
|
|
||||||
*/
|
|
||||||
protected void doStopAgent (Agent agent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BureauContext _ctx;
|
protected BureauContext _ctx;
|
||||||
protected BureauService _bureauService;
|
protected BureauService _bureauService;
|
||||||
protected HashIntMap<Agent> _agents = new HashIntMap<Agent>();
|
protected IntMap<Agent> _agents = IntMaps.newHashIntMap();
|
||||||
|
protected SafeSubscriber<AgentObject> _subscriber;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,17 @@ public interface BureauService extends InvocationService
|
|||||||
void bureauInitialized (Client client, String bureauId);
|
void bureauInitialized (Client client, String bureauId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the server that a previosuly requested agent is not created and ready to use.
|
* Notify the server that a previosuly requested agent is now created and ready to use.
|
||||||
* @see BureauReceiver#createAgent
|
* @see BureauReceiver#createAgent
|
||||||
*/
|
*/
|
||||||
void agentCreated (Client client, int agentId);
|
void agentCreated (Client client, int agentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the server that a previosuly requested agent could not be created.
|
||||||
|
* @see BureauReceiver#createAgent
|
||||||
|
*/
|
||||||
|
void agentCreationFailed (Client client, int agentId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the server that an agent is no longer running. Normally called in response
|
* Notify the server that an agent is no longer running. Normally called in response
|
||||||
* to a call to <code>destroyAgent</code>
|
* to a call to <code>destroyAgent</code>
|
||||||
|
|||||||
@@ -24,15 +24,35 @@ package com.threerings.bureau.data;
|
|||||||
import com.threerings.presents.net.Credentials;
|
import com.threerings.presents.net.Credentials;
|
||||||
import com.threerings.util.Name;
|
import com.threerings.util.Name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the basic credentials to provide bureau-specific fields.
|
||||||
|
*/
|
||||||
public class BureauCredentials extends Credentials
|
public class BureauCredentials extends Credentials
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The token to pass to the server when logging in. This is usually just passed to the bureau
|
* The token to pass to the server when logging in. This is usually just passed to the bureau
|
||||||
* on the command line to guard against outside connections being established. */
|
* on the command line to guard against outside connections being established.
|
||||||
|
*/
|
||||||
public String sessionToken;
|
public String sessionToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty credentials for streaming. Should not be used directly.
|
||||||
|
*/
|
||||||
public BureauCredentials ()
|
public BureauCredentials ()
|
||||||
{
|
{
|
||||||
super(new Name("$$$BUREAU$$$"));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new credentials for a specific bureau.
|
||||||
|
*/
|
||||||
|
public BureauCredentials (String bureauId)
|
||||||
|
{
|
||||||
|
super(new Name("@@bureau:" + bureauId + "@@"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// inherit documentation - from Object
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return super.toString() + ", token=" + sessionToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,19 @@ public class BureauMarshaller extends InvocationMarshaller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The method id used to dispatch {@link #agentCreationFailed} requests. */
|
||||||
|
public static final int AGENT_CREATION_FAILED = 2;
|
||||||
|
|
||||||
|
// from interface BureauService
|
||||||
|
public void agentCreationFailed (Client arg1, int arg2)
|
||||||
|
{
|
||||||
|
sendRequest(arg1, AGENT_CREATION_FAILED, new Object[] {
|
||||||
|
Integer.valueOf(arg2)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #agentDestroyed} requests. */
|
/** The method id used to dispatch {@link #agentDestroyed} requests. */
|
||||||
public static final int AGENT_DESTROYED = 2;
|
public static final int AGENT_DESTROYED = 3;
|
||||||
|
|
||||||
// from interface BureauService
|
// from interface BureauService
|
||||||
public void agentDestroyed (Client arg1, int arg2)
|
public void agentDestroyed (Client arg1, int arg2)
|
||||||
@@ -59,7 +70,7 @@ public class BureauMarshaller extends InvocationMarshaller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The method id used to dispatch {@link #bureauInitialized} requests. */
|
/** The method id used to dispatch {@link #bureauInitialized} requests. */
|
||||||
public static final int BUREAU_INITIALIZED = 3;
|
public static final int BUREAU_INITIALIZED = 4;
|
||||||
|
|
||||||
// from interface BureauService
|
// from interface BureauService
|
||||||
public void bureauInitialized (Client arg1, String arg2)
|
public void bureauInitialized (Client arg1, String arg2)
|
||||||
|
|||||||
@@ -63,6 +63,13 @@ public class BureauDispatcher extends InvocationDispatcher
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case BureauMarshaller.AGENT_CREATION_FAILED:
|
||||||
|
((BureauProvider)provider).agentCreationFailed(
|
||||||
|
source,
|
||||||
|
((Integer)args[0]).intValue()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
case BureauMarshaller.AGENT_DESTROYED:
|
case BureauMarshaller.AGENT_DESTROYED:
|
||||||
((BureauProvider)provider).agentDestroyed(
|
((BureauProvider)provider).agentDestroyed(
|
||||||
source,
|
source,
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ public interface BureauProvider extends InvocationProvider
|
|||||||
*/
|
*/
|
||||||
public void agentCreated (ClientObject caller, int arg1);
|
public void agentCreated (ClientObject caller, int arg1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a {@link BureauService#agentCreationFailed} request.
|
||||||
|
*/
|
||||||
|
public void agentCreationFailed (ClientObject caller, int arg1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a {@link BureauService#agentDestroyed} request.
|
* Handles a {@link BureauService#agentDestroyed} request.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,8 +30,11 @@ import com.threerings.bureau.data.AgentObject;
|
|||||||
import com.threerings.bureau.data.BureauCodes;
|
import com.threerings.bureau.data.BureauCodes;
|
||||||
import com.threerings.presents.data.ClientObject;
|
import com.threerings.presents.data.ClientObject;
|
||||||
import com.threerings.presents.dobj.RootDObjectManager;
|
import com.threerings.presents.dobj.RootDObjectManager;
|
||||||
|
import com.threerings.presents.dobj.ObjectDeathListener;
|
||||||
|
import com.threerings.presents.dobj.ObjectDestroyedEvent;
|
||||||
import com.threerings.presents.server.InvocationManager;
|
import com.threerings.presents.server.InvocationManager;
|
||||||
import static com.samskivert.util.StringUtil.safeToString;
|
import com.samskivert.util.StringUtil;
|
||||||
|
import com.samskivert.util.ProcessLogger;
|
||||||
|
|
||||||
import com.threerings.bureau.Log;
|
import com.threerings.bureau.Log;
|
||||||
|
|
||||||
@@ -42,31 +45,37 @@ import com.threerings.bureau.Log;
|
|||||||
public class BureauRegistry
|
public class BureauRegistry
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Defines a way to launch a bureau. Launchers are set by the server on startup and are
|
* Defines the commands that are responsible for invoking a bureau. Instances are associated to
|
||||||
* invoked whenever an agent is requested whose bureauType matches the registered type.
|
* bureau types by the server on startup. The instances are used whenever the registry needs to
|
||||||
* @see registerBureau
|
* launch a bureau for an agent with the assocated bureau type.
|
||||||
|
* @see setCommandGenerator
|
||||||
*/
|
*/
|
||||||
public static interface Launcher
|
public static interface CommandGenerator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Launches a new bureau using the given server connect-back url and other information.
|
* Launches a new bureau using the given server connect-back url and other information.
|
||||||
* Called by the registry when it decides a new bureau is needed.
|
* Called by the registry when it decides a new bureau is needed.
|
||||||
* @param serverUrl the url the bureau should use to connect back to the server
|
* @param serverNameAndPort the name and port the bureau should use to connect back to the
|
||||||
|
* server, e.g. server.com:47624
|
||||||
* @param bureauId the id of the bureau being launched
|
* @param bureauId the id of the bureau being launched
|
||||||
* @param token the token string to use for the credentials when logging in
|
* @param token the token string to use for the credentials when logging in
|
||||||
|
* @return the builder, ready to launch
|
||||||
*/
|
*/
|
||||||
Process launch (String serverUrl, String bureauId, String token);
|
String[] createCommand (
|
||||||
|
String serverNameAndPort,
|
||||||
|
String bureauId,
|
||||||
|
String token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new registry, prepared to provide bureau services.
|
* Creates a new registry, prepared to provide bureau services.
|
||||||
*/
|
*/
|
||||||
public BureauRegistry (
|
public BureauRegistry (
|
||||||
String serverUrl,
|
String serverNameAndPort,
|
||||||
InvocationManager invmgr,
|
InvocationManager invmgr,
|
||||||
RootDObjectManager omgr)
|
RootDObjectManager omgr)
|
||||||
{
|
{
|
||||||
_serverUrl = serverUrl;
|
_serverNameAndPort = serverNameAndPort;
|
||||||
_invmgr = invmgr;
|
_invmgr = invmgr;
|
||||||
_omgr = omgr;
|
_omgr = omgr;
|
||||||
|
|
||||||
@@ -74,9 +83,12 @@ public class BureauRegistry
|
|||||||
public void bureauInitialized (ClientObject client, String bureauId) {
|
public void bureauInitialized (ClientObject client, String bureauId) {
|
||||||
BureauRegistry.this.bureauInitialized(client, bureauId);
|
BureauRegistry.this.bureauInitialized(client, bureauId);
|
||||||
}
|
}
|
||||||
public void agentCreated (ClientObject client, int agentId) {
|
public void agentCreated (ClientObject client, int agentId) {
|
||||||
BureauRegistry.this.agentCreated(client, agentId);
|
BureauRegistry.this.agentCreated(client, agentId);
|
||||||
}
|
}
|
||||||
|
public void agentCreationFailed (ClientObject client, int agentId) {
|
||||||
|
BureauRegistry.this.agentCreationFailed(client, agentId);
|
||||||
|
}
|
||||||
public void agentDestroyed (ClientObject client, int agentId) {
|
public void agentDestroyed (ClientObject client, int agentId) {
|
||||||
BureauRegistry.this.agentDestroyed(client, agentId);
|
BureauRegistry.this.agentDestroyed(client, agentId);
|
||||||
}
|
}
|
||||||
@@ -88,20 +100,21 @@ public class BureauRegistry
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a launcher of a given type. When an agent is started and no bureaus are currently
|
* Registers a command generator for a given type. When an agent is started and no bureaus are
|
||||||
* running, the <code>bureauType</code> is used to determine the <code>Launcher</code> to call.
|
* running, the <code>bureauType</code> is used to determine the <code>CommandGenerator</code>
|
||||||
|
* instance to call.
|
||||||
* @param bureauType the type of bureau that will be launched
|
* @param bureauType the type of bureau that will be launched
|
||||||
* @param launcher the launcher to be used when the <code>bureauType</code> is requested
|
* @param cmdGenerator the generator to be used for bureaus of <code>bureauType</code>
|
||||||
*/
|
*/
|
||||||
public void setLauncher (String bureauType, Launcher launcher)
|
public void setCommandGenerator (String bureauType, CommandGenerator cmdGenerator)
|
||||||
{
|
{
|
||||||
if (_launchers.get(bureauType) != null) {
|
if (_generators.get(bureauType) != null) {
|
||||||
Log.warning("Launcher for type already exists [type=" +
|
Log.warning("Generator for type already exists [type=" +
|
||||||
bureauType + "]");
|
bureauType + "]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_launchers.put(bureauType, launcher);
|
_generators.put(bureauType, cmdGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +126,7 @@ public class BureauRegistry
|
|||||||
if (bureau != null && bureau.ready()) {
|
if (bureau != null && bureau.ready()) {
|
||||||
|
|
||||||
Log.info("Bureau ready, sending createAgent " +
|
Log.info("Bureau ready, sending createAgent " +
|
||||||
safeToString(agent));
|
StringUtil.toString(agent));
|
||||||
|
|
||||||
BureauSender.createAgent(bureau.clientObj, agent.getOid());
|
BureauSender.createAgent(bureau.clientObj, agent.getOid());
|
||||||
// !TODO: is this the right place to register the object?
|
// !TODO: is this the right place to register the object?
|
||||||
@@ -127,29 +140,38 @@ public class BureauRegistry
|
|||||||
|
|
||||||
if (bureau == null) {
|
if (bureau == null) {
|
||||||
|
|
||||||
Launcher launcher = _launchers.get(agent.bureauType);
|
CommandGenerator generator = _generators.get(agent.bureauType);
|
||||||
if (launcher == null) {
|
if (generator == null) {
|
||||||
Log.warning("Launcher not found for agent's " +
|
Log.warning("CommandGenerator not found for agent's " +
|
||||||
"bureau type " + safeToString(agent));
|
"bureau type " + StringUtil.toString(agent));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("Creating new bureau " +
|
Log.info("Creating new bureau " +
|
||||||
safeToString(agent) + " " +
|
StringUtil.toString(agent) + " " +
|
||||||
safeToString(launcher));
|
StringUtil.toString(generator));
|
||||||
|
|
||||||
bureau = new Bureau();
|
bureau = new Bureau();
|
||||||
|
bureau.bureauId = agent.bureauId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bureau.process = launcher.launch(_serverUrl, agent.bureauId, "");
|
// kick off the bureau's process
|
||||||
|
ProcessBuilder builder = new ProcessBuilder(
|
||||||
|
generator.createCommand(
|
||||||
|
_serverNameAndPort, agent.bureauId, ""));
|
||||||
|
|
||||||
|
builder.redirectErrorStream(true);
|
||||||
|
bureau.process = builder.start();
|
||||||
|
|
||||||
|
// log the output of the process and prefix with bureau id
|
||||||
|
ProcessLogger.copyMergedOutput(
|
||||||
|
Log.log, bureau.bureauId, bureau.process);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Log.warning("Could not launch process for bureau " +
|
Log.warning("Could not launch process for bureau " +
|
||||||
safeToString(agent));
|
StringUtil.toString(agent));
|
||||||
Log.logStackTrace(e);
|
Log.logStackTrace(e);
|
||||||
|
|
||||||
// !TODO: how to hook into caller and keep the other clients from hanging
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +195,7 @@ public class BureauRegistry
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.warning("Destroying agent " + safeToString(agent));
|
Log.warning("Destroying agent " + StringUtil.toString(agent));
|
||||||
|
|
||||||
// transition the agent to a new state and perform the effect of the transition
|
// transition the agent to a new state and perform the effect of the transition
|
||||||
switch (found.state) {
|
switch (found.state) {
|
||||||
@@ -197,7 +219,7 @@ public class BureauRegistry
|
|||||||
case Bureau.STILL_BORN:
|
case Bureau.STILL_BORN:
|
||||||
Log.warning("Acknowledging a request to destory an agent, but agent " +
|
Log.warning("Acknowledging a request to destory an agent, but agent " +
|
||||||
"is in state " + found.state + ", ignoring request " +
|
"is in state " + found.state + ", ignoring request " +
|
||||||
safeToString(found.agent));
|
StringUtil.toString(found.agent));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,16 +232,22 @@ public class BureauRegistry
|
|||||||
*/
|
*/
|
||||||
protected synchronized void bureauInitialized (ClientObject client, String bureauId)
|
protected synchronized void bureauInitialized (ClientObject client, String bureauId)
|
||||||
{
|
{
|
||||||
Bureau bureau = _bureaus.get(bureauId);
|
final Bureau bureau = _bureaus.get(bureauId);
|
||||||
if (bureau == null) {
|
if (bureau == null) {
|
||||||
Log.warning("Acknowledging initialization of non-existent bureau " +
|
Log.warning("Acknowledging initialization of non-existent bureau " +
|
||||||
safeToString(bureauId));
|
StringUtil.toString(bureauId));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bureau.clientObj = client;
|
bureau.clientObj = client;
|
||||||
|
|
||||||
Log.info("Bureau created " + safeToString(bureau) +
|
bureau.clientObj.addListener(new ObjectDeathListener() {
|
||||||
|
public void objectDestroyed (ObjectDestroyedEvent e) {
|
||||||
|
BureauRegistry.this.clientDestroyed(bureau);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Log.info("Bureau created " + StringUtil.toString(bureau) +
|
||||||
", launching pending agents");
|
", launching pending agents");
|
||||||
|
|
||||||
// find all pending agents
|
// find all pending agents
|
||||||
@@ -235,7 +263,7 @@ public class BureauRegistry
|
|||||||
|
|
||||||
// create them
|
// create them
|
||||||
for (AgentObject agent : pending) {
|
for (AgentObject agent : pending) {
|
||||||
Log.info("Creating agent " + safeToString(agent));
|
Log.info("Creating agent " + StringUtil.toString(agent));
|
||||||
BureauSender.createAgent(bureau.clientObj, agent.getOid());
|
BureauSender.createAgent(bureau.clientObj, agent.getOid());
|
||||||
bureau.agentStates.put(agent, Bureau.STARTED);
|
bureau.agentStates.put(agent, Bureau.STARTED);
|
||||||
}
|
}
|
||||||
@@ -268,7 +296,38 @@ public class BureauRegistry
|
|||||||
case Bureau.DESTROYED:
|
case Bureau.DESTROYED:
|
||||||
Log.warning("Received acknowledgement of the creation of an " +
|
Log.warning("Received acknowledgement of the creation of an " +
|
||||||
"agent in state " + found.state + ", ignoring request " +
|
"agent in state " + found.state + ", ignoring request " +
|
||||||
safeToString(found.agent));
|
StringUtil.toString(found.agent));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
found.bureau.summarize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the bureau client acknowledges the creation of an agent.
|
||||||
|
*/
|
||||||
|
protected synchronized void agentCreationFailed (ClientObject client, int agentId)
|
||||||
|
{
|
||||||
|
FoundAgent found = resolve(client, agentId, "agentCreationFailed");
|
||||||
|
if (found == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (found.state) {
|
||||||
|
case Bureau.STARTED:
|
||||||
|
found.bureau.agentStates.remove(found.agent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Bureau.STILL_BORN:
|
||||||
|
found.bureau.agentStates.remove(found.agent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Bureau.PENDING:
|
||||||
|
case Bureau.RUNNING:
|
||||||
|
case Bureau.DESTROYED:
|
||||||
|
Log.warning("Received acknowledgement of creation failure for " +
|
||||||
|
"agent in state " + found.state + ", ignoring request " +
|
||||||
|
StringUtil.toString(found.agent));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,13 +355,22 @@ public class BureauRegistry
|
|||||||
case Bureau.STILL_BORN:
|
case Bureau.STILL_BORN:
|
||||||
Log.warning("Acknowledging agent destruction, but state is " +
|
Log.warning("Acknowledging agent destruction, but state is " +
|
||||||
found.state + ", ignoring request " +
|
found.state + ", ignoring request " +
|
||||||
safeToString(found.agent));
|
StringUtil.toString(found.agent));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
found.bureau.summarize();
|
found.bureau.summarize();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: schedule a shutdown event for the bureau if this is the last agent
|
/**
|
||||||
|
* Callback for when a client is destroyed.
|
||||||
|
*/
|
||||||
|
protected synchronized void clientDestroyed (Bureau bureau)
|
||||||
|
{
|
||||||
|
// clean up any agents attached to this bureau
|
||||||
|
for (AgentObject agent : bureau.agentStates.keySet()) {
|
||||||
|
_omgr.destroyObject(agent.getOid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -319,7 +387,7 @@ public class BureauRegistry
|
|||||||
|
|
||||||
if (!(dobj instanceof AgentObject)) {
|
if (!(dobj instanceof AgentObject)) {
|
||||||
Log.warning("Object not an agent in " + resolver +
|
Log.warning("Object not an agent in " + resolver +
|
||||||
" " + safeToString(dobj));
|
" " + StringUtil.toString(dobj));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,27 +395,27 @@ public class BureauRegistry
|
|||||||
Bureau bureau = _bureaus.get(agent.bureauId);
|
Bureau bureau = _bureaus.get(agent.bureauId);
|
||||||
if (bureau == null) {
|
if (bureau == null) {
|
||||||
Log.warning("Bureau not found for agent in " + resolver +
|
Log.warning("Bureau not found for agent in " + resolver +
|
||||||
" " + safeToString(agent));
|
" " + StringUtil.toString(agent));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bureau.agentStates.containsKey(agent)) {
|
if (!bureau.agentStates.containsKey(agent)) {
|
||||||
Log.warning("Bureau does not have agent in " + resolver +
|
Log.warning("Bureau does not have agent in " + resolver +
|
||||||
" " + safeToString(agent));
|
" " + StringUtil.toString(agent));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bureau.clientObj == null) {
|
if (bureau.clientObj == null) {
|
||||||
Log.warning("Bureau not yet connected in " + resolver +
|
Log.warning("Bureau not yet connected in " + resolver +
|
||||||
" " + safeToString(agent));
|
" " + StringUtil.toString(agent));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client != null && bureau.clientObj != client) {
|
if (client != null && bureau.clientObj != client) {
|
||||||
Log.warning("Masquerading request in " + resolver +
|
Log.warning("Masquerading request in " + resolver +
|
||||||
" " + safeToString(agent) +
|
" " + StringUtil.toString(agent) +
|
||||||
" " + safeToString(bureau.clientObj) +
|
" " + StringUtil.toString(bureau.clientObj) +
|
||||||
" " + safeToString(client));
|
" " + StringUtil.toString(client));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,9 +515,16 @@ public class BureauRegistry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String _serverUrl;
|
// More readable generic map creation
|
||||||
|
// TODO: add to library or use existing
|
||||||
|
protected static <K, V> HashMap<K, V> hashMap ()
|
||||||
|
{
|
||||||
|
return new HashMap<K, V>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String _serverNameAndPort;
|
||||||
protected InvocationManager _invmgr;
|
protected InvocationManager _invmgr;
|
||||||
protected RootDObjectManager _omgr;
|
protected RootDObjectManager _omgr;
|
||||||
protected Map<String, Launcher> _launchers = new HashMap<String, Launcher>();
|
protected Map<String, CommandGenerator> _generators = hashMap();
|
||||||
protected Map<String, Bureau> _bureaus = new HashMap<String, Bureau>();
|
protected Map<String, Bureau> _bureaus = hashMap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,4 +179,24 @@
|
|||||||
</batchtest>
|
</batchtest>
|
||||||
</junit>
|
</junit>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="bureau-runserver" depends="compile"
|
||||||
|
description="Run the bureau test server.">
|
||||||
|
<java fork="true" classname="com.threerings.bureau.server.TestServer">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
</java>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<!-- NOTE: this target is launched by the bureau-runserver target, modelling the way bureaus -->
|
||||||
|
<!-- work. As such it is not currently useful on its own -->
|
||||||
|
<target name="bureau-runclient" depends="compile"
|
||||||
|
description="Run the bureau test client.">
|
||||||
|
<java fork="true" classname="com.threerings.bureau.client.TestClient">
|
||||||
|
<classpath refid="classpath"/>
|
||||||
|
<sysproperty key="serverName" value="${serverName}"/>
|
||||||
|
<sysproperty key="serverPort" value="${serverPort}"/>
|
||||||
|
<sysproperty key="token" value="${token}"/>
|
||||||
|
<sysproperty key="bureauId" value="${bureauId}"/>
|
||||||
|
</java>
|
||||||
|
</target>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 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.bureau.client;
|
||||||
|
|
||||||
|
import com.samskivert.util.OneLineLogFormatter;
|
||||||
|
import com.threerings.bureau.Log;
|
||||||
|
import com.samskivert.util.Queue;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
import com.threerings.bureau.client.BureauDirector;
|
||||||
|
import com.threerings.bureau.data.AgentObject;
|
||||||
|
import com.samskivert.util.RunQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends bureau client minimally and provides a static main function to create a client and
|
||||||
|
* connect to a server given by system properties.
|
||||||
|
*/
|
||||||
|
public class TestClient extends BureauClient
|
||||||
|
{
|
||||||
|
public static void main (String args[])
|
||||||
|
throws java.net.MalformedURLException
|
||||||
|
{
|
||||||
|
// make log pretty
|
||||||
|
OneLineLogFormatter.configureDefaultHandler();
|
||||||
|
|
||||||
|
// create the client and log on
|
||||||
|
TestClient client = new TestClient(
|
||||||
|
System.getProperty("token"),
|
||||||
|
System.getProperty("bureauId"));
|
||||||
|
client.setServer(
|
||||||
|
System.getProperty("serverName"),
|
||||||
|
new int[] {Integer.parseInt(System.getProperty("serverPort"))});
|
||||||
|
client.logon();
|
||||||
|
|
||||||
|
// run it
|
||||||
|
client.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements most basic run queue. Required to instantate a client.
|
||||||
|
*/
|
||||||
|
static protected class SimpleRunQueue implements RunQueue
|
||||||
|
{
|
||||||
|
public void postRunnable (Runnable r)
|
||||||
|
{
|
||||||
|
_queue.append(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDispatchThread ()
|
||||||
|
{
|
||||||
|
return _main == Thread.currentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
_main = Thread.currentThread();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Runnable r = _queue.get();
|
||||||
|
r.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Thread _main;
|
||||||
|
protected Queue<Runnable> _queue = new Queue<Runnable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The agent class used by our director. Does not actually load any code, just logs the
|
||||||
|
* start/stop requests.
|
||||||
|
*/
|
||||||
|
static protected class TestAgent extends Agent
|
||||||
|
{
|
||||||
|
public void start ()
|
||||||
|
{
|
||||||
|
Log.info("Starting agent " + StringUtil.toString(_agentObj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop ()
|
||||||
|
{
|
||||||
|
Log.info("Stopping agent " + StringUtil.toString(_agentObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new test client.
|
||||||
|
*/
|
||||||
|
protected TestClient (String token, String bureauId)
|
||||||
|
{
|
||||||
|
super(token, bureauId, new SimpleRunQueue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the event loop.
|
||||||
|
*/
|
||||||
|
protected void run ()
|
||||||
|
{
|
||||||
|
((SimpleRunQueue)_runQueue).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// overridden - creates a simple director
|
||||||
|
protected BureauDirector createDirector ()
|
||||||
|
{
|
||||||
|
// just use our test agent exclusively - in the real world, the agent created would depend
|
||||||
|
// on the object's type and/or properties
|
||||||
|
return new BureauDirector(_ctx) {
|
||||||
|
public Agent createAgent (AgentObject agentObj) {
|
||||||
|
return new TestAgent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2004 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.bureau.server;
|
||||||
|
|
||||||
|
import com.threerings.bureau.Log;
|
||||||
|
import com.threerings.bureau.data.AgentObject;
|
||||||
|
import com.threerings.presents.server.PresentsServer;
|
||||||
|
import com.samskivert.util.OneLineLogFormatter;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends a presents server to include a bureau registry.
|
||||||
|
*/
|
||||||
|
public class TestServer extends PresentsServer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The bureau registry for the server. Will be null until <code>init</code> is called.
|
||||||
|
*/
|
||||||
|
public static BureauRegistry breg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new server and runs it.
|
||||||
|
*/
|
||||||
|
public static void main (String[] args)
|
||||||
|
{
|
||||||
|
// make log pretty
|
||||||
|
OneLineLogFormatter.configureDefaultHandler();
|
||||||
|
|
||||||
|
final TestServer server = new TestServer();
|
||||||
|
try {
|
||||||
|
server.init();
|
||||||
|
|
||||||
|
// request a new agent
|
||||||
|
// TODO: more tests here - create a thread that posts different kinds of requests
|
||||||
|
// and somehow monitors results from client
|
||||||
|
server.omgr.postRunnable(new Runnable() {
|
||||||
|
public void run () {
|
||||||
|
server.createTestAgent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.run();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to initialize server.");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inherit documentation - from PresentsServer
|
||||||
|
public void init ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
super.init();
|
||||||
|
breg = new BureauRegistry("localhost:47624", invmgr, omgr);
|
||||||
|
|
||||||
|
breg.setCommandGenerator("test", new BureauRegistry.CommandGenerator() {
|
||||||
|
public String[] createCommand (
|
||||||
|
String serverNameAndPort,
|
||||||
|
String bureauId,
|
||||||
|
String token) {
|
||||||
|
|
||||||
|
int colon = serverNameAndPort.indexOf(':');
|
||||||
|
String [] cmd = {"ant",
|
||||||
|
"-DserverName=" + serverNameAndPort.substring(0, colon),
|
||||||
|
"-DserverPort=" + serverNameAndPort.substring(colon + 1),
|
||||||
|
"-DbureauId=" + bureauId,
|
||||||
|
"-Dtoken=" + token,
|
||||||
|
"bureau-runclient"};
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the bureau client create an agent.
|
||||||
|
*/
|
||||||
|
protected void createTestAgent ()
|
||||||
|
{
|
||||||
|
AgentObject obj = new AgentObject();
|
||||||
|
obj.bureauType = "test";
|
||||||
|
obj.bureauId = "test";
|
||||||
|
breg.startAgent(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user