Presents Design -*- outline -*-

* Why Presents?
The basic function of this layer is to provide a network presence (as you
can see, we love to pun; don't complain, this package used to be called
Cher) and to allow the sharing of information among different nodes in the
network.

* Overview
The Presents layer implements the distributed object services described in
the Narya design document. It does this within the context of an
extensible client/server application framework. Presents provides services
that can be integrated into your distributed application to share
information between a set of clients and entities operating on the server.

* Authentication and bootstrapping
The client initially transmits an authentication request to the server and
receives an authentication response in return. If successfully
authenticated, the client will then start up the distributed object
machinery, but will remain in a less functional state until the server
delivers the bootstrap notification.

The bootstrap notification contains the client's distributed object oid as
well as the invocation services oid. With this information the client can
complete initialization and attain a fully operational state.

The motivation for splitting up the authentication response and the
bootstrap notification is because the authentication process completes
separately from the server's client management initialization. The
authentication machinery replies to the client and sets the client
management machinery in motion. When that completes (and a client object
has been created for the client), the bootstrap notification is sent off
and normal operation ensues.

* Invocation services
To facilitate the client invoking code on the server (in a
request/response arrangement) and the server invoking code on the client
(in an asynchronous notification arrangement), the invocation services are
provided.

We make use of reflection to make the invocation services feel a bit like
remote procedure calls. All invocation traffic is managed by the
invocation manager, part of which resides on the client and part on the
server.

There are three classes involved when fully using the services. They are
the service class, the provider class and the receiver class.

** Service class
The service class provides the client-side API to the request/response
component. For example:

public class ChatService
{
    public void requestTell (String username, String message, 
                             Object rsptarget);
}

The tell() implementation would wrap the arguments up and pass them off to
the invocation manager for delivery to the server. If provided, the
response target object will receive a callback when the response comes in
from the server. The callback will come in the form of a call to a
reflected method on that object. The exact name of the method depends on
the implementation of the provider class which runs on the server.

** Provider class
The provider class implements the server-end of the service and is
registered with the invocation manager on the server to handle a
particular class of invocations. Continuing with our example:

public class ChatProvider
{
    public void handleTellRequest (int invid, String username, String message);
}

The handleTellRequest() function will process the request and then
generate a response which is passed on to the invocation manager for
delivery to the client. The response will be named and the name of the
response will dictate the method that is invoked on the response target
object. The arguments that go along with the name must correspond to the
signature of that method. For example:

    invmgr.respond(invid, "TellFailed", new Object[] { "m.no_such_user" });

will result in:

    public void handleTellFailed (String reason);

being called on the response target object. Because the response target
method is looked up only by name, all responses using the same name must
use the argument signature and the response target object may only have
one method with that particular name and its signature must match exactly
the signature dictated by the arguments.

** Receiver class
For asynchronous messages from the server to the client, there exists the
receiver class. The receiver is registered with the client invocation
manager to handle messages of a particular type (much like the provider
class is registered on the server) which is identified by a string name.

The receiver class provides methods named like so:

public class ChatReceiver
{
    public void handleTellNotification (String from, String msg);
}

where the arguments to the method again correlate with the arguments in
the invocation message.

The server wrapper that generates the corresponding invocation message for
delivery to the client will likely also reside in the ChatProvider class
already described. For example:

public class ChatProvider
{
    public void sendTell (BodyObject to, String from, String msg);
}

This function will simply wrap up the arguments and pass them to the
invocation manager for delivery to the appropriate client.

* Server configuration
The Presents server binds a properties file into the configuration name
space under the key "presents". This properties file lives in
rsrc/config/presents/server.properties and is loaded from the jar file in
which the Presents server code is provided.

Values specified in this properties file can be overridden by a mechanism
that will be provided by the configuration utilities used by the
server. This is accomplished by placing a properties file earlier in the
classpath than the one supplied with the Presents code. The values in that
earlier properties file will override the ones in the standard file.
Values not supplied in the override file will be retrieved from the
standard file.

Derived server classes should place their server properties into the
classpath with a path along the lines of
rsrc/config/<ident>/server.properties and should bind it into the config
namespace with their own identifier. If they desire to override values in
the Presents server configuration, they should provide a
rsrc/config/presents/server.properties in their jar file ensure that their
jar file occurs earlier in the classpath than the Presents server jar
file.

* A note on thread-safety
Distributed objects are designed only to be accessed from one thread. On
the server, there is a distributed object dispatch thread on which 95% of
all activity takes place anyway. It would be questionable to require that
thread to access distributed object members through synchronized members
just so that the few places where it is convenient to access dobjs off of
the dobjmgr thread are simplified. Instead we've opted for the performance
and care must be taken not to access distributed objects outside of the
dobjmgr thread.

Events can be generated from any thread, but values should not be read
from the distributed object on other threads because they are subject to
change at any time and could be half changed when some other thread goes
to read them.

On the client, care is taken to combine the AWT and dobj threads so that
life is simple from a synchronization standpoint. None the less, the same
care should be taken when other threads are introduced (IntervalManager
for example) not to read values from a distributed object on those other
threads.

This is easy enough to do. Simply copy the values you care about out of
the object before passing the information on to another thread (take care
to copy non-primitive values like arrays and OidLists). If you find the
need to fetch values from a distributed object after another thread has
already started, you'll just have to rethink your approach.

* Client components
** DObjectManager
Manages object proxies; converts value change requests into events,
forwards them via the iomgr; dispatches events on incoming queue; reaps
proxies when last subscriber goes away

** UI (AWT/Swing)
Standard AWT/Swing UI

** UI (Controller)?
Provides a paradigm of controllers and commands; code can post commands
back to the controller queue for later execution; UI elements structured
to automatically generate commands; will probably opt not to use this in
favor of Swing's built-in paradigms

** I/O Manager
*** Reader
Reads incoming data from the socket; decodes messages; posts events to
domgr queue; notifies object subscription penders (this should be done
asychronously)

*** Writer
Encodes object subscription and event forwarding requests; writes them to
the outgoing socket

** Client object
Informs exo-client about connection state changes; provides interface to
connection + authentication (logon) and disconnection (logoff); provides
access to omgr and client dobj

* Server components
** Connection Manager
Listens on accepting socket; creates and manages connection objects;
informs connection observer of state changes; handles all network traffic
on own thread; 

** Auth Manager
Processes auth requests on own thread; uses pluggable Authenticator to
perform actual authentication; 

** Client Manager
Registers with connection manager; manages authentication; maps
connections to existing client objects or creates new client objects for
newly connecting clients; 
