package __MASA_PACKAGE_thisagent;
import __MASA_PACKAGE_agentSystem__(*);
import __MASA_PACKAGE_agent__(*);
import __MASA_PACKAGE_CfMAF__(*);
import __MASA_PACKAGE__(tools.NameWrapper);
import __MASA_PACKAGE__(tools.Debug);
import __MASA_PACKAGE__(tools.GlobalConstants);
import java.io.*;
import java.util.*;
import org.omg.CosEventComm.*;
import org.omg.CosEventChannelAdmin.*;
import org.omg.CosNaming.*;
/**
* This is the class defining the ASManagementAgent.
* <br>The ASManagementAgent is a stationary agent which primary task it is to provide methods
* that allow applets to communicate with objects and CORBA services. In particular these are
* other agent systems, the CORBA Name Service and the CORBA Event Service, which are often not located
* on the same machines as the applets. The ASManagementAgent therefore acts as a proxy for these applets.
*
* @see StationaryAgent
* @author Stefan Gerber
*/
public class ASManagementAgentStationaryAgent extends StationaryAgent
implements ASManagementAgentOperations {
private org.omg.CosNaming.NamingContext agent_context; // CORBA naming context for agents
private ThreadEventListener eventlistener = null; //thread listening for CORBA events
private Vector pushConsumerVector = new Vector(0,1); //vector containing the pushConsumers that the applets register with the ASManagementAgent
private int id_incr = 0; //used to determine the IDs for the applet-pushConsumers
private Thread el_thread = null; //thread that will run the ThreadEventListener
public ASManagementAgentStationaryAgent() {
super();
//get_agent_context(); //doesn't work here, because _initContext = null at this moment
}
public void cleanUp() throws Throwable {
System.err.println("ASManagementAgentMobileAgent.cleanUp()");
el_thread.stop(); //stop the eventlistener thread
}
public void checkSerialization()
throws CouldNotMigrate {
}
/**
* Calls methods to fetch the naming contexts of agents/agent systems and starts the EventListener thread.
* <br>This method is called, when the agent is started.
*/
public void run() {
get_agent_context();
//Start the Thread that listens for CORBA events
eventlistener = new ThreadEventListener(_initContext);
el_thread = new Thread(eventlistener);
el_thread.start();
}
/**
* Fetches the naming context containing the agents of the different agent systems.
* <br>The naming context is saved into agent_context. This method is only for internal use.
*/
void get_agent_context() {
//get context of agents
try {
NameComponent comp1 = new NameComponent("Agent", "");
NameComponent name[] = {comp1};
agent_context = NamingContextHelper.narrow(_initContext.resolve(name));
} catch (Exception e) {
e.printStackTrace();
System.err.println("\nfailed :" + e.toString());
}
}
/**
* Registers a "clientīs" PushConsumer.
* <br>Clients (e.g. applets), which want to use the ASManagementAgent as CORBA event service proxy,
* call this method once to register their PushConsumers. An id number is returned to each client. This
* number is used by clients to deregister their PushConsumers with disconnect_push_consumer().
*
* @param pushConsumer PushConsumer thatīs to be registered
* @return ID number of type int
*/
public int connect_push_consumer(org.omg.CosEventComm.PushConsumer pushConsumer) {
//add the new pushConsumer and it's id to the global vector
VectorElement ve = new VectorElement(pushConsumer, id_incr);
pushConsumerVector.addElement(ve);
System.err.println("\nconnect_push_consumer: pushConsumer added");
System.err.println("connect_push_consumer: Now "+pushConsumerVector.size()+" PushConsumers registered");
return id_incr++; //return id for this new pushConsumer and increment id_incr afterwards
}
/**
* Deregisters a "clientīs" PushConsumer.
* <br>This method is invoked by clients (e.g. applets) that want to disconnect their PushConsumers from
* the ASManagementAgent. The PushConsumer with the ID number "id" is removed from the global vector
* containing all registered PushConsumers. If the client is an applet then its destroy()-method is
* a good place to invoke this method from.
*
* @param id ID of PushConsumer to be deregistered
*/
public void disconnect_push_consumer(int id) {
int size = pushConsumerVector.size(); // get size of vector
for (int i=0; i<size; i++) {
VectorElement ve = (VectorElement) pushConsumerVector.elementAt(i); //get element at index i
if (ve.id == id) {
//if id has been found remove the vector element
pushConsumerVector.removeElementAt(i);
System.err.println("\n\nASManagementAgent: pushConsumer (id="+id+") removed");
return;
}
}
System.err.println("\n\nASManagementAgent: pushConsumer to remove has not been found");
}
/**
* Returns a String[] containing a list of the names of the currently active agent systems.
* <br>This list is determined using the NamingContext object agent_context, which also
* contains the name space "global". "global" lists all agents that have been started with
* the option "exclusive". For further information consult the MASA manual.
*
* @return String[] containing the names of active agent systems
*/
public String[] identify_agentsystems() {
//get the naming context from the CORBA name service
//get_agent_context();
//get names of Agent Systems
BindingListHolder bl_holder = new BindingListHolder();
BindingIteratorHolder bi_holder = new BindingIteratorHolder();
agent_context.list(1000000, bl_holder, bi_holder);
Binding[] AS_bindings = bl_holder.value;
String as_names[] = new String[AS_bindings.length];
//copy the names separated by spaces into the String as_names
for (int i=0; i<AS_bindings.length; i++) {
as_names[i] = (String) AS_bindings[i].binding_name[AS_bindings[i].binding_name.length-1].id;
}
return as_names;
}
/**
* Returns a String array containing the parameter data types of all constructors of an agent.
* <br>agent_name, agent_package and agent_type specify the class of the agent. The method finds
* out all constructors of the agent and copies the set of parameters for each constructor into
* a String array which is then returned.
*
* @param agent_name name of the agent
* @param agent_package package containing the class of the agent
* @param agent_type type of the agent (MobileAgent or StationaryAgent)
* @return String array containing the parameter sets
*/
public String[] get_agent_parameters(String agent_name, String agent_package, String agent_type) {
String parametersets[] = new String[1]; //array to contain the parameter sets
try {
//get class of selected agent
String code_base = System.getProperty( GlobalConstants.masa_property_prefix+"agentCodeBase");
//get class of specified agent
//Class agent_class = java.rmi.server.RMIClassLoader.loadClass(new java.net.URL(code_base), agent_package + "." + agent_name + agent_type);
Class agent_class = AgentSystemClassLoader.loadClass( new java.net.URL( code_base), agent_package + "." + agent_name + agent_type);
//get constructors of the agent
java.lang.reflect.Constructor constructors[] = agent_class.getConstructors();
//get types of parameters for each constructor
int nr_of_parametersets = constructors.length;
parametersets = new String[nr_of_parametersets]; //nr_of_parametersets is always at least 1
for (int i=0; i<nr_of_parametersets; i++) {
Class parameter_types[] = constructors[i].getParameterTypes();
//create parameter set for one constructor (constructor[i])
parametersets[i] = " "; //prevent null-Strings in parametersets[], otherwise marshalling-exceptions are generated
for (int j=0; j<parameter_types.length; j++) {
parametersets[i] += parameter_types[j].getName() + " ";
}
}
} catch (Exception e1) {
if (e1 instanceof java.lang.ClassNotFoundException)
parametersets[0] = "failed";
else {
parametersets[0] = "failed";
e1.printStackTrace();
}
}
return parametersets;
}
/**
* Defines a thread that creates a PushConsumer and connects it to the CORBA event service.
* <br>The method used is the so called "Push method".
*/
class ThreadEventListener implements Runnable {
org.omg.CosNaming.NamingContext initContext = null;
ThreadEventListener(org.omg.CosNaming.NamingContext context) {
initContext = context;
}
public void run() {
try {
// get event channel
String channelName = System.getProperty( GlobalConstants.masa_property_prefix+"agent.channel", "AgentInitChannel");
org.omg.CosNaming.NameComponent ch = new org.omg.CosNaming.NameComponent(channelName,"");
org.omg.CosNaming.NameComponent[] arr_ch = new org.omg.CosNaming.NameComponent[1];
arr_ch[0] = ch;
org.omg.CosEventChannelAdmin.EventChannel eventChannel =
org.omg.CosEventChannelAdmin.EventChannelHelper.narrow(initContext.resolve(arr_ch));
#ifdef VISIBROKER30
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
// Initialize the BOA.
org.omg.CORBA.BOA boa = orb.BOA_init();
#endif
#ifdef ORBACUS311
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( new String[0], new java.util.Properties());
// Initialize the BOA.
org.omg.CORBA.BOA boa= ((com.ooc.CORBA.ORB)orb).BOA_init( new String[0], new java.util.Properties());
#endif
// create PushConsumer
PushConsumerImpl pushConsumer = new PushConsumerImpl();
#ifdef VISIBROKER30
boa.obj_is_ready(pushConsumer); //Export the newly created object
#endif
#ifdef ORBACUS311
boa.obj_is_ready(pushConsumer, null); //Export the newly created object
#endif
//get ProxyPushSupplier from the CORBA event service
org.omg.CosEventChannelAdmin.ProxyPushSupplier pushSupplier = eventChannel.for_consumers().obtain_push_supplier();
//connect the PushConsumer to the ProxyPushSupplier
pushSupplier.connect_push_consumer(pushConsumer);
//wait for events
#ifdef VISIBROKER30
boa.impl_is_ready();
#endif
#ifdef ORBACUS311
boa.impl_is_ready( null);
#endif
} catch (Exception el) {
el.printStackTrace();
}
}
}
/**
* Defines the behaviour of the ASManagementAgentīs PushConsumer.
* <br>Apart from the PushConsumers that clients can register with the ASManagementAgent, this agent
* has also its own PushConsumer. This one is connected directly to the CORBA event service using the
* "Push model". Whenever a CORBA event occurs the push() method of the PushConsumer is executed. In
* this push() method the push() methods of all the PushConsumers that clients connected to the
* ASManagementAgent are called one after another. This way the CORBA event is forwarded to the clients
* that cannot directly contact the CORBA event service.
*/
class PushConsumerImpl extends _PushConsumerImplBase {
public PushConsumerImpl()
{
System.err.println("\n\nASManagementAgent: PushConsumer erstellt");
}
public void push(org.omg.CORBA.Any any)
{
int nopc = pushConsumerVector.size(); //get the number of pushConsumers
org.omg.CosEventComm.PushConsumer tmpPushConsumer = null;
VectorElement ve = null;
for (int i=0; i<nopc; i++) {
try {
ve = (VectorElement) pushConsumerVector.elementAt(i);
System.err.println("\nASManagementAgent: executing push() for pushConsumer #"+ve.id);
tmpPushConsumer = ve.pushConsumer;
tmpPushConsumer.push(any);
} catch (Exception e) {
System.err.println("\n\nASManagementagent: push() failed!");
if(e instanceof org.omg.CORBA.COMM_FAILURE) { //no communication possible
System.err.println("\n\nASManagementAgent: removing pushConsumer #"+ve.id);
pushConsumerVector.removeElement(ve);
}
e.printStackTrace();
}
}
}
public void disconnect_push_consumer() {
try {
#ifdef VISIBROKER30
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
// Initialize the BOA.
org.omg.CORBA.BOA boa = orb.BOA_init();
#endif
#ifdef ORBACUS311
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( new String[0], new java.util.Properties());
// Initialize the BOA.
org.omg.CORBA.BOA boa= ((com.ooc.CORBA.ORB)orb).BOA_init( new String[0], new java.util.Properties());
#endif
System.err.println("\n\nDisconnecting push_consumer...\n");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* Datatype for use in pushConsumerVector.
* <br>This data type is used as a wrapper for the PushConsumers that clients connect to the
* ASManagementAgent. It contains the PushConsumer itself and the ID number that is assigned
* to it by connect_push_consumer().
*/
class VectorElement {
public org.omg.CosEventComm.PushConsumer pushConsumer = null;
public int id = 0;
//Constructor
public VectorElement(org.omg.CosEventComm.PushConsumer _pushConsumer, int _id) {
pushConsumer = _pushConsumer;
id = _id;
}
}
}