<commit_before>/*****************************************************************
JADE - Java Agent DEvelopment Framework is a framework to develop 
multi-agent systems in compliance with the FIPA specifications.
Copyright (C) 2000 CSELT S.p.A. 

GNU Lesser General Public License

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, 
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA  02111-1307, USA.
*****************************************************************/

package jade.tools.sniffer;


import java.io.StringReader;

import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

import jade.core.*;
import jade.core.behaviours.*;

import jade.domain.FIPAException;
import jade.domain.JADEAgentManagement.*;
import jade.domain.introspection.*;
import jade.domain.FIPAServiceCommunicator;

import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.ACLCodec;
import jade.lang.acl.StringACLCodec;

import jade.lang.sl.SL0Codec;

import jade.onto.basic.Action;

import jade.proto.FipaRequestInitiatorBehaviour;

import jade.tools.ToolAgent;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.io.*;


/**
 *  This is the <em>Sniffer</em> agent.<br>
 *  This class implements the low level part of the Sniffer, interacting with Jade
 *  environment and with the sniffer GUI.<br>
 *  At startup, the sniffer subscribes itself as an rma to be informed every time
 *  an agent is born or dead, a container is created or deleted.<br>
 *  For more information see <a href="../../../../intro.htm" target="_top">Introduction to the Sniffer</a>
 * Javadoc documentation for the file
 * @author <a href="mailto:<EMAIL>"> <NAME> </a>(Developement) 
 * @author <NAME> (Concept & Early Version)
 * @version $Date$ $Revision$
 * 
 * Modified by:
 * @author <NAME>, University of Utah
 * Added the ability to have a configuration file (snifferagentname.inf) which allows
 * you to specify agents that should be sniffed as soon as they appear.  The file
 * contains a line by line list of agent names (if there is no @ in the name, it assumes
 * the current HAP for it).  Following the agent name is an optional list of performatives
 * that the sniffer will sniff.  If the list is not present, then the sniffer will
 * display all messages.  Otherwise, only those messages that have a matching
 * performative mentioned will be displayed.  A typical file might contain:
 * da0
 * da1 inform propose 
 * sniffer0@disjunior:1099/JADE
 *
 * Note - the file is looked for in the current directory, and if not found, it scans
 * for the file at the top level directory (/snifferagentname.inf)
 *
 * One other change was made to the system - that is the performative of the message
 * is now displayed above each message.  This gives additional information to the
 * user so they can see exactly what is happening dynamically.
 *
 * More changes - <NAME> changed the display to include information about the 
 * conversation id and other ids.  He also enhanced the one click information at the
 * bottom.  <NAME> changed MainPanel, so the scrollPane has a column header, which
 * is the agent canvas list.  Now when it scrolls down, the agents stay on top.
 *
 * This functionality required changes to: Sniffer (read the file, when an agent is 
 * born - see if in the list and auto sniff, and when a message arrives - determine 
 * if it should be displayed or not); MainWindow (made the ActionProcessor local 
 * variable public so we can get a hold of the code in DoSniffAction); DoSniffAction
 * (modified so there is a new method doSniff - which takes an agent name and does
 * the actual sniffing - I broke this out from the doAction method); MMCanvas (added
 * the ability to display the performative name above the message).
 *
 * Some notes:
 * 1-if a message is one that is to be ignored, then it is dropped totally.  If you
 *   look at the sniffer dump of messages, it will not be there.  Might want to change
 *   this.
 * 2-Should develop a GUI to allow dynamically setting which messages are filtered instead
 *   of forcing them to be in the .inf file.
 * 3-Probably should allow one to turn on and off the display of the performative name.
 *   Although, it seems pretty nice to have this information and although one might
 *   consider that it clutters the display, it sure provides a lot of information with
 *   it.
 * 4-Since we can now sniff agents when they appear, you could imagine another option
 *   that would allow you to turn on a sniff all new agents flag.
 *
 */
public class Sniffer extends ToolAgent {

  public static final boolean SNIFF_ON = true;
  public static final boolean SNIFF_OFF = false;
  
  // Note - these two are parallel vectors, so we add at the same time to both.
  // Could use a better mechanism, like a vector of two element lists or something.
  private Vector preLoadedAgents; // The agents in the .inf file that we are to pre-sniff.
  private Vector preLoadedFilters; // Filtering array for the pre-sniffed agents.

  private LinkedList agentsUnderSniff = new LinkedList();


  // Sends requests to the AMS
  private class AMSClientBehaviour extends FipaRequestInitiatorBehaviour {

    private String actionName;

    public AMSClientBehaviour(String an, ACLMessage request) {
      super(Sniffer.this, request,
	    MessageTemplate.and(MessageTemplate.MatchOntology(JADEAgentManagementOntology.NAME),
				MessageTemplate.MatchLanguage(SL0Codec.NAME)
				)
	    );
      actionName = an;
    }

    protected void handleNotUnderstood(ACLMessage reply) {
      myGUI.showError("NOT-UNDERSTOOD received by RMA during " + actionName);
    }

    protected void handleRefuse(ACLMessage reply) {
      myGUI.showError("REFUSE received during " + actionName);
    }

    protected void handleAgree(ACLMessage reply) {
      // System.out.println("AGREE received");
    }

    protected void handleFailure(ACLMessage reply) {
      myGUI.showError("FAILURE received during " + actionName);
    }

    protected void handleInform(ACLMessage reply) {
      // System.out.println("INFORM received");
    }

  } // End of AMSClientBehaviour class


  private class SniffListenerBehaviour extends CyclicBehaviour {

    private MessageTemplate listenSniffTemplate;

    SniffListenerBehaviour() {
      listenSniffTemplate = MessageTemplate.MatchConversationId(getName() + "-event");<commit_msg>Fixed a wrong error message.<commit_after>/*****************************************************************
JADE - Java Agent DEvelopment Framework is a framework to develop 
multi-agent systems in compliance with the FIPA specifications.
Copyright (C) 2000 CSELT S.p.A. 

GNU Lesser General Public License

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, 
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA  02111-1307, USA.
*****************************************************************/

package jade.tools.sniffer;


import java.io.StringReader;

import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

import jade.core.*;
import jade.core.behaviours.*;

import jade.domain.FIPAException;
import jade.domain.JADEAgentManagement.*;
import jade.domain.introspection.*;
import jade.domain.FIPAServiceCommunicator;

import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.ACLCodec;
import jade.lang.acl.StringACLCodec;

import jade.lang.sl.SL0Codec;

import jade.onto.basic.Action;

import jade.proto.FipaRequestInitiatorBehaviour;

import jade.tools.ToolAgent;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.io.*;


/**
 *  This is the <em>Sniffer</em> agent.<br>
 *  This class implements the low level part of the Sniffer, interacting with Jade
 *  environment and with the sniffer GUI.<br>
 *  At startup, the sniffer subscribes itself as an rma to be informed every time
 *  an agent is born or dead, a container is created or deleted.<br>
 *  For more information see <a href="../../../../intro.htm" target="_top">Introduction to the Sniffer</a>
 * Javadoc documentation for the file
 * @author <a href="mailto:<EMAIL>"> <NAME> </a>(Developement) 
 * @author <NAME> (Concept & Early Version)
 * @version $Date$ $Revision$
 * 
 * Modified by:
 * @author <NAME>, University of Utah
 * Added the ability to have a configuration file (snifferagentname.inf) which allows
 * you to specify agents that should be sniffed as soon as they appear.  The file
 * contains a line by line list of agent names (if there is no @ in the name, it assumes
 * the current HAP for it).  Following the agent name is an optional list of performatives
 * that the sniffer will sniff.  If the list is not present, then the sniffer will
 * display all messages.  Otherwise, only those messages that have a matching
 * performative mentioned will be displayed.  A typical file might contain:
 * da0
 * da1 inform propose 
 * sn<EMAIL>:1099/JADE
 *
 * Note - the file is looked for in the current directory, and if not found, it scans
 * for the file at the top level directory (/snifferagentname.inf)
 *
 * One other change was made to the system - that is the performative of the message
 * is now displayed above each message.  This gives additional information to the
 * user so they can see exactly what is happening dynamically.
 *
 * More changes - <NAME> changed the display to include information about the 
 * conversation id and other ids.  He also enhanced the one click information at the
 * bottom.  <NAME> changed MainPanel, so the scrollPane has a column header, which
 * is the agent canvas list.  Now when it scrolls down, the agents stay on top.
 *
 * This functionality required changes to: Sniffer (read the file, when an agent is 
 * born - see if in the list and auto sniff, and when a message arrives - determine 
 * if it should be displayed or not); MainWindow (made the ActionProcessor local 
 * variable public so we can get a hold of the code in DoSniffAction); DoSniffAction
 * (modified so there is a new method doSniff - which takes an agent name and does
 * the actual sniffing - I broke this out from the doAction method); MMCanvas (added
 * the ability to display the performative name above the message).
 *
 * Some notes:
 * 1-if a message is one that is to be ignored, then it is dropped totally.  If you
 *   look at the sniffer dump of messages, it will not be there.  Might want to change
 *   this.
 * 2-Should develop a GUI to allow dynamically setting which messages are filtered instead
 *   of forcing them to be in the .inf file.
 * 3-Probably should allow one to turn on and off the display of the performative name.
 *   Although, it seems pretty nice to have this information and although one might
 *   consider that it clutters the display, it sure provides a lot of information with
 *   it.
 * 4-Since we can now sniff agents when they appear, you could imagine another option
 *   that would allow you to turn on a sniff all new agents flag.
 *
 */
public class Sniffer extends ToolAgent {

  public static final boolean SNIFF_ON = true;
  public static final boolean SNIFF_OFF = false;
  
  // Note - these two are parallel vectors, so we add at the same time to both.
  // Could use a better mechanism, like a vector of two element lists or something.
  private Vector preLoadedAgents; // The agents in the .inf file that we are to pre-sniff.
  private Vector preLoadedFilters; // Filtering array for the pre-sniffed agents.

  private LinkedList agentsUnderSniff = new LinkedList();


  // Sends requests to the AMS
  private class AMSClientBehaviour extends FipaRequestInitiatorBehaviour {

    private String actionName;

    public AMSClientBehaviour(String an, ACLMessage request) {
      super(Sniffer.this, request,
	    MessageTemplate.and(MessageTemplate.MatchOntology(JADEAgentManagementOntology.NAME),
				MessageTemplate.MatchLanguage(SL0Codec.NAME)
				)
	    );
      actionName = an;
    }

    protected void handleNotUnderstood(ACLMessage reply) {
      myGUI.showError("NOT-UNDERSTOOD received during " + actionName);
    }

    protected void handleRefuse(ACLMessage reply) {
      myGUI.showError("REFUSE received during " + actionName);
    }

    protected void handleAgree(ACLMessage reply) {
      // System.out.println("AGREE received");
    }

    protected void handleFailure(ACLMessage reply) {
      myGUI.showError("FAILURE received during " + actionName);
    }

    protected void handleInform(ACLMessage reply) {
      // System.out.println("INFORM received");
    }

  } // End of AMSClientBehaviour class


  private class SniffListenerBehaviour extends CyclicBehaviour {

    private MessageTemplate listenSniffTemplate;

    SniffListenerBehaviour() {
      listenSniffTemplate = MessageTemplate.MatchConversationId(getName() + "-event");
{'fraction_non_alphanumeric': 0.08604898828541001, 'fraction_numerical': 0.004614838480653177, 'mean_word_length': 3.9148639218422887, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '230610', 'n_tokens_mistral': 3906, 'n_tokens_neox': 3714, 'n_words': 1721}