Context-Aware Mobile Agents
An overview of CAMA programming concepts is given on the basis of a small agent application. The application offers a shared drawing board to two or more users. Whatever any of the users draws immediately appears on screens of all other users. The application has a simple two-thread structure. One of the threads continuously monitors for any new data from other users while the other one is getting new input from a user and sends to the coordination server.
 * This file is a test agent for jCAMA package - Java adaptation layer for the CAMA middleware. You can use
 * and redistributed it under the terms of the GPL.
 * University of Newcastle upon Tune, Newcastle upon Tune, UK
 * Distributed drawing blackboard agent

import*; import java.awt.*; import java.awt.event.*;
import java.util.Vector;

import jcama.*;

public class chatG extends Frame implements Runnable {

        private static final int UP = 0;
        private static final int DOWN = 1;

        int last_x, last_y;
    Color colour =;
        private int px, py, state;

        Scope chatGScope;
        String uname = "aaa";

        int sent_messages = 0;

    public static void main(String[] argsthrows CamaException
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(;

                try {
                    System.out.print("Cama host>");
                    String locHost = stdIn.readLine();
                    System.out.print("Your name>");
                    String name = stdIn.readLine();
                    new chatG(locHost, name);
                catch(IOException e) {
                    System.err.println("Io error");

    chatG(String host, String namethrows CamaException
        super("CAMA example - chatG");

        this.enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);;

        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {

        uname = name;
        chatGConnect(new Location(host, 1234));

        public void processMouseMotionEvent(MouseEvent me)
                if (me.getID() != MouseEvent.MOUSE_DRAGGED) {
                        state = UP;

                if (state == UP) {
                        last_x = me.getX();
                        last_y = me.getY();
                        state  = DOWN;

        Graphics g = getGraphics();
        g.drawLine(last_x, last_y, me.getX(), me.getY());

                sendGChatMessage(new objects_t(last_x, last_y, me.getX(), me.getY(), colour));

        last_x = me.getX();
        last_y = me.getY();

        private void chatGConnect(Location locthrows CamaException
            Scope lambda, ws;
            ScopeName nlist;

                // Engage the location (handshake and get engagement key)
                lambda = loc.Engage();

                // Request the list of all top-level scopes with the specified scope type
                nlist = lambda.GetScopes(new CamaKey("chatG"));

                // If there are any try to connect to the first one (just for simplicty)
                if (nlist.getLength() 0) {

                    // Create scope name, this should be changed to better syntax in future
                    ScopeName sn = new ScopeName().addSuffix(nlist.get(0));

                    // Join the scpefied scope with the role number one and role key derived from string "Chatter"
                    chatGScope = lambda.JoinScope(sn, 1new CamaKey("Chatter"));
                else // If there are no scopes create a new one

                    // Create scope description with 1 role and type CamaKey("chatG")
                    ScopeDescr descr = new ScopeDescr(1new CamaKey("chatG")).
                            // Put the restrictions on the first role and role key (CamaKey("Chatter")):
                            // 1st arg (1) - min required number of agent for this role
                            // 2nd arg (1) - max required -.-
                            // 3rd arg (10) - maximum allowed number of agents
                            add(new ScopeRoleRest(1110)new CamaKey("Chatter"));

                    // request the location to create the scope with the given literal name (to distinguish between
                    // several scopes of the same type)
                    chatGScope = lambda.CreateScope("chatGScope", descr);

                    // join the scope with role number 1 and rolekey CamaKey("Chatter") (must match the one supplied in the scope description)
                    chatGScope.JoinScope(chatGScope.scopeName(),  1new CamaKey("Chatter"));

                    // make the scope visible for other agents

                try {
                    new Thread(this).start();
                catch(Exception e) {}

        private void sendGChatMessage(objects_t obj)
                Tuple sendobj = new Tuple(3).add("chatG").add(uname).add(obj);
                Templ cleant = new Templ(3).addEql("chatG").addEql(uname).addAny(objects_t.class);

                try {

                    // if (sent_messages > 10) chatGScope.inp(cleant); - actually never clean up
                catch(CamaException e) {
                    System.out.println("Got Cama Exception in reader - " + e);

        public void run()
                Graphics g = getGraphics();
                objects_t o;
                Templ objt = new Templ(3).addEql("chatG").addNeq(uname).addAny(objects_t.class);

                try {
                    Scope scope = Location.newInstance(chatGScope);
                    while(true) {
                        o = (objects_tscope.rdn(objt).get(2).getValue();
                        g.drawLine(o.x1, o.y1, o.x2, o.y2);
                catch(CamaException e) {
                    System.out.println("Got Cama Exception in reader - " + e);


class objects_t implements Serializable {
    public int x1, y1, x2, y2;
    public Color colour;
    public objects_t(int x1, int y1, int x2, int y2, Color col) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.colour = col;