Aglets Specification (1.0)


Version 0.60
May 20th, 1997
Author: Mitsuru Oshima and Guenter Karjoth
Send comments to aglets@yamato.ibm.co.jp.

Introduction


Overview

Aglets are Java objects that can move from one host on the network to another. That is, an aglet that executes on one host can suddenly halt execution, dispatch to a remote host, and start executing again. When the aglet moves, it takes along its program code as well as the states of all the objects it is carrying. A built-in security mechanism makes it safe to host untrusted aglets.

System Goals


Aglet Object Model


Aglet API Overview

The Aglet API defines the fundamental functionality of mobile agents. The following figure shows the major interfaces and classes defined in the Aglet API and the relationship between these interfaces.

com.ibm.aglet.Aglet
The Aglet abstract class defines the fundamental methods (for example, dispatch(URL)) for a mobile agent. to control their mobility and lifecycle. All mobile agents defined in Aglets have to extends this abstract class. The Aglet.dispatch(URL) primitive causes an aglet to move from the local host to the destination given as the argument. The Aglet.deactivate(long time) primitive allows an aglet to be stored in secondary storage, and the Aglet.clone() primitive spawns a new instance of the aglet which has the state of the original aglet. Note that the object returned by the clone primitive is not an Aglet object but an AgletProxy object.

The Aglet class is also used to access the attributes associated with an aglet. The com.ibm.aglet.AgletInfo object, which can be obtained by Aglet.getAgletInfo(), contains an aglet's inherent attributes, such as its creation time and codebase, as well as its dynamic attributes, such as its arrival time and the address of its current context.

com.ibm.aglet.AgletProxy
The AgletProxy interface acts as a handle of an aglet and provides a common way of accessing the aglet behind it. Since an aglet class has several public methods that should not be accessed directly from other aglets for security reasons, any aglet that wants to communicate with other aglets has to first obtain the proxy object, and then interact through this interface. In other words, the aglet proxy acts as a shield object that protects an agent from malicious agents. When invoked, the proxy object consults the SecurityManager to determine whether the current execution context is permitted to perform the method. Another important role of the AgletProxy interface is to provide the aglet with location transparency. If the actual aglet resides at a remote host, it forwards the requests to the remote host and and returns the result to the local host.

The AgletProxy can be obtained in the following ways:

The runtime library is responsible for providing the implementation of the AgletProxy interface; thus, aglet programmers do not have to implement this interface.

com.ibm.aglet.AgletContext
AgletContext provides an interface to the runtime environment that occupies the aglet. Any aglet can obtain a reference to its AgletContext object via the Aglet.getAgletContext() primitive, and use it to obtain local information such as the address of the hosting context and the enumeration of AgletProxies, or to create a new aglet in the context. Once the aglet has been dispatched, the context object currently occupied is detached and the new context is attached. The runtime library is responsible for providing the implementation of this interface; thus, aglet programmers do hot have to implement this interface.

com.ibm.aglet.Message
Aglet objects communicate by exchanging objects of the Message class. A message object can have a String object to specify the kind of the message and arbitrary objects as arguments. A message can be sent to the aglet by calling Object AgletProxy.sendMessage(Message msg) , FutureReply AgletProxy.sendAsyncMessage(Message msg) , or void AgletProxy.sendOnewayMessage(Message msg) and it is passed as an argument to Aglet.handleMessage(Message msg). Please see the section on messaging for more details.

com.ibm.aglet.FutureReply
The object defined by the FutureReply interface is returned by the asynchronous message-sending and used as a handler to receive the result later asynchronously. With this interface, the receiver can determine whether a reply is available, and can wait for the result with a specified timeout value so that it can continue its execution if a reply was not returned within the specified time.

In the following sections, you will see more classes and interfaces that allow you to control the activities of an aglet.

Extending the Aglet class

Here are the general rules for extending an abstract Aglet class. The following methods of the Aglet class are supposed to be overridden by a subclass to allow an aglet to implement its own specific behavior:
void Aglet.onCreation(Object init)
This method is supposed to be called only once during its lifecycle, when it is created. Aglet programmers have to use onCreation(Object init) to initialize an aglet object, because the Aglet API (dispatch(URL) for example) is not available in the constructor.

void Aglet.onDisposing()
This method is called when an aglet is disposed of. The aglet is supposed to release any resources previously allocated. It can perform additional actions in response to its own disposal.

void Aglet.run()
The run() method in the Aglet class is called whenever an instance is reconstructed, that is, when the instance is created when it is cloned, when it arrives at the destination, and when it is activated.

Because this method is called whenever it occupies the context, this is a good place to define the common task.

boolean Aglet.handleMessage(Message msg);
All messages sent to the aglet are passed to the handleMessage method. Aglet programmers can check whether the incoming message is a known message, and can perform the task according to the kind of message.

    public class HelloAglet extends Aglet {
        public void onCreation(Object init) {
            System.out.println("created!");
        }
        public void run() {
            System.out.println("hello!");
        }
        public boolean handleMessage(Message msg) {
            if (msg.sameKind("sayHelloAgain") {
                System.out.println("hello!");
                return true;
            }
            return false;
        }
        public void onDisposing() {
            System.out.println("bye!");
        }
    }

Aglet Object and Its Life Cycle

The Aglets class provides the basic functionality for a mobile object, and every mobile object (aglet objects) has to be an instance of a subclass of the com.ibm.aglet.Aglet class. To be useful, an aglet has to be instantiated first. There are two ways to create a new instance of an aglet. The first is to instantiate a completely new aglet from class definitions by calling AgletContext.createAglet(URL codebase, String name, Object init). This primitive creates a new instance within the specified context and initializes it if necessary, then invokes Aglet.onCreation(Object init) on the created object along with the initializer object passed to the createAglet primitive. The other way is to create a copy of an existing aglet by using the Aglet.clone() primitive. The cloned aglet has the same state as the original one but has a different AgletID object, an thus a distinct identity.

Once created, an aglet object can be dispatched to and/or retracted from a remote host, deactivated and placed in secondary storage, then activated later.

An aglet can dispatch itself to a remote host by calling the Aglet.dispatch(URL dest) primitive. To be more precise, an aglet occupies the aglet context and can move from this context to others during its execution. Because the runtime system may serve multiple contexts within one Java VM, these contexts can be in the same VM. Dispatching causes an aglet to suspend its execution, serialize its internal state and bytecode into the standard form and then to be transported to the destination. On the receiver side, the Java object is reconstructed according to the data received from the origin, and a new thread is assigned and executed.

Aglets support persistency of aglet objects. All mobile aglet objects can be persistent in nature, because they must be convertable into a bit-stream; consequently, this stream can be stored in secondary storage. The Aglet.deactivate(long timeout) primitive causes an aglet to be stored in secondary storage and to sleep for a specified number of milliseconds. After the given time has passed or another program has requested its activation, the aglet is activated within the same context where as that in which it was deactivated.

Unlike normal Java objects, which are automatically released by garbage collector, an aglet object, since it is active, can decide whether or not to die. If you call the dispose() method to kill the aglet, onDisposing() is called to perform the finalization suitable for the current state of the aglet. Aglet programmers are responsible for releasing allocated resources such as file descriptors or DB connections, because these may not be released automatically.


Once disposed of, the instance becomes an invalid entity, and any attempt to operate it will result in a SecurityException. (This may be replaced with another Exception class).

Aglets Event and Delegation Event Model

Java VM doesn't allow to marshal the stack frame of a Thread object. It is impossible to migrate a Thread object to a remote host or to save it to secondary storage while preserving its execution state.
Instead, Aglets uses an event model to give programmers a chance to implement an action that emulates the migration. When an aglet dispatches, the Aglet runtime system issues the corresponding event to notify that it is being dispatched, or it is arriving at the destination.
For example, the following code fragment defines the MyListener class, which implements the MobilityListener interface, and MyAglet, which extends the Aglet class.
    import com.ibm.aglet.Aglet;
    import com.ibm.aglet.event.MobilityEvent;
    import com.ibm.aglet.event.MobilityListener;

    class MyListener implements MobilityListener {
        public void onDispatching(MobilityEvent l) {
        }
        public void onReverting(MobilityEvent l) {
        }
        public void onArrival(MobilityEvent l) {
        }
    }

    public class MyAglet extends Aglet {
        public void onCreation(Object init) {
            MobilityListener listener = new MyListener();
            addMobilityListener(listener);            
        }
    }
Before an aglet is actually dispatched, the onDispatching() method of the MyListener object is called, and the onArrival() method is called after the aglet arrives at its destination. In this way, an aglet programmer can implement an action that should be taken in response to these events (dispatch, for instance) regardless of when or by whom an aglet is dispatched.

When Event Object Listener Method called
about to be clonedCloneEventCloneListeneronCloning
clone is created CloneEvent CloneListener onClone
after the clone was created CloneEvent CloneListener onCloned
about to be dispatched MobilityEvent MobilityListener onDispatching
about to be retracted MobilityEvent MobilityListener onReverting
after arrived at the destination MobilityEvent MobilityListener onArrival
about to be deactivated PersistencyEvent PersistencyListener onDeactivating
after activated PersistencyEvent PersistencyListener onActivation

Note that these callbacks are also inserted into the message queue. You will not receive the event until the current message owning the monitor is completed. Please refer to the messaging section for more details.

Difference between writeObject/readObject Methods and Listeners

ObjectSerialization provides an object with a way of customizing its own serialization by overriding two method, called writeObject(ObjectOutputStream) and readObject(ObjectInputStream). These can be used to implement an action that should be taken in response to an AgletEvent, because these two methods are always called when such an event occurs. The AgletEvent callbacks are different from the readObject/writeObject method in the sense that the aglet programmer can determine what kind of event occurred and can thus implement a different behavior for each event. For example, different behaviors are often implemented for the original object and its clone object, depending on whether the object is a parent or a child. The following code fragments define the CloneLimiter, which controls the maximum number of clones the aglet can create.
      public class CloneLimiter implements CloneListener() {
          boolean original = true;
          int number_of_clones = 0;
          public void onCloning(CloneEvent ev) {
              if (original == false) {
                  throw new SecurityException("Clone cannot create a clone");
                  // this exception may be replaced with another class.
              }
              if (number_of_clones>10) {
                  throw new SecurityException("Exceeds the limit");
              }
          }
          public void onClone(CloneEvent ev) {
              original = false;
          }
          public void onCloned(CloneEvent ev) {
              number_of_clone++;
          }
      }
Unlike overriding the readObject/writeObject methods, listener objects are pluggable and can be added to and removed from the aglet at runtime, so listener classes can be used as a library for aglets. You can use the CloneLimiter class for any aglet class to specify the maximum number of clones, for example.
Another important difference the aglet programmer should be aware of is that onDispatching() is called while the aglet is running, while the writeObject is called after the aglet is suspended. Similarly, readObject() is called while being unmarshaled, which means that Aglet primitives such as getAgletContext() do not work. On the other hand, onArrival() is called after the entire aglet has been restored and activated successfully, so you can call the Aglets API.
However, readObject/writeObject is the right place to implement general and common behavior for storing or restoring the state of an object.

Migration of Object in Aglets

Serializing an Aglet Object

When and aglet is dispatched, cloned or deactivated, it is marshaled into a bit-stream, then unmarshaled later. Aglets uses ObjectSerialization of Java to marshal and unmarshal the state of agents, and tries to marshal all the objects that are reachable from the aglet object. All objects to be serialized have to implement either java.io.Serializable or java.io.Externalizable. If there is a non-serializable object that is directly or indirectly referenced by an aglet, you should declare the reference as transient. Otherwise, the above operations will fail and will throw a java.io.NotSerializableException that is a subclass of the java.io.IOException class.

Serializing Nonproxy Objects

A nonproxy object, which is reachable from an aglet, is migrated by copy. This means that once serialized, an object shared by multiple aglets is copied and is no longer shared after the above operations.

Serializing Proxy Objects

When a proxy object is migrated, it keeps the aglet id and its address, and restores the reference to the original aglet object. The AgletProxy object can keep the reference to the actual aglet even if the proxy is transferred to a remote host or deactivated, as long as the aglet resides in the same location.

Remote Objects in RMI

The remote interface is defined in RMI and is used to identify remote objects whose methods can be invoked remotely. The RMI Client program works with the Aglets library without modification. That is, when dispatching an aglet along with the remote object, it is automatically rebound when the aglet is unmarshaled.

RemoteServer Objects in RMI

RemoteServer objects defined by RMI are stationary objects, thus it cannot be transferred along with your aglet. This support will be supported in the future.

Proxy Object Whose Aglet is Dispatched

Currently, the AgletProxy cannot keep track of roaming aglets. Once an aglet is dispatched, the proxy previously referencing the aglet is no longer valid. A mechanism for preserving the reference will be provided in the future.

How Dispatch Works

When an aglet is dispatched, corresponding listener objects are called immediately. If these invocations are successfully completed, a thread is suspended first, then ObjectSerialization is called and the aglet and its associated objects are marshaled. After these objects have been successfully marshaled and transported to the destination, the thread is killed and related resources are deallocated.
If the aglet has more than one thread created by itself, these threads are also automatically terminated. To avoid any problem caused by unexpected termination, an aglet should implement a listener interface and terminate these threads in the listener's callback method.

Messaging in Aglets

An application program or an aglet can communicate with the aglet object by message passing. An aglet that wants to talk to another aglet first has to create a message object, then send it to the peer aglet. A message object has, as its argument, a kind attribute of the class message and an arbitrary object. The receiver aglet can determine what to do by checking the kind of received message in the Aglet.handleMessage() method.
    MyAglet extends Aglet {
        public boolean handleMessage(Message msg) {
            if (msg.sameKind("doJob")) {
                doJob();
	    } else if (msg.sameKind("shutdown")) {
                deactivate(0);
	    }
        }
    }
Aglets supports the following types of message passing:
Now-type: AgletProxy.sendMessage(Message msg)
A now-type message is synchronous and blocks until the receiver has completed the handling of the message.
       String answer = proxy.sendMessage(new Message("question"));
       System.out.println(answer);

Future-type: AgletProxy.sendAsyncMessage(Message msg)
A future-type message is asynchronous and does not block the current execution. The method returns an FutureReply object, which can be used to obtain the result or wait for it later.
       FutureReply future =
           proxy.sendAsyncMessage(new Message("question"));
       int num_task = 10;
       // do private job at most 10 times while waiting for the result.
       while(future.isAvailable() == false && num_task-- >0) {
           doPrivateJob();
       }
       System.out.println( (String)future.getReply() );
Note: If an aglet sends a message to itself, the message is not put at the tail of the queue. Instead, it is placed at the head of the queue and executed immediately, to avoid deadlock.

Oneway-type: AgletProxy.sendOnewayMessage(Message msg)
A oneway-type message is asynchronous and does not block the current execution. It differs from a future-type message in the way it is placed at the tail of the queue even if it is sent to the aglet itself. [, does not have return value.]
         proxy.sendOnewayMessage(new Message("question"));
Note: Oneway type message passing is not implemented as of this writing.

The receiver aglet has to define its handleMessage(Message msg) method to handle the incoming messages. In the handleMessage method, a message object is passed as an argument and can be used to perform the operation according to the kind of message. If it is handled, the method has to return a boolean value indicating whether it has been handled or not.
    public boolean handleMessage(Message msg) {
        if (msg.sameKind("sayHello")) {
            System.out.println("Hello");
            return true; // i know this message...
        }
        return false; // false, otherwise
    }
If it returns false, the sender of the message receives a NotHandledException and thus knows that the message has not been handled. There is no way of knowing whether a oneway message has been handled or not.
    Future future = proxy.sendAsyncMessage();
    ...
    try {
        Object reply future.getReply();
    } catch (NotHandledException ex) {
        // the receiver didn't handled the message
    } catch (MessageException ex) {
        // an exception has been throwen in the receiver's handleMessage()
        System.out.println(ex.getException());
    }
Messages in Aglets also support acknowledge-type replies, whereby the receiver can send the reply (result) even before completing the handling of the message. When you have a return value, you need to use this interface to return the value. Once you send a reply via the Message.sendReply() method, you cannot send a reply again, and the return value of handleMessage will be ignored.
    public boolean handleMessage(Message msg) {
        if (msg.sameKind("accessDB")) {
            openDB(); // pseudo code
            Object reply = accessDB(msg.getArg());
            msg.sendReply(reply);
            closeDB();
            return true; // i know this message...
        }
        return false; // false, otherwise
    }

Message Queue and Priority

All aglet objects have a message queue object. All incoming messages are stored in the message queue, basically, and then handled one by one. The messaging in Aglets follows the transmission-ordering law; that is, messages arrive in the order in which they were sent. For example, if you send messages in the order "A", "B", "C", the receiver receives them in the same order "A", "B", "C".
                   queue
         [A]  ->         {}: Aglet
         [B]  ->      {[A]}: Aglet
         [C]  ->   {[B][A]}: Aglet
                   {[C][B]}: Aglet ( handling [A] )
                      {[C]}: Aglet ( handling [B] )
                         {}: Aglet ( handling [C] )
You can specify the priority associated with kinds of messages. The messages with high priority are queued in higher positions. Suppose that there are three messages in the queue, with the priorities 3, 5, and 6, and that you send two messages with priorities 4 and 7 asynchronously. Even if you sent the message with priority 4 first, the message with priority 7 will be handled first.
                 {[3][5][6]}: Aglet
       [4]  ->   {[3][5][6]}: Aglet
       [7]  ->   {[3][4][5]}: Aglet (handling [6])
              {[3][4][5][7]}: Aglet (handling [6] cont'd)
                 {[3][4][5]}: Aglet (handling [7])
Aglets also supports a NOT_QUEUED priority, whereby the message is not queued. Suppose the Message [D] has priority NOT_QUEUED; then that message will be passed to an aglet and handled immediately.
         [A]  ->         {}: Aglet
         [B]  ->      {[A]}: Aglet
         [D]  ->   {[B][A]}: Aglet
                      {[B]}: Aglet ( handling [A] ) ( handling [D] )
                         {}: Aglet ( handling [B] ) ( handling [D] )
                         {}: Aglet ( handling [D] )
You can set priority of the message by the primitive MessageManager.setPriority(String, int), and a MessageManager object of the agent can be obtained via Aglet.getMessageManager() primitive.

Synchronizing Messages

Although messages are normally handled one by one, it often happens that the thread currently handling the message has to wait until the aglet's state meets some condition, or has to inform the waiting thread or incoming message that the condition is satisfied. The Aglet API has five methods to synchronize messages.
Aglet.waitMessage();
Aglet.waitMessage(long timeout);
Aglet.waitMessage() causes the current thread to wait until another message instructs it to resume its execution. Only the thread that owns the message-handling monitor can call this method and wait. Otherwise, the IllegalMonitorStateException will be thrown.
If another thread handling another message instructs the waiting thread to resume the waiting thread by calling Aglet.notifyMessage(), it wakes up and resumes execution. If it is not instructed to resume, it will wait forever until it is stopped. On the other hand, the waitMessage(long timeout) is used to wait at most for timeout millisecond, and wakes up when the specified timeout expires.

Aglet.notifyMessage();
Aglet.notifyAllMessages();
Aglet.notifyMessage() instructs the waiting thread to wake up and resume execution. The caller thread is put at the head of the message queue and waits until the resumed thread completes the message handling or exits the monitor. Only the thread that owns the message-handling monitor can call this method. Otherwise the IllegalMonitorStateException will be thrown.
          queue        waiting
        {[D][C]}: Aglet {[A][B]}
           {[D]}: Aglet {[A][B]} (handling[C] calls notifyMessage())
        {[D][C]}: Aglet {[B]} (handling[A])
Aglet.notifyAllMessages() causes all waiting threads to wake up one by one. These threads are placed at the head of the message queue and the oldest waiting thread is immediately resumed. The caller thread is placed at the next position of these thread and will be resumed alter these resumed thread has completed.
         queue         waiting
       {[D][C]}: Aglet {[A][B]}
          {[D]}: Aglet {[A][B]} (handling[C] calls notifyAllMessages())
    {[D][C][B]}: Aglet (handling[A])
Aglet.exitMonitor();
exitMonitor() causes the current execution thread to release the monitor owned by the thread and exit the synchronization block. The next message in the message queue is then executed. Note that exitMonitor() does not activate the waiting messages but only the incoming messages.
         queue
       {[C][B]}: Aglet (handling[A]* calls exitMonitor())
          {[C]}: Aglet (handling[B]*) (handling[A])

Note: * indicates the owner of the monitor
With this API, you can implement a background task while receiving the message.
      public void SiteWatcherAglet extends Aglet {
          public void run() {
              exitMonitor(); // now the next message would start.
              while( condition == true) {
                  watchSite("http://home/index.html");
              }
          }
      }

The following "StackAglet" example illustrates how synchronization between messages can be achieved.
    public StackAglet extends Aglets {
        static int capacity = 10;
        Object stack[] = new Object[capacity];
        int num = 0;

        public handleMessage(Message msg) {
	    if (msg.sameKind("push")) {
                push(msg);
	    } else if (msg.sameKind("pop")) {
                pop(msg);
	    } else if (msg.sameKind("isFull")) {
                msg.sendReply( num == capacity);
	    } else if (msg.sameKind("isEmpty")) {
                msg.sendReply( num == 0 );
	    } else return false;
	    return true;
        }

	private void push(Message msg) {
            while (num == capacity) {
                waitMessage();
            }
            stack[num++] = msg.getArg();
            if (num==1) {
                notifyMessage(); // wake up "pop" message
            }
        }

        private void pop(Message msg) {
           while(num==0) {
               waitMessage();
           }
           msg.sendReply(stack[--num]);
           if (num == (capacity -1)) {
               notifyMessage(); // wake up "push" message
           }
        }
    }


    Note:

Remote Messaging in Aglets

Aglets supports remote message passing, and aglet objects can communicate through messages remotely as well as locally. Parameter objects or return value passed by remote messaging can be of any Java type that implements java.io.Serializable, and are marshaled and unmarshaled by ObjectSerialization. Sending a remote message is different from dispatching an aglet in a sense that a remote message does not cause any transfer of bytecode, and therefore the classes used in the message have to be installed in both hosts.
Remote message passing can be used as a lightweight way of communicating between aglets that reside on the different hosts, and can reduce the network traffic, the cost of defining classes, and security issues, while dispatching an aglet can take advantage of locality, for example disconnected operations or intensive interaction with hosts.

Exception Handling in Aglets

T.B.D.

System Architecture


Overview

The Aglets architecture consists of two APIs and two implementation layers.

The Aglets runtime layer is the implementation of Aglet API, which provides the fundamental functionality such as creation, management or transfer of aglets. This layer defines the behavior of APIs such as Aglet and AgletContext, and can serve multiple AgletContext objects.

The transport layer is responsible for transporting an agent to the destination in the form of a byte stream that contains class definitions as well as the serialized state of the agent. This layer is also defined as an API, called Agent Transfer and Communication Interface (ATCI), which allows the Aglets runtime to use the transport layer in a protocol-independent manner. The implementation of ATCI is responsible for sending and receiving an agent and establishing a communication between agents. The current Aglets implementation uses the Agent Transfer Protocol (ATP), which is an application-level protocol for transmission of mobile agents. ATP is modeled on the HTTP protocol, and can be used to transfer the content of an agent in an agent-system-independent manner. To enable communication between agents, ATP also supports message-passing.

When an aglet issues a request to dispatch itself to a destination, the request travels down to the Aglets runtime layer, which converts the aglet into the form of a byte array consisting of its state data and its code. If the request is successful, the aglet is terminated, and the byte array is passed to the ATP layer through the ATCI. The ATP, which is the implementation of ATCI, then constructs a bit stream that contains general information such as the agent system name and agent identifier, as well as the byte array from the Aglets runtime.

Note: The API of the transport Layer, ATCI, will be replaced with the MAF standard interface currently being proposed to Object Management Group (OMG).

Agent Transfer Protocol

ATP is a simple application-level protocol designed to transmit an agent in an agent-system-independent manner. Its request consists of a request line, header fields, and a content. The request line specifies the method of the request, while the header fields contain the parameters of the request. ATP defines the following four standard request methods:
Dispatch
The dispatch method requests a destination agent system to reconstruct an agent from the content of a request and start executing the agent. If the request is successful, the sender must terminate the agent and release any resources consumed by it.
Retract
The retract method requests a destination agent system to send the specified agent back to the sender. The receiver is responsible for reconstructing and resuming the agent. If the agnet is successfully transfered, the receiver must terminate the agent and release any resources consumed by it.
Fetch
The fetch method is similar to the GET method in HTTP; it requests a receiver to retrieve and send any identified information. (normally class files).
Message
The message method is used to pass a message to agent identified by agent-id and return a reply value in the response. Although the protocol adopts a request/reply form, it does not lay down any rules for communication scheme between agents.
Please refer to the ATP specification for more details.

Note: Aglets team is currently working on standardization of the agent transfer layer, as a part of the Mobile Agent Facility (MAF) standard proposing to OMG. If it is accepted, we may change the interface of the transport layer from ATCI to MAF and provide a new transport layer with CORBA/IIOP, as well as ATP.

Thread Usage in ATP

The ATP implementation does not require creation of a new thread to handle an incoming connection request. Instead, ATP contains a pool of threads and pulls out an available thread from it, then assigns it to handle the request. Consequently, it is possible to handle multiple requests efficiently. Since an aglet has its own threads of control, it is guaranteed that all threads used to call it belong to the aglet's thread group, and are not the same as the threads in the pool.

Proxy and Reference Architecture

T.B.D.

Class Loading and Mobility

In Aglets, a class for creating an aglet is determined dynamically at runtime; thus, the class definitions(bytecode) for the aglet need to be loaded dynamically as required. This dynamic class-loading may occur during the aglet's execution at destination hosts as well as when the aglet is created. Furthermore, in mobile agent systems, class definitions are transmitted along with an aglet's state as it moves. The following questions are therefore of interest to the aglet developer:

How a Class Loader is Chosen

In Java, the class loader that first loads a class is used to load all subsequent interfaces and classes that are used directly in the class. In Aglets, the AgletClassLoader is used by default to load aglet classes. A class loader is chosen in accordance with its codebase, which is given as an argument to AgletContext.createAglet(URL codebase, String name, Object init) primitive at the time of creation; thus, a new instance of AgletClassLoader is created for each codebase, and aglet objects that have the same codebase share the same class loader as a general rule. A codebase is an immutable attribute of an aglet, and never changes during its lifecycle. The following are examples of codebase definitions:
Directory
atp://mycomputer.com:434/AWB/Aglets/public
http://codeserver.com/~userid/aglets
file:///AWB/Aglets/public
Jar files
http://codeserver.com/home/moshima/Aglets/public/helloAglet.jar
If the null value is given as an argument to the primitive, the Aglets library looks up the class in the directories in the AGLET_PATH and locates the directory in which the class for the specified name was found.

If a class is found in the local CLASSPATH, however, the AgletClassLoader delegates the request to the system class loader and that class loader is used to load the class. All classes used directly in the class are subsequently loaded by the system class loader. Note that this occurs even when the aglet class itself is loaded, and that the aglet therefore has no class loader. If the aglet class definition is located on the CLASSPATH, the entire aglet will be loaded by the system class loader.

As a consequence, all classes to be loaded by an aglet have to be available either in the codebase or on the CLASSPATH. There is no way to load a class from a place other than the CLASSPATH and the codebase.

When an aglet is dispatched or deactivated, the codebase of the aglet is stored in the stream and used to create a new class loader for the aglet. If a class loader with the same codebase already exists in the cache, it is used as the class loader for the aglet to define the incoming classes, instead of creating a new one. All subsequent classes used directly by classes defined by this class loader are loaded by either the same class loader or the system class loader.

Class Cache and Bytecode Evolution
The AgletClassLoader has a class cache, and stores all classes that it is requested by aglets to load from its codebase. If the class requested by an aglet already exists in the cache, it is used instead of downloading a new class from the codebase; thus reduces the network load and improves the performance.

There may be cases, however, in which the bytecode of an aglet has been updated and the new class definition conflicts with an existing class cached in the class loader. When an aglet is dispatched, the Aglets runtime that receives the aglet checks whether the incoming class definitions are fully compatible with existing classes in the cache and creates a new loader if there is at least one conflicting class. Note that only classes stored in the stream are checked, while classes to be dynamically loaded later are not checked. In other words, the current runtime library does not check whether new classes are located in the codebase when an aglet is created. This will be improved when Aglets supports "Jar" format.

Class Mobility

In mobile agent systems, class definitions are transmitted along with their state as the agent moves. Aglets classifies Java classes into three categories, according to their codebases, and manages them in different ways.
A System Class
A class which is loaded from CLASSPATH; and thus, does not have a codebase.
A Codebase Class
A class that is loaded from the aglet's codebase.
Other Classes
An aglet might refer to other classes that are loaded from other codebases by other aglets. This happens when an aglet receives a message that includes as an argument an object whose class was loaded from the sender's codebase.
When an aglet is dispatched or deactivated, the bytecode of codebase classes used by it are stored in stream form during the process of ObjectSerialization, and then sent to the destination or placed in secondary storage. In contrast, the system classes are not stored in the stream. Consequently, they never get sent to the destination. In other words, Aglets assumes that all system classes used by an aglet are available at the destination as well. If any one of these classes is not available at the destination, the dispatch operation will fail with an exception. On the other hand, if a user attempts to serialize an object whose class loader is different from the aglet's class loader, it will fail with a SecurityException. This is because Aglets does not allow an aglet to load a class from two different codebases, for security reasons. When an aglet arrives or is activated, the bytecode in the stream is retrieved and then used to define the classes needed to reconstruct the aglet. If a local class has the same name as a class in the stream transmitted, the local class is chosen and used to reconstruct the aglet. If the local class is not compatible with the original class in terms of the serialization, it will also fail with an exception.

Security
When bytecode is carried out, the runtime consults the SecurityManager to determine whether an aglet is allowed to carry it out. When bytecode is carried in, it does so to determine wheter the aglet is allowed to carry the bytecode into the runtime and to define the class.
Furthermore, a request from an aglet that went out of the server to fetch a class file must also be referred to the SecurityManager. If the requested file is not allowed to be fetched, the SecurityManager refuses the request.

Resource Management

T.B.D

HTTP Tunneling via Proxy Servers

The ATP layer normally attempts to make a direct connection to hosts on the network. In almost all intranet situations, however, there is a firewall that prevents users from opening a direct socket connection to an external node. This means that an aglet cannot be dispatched or retracted through the firewall. To make it possible, the ATP layer supports a technique called HTTP tunneling that enables an ATP request to be sent outside of the firewall as a HTTP POST request and the response to be retrived as the HTTP response. In addition, the Aglets server has to be somehow capable of receiving that HTTP-wrapped ATP request. Therefore, the Aglets server can be configured so that it can receive an HTTP POST message with the content type "x-atp" and can unwrap the ATP request. If it receives an HTTP-wrapped ATP request, it sends an HTTP response in the same way.

Configuring a Sender

To send a HTTP tunneling request, you have to specify the HTTP proxy host to be used.
  1. Open the Network configuration panel by selecting:
    Options -> Network Preference
  2. Check the "Use HTTP Proxy" in the "HTTP Tunneling" panel.
  3. Type the host name and port number of the proxy server.
  4. Input the beginning string or ending string of the address for which you do not want to use a proxy.
  5. Press the OK buton

Configuring a Receiver

To receive an HTTP tunneling request, a receiver has to be configured so that it can receive an HTTP-wrapped ATP request.

  1. Open the Network configuration panel by selecting:
    Options -> Network Preference
  2. Check the "Accept HTTP tunneling Request" in the "HTTP tunneling" panel .
  3. Press the OK button.

Limitation of HTTP tunneling

Because the firewall allows only a one-way connection to the outside, the dispatched aglet cannot fetch a class on demand. Make sure that all necessary classes are stored in the stream and transferred to the destination by making references to those classes inside the object.

Furthermore, it is impossible for an aglet to dispatch itself back into the intranet through the firewall. To get back inside a firewall, an aglet has a unique primitive, called retract, which lets a client to "pull" the dispatched aglet from a remote site. In this way, you can dispatch an aglet outside the firewall and get it back into the intranet.


Security in Aglets


Security is essential to any mobile agent system because accepting a hostile agent may lead to being harmed your computer or your privacy breaked. This section gives an overview of the key security mechanisms provided in the 1.0 release.

Note: Please report any security problems you uncover to the Aglets team listed at the bottom of this page. In this 1.0 release, some security problems should be anticipated.

Environment Variables and File Protection

The Aglets library is loaded from Java classes on the CLASSPATH. The AGLET_PATH is the default lookup path for aglet creation. The AGLET_EXPORT_PATH directory contains the fetchable aglet classes. Make sure that all these directories are properly protected, i.e. that only authorized users have write access. Otherwise it would be possible to replace security-relevant Java classes of the Aglets Workbench, such as ibm.atp.agentsystem.aglets.AgletsSecurity, and thus to bypass security checks.

Only classes that are not on the CLASSPATH can be transferred and only classes which are on AGLET_EXPORT_PATH are fetchable from remote sites.

Aglets stores its security settings in $HOME/.aglets/security/{trusted|untrusted}. Again, this file must be properly protected.

Aglet Properties

The following information is associated with each aglet:

Aglet InstanceAglet Class
identity Class name
owner id code base
creation date version
trust

Aglets are identified by their code base and identity. The owner of the aglet is identified by his/her user name and e-mail address.

Trust

Aglets may have different levels of trust. In ASDK1.0, aglets are classified as either trusted or untrusted.

Aglets are considered to be trusted if their code base is local, that is, the class definition is loaded from trusted host, that is, your local hard disk. (e.g., file:/SomePath/someClass).

All other aglets are treated as untrusted. Examples of untrusted aglets are aglets that come from an external server or that are generated as instances of an aglet class located at a remote site. Note that an aglet with code base atp://localhost/SomePath/SomeClass is treated as untrusted!

A trusted aglet has the privilege of creating another trusted aglet on the same aglet server.

In general, the access control setting is specified more strictly for an untrusted aglet than for a trusted one.

Security Preferences (Policy Database)

A user can specify specific authorizations for trusted and untrusted aglets that govern read/write access to files and libraries, object instantiation, and window access and warning. These security options are defined for each aglet security category (trusted and untrusted) and are stored in the files

Note: Addition or removal of rights should only take place via utilities described below. It is highly recommended that the above security profile files should not be modified directly, for example, by using an editor.

Again, the above files have to have proper file access protection. Otherwise, one could modify the privileges of untrusted aglets to include file write access to any subdirectory. In general, aglets should never have file write access to $HOME/.aglets, $CLASSPATH, $AGLET_PATH, and $AGLET_EXPORT_PATH.

For each security category, the following resource categories are currently supported: FileSystem, Network, Property, and Others. In the following, we describe a graphical user interface for setting security options.

Setting Security Options

File Access Control

Tahiti controls the access to the local file system. For each category of aglets, a file access path specified by a list of directory path names defines the part of the file system that is accessible in either read or read/write mode.

Network Access Control

Specified <port number>s are kept in the Listen list box. Aglets server in the current aglet security category is enabled to listen to these ports. Specified <hostname:port number>s are kept in the Connect list box. Aglets server in the current aglet security category is enabled to connect to these ports.

Properties

Not implemented yet.

However, as a work-around, is is possible to control access to properties by inserting appropriate rules in the security profiles. The following table gives examples:
RuleMeaning
property.access.java.version=trueJava version number
property.access.browser=true???

Note: Inserting the rule property.access.*=true gives an aglet of that category the right to read all system properties. These include sensitive information such as:

Key Meaning
java.home Java installation directory
java.class.path Java classpath
user.name User account name
user.home User home directory
user.dir User home directory

It is highly recommended that untrusted aglets should not have access to the above properties.

Others

When the box labeled "Warning Message on Aglet Windows" for a trusted aglet is checked, a warning window appears at the bottom of the window when the aglet performs an operation, even if it was created as a trusted aglet.

When the box labeled "Enable to Open Windows" for an untrusted is checked, untrusted aglets are allowed to open windows.

Security Manager (ibm.aglets.AgletsSecurityManager)

The Aglet Security Manager is part of the security concept of the Java language. The Java Security Manager contains a number of methods that are intended to be called to check specific types of security-sensitive actions. The following table provides a list of the public methods with their intended uses:

Method Description
checkAccess Check whether a thread or thread group can modify the thread group.
checkExit Checks whether the Exit command can be executed.
checkExec Checks whether the system commands can be executed.
checkLink Checks whether dynamic libraries can be linked (used for native code).
checkRead Checks whether a file can be read from.
checkWrite Checks whether a file can be written to.
checkConnect Checks whether a network connection can be created.
checkListen Checks whether a certain network port can be listened to for connections.
checkAccept Checks whether a network connection can be accepted.
checkProperties Checks whether the System properties can be accessed.
checkTopLevelWindow Checks whether a window must have a special warning.
checkPackageAccess Checks whether a certain package can be accessed.
checkPackageDefinition Checks whether a new class can be added to a package.
checkSetFactory Check whether an Applet can set factory objects.

By default, aglets cannot perform most of the above actions, and windows opened by untrusted aglets have a warning.

The Java SecurityManager class itself is not intended to be used directly. In the AWB, it is subclassed and installed as the AgletsSecurityManager and enforces the desired security policy. The AgletsSecurityManager provides the following checks:

checkCreateAgletContext();
Checks whether the current execution can create a new agletContext.
checkAgletContextAccess(AgletContext cxt);
Checks whether the current execution can acces the agletContext.
checkAgletAccess(Aglet aglet);
Checks whether the specified aglet can be accessed.
checkCreate(URL agletURL, String name);
Checks whether the current thread is allowed to access the aglet.
checkClone(Aglet aglet);
Checks whether the current execution can clone the aglet.
checkRevert(Identity who, Aglet aglet, URL uRL);
Checks whether the aglet can be retracted by the remote host.
checkRetract(URL agletURL, AgletID aid);
Checks whether the aglet can retract the aglet.
checkReceive(Identity who, Identity manufacturer, AgletID id, URL from);
Checks whether the aglet can be received.
checkDispose(Aglet aglet);
Checks whether the current execution can dispose of the aglet.
checkDispatch(Aglet aglet, URL uRL);
Checks whether the current execution can dispatch the aglet.
checkDeactivate(Aglet aglet, long i);
Checks whether the current execution can deactivate the aglet.
checkActivate(AgletIdentifier agletIdentifier);
Checks whether the current execution can activate the aglet.
checkSubscribeMessage(String msg);
Checks whether the current execution can subscribe to multicast messages.
checkMulticastMessage(Message msg);
Checks whtether the current execution can send a multicast message to the aglet.
checkMessage(Aglet aglet, Message msg);
Checks whtether the current execution can send a message to the aglet.
checkPackageTransfer(String string);
Checks whether the current execution can transfer the object of the specified class name.

Possible Attacks

To be rechecked.

Building Applications with Aglets


The Aglets library provides developers with a set of APIs to build and configure your applications using Aglets technology. With one of these APIs, an application can have its own configured viewer, import a portion of server facilities, or create and launch an aglet without server capabilities.

Scenarios

There are several scenarios for building an application by using Aglets technology. While a server can host running aglets, a client can create and control an aglet remotely without any aglet context. Applets can be on either a server or a client, although it is impossible to dispatch an aglet to an applet.

Aglet Components Only

This typical scenario does not require any additional APIs. The application only consists solely of set of aglets built on an Aglets API. Such a configuration normally includes a stationary agent that has privileged access to local resources such as databases and file systems, and provides services for incoming aglets. The classes used to define the stationary agent can be from either local disk (CLASSPATH) or a given codebase. If it's loaded from CLASSPATH, no security limitation is enforced by the security manager, the aglet has the highest privileges, that is, it can do whatever it wants. If it is loaded from a codebase, appropriate security enforcement will be applied in accordance with its identity.

With this configuration, an incoming aglet normally gains access to services via message passing. Then, it can leave for the next server along with the result obtained in the server, or send it to the home server by remote message passing and die. Message passing is also under the control of the security manager and a receiver aglet can also deny a request.

The server can be also configured so that it allows a limited set of aglets (trusted or untrusted in current version) to access the local resources and services. In this case, for example, an aglet may open a direct connection to a database and issue a SQL request. This gives an aglet great flexibility in an using the server resources, while is also creates the risk that an aglet may misuse or abuse these resources, and eventually may cause the system to misbehave or even crash.

Customized Aglet Viewer

A viewer of an Aglets server can be configured by using the context event and listener API, and a server can define its own viewer. Such a viewer may provide a sophisticated management tool for an administrator, or a easy-to-use and application-specific interface for end users.

For example, a good administration tool would provide comprehensive ways of creating service aglets, monitoring visiting aglets, and disposing of them if necessary. Furthermore, the viewer can provide service for an incoming aglet in response to its arrival. For example, a gateway server may offer an incoming aglet the itinerary object for a further trip inside the gateway when it arrives.

On the other hand, the viewer can be customized for users or specific services. For example, a desktop-like interface may use an icon for aglets and drag anddrop operations to manipulate them for people who is familiar with PCs, while a kiosk for novice users will define a single-click, Web style interface.

Applications embedding Aglets Server Facility

This scenario is a typical way of adding the functionality of accepting and hosting aglets into a traditional application. For example, a simple groupware application may use Aglets to provide service and to use it, or to communicate with members. It would be inadequate for such applications to just use the aglet server as it is, even if the developer can implement its own viewer.

The Aglets Server API allows developers to embed and bootstrap the aglets server in their applications, and to configure the server's SecurityManager, Persistence, Viewer, and so on.

Furthermore, an application may not want to accept incoming aglets while it is creating an aglet or dispatching and retracting it to obtain a service. The Server API allows an application to run the Aglets runtime library without daemon capability for this purpose.

Client Applications

A client application has no server facility; it only has communication facilities for creating and controling an aglet remotely, or for sending a remote message. Therefore, this configuration requires fewer resources to use aglets and reduce security threats, because it does not download any bytecode, although it can still take advantage of mobile agents on the server sides.

For example, the console of a massive network management system may not have to install the server facility. The console application, which typically has a client capability, can create a monitor aglet on a machine, and let a detective aglet roam multiple machines and send information back to the console.

Server API Overview

Aglets provides developers with a set of APIs that support several kinds of server scenario.

The ContextEvent class and ContextListener interface enable you to monitor the activities of aglets and to take actions in response to these activities. The typical application of this API is "AgletViewer" which displays a list of aglets running in the server and lets you control them by disposing of them or dispatching them, for example.

The Aglets Server interface makes it possible to write an application capable of hosting, receiving, and dispatching aglets. With this interface, you can take advantage of mobile agent technology in one's application without running an independent, separate server program such as Tahiti.

com.ibm.aglet.event.ContextListener
The ContextListener interface defines a set of methods to be called when a context related event is occured. The Listener object can be set by calling the AgletContext.addContextListener(ContextListener) primitive. The contextStarted method is called when the context is started, and should define the initialization process to validate the context. The contextShutdown is called when the context is shutdown, and is supposed to perform a finalization process to invalidate the context and release the resources used by the context. Note that if you add the context listener after the context is started, or if you remove the context before the context is shutdown, these two methods will not be called.

The other methods are for notification of the activities of aglets. It is guaranteed that when an event occurs, the proxy of an aglet given as a parameter in the ContextEvent is still available via the getAgletProxies() primitive. If an aglet is being disposed of, or dispatched, however, the instance of the aglet is in the middle of an invalidating process and may have an intermediate state. Therefore only the limited operations listed below are allowed to be performed, and check methods such as isValid() and isRemote etc., may not return correct values.

package com.ibm.aglet.system;
public interface ContextListener {

    public void contextStarted(ContextEvent ev);

    public void contextShutdown(ContextEvent ev);

    public void agletCreated(ContextEvent ev);

    public void agletCloned(ContextEvent ev);

    public void agletArrived(ContextEvent ev);

    public void agletActivated(ContextEvent ev);

    public void agletReverted(ContextEvent ev);

    public void agletDisposed(ContextEvent ev);

    public void agletDispatched(ContextEvent ev);

    public void agletDeactivated(ContextEvent ev);

    public void agletStateChanged(ContextEvent ev);

    public void showDocument(ContextEvent ev);

    public void showMessage(ContextEvent ev);
}
agletStateChanged() is called when an aglet changes its state by, for example, calling Aglet.setText(String); primitive. showDocument() is called when an aglet calls the Aglet.showDocument(URL) primitive to request that the specified document be shown. It is left to the context implementor to decide whether or how to implement the showDocument method. The default implementation of Tahiti launches an external web browser, but another implementation may use an internal browser written in Java to load and display an HTML document.

com.ibm.aglet.event.ContextEvent
The ContextEvent class is an Event class, which is deliverered to listeners when the state of the context or aglets in it changes.
package com.ibm.aglet.system;

public class ContextEvent extends AgletEvent {
    public static final int CONTEXT_FIRST = 1000;
    public static final int CONTEXT_LAST  = 1012;

    public static final int STARTED        	= CONTEXT_FIRST;	// 1000
    public static final int SHUTDOWN		= CONTEXT_FIRST + 1;	// 1001
    public static final int CREATED		= CONTEXT_FIRST + 2;	// 1002
    public static final int CLONED    		= CONTEXT_FIRST + 3;	// 1003
    public static final int DISPOSED    	= CONTEXT_FIRST + 4;	// 1004
    public static final int DISPATCHED  	= CONTEXT_FIRST + 5;	// 1005
    public static final int REVERTED		= CONTEXT_FIRST + 6;	// 1006
    public static final int ARRIVED		= CONTEXT_FIRST + 7;	// 1007
    public static final int DEACTIVATED		= CONTEXT_FIRST + 8;	// 1008
    public static final int ACTIVATED		= CONTEXT_FIRST + 9;	// 1009
    public static final int STATE_CHANGED	= CONTEXT_FIRST + 10;	// 1010
    public static final int SHOW_DOCUMENT	= CONTEXT_FIRST + 12;	// 1012
    public static final int MESSAGE     	= CONTEXT_FIRST + 13;	// 1013
    public static final int NO_RESPONSE		= CONTEXT_FIRST + 14;	// 1014

    public Object arg = null;

    public AgletContext getAgletContext();
    public AgletProxy getAgletProxy();
    public String getMessage();
    public String getText();
    public URL getDocumentURL();
    public ContextEvent(int id, Object context, AgletProxy target, Object arg);
    public ContextEvent(int id, Object context, AgletProxy target);
}
ibm.atp.daemon.Daemon Class
The ibm.atp.daemon.Daemon class for receiving incoming aglets and accepting remote messages to the aglets resides in the local context. When created, it opens the server socket, listens to the ATP requests and forwards them to the AgentRequestHandler associated with the agent system type specified in the request.

The port number can be specified when a daemon object is created. This may fail if the same number is already in use or the user is not allowed to open the number. (In Unix-based systems, for example, normal users are not allowed to open ports lower than 1024) Finally, the start(String agentSystem) primitive creates the appropriate Handler object for the given agentSystem and starts the daemon.

package ibm.atp.daemon;
public Daemon() {

    public Daemon();

    public void setAccessLogStream(OutputStream out);

    public void setAccessLogFile(String filename) throws IOException;

    public void setErrorLogStream(OutputStream out);

    public void setErrorLogFile(String filename) throws IOException;

    public void setMessageLogStream(OutputStream out);

    public void setMessageLogFile(String filename) throws IOException;

    public void message(long time, String msg);

    public void error(InetAddress host, long time, String err, String reason);

    public void access(InetAddress host, long time, String requestLine,
		       int statusCode, String misc);

    public void start(String agentSystem);

    public AgentRequestHandler getRequestHandler(String agentSystem);
}
com.ibm.aglet.system.AgletRuntime Class
The com.ibm.aglet.system.AgletRuntime class provides an interface for creating and managing the context. The only instance of this class is automatically created by the runtime, and neither an application nor an aglet can create an object of this class. Instead, an application must use getAgletRuntime() primitive to obtain the reference to the runtime object.

createAgletContext(String name) primitive creates a new instance of the runtime with the given name. If there is an existing context with the same name, the primitive throws an IllegalArgumentException. These contexts created in the runtime can be obtained by either the getAgletContext(String name) or the getAgletContexts() primitive. removeAgletContext(AgletContext cxt) removes the specified context from the internal context table. A living AgletContext can be removed from the runtime table without shutdown. Such a context becomes invisible, and cannot be accessed either remotely or locally. This can be used to create a sort of "private" context into which no aglet be dispatched.

class AgletRuntime {

    AgletRuntime getAgletRuntime();

    public AgletContext createAgletContext(String name);

    public AgletContext getAgletContext(String name);

    public void removeAgletContext(AgletContext cxt);

    public AgletContext[] getAgletContexts();

}
AgletsSecurityManager Class T.B.D.

Client API

Aglets Class

The com.ibm.aglet.system.Aglets class lets an application program create and control an aglet remotely without requiring the AgletContext.
class Aglets {

    public static AgletProxy createAglet(String contextAddress,
					 URL codebase,
					 String classname,
					 Object init);

    public static AgletProxy getAgletProxy(String contextAddress, AgletID id);

    public static AgletProxy[] getAgletProxies(String contextAddress);
}
You are not required to do the bootstrapping for client applications.
    public void main(String args[]) throws Exception {
        String contextAddress = "atp://host.name:434/contextName";

        AgletProxy proxy = Aglets.createAglet(contextAddress, null,
                                              "your.Aglet", null);
        proxy.sendMessage(new Message("buy", "jewel"));

        AgletProxy proxies[] = Aglets.getAgletProxies(contextAddress);

        // dispose all aglets
        for (int i=0; i < proxies.length; i++) {
            proxies[i].dispose();
        }
    }

Bootstrapping the Server

For the Aglet runtime to be able to create AgletContexts, to accept incoming aglets and to host aglets, a bootstrapping application is required to properly initialize the system and start up the daemon. To do this, the application program must follow the steps below:
  1. Initialize the Daemon and obtain the daemon object.
  2. Initialize the Aglet runtime system and obtain the runtime object.
  3. Create a AgletContext with/without name.
  4. Create a ContextListener for the context and add the listener to it.
  5. Start the daemon object if you want to accept incoming requests.
  6. Start the context.
  7. From here on, you can make use of the Aglets facility.
The following example shows how to bootstrap the daemon and Aglets runtime.
public class MyServer {

    static public void main(String args[]) {

	//
	// Create a daemon object and initialize it with arguments
	//
	Daemon daemon = Daemon.init(args);

        //
        // Obtain a runtime object and initialize it with arguments
        //
	AgletRuntime runtime = AgletRuntime.init(args);

        //
        // Creates a named context. To dispatch to this context, you have to
        // specify a destination such as "atp://aglets.trl.ibm.com:434/test"
        //
        AgletContext cxt = runtime.createAgletContext("test");

        ContextListener listener = new ContextAdapter () {
            public void agletArrived(ContextEvent ev) {
                AgletProxy proxy = ev.getAgletProxy();
                try {
                    System.out.println("Aglet is arriving."+
                                       proxy.getAgletInfo());
                } catch (InvalidAgletException ex) {
                    ex.printStackTrace();
                }
            }
            public void agletDispatched(ContextEvent ev) {
                AgletProxy proxy = ev.getAgletProxy();
                try {
                    System.out.println("Aglet is leaving."+
                                       proxy.getAgletInfo());
                } catch (InvalidAgletException ex) {
                    ex.printStackTrace();
                }
            }
        }

        cxt.addContextListener(listener);

        //
        // Create a daemon initialized with args
        //
        daemon.start("aglets");

	//
	// Start a context
	//
        cxt.start();

        AgletProxy myAglet = cxt.createAglet(null, "MyAglet", null);

        myAglet.sendMessage(new Message("startTrip"));
    }
}

Properties in Aglets

Aglets Properties

The following table contains a list of properties typically used by the Aglets runtime library for configuration.

Property Name Description Example
aglets.class.path Specifies the default lookup path for a codebase. This is used when a null
value is given as a codebase in the AgletContext.createAglet(..) primitive.
/usr/local/AWB/Aglets/public:/myhome/public
C:\AWB\Aglets\public:D:\myaglets\public
aglets.export.path Specifies the directory containing classes that can be fetched from
a remote server. (Available for public access.)
/usr/local/AWB/Aglets/public:/myhome/public
C:\AWB\Aglets\public:D:\myaglets\public
aglets.viewer Specifies the class name that is used for the server.
The class must implement a ContextListener interface.
ibm.aglets.tahiti.Tahiti

ATP Properties

The following table contains a list of properties typically used by the ATP transport layer for configuration.

Property Name Description Example
atp.useHttpProxy Turn on and off the http proxy. true/false
atp.http.proxyHost Host firewall.ibm.com
atp.http.proxyPort Port number 8080
atp.noProxy The proxy is not used for the hosts whose addresses start with the string specified here ibm.com

Tahiti Properties

The following table contains a list of properties typically used by the Tahiti viewer for configuration.

Property Name Description Example
tahiti.browser_command openurl Specifies the command to launch the browser

Other Properties

T.B.D.

Itinerary and Patterns


T.B.D.
Copyright (C) 1997, 1998 IBM Corp. All rights reserved.
Aglets is a trademark of IBM Corp.
Java is a trademark of Sun Microsystems, Inc.