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; } }