package de.unimuenchen.informatik.mnm.masa.agentSystem.voyagerintegration;
import com.objectspace.voyager.*;
import com.objectspace.voyager.agent.*;
import com.objectspace.voyager.message.*;
import com.objectspace.lib.util.*;
import org.omg.CosNaming.*;
import java.util.*;
import CfMAF.*;
import de.unimuenchen.informatik.mnm.masa.tools.*;
import de.unimuenchen.informatik.mnm.masa.agentSystem.*;
import de.unimuenchen.informatik.mnm.masa.agent.voyagerproxyagent.*;
public class VoyagerAgentManager extends GenericAgentManager
{
/**
* CfMAF.Type of the Voyager-Agentsystem
*/
private Short VOYAGER_TYPE = new Short (System.getProperty("de.unimuenchen.informatik.mnm.masa.voyager.type","5"));
/**
* running _agentsVoyagerName
* form: (String agent_name, String //voyagerhost:port/agent_name)
*/
private Hashtable _agentsVoyagerName = new Hashtable();
/**
* proxy agents in masa
* form: (String agent_name, CfMAF.Name proxy)
*/
private Hashtable _voyagerProxy = new Hashtable();
/**
* MASA-AgnetSystem
*/
private AgentSystemService _masaAgentSystemService;
/**
* voyager naming context in masa
*/
private NamingContext _voyagerContext;
/**
* context in which VoyagerMasaGateway bound to
*/
private NamingContext _ownContext;
/**
* Constructor
*/
public VoyagerAgentManager(AgentSystemService masaAgentSystemService, NamingContext voyagerContext, NamingContext ownContext)
{
Debug.debug("VoyagerAgentManager.<init>");
// init attirbutes
this._masaAgentSystemService = masaAgentSystemService;
this._voyagerContext = voyagerContext;
this._ownContext = ownContext;
}
/**
* @see AgentManager.connectToAgent()
*/
public org.omg.CORBA.Object connectToAgent(Name agent_name)
throws AgentNotFound
{
return null; // not supported
}
/**
* @see AgentManager.getAgentSystemURL()
*/
protected String getAgentSystemURL(){
return null; // not supported
}
/**
* Creates a voyageragent and a voyagerproxyagent:
* 1. get agent arguments
* 2. get agent's classname
* 3. create proxy agent in MASA
* 4. create Voyager agent
* 5. update internal data
* If creation of Voyager agent fails then the
* already created voyagerproxyagent will be terminated
* because its easier to terminate a voyagerproxyagent
* in MASA than a Voyager agent
*
* @param agent_name Agentname
* @param agent_profile not used
* @param agent not used
* @param place_name Voyager server on which remote object will be created
* @param arguments not used
* @param class_names List of classnames to instantiate agent,
* only necessary if classname different from agentname
* @param code_base not used
* @param class_provider not used
*
*/
public synchronized Name create_agent(Name agent_name,
AgentProfile agent_profile,
byte[] agent,
String place_name,
byte[] arguments,
ClassName[] class_names,
String code_base,
MAFAgentSystem class_provider)
throws ClassUnknown, ArgumentInvalid,
DeserializationFailed, MAFExtendedException{
/**************************
* 1. get agent arguments
**************************/
java.util.Vector agentArgs= null;
if ( agent.length > 0 ) {
agentArgs= new java.util.Vector(4);
try {
java.io.ObjectInputStream input=
new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(agent));
while( true ){
agentArgs.addElement(input.readObject());
}
}
catch(java.io.EOFException eofe){
Debug.debug("VoyagerAgentManager.create_agent():Stream fully read!");
//Ok, Stream full readed
}
catch(Throwable e){
e.printStackTrace();
throw new ArgumentInvalid();
}
}
/**************************
* 2. get agent's classname
**************************/
// get classname, if classname is different
// from agent_name then it is defined
// in class_names else class_names is empty
String className;
if (class_names.length != 0)
className = class_names[0].name;
else
className = new String(agent_name.identity);
int indexPackageName= 0;
String packageName= (String)agentArgs.elementAt(indexPackageName);
if ( packageName.length() > 0 )
className= packageName + "." + className;
// build agent name,
// if already agent_name exists
// then put <n> to the end of the name (voyager) convention
Debug.debug("VoyagerAgentManager.create_agent() - build agent name");
String agentName= new String(agent_name.identity);
// check whether already exists
if(_agentsVoyagerName.containsKey(agentName)){
// have to change agent_name
int i= 1;
Debug.debug("VoyagerAgentManager.create_agent() - _agentsVoyagerName: " + _agentsVoyagerName.toString());
while(_agentsVoyagerName.containsKey(new String(agentName + "<"+i+">"))){
Debug.debug("VoyagerAgentManager.create_agent() - existing agent names: " + new String(agentName + "<"+i+">"));
i++;
}
agentName = agentName + "<"+i+">";
}
Debug.debug("VoyagerAgentManager.create_agent() - agentName: " + agentName);
/********************************
* 3. create proxy agent in MASA
********************************/
// create proxy for MASA
try{
create_voyagerproxyagent(agentName,place_name);
}catch (Exception createProxyException){
createProxyException.printStackTrace();
throw new MAFExtendedException();
}
/********************************
* 4. create Voyager agent
********************************/
try{
// start voyager client
try{
Voyager.startup();
}catch(com.objectspace.voyager.StartupException e){
Debug.debug("WARNING: " + e);
}
// create remote object in voyager
java.lang.Object obj = null;
Debug.debug("VoyagerAgentManager.create_agent() - className:" + className);
Debug.debug("VoyagerAgentManager.create_agent() - place_name:" + place_name);
obj = Factory.create(className,place_name);
// bind voyager remote object to voyager-namespace
Debug.debug("VoyagerAgentManager.create_agent() - Namespace.bind: "
+ place_name
+ "/"
+ new String(agent_name.identity));
Namespace.bind(place_name + "/" + agentName,obj);
// shutdown Voyager client
Voyager.shutdown();
} catch (Exception generalVoyagerException){
generalVoyagerException.printStackTrace();
try{
Voyager.shutdown();
}catch(Exception shutdownVoyagerException){
shutdownVoyagerException.printStackTrace();
}
// could not create voyager agent so terminate voyager proxy agent in MASA
try{
terminate_voyagerproxyagent(agentName);
} catch(CfMAF.TerminateFailed terminateException){
terminateException.printStackTrace();
}
throw new MAFExtendedException();
}
Debug.debug("VoyagerAgentManager.create_agent() - _agentsVoyagerName: " + _agentsVoyagerName.toString());
/************************
* 5. update internal data
************************/
// update agent_name
agent_name.identity = agentName.getBytes();
return agent_name;
}
/**
* @see AgentManager.get_agent_status()
*/
public AgentStatus get_agent_status(Name agent_name)
throws AgentNotFound{
return null; // not supported
}
/**
* @see AgentManager.get_authinfo()
*/
public AuthInfo get_authinfo(Name agent_name)
throws AgentNotFound{
return null; // not supported
}
/**
* Lists all voyager agents
*/
public CfMAF.Name[] list_all_agents(){
CfMAF.Name [] result = new CfMAF.Name[0];
try{
Debug.debug("VoyagerAgentManager.list_all_agents() - proxys: " + _voyagerProxy.toString());
result = new CfMAF.Name[_voyagerProxy.size()];
Enumeration agents = _voyagerProxy.keys();
Debug.debug("VoyagerAgentManager.list_all_agents() - got "
+ result.length + " keys from table");
for(int i=0; i<result.length; i++){
result[i] = new CfMAF.Name();
result[i].identity = ((String) agents.nextElement()).getBytes();
}
} catch (Exception e){
e.printStackTrace();
}
return result;
}
/**
* @see AgentManager.list_all_agents_of_authority()
*/
public CfMAF.Name[] list_all_agents_of_authority(byte [] authority){
return null; // not supported
}
/**
* @see AgentManager.receive_agent()
*/
public void receive_agent(Name agent_name,
AgentProfile agent_profile,
byte[] agent,
String place_name,
ClassName[] class_names,
String code_base,
MAFAgentSystem agent_sender)
throws ClassUnknown, ArgumentInvalid,
DeserializationFailed, MAFExtendedException{
// not supported
}
/**
* @see AgentManager.resume_agent()
*/
public void resume_agent(Name agent_name)
throws AgentNotFound, ResumeFailed, AgentIsRunning{
// not supported
}
/**
* @see AgentManager.suspend_agent()
*/
public void suspend_agent(Name agent_name)
throws AgentNotFound, SuspendFailed, AgentIsSuspended{
// not supported
}
/**
* Terminates a Voyager agent, i.e. unbins it
* from Namespace and hopes that
* Garbage Collection will delete it
*
* @param agent_name name of the Voyager agent
*/
public synchronized void terminate_agent(Name agent_name)
throws AgentNotFound, TerminateFailed{
// unbind agent in voyager
try{
try{
Voyager.startup();
}catch(com.objectspace.voyager.StartupException e){
System.out.println("WARNING: " + e);
}
Namespace.unbind((String)_agentsVoyagerName.get(new String (agent_name.identity)));
Voyager.shutdown();
} catch(Exception e){
e.printStackTrace();
Voyager.shutdown();
throw new TerminateFailed();
}
// terminate proxy agent
try{
terminate_voyagerproxyagent(new String (agent_name.identity));
}catch(Exception e){
e.printStackTrace();
throw new TerminateFailed();
}
}
/**
* @see AgentManager.terminateAgentManager()
*/
protected void terminateAgentManager()
throws TerminateFailed{
// not supported
}
/**
* @see AgentManager.setAgentSystemService()
*/
protected void setAgentSystemService(AgentSystemService ass){
// not supported
}
/**
* @see AgentManager.writeAgentToFile()
*/
public void writeAgentToFile(CfMAF.Name agentName, java.lang.String file)
throws WriteFailed{
// not supported
}
/**
* @see AgentManager.readAgentFromFile()
*/
public CfMAF.Name readAgentFromFile(java.lang.String file)
throws ReadFailed{
return null; // not supported
}
/**
* Creates ProxyVoyagerAgents for the VoyagerAgents
*
* @param agent_names Name of the created Voyager agent
* @param voyager_server Voyager server on which Voyager agent has been created
*/
public void create_voyagerproxyagent(String agent_name, String place_name) throws CfMAF.ArgumentInvalid, CfMAF.DeserializationFailed, CfMAF.MAFExtendedException,CfMAF.ClassUnknown
{
// create the parameters for the create_agent() call
java.io.ByteArrayOutputStream agentBytes = new java.io.ByteArrayOutputStream();
java.io.ObjectOutputStream outputAgent;
java.io.ObjectOutputStream constructorObject;
java.io.ByteArrayOutputStream constructorArgs;
CfMAF.ClassName [] className;
try{
outputAgent = new java.io.ObjectOutputStream(agentBytes);
outputAgent.writeObject("de.unimuenchen.informatik.mnm.masa.agent.voyagerproxyagent");
outputAgent.writeObject("MobileAgent");
outputAgent.writeObject("_tie_");
outputAgent.writeObject("Operations");
outputAgent.writeObject(new Boolean(false));
outputAgent.writeObject("");
constructorArgs = new java.io.ByteArrayOutputStream();
constructorObject = new java.io.ObjectOutputStream(constructorArgs);
// set Classname of agent
className = new CfMAF.ClassName[1];
className[0] = new CfMAF.ClassName("VoyagerProxyAgent", new byte[0]);
constructorObject.writeObject(agent_name); // write the values to constructorObject
}catch(java.io.IOException ioException){
ioException.printStackTrace();
throw new ArgumentInvalid();
}
// agents names in MASA must NOT contain "."
// change "." to "_"
StringTokenizer token = new StringTokenizer(agent_name,".");
String new_name = new String();
while(token.hasMoreElements())
{
new_name = new_name + token.nextToken() + "_";
if (!token.hasMoreElements())
new_name = new_name.substring(0,new_name.length()-1);
}
agent_name = new_name;
NameWrapper nw = new NameWrapper(agent_name);
//create the profile of the agent
CfMAF.AgentProfile ap = new CfMAF.AgentProfile();
org.omg.CORBA.Any props[] = new org.omg.CORBA.Any[1];
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.Any any = orb.create_any();
any.insert_wstring("Property");
props[0]=any;
ap.language_id=1;
ap.serialization=1;
ap.properties= props;
ap.agent_system_description= "Voyager Agent System of MNM-Team";
// create the agent
CfMAF.Name res = _masaAgentSystemService.create_agent(nw._name,
ap,
agentBytes.toByteArray(),
new String("default"),
constructorArgs.toByteArray(),
className,
"",
(CfMAF.MAFAgentSystem) _masaAgentSystemService);
try{
// get agent corba reference
org.omg.CORBA.Object agentRef = _ownContext.resolve(NameWrapper.getNameComponents(res,false));
// put agent in voyager namingcontext
_voyagerContext.bind(new NameComponent [] {new NameComponent(new String(res.identity),"")}, agentRef);
// save agent and its CfMAF name in table
_voyagerProxy.put(agent_name,res);
// save full voyager Name
// put agent and its voyager name in agent-hashtable
_agentsVoyagerName.put(agent_name,place_name + "/" + agent_name);
}catch(Exception corbaException){
corbaException.printStackTrace();
// try to terminate proxy again
try{
terminate_voyagerproxyagent(agent_name);
}catch(Exception terminateProxyException){
terminateProxyException.printStackTrace();
// can't do any thing more, user should restart VoyagerMasaGateway!
}
throw new CfMAF.MAFExtendedException();
}
}
/**
* Terminates a Voyager Agent's proxyavoyageragent in Masa
*
* @param agent_name Name of the Voyager Agent
*/
public void terminate_voyagerproxyagent(String agent_name) throws TerminateFailed{
Debug.debug("VoyagerAgentManager.terminate_voyagerproxyagent()");
try{
CfMAF.Name name = (CfMAF.Name) _voyagerProxy.remove(agent_name);
// set voyager proxy ready for termination
org.omg.CORBA.Object obj = _ownContext.resolve(NameWrapper.getNameComponents(name,false));
VoyagerProxyAgent proxyAgent = VoyagerProxyAgentHelper.narrow(obj);
proxyAgent.setReadyForTermination();
// terminate voyager proxy
_masaAgentSystemService.terminate_agent(name);
// unbind it from voyager directory in MASA
_voyagerContext.unbind(new NameComponent [] {new NameComponent(new String(name.identity),"")});
// remove voyager agent name from table
_agentsVoyagerName.remove(agent_name);
}catch(Exception generalTerminateException){
generalTerminateException.printStackTrace();
throw new TerminateFailed();
}
}
/**
* Terminates all voyager proxy agents
* in MASA at termination of voyager masa gateway
*/
public void cleanUp() throws CfMAF.TerminateFailed{
// terminate all proxy agents
Enumeration proxyAgents = _voyagerProxy.keys();
while(proxyAgents.hasMoreElements()){
terminate_voyagerproxyagent((String) proxyAgents.nextElement());
}
}
/**
* migrates a voyager agent
*
* @param agent_name Name pf the Voyager agent in MASA
* @param target Voyager server to which the agent should be migrated
* @param execute Name of the mathod which will be executed after migration
* @param args Arguments for the method
*/
public synchronized void migrate_agent(String agent_name, String target, String execute, Object [] arguments) throws MAFExtendedException{
// build agentname for voyager
String voyager_agent_name = (String) _agentsVoyagerName.get(agent_name);
try{
try{
Voyager.startup();
}catch(com.objectspace.voyager.StartupException e){
System.out.println("WARNING: " + e);
}
// get proxy
Object remObj = Namespace.lookup(voyager_agent_name);
// make agent of remote object
IAgent agent = Agent.of(remObj);
// migrate agent
if(execute.length() > 0 && arguments.length > 0){
agent.moveTo(target,execute,arguments);
}
else if (execute.length() > 0)
agent.moveTo(target,execute);
else
agent.moveTo(new String(target));
Namespace.unbind(voyager_agent_name);
try{
Namespace.bind(target + "/" + agent_name,remObj);
// update entry in agent table with new location of voyager agent
_agentsVoyagerName.put(agent_name,target + "/" + agent_name);
}catch(NamespaceException bindException){
//try to rebind to old location
Namespace.bind(voyager_agent_name,remObj);
throw new MAFExtendedException();
}
// shutdown voyager client
Voyager.shutdown();
} catch (Exception generalVoyagerException){
generalVoyagerException.printStackTrace();
Voyager.shutdown();
throw new MAFExtendedException();
}
}
/**
* Executes a method of a Voyager Agent
* @param agent_name Name of the Voyager agent
* @param method Methodname
* @param args List of Arguments for method
*/
public String execute_agent(String agent_name, String method, Object[] args)throws CfMAF.MAFExtendedException{
try{
Voyager.startup();
}catch(StartupException e){
System.out.println("WARNING: " + e);
}
try{
String voyagerName = (String) _agentsVoyagerName.get(agent_name);
if(voyagerName == null)
throw new CfMAF.MAFExtendedException();
Object ref = Namespace.lookup(voyagerName);
Debug.debug("changed");
Result result = result = Sync.invoke(ref,method,args);
Voyager.shutdown();
try{ return result.readObject().toString();}
catch(NullPointerException voidReturnException){return "void";}
}catch(Exception e){
e.printStackTrace();
throw new CfMAF.MAFExtendedException();
}
}
/**
* Returns the location of a Voyager server
*
* @param agent_name Name of the Voyager agent
*/
public String get_server(String agent_name){
String fullName = (String) _agentsVoyagerName.get(agent_name);
fullName = fullName == null ? "" : fullName.substring(0,fullName.indexOf(agent_name));
return fullName;
}
}