package __MASA_PACKAGE_thisagent; //import __MASA_PACKAGE_thisagent__(*); //import __MASA_PACKAGE_agentSystem__(AgentSystem.*); import __MASA_PACKAGE_agent__(ASManagementAgent.*); import __MASA_PACKAGE_agent__(*); import __MASA_PACKAGE_agentSystem__(*); import __MASA_PACKAGE__(tools.NameWrapper); import __MASA_PACKAGE_CfMAF__(AgentStatus); import org.omg.CosNaming.*; import java.awt.*; import java.applet.*; import java.util.*; import java.awt.event.*; import com.sun.java.swing.*; import com.sun.java.swing.text.*; import com.sun.java.swing.table.*; import com.sun.java.swing.tree.*; import com.sun.java.swing.event.*; import org.omg.CosEventComm.*; import org.omg.CosEventChannelAdmin.*; /** * This is the applet of the RegionManagementAgent. * <br>Its main use is to display a split window the left half of which showing the currently active * agent systems, the right half listing the agents loaded into these agent systems. One can also * use the applet to call up the webpages/applets of the different agents and agent systems. Agents can be * tranferred from one agent system to another. * * @author Stefan Gerber */ public class RegionManagementAgentApplet extends AgentApplet { /* * CORBA reference to the agent system */ private AgentSystemService _ass; private ASManagementAgent _asm; private RegionManagementAgent _rma; private JSplitPane splitpane; private JScrollPane tree_panel; private JScrollPane leaf_panel; private DefaultMutableTreeNode root; private JTree tree; private DefaultTreeModel treemodel; private AppletTableModel myModel; private JTable agentTable; private JPopupMenu popup; private int row; //is set by the ListSelectionListener of agentTable private Vector as_names; //needed primarily for invoking CommonAppletHelpers.show_migrate_menu() private DefaultMutableTreeNode selected_node; //is set by the TreeSelectionListener of tree private JPopupMenu as_popup; private JButton updateTreeButton; private JButton updateListButton; private JPanel left_panel; private JPanel right_panel; private PushConsumerImpl pushConsumer; /** * Initialize this applet and connect to ASManagementAgent and RegionManagementAgent. * <br>Sets and displays all JFC components and calls various methods to get initial information * about the agent systems and their agents (e.g. list of active agent systems, list of agents loaded * in the currently selected agent system) * * @see ASManagementAgent */ public void init() { // Set layout to GridBag GridBagLayout gridBag = new GridBagLayout(); getContentPane().setLayout(gridBag); GridBagConstraints c_root = new GridBagConstraints(); // Connect to appropriate agent system try { org.omg.CORBA.Object obj = initCORBA("AgentSystemService"); _ass = AgentSystemServiceHelper.narrow(obj); } catch(java.net.MalformedURLException e) { System.err.println(e.toString()+"\n"); } catch(java.io.IOException ioe) { System.err.println(ioe.toString()+"\n"); } //get CORBA reference of the own agent system's ASManagementAgent try { org.omg.CORBA.Object objekt = initCORBA("ASManagementAgent"); _asm = ASManagementAgentHelper.narrow(objekt); } catch(java.net.MalformedURLException e) { System.err.println(e.toString()+"\n"); } catch(java.io.IOException ioe) { System.err.println(ioe.toString()+"\n"); } //get CORBA reference of the own RegionManagementAgent try { org.omg.CORBA.Object objekt = initCORBA("RegionManagementAgent"); _rma = RegionManagementAgentHelper.narrow(objekt); } catch(java.net.MalformedURLException e) { System.err.println(e.toString()+"\n"); } catch(java.io.IOException ioe) { System.err.println(ioe.toString()+"\n"); } // test if ASManagementAgent has been found // if not, then display warning message if (_asm == null) { JOptionPane.showMessageDialog(null, "ASManagementAgent could not be found.\nPlease load it and restart the applet."); } else { /*********************************************************** ******* Panel for the tree **************** ***********************************************************/ //Create tree of currently active agent systems create_tree(); //panel to the left which contains the tree tree_panel = new JScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); tree_panel.setBorder(BorderFactory.createTitledBorder("Agent Systems & Co")); //create Button that updates the agentsystems-tree updateTreeButton = new JButton("update manually"); updateTreeButton.setMnemonic('u'); updateTreeButton.setToolTipText("update tree of agent systems manually"); updateTreeButton.setActionCommand("button"); updateTreeButton.setBackground(new Color(12632256)); updateTreeButton.setMargin(new Insets(2,2,2,2)); updateTreeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { update_tree(); } } ); // Set layout of left_panel to GridBag GridBagLayout left_gridBag = new GridBagLayout(); GridBagConstraints panel_constraints = new GridBagConstraints(); //create the panel that will contain the agentsystems-tree and the button(s) left_panel = new JPanel(left_gridBag); /*********************************************************** ******* Panel for the agent table **************** ***********************************************************/ //Creating the table showing the agents of the selected system myModel = new AppletTableModel(); myModel.AppletTableModel(); //create a new vector agentTable = new JTable(myModel); agentTable.setSelectionMode((new DefaultListSelectionModel()).SINGLE_SELECTION); myModel.addTableModelListener(agentTable); //add PopupMenu and MouseListener to agentTable popup = create_popup(); //the global variabel row is set to the number of the row in agentTable selected by the user MouseListener ml_table = new MouseAdapter() { public void mousePressed(MouseEvent e) { String selected_cell = (String) selected_node.getUserObject(); if (!(selected_cell.equals("global")) && !(selected_cell.equals("voyager"))) { //if global or voyager are not selected if (e.isPopupTrigger()) { //right mouse button clicked row = agentTable.rowAtPoint(e.getPoint()); //get row on which Mouse is located on //check if agent is mobile String impl_agents = CommonAppletHelpers.retrieve_implemented_agents_file(_ass.getURL()); java.util.StringTokenizer agent_tokenizer = new java.util.StringTokenizer(impl_agents); String agent_type = new String(); while (agent_tokenizer.hasMoreTokens()) { if ((agent_tokenizer.nextToken()).equals((String) myModel.getValueAt(row,0))) { //if selected agent has been found in the list of implemented agents agent_type = agent_tokenizer.nextToken(); //this is the agent´s package agent_type = agent_tokenizer.nextToken(); //this is the agent´s type break; } } //then find out if selected agent is mobile if (agent_type.equals("StationaryAgent")) { //agent cannot be migrated //get menuitem "migrate" and disable it JMenuItem mi = (JMenuItem) popup.getComponentAtIndex(0); mi.setEnabled(false); } else { //get menuitem "migrate" and enable it JMenuItem mi = (JMenuItem) popup.getComponentAtIndex(0); mi.setEnabled(true); } popup.show(e.getComponent(), e.getX(), e.getY()); } //if agent is double-clicked then show its webpage/applet if (e.getClickCount() == 2) { //Double Click show_agents_webpage(); } } } }; agentTable.addMouseListener(ml_table); //create panel which contains agentTable leaf_panel = new JScrollPane(agentTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); leaf_panel.setBorder(BorderFactory.createTitledBorder("Agents in selected agent aystem")); //create Button that updates the list of agents updateListButton = new JButton("update manually"); updateListButton.setMnemonic('p'); updateListButton.setToolTipText("update list of agents in selected agent system manually"); updateListButton.setActionCommand("button"); updateListButton.setBackground(new Color(12632256)); updateListButton.setMargin(new Insets(2,2,2,2)); updateListButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { list_agent_names(); } } ); // Set layout of right_panel to GridBag GridBagLayout right_gridBag = new GridBagLayout(); //create the panel that will contain the list of agents and the button(s) right_panel = new JPanel(right_gridBag); /*********************************************************** ******* add the components to their panels **************** ***********************************************************/ panel_constraints.fill = GridBagConstraints.BOTH; panel_constraints.gridwidth = GridBagConstraints.REMAINDER; panel_constraints.gridx = 0; panel_constraints.weightx = 1; panel_constraints.weighty = 1; left_gridBag.setConstraints(tree_panel, panel_constraints); left_panel.add(tree_panel); right_gridBag.setConstraints(leaf_panel, panel_constraints); right_panel.add(leaf_panel); panel_constraints.fill = GridBagConstraints.HORIZONTAL; panel_constraints.gridwidth = GridBagConstraints.REMAINDER; panel_constraints.gridx = 0; panel_constraints.weightx = 1; panel_constraints.weighty = 0; left_gridBag.setConstraints(updateTreeButton, panel_constraints); left_panel.add(updateTreeButton); right_gridBag.setConstraints(updateListButton, panel_constraints); right_panel.add(updateListButton); //create the splitpane to contain right_panel and left_panel splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left_panel, right_panel); //splitpane.setDividerLocation(0.4); //ignored by JVM, reported Bug splitpane.setPreferredSize(new Dimension(280, 520)); //workaround splitpane.setBorder(BorderFactory.createLineBorder(new Color(255,255,255).lightGray, 5)); c_root.fill = GridBagConstraints.BOTH; c_root.gridx = 0; c_root.gridwidth = GridBagConstraints.REMAINDER; c_root.gridheight = GridBagConstraints.REMAINDER; c_root.weightx = c_root.weighty = 1.0; gridBag.setConstraints(splitpane, c_root); //add splitpane to Applet getContentPane().add(splitpane); //create pushConsumer and connect it to the ASManagementAgent //needed to react to events from CORBA event service create_pushConsumer(); } } /** * Defines what´s to be done when applet is terminated. * <br>Disconnects pushConsumer that has been registered with the ASManagementAgent */ public void destroy() { try { _asm.disconnect_push_consumer(pushConsumer.id); } catch (Exception e) { System.err.println("\n\nRegionManagementAgentApplet: Could not disconnect pushConsumer"); e.printStackTrace(); } } /** * Opens a new browser window and displays the webpage of the agent system specified by "as". * <br>The URL is achieved using the RegionManagementAgent method "get_AS_URL()", because the applet * cannot communicate with an agent system not located on the same machine. * * @param as name of the agent system */ public void show_agentsystems_webpage(String as) { try { //generate URL of selected Agent system's webserver java.net.URL url_target = new java.net.URL(_rma.get_AS_URL(as)); //Open new browser window and show agent system's webpage (titled "as") getAppletContext().showDocument(url_target, as); } catch (java.net.MalformedURLException mfe) { mfe.printStackTrace(); } } /** * Opens a new browser window and displays the webpage of the selected agent. * <br>The URL is achieved using CommonAppletHelpers.getAgentURL(). This method is called * when the user selects the appropriate menu item from the context menu of an agent. */ public void show_agents_webpage() { //get name of selected agent. "row" has been set when right mouse button was clicked on the agent String agent_identity = (String) myModel.getValueAt(row,0); try { //get the URL of the selected agent. java.net.URL agent_url = CommonAppletHelpers.getAgentURL(agent_identity, _rma.get_AS_URL((String) selected_node.getUserObject())); getAppletContext().showDocument(agent_url, agent_identity); //open another browser window and show agent's webpage } catch (Exception eaw) { eaw.printStackTrace(); } } /** * Creates and returns the popup menu for the tree of active agent systems. * <br>The menu is shown, when the user right-clicks on an agent system in the tree. * * @param as name of agent system * @return JPopupMenu for the agent system */ public JPopupMenu create_as_popup(final String as) { JPopupMenu popup = new JPopupMenu(); //define menu item that will show the selected agent system´s webpage JMenuItem mi = new JMenuItem("Show webpage"); mi.setActionCommand("show_webpage"); mi.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { show_agentsystems_webpage(as); } } ); popup.add(mi); JMenuItem mi2 = new JMenuItem("Terminate agent system"); mi2.setActionCommand("terminate_agent_system"); mi2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { try { //give the user a last chance to cancel int answer = JOptionPane.showConfirmDialog(null, "Do you really want to terminate this agent system?", "Warning!", JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.NO_OPTION) { return; } _rma.terminate_agent_system(as); } catch (Exception exc) { exc.printStackTrace(); System.err.println("\nRegionManagementAgentApplet: terminate_agent_system failed!"); } } } ); popup.add(mi2); return popup; } /** * Creates and returns the popup menu for the list of agents in the selected agent system. * <br>The menu is shown, when the user right-clicks on an agent in the table. * * @return JPopupMenu for the agents */ public JPopupMenu create_popup() { //define menu item that initiates transfer of an agent JPopupMenu popup = new JPopupMenu(); JMenuItem mi = new JMenuItem("Migrate agent"); mi.setActionCommand("migrate"); mi.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { migrate_agent(); } } ); popup.add(mi); //define menu item that will show the selected agent´s webpage JMenuItem mi2 = new JMenuItem("Show webpage"); mi2.setActionCommand("Show_Webpage"); mi2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { show_agents_webpage(); } } ); popup.add(mi2); return popup; } /** * Transfers the agent selected in agentTable to another agent system. * <br>This method is called when the user selects "Migrate Agent" from the context menu of an agent * in the agentTable. The user is first presented with a dialogue where he can select the target * agent system. After he has chosen the target the agent is transferred to it. This is done using * the RegionManagementAgent because the applet cannot communicate with an agent system not located on * the same machine. * * @see CommonAppletHelpers */ public void migrate_agent() { //get the name of the selected agent String agent_identity = (String) myModel.getValueAt(row,0); //check if RegionManagementAgent is to be migrated and warn user if(agent_identity.equals("RegionManagementAgent")) { int answer = JOptionPane.showConfirmDialog(null, "Do you really want to migrate the RegionManagementAgent?\nThis applet would no longer work correctly\nif it belongs to this agent!", "Warning!", JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.NO_OPTION) { return; } } //get target agent system. String target = CommonAppletHelpers.show_migrate_menu(this, agent_identity, as_names); //initialize agentsystemservice object String as = (String) selected_node.getUserObject(); //get name of agent system represented by the node _rma.migrate_agent(agent_identity, target, as); } /** * Sets up the tree of agent systems. * <br>This method is called only once in the init() method of this applet. It identifies all currently * active agent systems (via ASManagementAgent) and sets up the tree and its TreeModel with this * information. In addition to this it generates a TreeSelectionListener and a MouseListener for * the tree. */ public void create_tree() { //set up tree components root = new DefaultMutableTreeNode("Agent System Context"); treemodel = new DefaultTreeModel(root); tree = new JTree(treemodel); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); //add a tree selection listener //if a node is selected then the global variable "selected_node" is set to it and the list of //agents in the agent system represented by this node is generated. tree.addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { selected_node = (DefaultMutableTreeNode) (e.getPath().getLastPathComponent()); list_agent_names(); } } ); //create MouseListener for the tree MouseListener ml_tree = new MouseAdapter() { public void mousePressed(MouseEvent e) { TreePath tp = tree.getPathForLocation(e.getX(), e.getY()); tree.setSelectionPath(tp); DefaultMutableTreeNode node = (DefaultMutableTreeNode) (tp.getLastPathComponent()); String as = (String) node.getUserObject(); //get name of agent system if (!(as.equals("global")) && !(as.equals("voyager")) && !(as.equals("Agent System Context"))) { if (e.getClickCount() == 2) { //if double clicked then show the webpage for the agent system show_agentsystems_webpage(as); } if (e.isPopupTrigger()) { //if right clicked then show popup menu as_popup = create_as_popup(as); //create Popup Menu as_popup.show(e.getComponent(), e.getX(), e.getY()); } } } }; tree.addMouseListener(ml_tree); //get list of active agent systems from ASManagementAgent and add it to the tree String agentsystems[] = _asm.identify_agentsystems(); as_names = new java.util.Vector(0,1); //needed for CommonAppletHelpers.show_migrate_menu() int n_o_t = agentsystems.length; for (int i=0; i<n_o_t; i++) { as_names.addElement(agentsystems[i]); root.add(new DefaultMutableTreeNode(as_names.elementAt(i))); } //repaint the tree treemodel.reload(); } /** * Refreshes the tree showing the active agent systems. * <br>Invoked by the update-agent-system-list button. It fetches the list of active agent systems * from the ASManagementAgent (because the applet cannot communicate with the CORBA name service * directly) and recreates the tree with it. */ public void update_tree() { root = new DefaultMutableTreeNode("Agent System Context"); //create a new root //get list of active agent systems from ASManagementAgent and add it to the tree String agentsystems[] = _asm.identify_agentsystems(); as_names = new java.util.Vector(0,1); //needed for CommonAppletHelpers.show_migrate_menu() int n_o_t = agentsystems.length; for (int i=0; i<n_o_t; i++) { as_names.addElement(agentsystems[i]); root.add(new DefaultMutableTreeNode(as_names.elementAt(i))); } treemodel.setRoot(root); selected_node = (DefaultMutableTreeNode) treemodel.getChild(root, 0); //repaint the tree treemodel.reload(); } /** * Retrieves a list of agents on the selected agent system. * <br>When the user selects an agent system in the tree this method is invoked by the tree´s * TreeSelectionListener. It uses the RegionManagementAgent to get the list of agents in this agent system * (because the applet cannot communicate with the CORBA name service directly), replaces the old * information in the agentTable with it and repaints the table. */ public void list_agent_names() { myModel.AppletTableModel(); //create new data vector String agents[] = _rma.list_agent_names((String) selected_node.getUserObject()); int n_o_t = agents.length; for (int i=0; i<n_o_t; i++) { myModel.addValue(agents[i]); } getContentPane().validate(); leaf_panel.repaint(); agentTable.repaint(); } /** * Create a PushConsumer and register it with the ASManagementAgent. * <br>The pushConsumer is then provided with CORBA events and reacts appropriately */ public void create_pushConsumer() { try { // create PushConsumer pushConsumer = new PushConsumerImpl(); org.omg.CORBA.ORB orb = CommonAppletHelpers.initialize_orb_for_push_consumer(); //use the Portable Object Adapter (POA) to register the object with the ORB orb.connect(pushConsumer); //register pushConsumer with the ASManagementAgent and retrieve the ID //It is later used to disconnect the pushConsumer from the asm again pushConsumer.id = _asm.connect_push_consumer(pushConsumer); } catch (Exception el) { el.printStackTrace(); } } /** * Implements the PushConsumer that is connected to the ASManagementAgent. * <br>The applet connects an instance of this class to the ASManagementAgent on startup. The agent calls * the PushConsumer´s push() method when a CORBA event is registered and supplies the event data. The * push() method defined in this class finds out which CORBA event occurred and reacts appropriately. * * @see ASManagementAgent * @author Stefan Gerber */ class PushConsumerImpl extends _PushConsumerImplBase { String[] event_data; public int id = 0; //id of this pushConsumer, needed for disconnection from ASManagementAgent public PushConsumerImpl() { System.err.println("\n\nRegionManagementAgentApplet: PushConsumer created"); } public void push(org.omg.CORBA.Any any) { event_data = new String[5]; CosNotification.StructuredEvent se = CosNotification.StructuredEventHelper.extract(any); event_data[0] = se.header.fixed_header.event_type.domain_name; event_data[1] = se.header.fixed_header.event_type.type_name; //AgentUp/AgentDown/agentSystemUp/agentSystemDown event_data[2] = se.filterable_data[0].value.extract_string(); //agent_type event_data[3] = se.filterable_data[1].value.extract_string(); //agent_name/agent_system_ame event_data[4] = se.filterable_data[2].value.extract_string(); //event_channel_name if (event_data[1].equals("agentSystemUp")) { //new agent system was started //add the name of the agent system to the as_names vector and to the tree as_names.addElement(event_data[3]); root.add(new DefaultMutableTreeNode(as_names.lastElement())); //refresh the tree treemodel.reload(); } else if (event_data[1].equals("agentSystemDown")) { //agent system was shut down //select another node if selected_node is agentsystem to be removed DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(); if (((String) selected_node.getUserObject()).equals(event_data[3])) { new_node = (DefaultMutableTreeNode) root.getChildBefore(selected_node); if (new_node == null) { //selected_node is already first child new_node = (DefaultMutableTreeNode) root.getChildAfter(selected_node); } tree.setSelectionPath(new TreePath(new_node.getPath())); } //remove the agent system from as_names Vector as_names.removeElement(event_data[3]); //remove agent system from the tree DefaultMutableTreeNode as_node; for(int i = 0; i < root.getChildCount(); i++) { //scanning the tree for the node to remove as_node = (DefaultMutableTreeNode) root.getChildAt(i); if (((String) as_node.getUserObject()).equals(event_data[3])) { //node found root.remove(as_node); break; } } //refresh tree treemodel.reload(); } else if (event_data[1].equals("AgentUp")) { //new agent is up //if agent system currently shown in agentTable equals the agent system where the new agent //has been started up then add new agent to agentTable if (((String) selected_node.getUserObject()).equals(event_data[0])) { myModel.addValue(event_data[3]); } } else if (event_data[1].equals("AgentDown")) { //agent is down //if agent system currently shown in agentTable equals the agent system where the agent //has been terminated then remove agent from agentTable if (((String) selected_node.getUserObject()).equals(event_data[0])) { myModel.rmValue(myModel.whereis(event_data[3])); } } } public void disconnect_push_consumer() { try { // Initialize the ORB. //org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(); // Initialize the BOA. //org.omg.CORBA.BOA boa = orb.BOA_init(); System.err.println("\n\nDisconnecting push_consumer...\n"); //boa.exit_impl_ready(); } catch (Exception ex) { ex.printStackTrace(); } } } /** * TableModel managing the list of loaded agents in the selected agent system. * <br>One column is defined, which contains the names of the currently loaded agents in the * agent system selected in the tree. * * @see AbstractTableModel * @author Stefan Gerber */ class AppletTableModel extends AbstractTableModel { String[] columnNames = {"Agents"}; Vector data; public void AppletTableModel() { data = new Vector(0,1); } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.size(); } public String getColumnName (int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return (String) data.elementAt(row); } public void setValueAt(Object value, int row, int col) { data.setElementAt((String) value, row); fireTableCellUpdated(row, col); } public void addValue(String value) { data.addElement(value); fireTableRowsInserted(data.size()-1, data.size()-1); } public void rmValue(int row) { data.removeElementAt(row); fireTableRowsDeleted(row, row); } //returns the row number where agent "an" is located public int whereis(String an) { for (int i=0; i<data.size(); i++) { if (an.equals((String) data.elementAt(i))) return i; } return (-1); } } }