Revamped "persona selection" support. Things now actually work, and in as

sensible a way as we can hope for.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1717 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2002-09-19 23:36:59 +00:00
parent 0df0ec348d
commit ba4985053f
10 changed files with 301 additions and 135 deletions
@@ -1,5 +1,5 @@
//
// $Id: PresentsClient.java,v 1.37 2002/09/18 01:10:27 shaper Exp $
// $Id: PresentsClient.java,v 1.38 2002/09/19 23:36:59 mdb Exp $
package com.threerings.presents.server;
@@ -20,6 +20,7 @@ import com.threerings.presents.dobj.Subscriber;
import com.threerings.presents.net.BootstrapData;
import com.threerings.presents.net.BootstrapNotification;
import com.threerings.presents.net.Credentials;
import com.threerings.presents.net.EventNotification;
import com.threerings.presents.net.UpstreamMessage;
@@ -54,6 +55,32 @@ public class PresentsClient
implements Subscriber, EventListener, MessageHandler,
ClientResolutionListener
{
/** Used by {@link #setUsername} to report success or failure. */
public static interface UserChangeListener
{
/** Called when the new client object has been resolved and the
* new client object reported to the client, but the old one has
* not yet been destroyed. Any events delivered on this callback
* to the old client object will be delivered. */
public void changeReported (ClientObject newObj);
/** Called when the user change is completed, the old client
* object is destroyed and all updates are committed. */
public void changeCompleted (ClientObject newObj);
/** Called if some failure occurs during the user change
* process. */
public void changeFailed (Exception cause);
}
/**
* Returns the credentials used to authenticate this client.
*/
public Credentials getCredentials ()
{
return _creds;
}
/**
* Returns the username with which this client instance is associated.
*/
@@ -79,17 +106,58 @@ public class PresentsClient
* services when the user logs on, but anything else that has had its
* grubby mits on the username will be left to its own devices, hence
* the care that must be exercised when using this method.
*
* @param ucl an entity that will (optionally) be notified when the
* username conversion process is complete.
*/
public void setUsername (String username)
public void setUsername (String username, final UserChangeListener ucl)
{
// remap the client object in the client manager
if (_cmgr.remapClient(_username, username)) {
// change our internal business
_username = username;
} else {
Log.warning("Unable to remap username [client=" + this +
", newname=" + username + "].");
}
ClientResolutionListener clr = new ClientResolutionListener() {
public void clientResolved (String username, ClientObject clobj) {
// let the client know that the rug has been yanked out
// from under their ass
Object[] args = new Object[] { new Integer(clobj.getOid()) };
_clobj.postMessage(ClientObject.CLOBJ_CHANGED, args);
// let the caller know that we've got some new business
if (ucl != null) {
ucl.changeReported(clobj);
}
// release our old client object
_cmgr.releaseClientObject(_username);
// unmap the old client object; this will destroy it and
// clear out our username mapping
_cmgr.unmapClientObject(_username);
// update our internal fields
_username = username;
_clobj = clobj;
// lock our new client object
_cmgr.lockClientObject(_username);
// let our listener know we're groovy
if (ucl != null) {
ucl.changeCompleted(_clobj);
}
}
public void resolutionFailed (String username, Exception reason) {
Log.warning("Unable to resolve new client object " +
"[oldname=" + _username + ", newname=" + username +
", reason=" + reason + "].");
// let our listener know we're hosed
if (ucl != null) {
ucl.changeFailed(reason);
}
}
};
// resolve the new client object
_cmgr.resolveClientObject(username, clr);
}
/**
@@ -105,14 +173,34 @@ public class PresentsClient
* connection instance and client object and begins a client session.
*/
protected void startSession (
ClientManager cmgr, String username, Connection conn)
ClientManager cmgr, Credentials creds, Connection conn)
{
_cmgr = cmgr;
_username = username;
_creds = creds;
setConnection(conn);
// obtain our starting username
assignStartingUsername();
// obtain a lock for our username->client object mapping while we
// have an active session
cmgr.lockClientObject(_username);
// resolve our client object before we get fully underway
cmgr.resolveClientObject(username, this);
cmgr.resolveClientObject(_username, this);
}
/**
* This is factored out to allow derived classes to use a different
* starting username than the one supplied in the user's credentials.
* Generally one only wants to munge the starting username if the user
* will subsequently choose a "screen name" and it is desirable to
* avoid collision between the authentication user namespace and the
* screen namespace.
*/
protected void assignStartingUsername ()
{
_username = _creds.getUsername();
}
// documentation inherited from interface
@@ -307,6 +395,9 @@ public class PresentsClient
// about to generate
clearSubscrips();
// release our locked client object
_cmgr.releaseClientObject(_username);
// then let the client manager know what's up (it will take care
// of destroying our client object for us)
_cmgr.clientDidEndSession(this);
@@ -616,6 +707,7 @@ public class PresentsClient
}
protected ClientManager _cmgr;
protected Credentials _creds;
protected String _username;
protected Connection _conn;
protected ClientObject _clobj;