The Electric Communities Distributed Application Framework (ECDAF)
Application Startup and Core System ServicesLast updated: [98/07/17 Chip] This page was written by Chip. This document describes ECDAF API for application startup and initial
access to core system services.
Basic Startup APIThe basic API for application startup is very simple. However it is highly configurable and it is in this configurability where most of the details reside. An ECDAF application must provide a startup class which implements the interface org.erights.e.boot.ELaunchable. This interface consists of a single method: public interface ELaunchable { void go(EEnvironment env); } In addition to implementing ELaunchable, the startup class must have a public, zero-argument constructor, so that the boot code can create an instance of it by invoking the newInstance() method on the startup class's Class object. The application is started with a command line of the form: java org.erights.e.boot.Boot startclass args... where startclass is the fully qualified path name of your application startup class, and args... are any command line arguments that you wish to pass to the application itself. The Boot class parses the command line, initializes the core system services, constructs the EEnvironment, creates an instance of your startup class, and then actually starts the application by sending the EEnvironment to the startup object in a go() message. From the EEnvironment object your application can then obtain the command line arguments, the properties, and the root capabilities for all the core system services (see Core System Services below). For example, you might create an application: package com.fudco.cool; public class CoolApp implements ELaunchable { public void go(EEnvironment env) { your stuff here... } } and then you might start it with a command line something like: java org.erights.e.boot.Boot com.fudco.cool.CoolApp args...
Properties and Command Line ArgumentsThe application can obtain the command line arguments from the EEnvironment. Before being given to the application, however, the command line will first be parsed for arguments which modify the property settings and any such arguments will be removed from the arguments made available to the application. The property settings are also available from the EEnvironment, but are indexed by keyword rather than by position on the command line. Property settings may come from property files or from the command line directly. A properties file is simply a file with a series of lines of the form: name=value which is interpreted as setting the value of the property specified by the keyword name to the string value. Prior to processing the command line itself, a set of default properties files are read. Currently, ECDAF tries to read three default properties files: "/usr/local/lib/eprops/systemdefault", ".eprops/default" (in the user's home directory), and "/eprops.txt", in that order. If any or all of these files are missing, the absence is silently ignored. Furthermore, a startup command line argument of the form: -ECNoDefaults will suppress the reading of these default properties files entirely, leaving only those properties which are explicitly derived from the command line. A command line argument of the form: -ECproperties filename will cause property settings to be read from the properties file named by filename. A command line argument of the form: name=value will be interpreted as a direct property assignment. All these property settings are cumulative. That is, you can specify any number of individual property settings and property files and they will all be interpreted. Property settings are processed from left to right and a later setting of a given property will replace an earlier setting. Any command line arguments remaining, after the property setting arguments are removed, are made available to the application in an args array. For example, if we started the sample application with a command line like: java org.erights.e.boot.Boot com.fudco.cool.CoolApp arg1 Checkpoint=D:\foobar.cpt arg2 then the application would see the command line arguments "arg1"
and "arg2" and the "Checkpoint"
property would be set to "D:\foobar.cpt".
Configurability ECDAF applications may be configured from the environment by the selective
setting of properties. Class preloading: "StartupClassPreload" and "PreloadListFile" Class preloading is a feature wherein the startup code forces the loading of a collection of classes in order to (a) avoid having to wait for class load later when it might be less convenient to have a delay, and (b) to get some control over the in-memory placement of the classes (in terms of ordering and memory packing) in hopes of improving virtual memory performance. This is a semi-experimental feature, in that the benefits are somewhat unclear and vary from case to case. However, the feature is available if you wish to make use of it. Class preloading can be enabled by setting the "StartupClassPreload"
property. If the property is set to the value "preload",
the classes will be preloaded directly as part of the startup sequence.
If the property is set to the value "background",
the classes will be preloaded in a separate thread that will run concurrently
with the startup sequence. If the property is set to any other value or
if it is not set at all, no class preloading will be done. In either of
the cases where class preloading is enabled, the value of the property
"PreloadList" will be taken as the name of a file containing
a list of the classes to be preloaded. The format of this file is simple:
one line per class to be preloaded, each line containing one fully qualified
class name. Short-circuiting entropy collection: "DeveloperEntropy" The normal startup sequence goes through various motions to collect entropy with which to seed the cryptographic random number generator. Unfortunately, this process takes a bit of time, which can be especially annoying during program development when frequent restarts of the application are common and the security value of good random numbers is small to non-existent. As a development aid, the startup sequence provides a mechanism to short-circuit this entropy collection by seeding from some fast but not-highly-unguessable sources. The entropy collection short-circuit feature can be enabled by setting
the "DeveloperEntropy" property to "true".
Setting it to any other value or not setting it at all will disable this
feature. Customizable login interface: "LoginUIClass" Many applications, notably Microcosm, begin with a user login dialog, to capture a user name and passphrase. Ideally this login should happen as early in the startup process as possible so as to avoid making the user wait for all the various initializations to complete. In addition, the user passphrase can be used to secure the checkpoint file (see Persistent long-term state below). The ECDAF startup procedure provides a hook for the application to provide its own login dialog. A custom login dialog can be enabled by setting the property "LoginUIClass" to the fully qualified class name of an application login dialog class. Such a class must have a public, zero-argument constructor and must implement the interface org.erights.e.boot.login.LoginPresenter. If the "LoginUIClass" property is not set, no login dialog will be invoked. Instead, the startup sequence will proceed with launching the application. However, in the absence of a passphrase, the application may be unable to run, or at least unable to restore from its checkpoint file, so take care. If "LoginUICLass" is set, the startup code will create an instance of the login dialog class and then call its login() method: public interface LoginPresenter { public void login(org.erights.e.boot.login.LoginCompletionHandler completion, org.erights.e.elib.util.ECProperties properties, org.erights.e.boot.login.PassphraseVerifier verifier); } where completion is a call-back object via which the login dialog indicates the result of the login dialog, properties is the collection of properties which the startup code has collected (see Properties and Command Line Arguments above); and verifier is a passphrase verifier which the login dialog can use to check a passphrase against the checkpoint file. The login dialog may do whatever it wishes to capture the user identity and passphrase (and whatever other information the application may be interested in getting, for its own purposes, as part of login). The passphrase verifier should be called if the application is concerned with using a passphrase-protected checkpoint file. The passphrase verification interface, org.erights.e.boot.login.PassphraseVerifier, is quite simple: public interface PassphraseVerifier { public boolean verify(String passphrase); } The verify method will return true if and only if the given passphrase matches the one associated with the current checkpoint file (see below). The login dialog may also modify the property settings to alter the application's behavior as it sees fit. In particular, it may set the "Checkpoint" property to select the checkpoint file (say, on the basis of the user name). Furthermore, it must set the "Passphrase" property to indicate the checkpoint file passphrase, if there is one. When the login dialog is finished, it should call the login completion handler's afterLogin() method to inform the startup code of the outcome. This interface, org.erights.e.boot.login.LoginCompletionHandler, is also quite simple: public interface LoginCompletionHandler { public void afterLogin(boolean success); } where success indicates the success or failure
of the login. Success means that the application should proceed with the
rest of startup. Failure means that the startup code will immediately
exit. User interface selection: "UIFrameworkClass" The ECDAF is agnostic about the application's user interface or user interface framework. However, it does have a notion that the application at least possesses some kind of user interface, so there is support for this concept in the environment. In particular, we would like the user interface to be configurable so that alternative UI implementations may be selected in different contexts (for example, we often wish to select a GUI for a client-side startup and a CLI for a server-side startup). The user interface framework is selected by setting the "UIFrameworkClass" property to the fully qualified class name of a user interface framework class. Such a class must have a public, zero-argument constructor and must implement the interface org.erights.e.boot.UIFramework. If the "UIFrameworkClass" property is not set, no UI framework will be established and the application will be entirely on its own in the user interface department. If the "UIFrameworkClass" is set, the startup code will create an instance of the UI framework class and then call its init() method: public interface UIFramework { public void init(org.erights.e.boot.EEnvironment env); } where env is the EEnvironment that is established as part of the normal application startup. This is the same EEnvironment that is passed to the application startup object in the go() message. The UI framework object will itself be placed in the EEnvironment
where it will be accessible to the application startup class. Persistent long-term state: "Checkpoint" and "Passphrase" The ECDAF supports a form of non-orthogonal persistence built around the concept of a single checkpoint file which captures all the important state of an application (where "important" is defined here as being whatever the application considers worth saving plus the information that ECDAF itself needs to save to keep working). The persistence mechanism per se is accessed via the EEnvironment and will be explained in more detail below. However, property settings control the mechanism's general behavior. The persistence mechanism can be enabled by setting the "Checkpoint" property to the name of a checkpoint file. This can name either an existing checkpoint file somewhere on the computer or a checkpoint file that has yet to be created. If the "Checkpoint" property is not set, the execution of the application will be considered ephemeral and it will not be able to save its state. If the checkpoint file does not exist at startup time, a new persistent ECDAF process will be created, including a new VatIdentity and an empty Registrar table, and the application's state will be null. If the checkpoint file exists, it will be deserialized to yield the previously saved application state, VatIdentity, and so on. The checkpoint file may be passphrase protected. If so, the file will be saved in encrypted form using a passphrase to generated the encryption key. The operation of restoring from this checkpoint file at application startup time will then require this same passphrase in order to succeed in decrypting the file. The passphrase for decrypting and encrypting the checkpoint file may be specified by setting the "Passphrase" property. If this property is not set or if it is set to the empty string (""), the file will be saved in unencrypted form. And if the passphrase is null, startup will only succeed if directed to an unencrypted checkpoint file. Note that by setting the "Checkpoint" and "Passphrase"
properties while omitting to set the "LoginUIClass" property,
it is possibly to startup an ECDAF application non-interactively, even
if would normally have an interactive login. Participation in the networked world: "ListenAddress" and "SearchPath" In order to be a fully functional networked application, it is generally necessary not only to be able to communicate with other entities on the net but to enable them to communicate with you. To this end, the data communications subsystem needs two critical pieces of configuration information: what address and port to listen for incoming connections on, and what information to provide to others (for example, in SturdyRefs) to enable them to locate the application's process in the future. The network address and port upon which to listen for incoming connections is specified by setting the "ListenAddress" property. This property should be set to a string of the form: domainname:portnumber or simply domainname where domainname is the either an Internet domain name or dotted-quad IP address; and portnumber is the (decimal integer) port number. If the port number is omitted, it defaults to 0. If the "ListenAddress" property is not set at all, it will default to the local host name, or "localhost" if the local host name cannot be determined. Confusingly, however, the domainname portion of the address will be ignored for purposes of setting up data communications; the network address being listened upon will always be that of the computer that the application is running on (as it should be). For example, our sample application might specify a listen address of: coolserv.fudco.com:2347 which would indicate that the domain name is "coolserv.fudco.com" and the port number is 2347. An ECDAF process is located in the network using a "search path". This is simply a list of network addresses which are tried in sequence as either plausible candidates for the actual process host machine itself or as the addresses of Process Location Servers (PLSs) which might know the actual address. When an application starts up, it is given such a search path that should be usable for finding itself. The Registrar that the startup process creates will use this search path in constructing any SturdyRefs which the application creates. In addition, as part of startup, each of the elements in the search path will be treated as the possible address of a PLS and the communications subsystem will attempt to register the ECDAF process with each of them (and, as long as the process continues to execute, will periodically refresh these registrations so that they don't expire). The search path is specified by setting the "SearchPath" property. The value of the "SearchPath" property should consist of one or more network addresses in the form described above for the "ListenAddress" property. Multiple addresses should be separated by semicolon (";") characters. Our example thus might have a search path something like: coolserv.fudco.com:2347;pls.fudco.com;pls.communities.com which would first direct someone to a plausible address for the process
itself, then have them check with the FUDCO PLS and then the Communities.com
PLS. Upon startup the process would register itself with these two PLSs.
Core System Services The final important function of the ECDAF startup code is to initialize
the core system services and make them available to the application. These
services are all encapsulated by the EEnvironment
object which is passed to the application in the go()
message. All these services are then usable either directly via methods
on the EEnvironment object itself or via capabilities
which can be obtained from the EEnvironment
object. Properties and command line arguments The EEnvironment provides access to the command line arguments and the property settings. Command line arguments are obtainable via the method: String[] args(); which returns the arguments in an array. If there were no command line arguments the result will be a 0 element array. Access to the properties is via a set of methods which echo the read-only portion of the org.erights.e.elib.util.ECProperties method protocol. That is, entities with access to the EEnvironment can interrogate the property settings but may not modify them. The methods available are: String getProperty(String key); String getProperty(String key, String defaultValue); int intProperty(String key, int defaultValue); boolean testProperty(String key); Enumeration propertyNames(); see the Javadoc for org.erights.e.elib.util.ECProperties
for full descriptions of these. Persistence The EEnvironment provides access to the persistent data storage mechanism. In addition to the information which ECDAF saves for its own use, the application may specify an arbitrary Serializable object of its own which is to be saved. This object should be the root of a reference graph of objects which encompasses all state that the application cares to have persisted. The method: void setApplicationStateBundle(Serializable bundle); specifies the object which is to fill this role (i.e., be saved when the application persists), while the method: Serializable applicationStateBundle(); returns the object which is currently in this role. Upon application startup, this can be interrogated to determine if the startup is a restore from checkpoint. If applicationStateBundle() returns null, then either this is a freshly minted ECDAF process or the process persisted with no application-relevant state (which is functionally the same thing from the application's point of view). The methods: void commit(); void commit(StableStoreWatcher watcher); cause the current state of the ECDAF process (including the application state bundle if there is one) to be serialized to the checkpoint file. The second form of the method allows you to specify an object which will be asynchronously notified when the checkpoint completes (see the Javadoc for org.erights.e.boot.persist.StableStoreWatcher for details). As discussed above under Persistent long-term state, the checkpoint file can be protected with a passphrase. The method: String passphrase(); returns the passphrase currently being used, while the method: void setPassphrase(String passphrase); changes the passphrase, including rewriting the checkpoint file with
the new encryption key. Core Service capabilities The ECDAF sets up a variety of services that are accessed by capabilities available from the EEnvironment. The methods: DirectoryRootMaker directoryRootMaker(); CapTPMgr proxyManager(); Registrar registrar(); UIFramework uiFramework(); return these various capabilities: the capability-oriented file system
root, the proxy manager (which is actually the main capability to the
communications subsystem), the Registrar and the user interface framework.
Consult the Javadoc for the various classes (org.erights.e.extern.file.DirectoryRootMaker,
org.erights.e.net.proxy.CapTPMgr, org.erights.e.net.proxy.Registrar,
and org.erights.e.boot.UIFramework) for more
detail on these capabilities and their use.
|
||||||||||||
Unless stated otherwise, all text on this page which is either unattributed or by Mark S. Miller is hereby placed in the public domain.
|