Mobile Agents
An Introduction with Examples in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
A UML Sequence Diagram
NewAgent
state
BeforeDeparting
state
(and executes a series of operations on its "home" host)
Arrived
state
(which can happen any number of times)
ReturnedHome
state
Using a Variant of the Strategy Pattern or Command Pattern
/** * A Sandbox that an Agent can "play" in. * * Each Sandbox runs in its own thread of execution. * It runs its Agent in that thread. * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public class Sandbox implements Runnable { private Agent agent; private Thread controlThread; /** * Explicit Value Constructor * * @param agent The Agent to execute */ public Sandbox(Agent agent) { this.agent = agent; controlThread = new Thread(this); } /** * The code to execute in this Sandbox object's * thread of execution */ public void run() { agent.run(); } /** * Start this Sandbox */ public void start() { controlThread.start(); } }
import java.io.*; import java.net.*; /** * An server that creates Sandbox objects for Agent * objects * * @version 1.0 * @author Prof. David Bernstein, James Madison Univeristy */ public class SandboxServer { public static final int PORT = 9200; public static final String EXT = ".class"; /** * The entry point of the application * * @param args The command-line arguments */ public static void main(String[] args) { Agent agent; byte[] byteCodes; Class agentClass; FileOutputStream out; ObjectInputStream in; Sandbox sandbox; ServerSocket ss; Socket s; String agentName; try { ss = new ServerSocket(PORT); while (true) { s = ss.accept(); in = new ObjectInputStream(s.getInputStream()); // Read the class name agentName = (String)in.readObject(); // Read the byte codes byteCodes = (byte[])in.readObject(); // Save the class on the local file system // for tracking purposes out = new FileOutputStream(agentName+".class"); out.write(byteCodes); // Read the Agent agent = (Agent)in.readObject(); // Run the Agent in its own Sandbox sandbox = new Sandbox(agent); sandbox.start(); in.close(); s.close(); } } catch (Exception ex) { ex.printStackTrace(); } } }
import java.io.*; import java.net.*; import java.util.*; /** * A simple mobile agent * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public abstract class Agent implements Runnable, Serializable { private byte[] byteCodes; private LinkedList<String> hosts; private String home; public static final int PORT = 9200; public static final String EXT = ".class"; /** * Explicit Value Constructor * * @param home The "home" host */ public Agent(String home) { FileInputStream in; byteCodes = null; try { in = new FileInputStream(getName()+EXT); byteCodes = new byte[in.available()]; in.read(byteCodes); } catch (IOException ioe) { byteCodes = null; } this.home = home; } /** * Add a host to the top of the stack * * @param host The host */ public void addHost(String host) { hosts.addFirst(host); } /** * The code that should be executed before this * Agent leaves home */ public abstract void beforeDeparture(); /** * Get the Java byte codes for this Agent * * @return The byte codes */ public byte[] getByteCodes() { return byteCodes; } /** * Get the name of the class for this Agent * * @return The name */ public String getName() { return getClass().getName(); } /** * Move this Agent to a Sandbox * * @param host The host to go to */ public void goTo(String host) { ObjectOutputStream out; Socket s; try { s = new Socket(host, PORT); out = new ObjectOutputStream(s.getOutputStream()); out.writeObject(getName()); out.writeObject(getByteCodes()); out.writeObject(this); } catch (IOException ioe) { host = hosts.getFirst(); hosts.removeFirst(); if (host != null) goTo(host); } } /** * The code that should be executed when this * Agent arrives at a remote Sandbox */ public abstract void onArrival(); /** * The code that should be executed when this * Agent returns home */ public abstract void onReturn(); /** * The entry point for the controlling thread * of execution */ public void run() { String host; if (hosts == null) { hosts = new LinkedList<String>(); hosts.addLast(home); beforeDeparture(); } else if (hosts.size() == 0) { onReturn(); } else { onArrival(); host = hosts.getFirst(); hosts.removeFirst(); goTo(host); } // Drop out of the run method which // will terminate the thread on the old // Sandbox } }
import java.awt.*; import java.io.*; /** * A simple Agent that makes you aware * of its arrival * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public class Kilroy extends Agent { /** * Explicit Value Constructor * * @param home The "home" host */ public Kilroy(String home) { super(home); } /** * The code that should be executed before this * Agent leaves home */ public void beforeDeparture() { goTo("localhost"); } /** * The code that should be executed when this * Agent arrives at a remote Sandbox */ public void onArrival() { Frame f; f = new Frame("Kilroy"); f.setLayout(new BorderLayout()); f.add(new Label("Kilroy Was Here!", Label.CENTER)); f.setSize(400,50); f.show(); f.toFront(); try { Thread.sleep(5000); } catch (InterruptedException ie){}; f.dispose(); } /** * The code that should be executed when this * Agent returns home */ public void onReturn() { } }