|
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()
{
}
}