
//--------------------------------------------------------------------
// Class FileMonitor extends Frame
//
// Purpose  : window monitoring all files being accessed by any clients
//--------------------------------------------------------------------

import java.io.*;
import java.util.*;
import java.awt.*;

public class FileMonitor extends Frame
{

	private static TextArea theDisplay;
	private static String theFileList;


//--------------------------------------------------------------------
// Contructor for FileMonitor (1)
//
// Input	: None
// Output   : None
// Purpose  : construct the window display monitoring all files being 
//            accessed by any clients
//--------------------------------------------------------------------
	
	FileMonitor( )
	{
		super ("File Server Monitor");
		theFileList = new String();
		theDisplay = new TextArea ();
		add ("Center", theDisplay );
		theDisplay.setEditable (false);
		theDisplay.setFont(new Font("Monospaced", Font.PLAIN, 17));
		setSize(720, 320);		
		show();
		toFront();
		theDisplay.setText(new String());
		setTitle("File Server Monitor = " + getNoOfRecords() + " logs.");
	}


//--------------------------------------------------------------------
// Synchronized Method add
//
// Input	: fileName, client
// Output   : none
// Purpose  : add the newly-accessed file to the monitor 
//--------------------------------------------------------------------

	public synchronized void add (String fileAccess, String client)
	{
		theFileList = theFileList + fileAccess + "\t: " + client + "\n";
		theDisplay.setText(theFileList);
		setTitle("File Server Monitor = " + getNoOfRecords() + " logs.");
		return;
	}


//--------------------------------------------------------------------
// Synchronized Method remove
//
// Input	: fileName, client
// Output   : none
// Purpose  : remove the file that no longer being accessed; correspond
//            to the event when client close the file editor windows.
//--------------------------------------------------------------------

	public synchronized void remove (String fileName, String client)
	{
		String access = fileName + "\t: " + client + "\n";
		int begin = 1, end;
		int pos = 0;
		if ((pos = theFileList.indexOf(access)) == -1)
		{
			System.err.println("FileMonitor : Try to remove and invalid acces.");
			return;
		}

		// locate the file accessed list in the monitor
		while ((end = theFileList.indexOf("\n", begin)) != -1)
		{
			if (end > pos) break;
			begin = end + 1;
		}

		if ((begin == 1) && (end+1 >= theFileList.length()))
		{
			theFileList = new String();
		} 
		else if (begin == 1)
		{
			theFileList = theFileList.substring(end + 1);
		}
		else
		{
			theFileList = theFileList.substring(0, begin) 
				+ theFileList.substring(end + 1);
		}

		theDisplay.setText(theFileList);
		setTitle("File Server Monitor = " + getNoOfRecords() + " logs.");
		return;
	}


//--------------------------------------------------------------------
// Synchronized Method remove
//
// Input	: client
// Output   : none
// Purpose  : remove all files being accessed by specific client;
//	          correspond to the event when client close the socket
//            connection.
//--------------------------------------------------------------------

	public synchronized void remove (String client)
	{
		int begin = 0, end;
		int pos = 0;
		while ((pos = theFileList.indexOf(client, begin + 1)) != -1)
		{
			begin = theFileList.lastIndexOf("\n", pos);
			end = theFileList.indexOf("\n", pos);

			if (begin <= 0)
			{
				theFileList = theFileList.substring(end + 1);
			}
			else
			{
				theFileList = theFileList.substring(0, begin + 1) 
					+ theFileList.substring(end + 1);
			}
		}
		theDisplay.setText(theFileList);
		setTitle("File Server Monitor = " + getNoOfRecords() + " logs.");
		return;
	}


//--------------------------------------------------------------------
// Synchronized Method isBeingRead
//
// Input	: fileName
// Output   : flag true if file is being read
// Purpose  : query file status in file monitor
//--------------------------------------------------------------------

	public synchronized boolean isBeingRead (String fileName)
	{
		return ((theFileList.indexOf("read " + fileName) != -1) ||
			    (theFileList.indexOf("cat " + fileName) != -1));
	}


//--------------------------------------------------------------------
// Synchronized Method isBeingWritten
//
// Input	: fileName
// Output   : flag true if file is being written
// Purpose  : query file status in file monitor
//--------------------------------------------------------------------

	public synchronized boolean isBeingWritten (String fileName)
	{
		return ((theFileList.indexOf("write " + fileName) != -1) ||
			    (theFileList.indexOf("cat > " + fileName) != -1));
	}

//--------------------------------------------------------------------
// Synchronized Method isBeingAccesed
//
// Input	: fileName
// Output   : flag true if file is being accessed (read or written)
// Purpose  : query file status in file monitor
//--------------------------------------------------------------------

	public synchronized boolean isBeingAccessed (String fileName)
	{
		return (theFileList.indexOf(fileName) != -1);
	}


//--------------------------------------------------------------------
// Method getNoOfRecords
//
// Input	: None
// Output   : noOfRecords
// Purpose  : to get current records in fileMonitor
//--------------------------------------------------------------------

	public int getNoOfRecords ()
	{
		String content = getContent();
		int begin = 0, noOfRecords = 0;
		while (true)
		{
			begin = content.indexOf("\n", begin + 1);
			if (begin == -1) break;
			++noOfRecords;
		}

		return noOfRecords;
	}


//--------------------------------------------------------------------
// Method getContent
//
// Input	: None
// Output   : file monitor content
// Purpose  : to get file monitor Content
//--------------------------------------------------------------------

	public String getContent ()
	{
		return theDisplay.getText();
	}


//--------------------------------------------------------------------
// Method reset
//
// Input	: None
// Output   : None
// Purpose  : to clear (reset) the file monitor
//--------------------------------------------------------------------

	public void reset ()
	{
		theFileList = new String();
		theDisplay.setText(new String());
		setTitle("File Server Monitor = " + getNoOfRecords() + " logs.");
		return;
	}

}

//--------------------------------------------------------------------
// End Class FileMonitor
//--------------------------------------------------------------------
