Click here to Skip to main content
15,893,487 members
Articles / Programming Languages / Java / Java SE

Free "tail -f" Tool for all Platforms: Tail for Windows, Tail for Linux and Tail for Mac

Rate me:
Please Sign up or sign in to vote.
2.08/5 (8 votes)
19 Jul 2006CPOL3 min read 56K   1.1K   24  
MakeLogic Tail is a freeware similar to " tail -f " of Linux. It is Tail for Windows, Tail for Linux and Tail for Mac
/******************************************************************************
 
Copyright (C) 2005  MakeLogic

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


Date		: 14th December 2005
Authors		: MakeLogic

Design		: Ujjwal
Developer	: Dharma

********************************************************************************/


package com.makeLogic;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Insets;
import java.awt.Toolkit;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import javax.swing.*;
import javax.swing.text.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;

import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import com.makeLogic.utils.InternalFrameClosingHandler;

public class TailInternalFrame extends JInternalFrame implements Runnable,CaretListener
{
	//...Fileds

	JScrollPane scrollPane;

	//JTextArea textArea;
	JTextPane textPane;
	StyledDocument styledDoc;
	Style def;
	Style errorStyle;

	long counter;
	boolean edit;

	static int openFrameCount = 0;
	static final int xOffset = 30, yOffset = 30;

	//..StatusBar
	private JPanel statusBarPanel;

	private JLabel caretPosLabel;
	private JLabel fileSizeLabel;
	private JLabel fileLastModifiedDateLabel;

	private boolean stopFileDetailsThread;
	private String fileName;
	private ClassLoader cl;

	long initialLineNo;

	//...Constructors

	public TailInternalFrame(String title, String fileName)
	{

		super(title,true,true,true,true);
		this.fileName = fileName;

		//..Set the intialLine to 0
		initialLineNo = 0;

		//..Debug set the icon
		//this.setFrameIcon(new ImageIcon("images/green-ball.gif"));
		
		// Get current classloader 
		cl = this.getClass().getClassLoader();
		//this.setFrameIcon(new ImageIcon(cl.getResource("green-ball.gif")));
		
		this.getContentPane().setLayout(new BorderLayout());

		textPane = new JTextPane();
		//textPane = createTextPane();
		
		
		styledDoc = textPane.getStyledDocument();// new DefaultStyledDocument();

		//..Regulat Text Style
		Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
		Style regular = styledDoc.addStyle("regular", def);
		StyleConstants.setForeground(regular, Color.lightGray);
		StyleConstants.setBackground(regular, Color.black);
		StyleConstants.setFontFamily(regular, "Courier New");
		StyleConstants.setFontSize(regular,12);
		StyleConstants.setLineSpacing(regular, 0.25f);


		//..Keyword1 Text Style
		Style keyword1Style =  styledDoc.addStyle("keyword1Style", regular);
		StyleConstants.setForeground(keyword1Style, Color.red);
		StyleConstants.setBackground(keyword1Style, Color.black);
		StyleConstants.setFontFamily(keyword1Style, "Courier New");
		StyleConstants.setFontSize(keyword1Style,12);
		StyleConstants.setBold(keyword1Style,false);
		StyleConstants.setLineSpacing(keyword1Style, 0.25f);

		//..Keyword2 Text Style
		Style keyword2Style =  styledDoc.addStyle("keyword2Style", regular);
		StyleConstants.setForeground(keyword2Style, Color.green);
		StyleConstants.setBackground(keyword2Style, Color.black);
		StyleConstants.setFontFamily(keyword2Style, "Courier New");
		StyleConstants.setFontSize(keyword2Style,12);
		StyleConstants.setBold(keyword2Style,false);
		StyleConstants.setLineSpacing(keyword2Style, 0.25f);


		textPane.setMargin(new Insets(0,30,30,0));
		textPane.setBackground(Color.black);
		textPane.setLogicalStyle(regular);
		//textPane.setForeground(Color.white);
		

		//..Set the Caret Color to white
		textPane.setCaretColor(Color.white);
		

		textPane.addCaretListener(this);

		scrollPane = new JScrollPane(textPane);

		counter=0;
		edit = false;

		getContentPane().add(scrollPane,BorderLayout.CENTER);

		//..StatusBar
		statusBarPanel = new JPanel();
		statusBarPanel.setBorder(new EtchedBorder());
		statusBarPanel.setLayout(new BorderLayout());
		
		//..Create the JLabel objects for status bar
		fileSizeLabel = new JLabel();
		statusBarPanel.add(fileSizeLabel,BorderLayout.WEST);
		
		fileLastModifiedDateLabel = new JLabel();
		statusBarPanel.add(fileLastModifiedDateLabel,BorderLayout.CENTER);
		stopFileDetailsThread = false;

		//..Caret Position Label
		caretPosLabel = new JLabel("");
		statusBarPanel.add(caretPosLabel,BorderLayout.EAST);
        
		getContentPane().add(statusBarPanel,BorderLayout.SOUTH);
		
		addInternalFrameListener(new InternalFrameClosingHandler());

		setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
		//setSize(700,300);
		setSize(getContentPane().getSize());
		openFrameCount++;

		//..Start the file details thread ie this thread
		Thread fileDetailsThread = new Thread(this);
		fileDetailsThread.start();

	}

	

//..Set the intialLine No
	public void setInitialLineNo(long lineNo){

		this.initialLineNo = lineNo;
	}

	//...setText

	public void setText(String text)
	{

		//textArea.setText(text);

		try
		{
			styledDoc.insertString(styledDoc.getLength(), text,def);
		}
		catch (BadLocationException ble) 
		{
			System.err.println("Couldn't insert initial text into text pane.");
		}

}

//...getText

	public String getText(){
		return textPane.getText();
	}

//...getDocument

	public String getDocumentString(){
		try
		{
			return textPane.getDocument().getText(0,textPane.getDocument().getLength());
		}
		catch(Exception exp)
		{
			//..Do Nothing
			return "";
		}
	}


//..setSelected Text for search results
	
	public void setSelectedText(int selectionStart,int selectionEnd)
	{
		textPane.setSelectionStart(selectionStart);
		textPane.setSelectionEnd(selectionEnd);
	}

//..getSelectedText 

	public String getHighlightedText(){
		return textPane.getSelectedText();
	}



//...appendText

	public void append(String text)
	{

		//..Highlight the text if some keyword is found

		////System.outprintln("Document Object : " +textPane.getDocument());
		int docLengthBeforeInsert = textPane.getDocument().getLength();

		//..First of all, insert the string in regular style
		try
		{
			styledDoc.insertString(styledDoc.getLength(), text,styledDoc.getStyle("regular"));
			////System.outprintln("...KEYWORD inserted...");
		}
		catch (BadLocationException ble) 
		{
			System.err.println("Couldn't insert initial text into text pane.");
		}


		//..Verify if the text contains any of keywords set1 or set2 items
		//int keywordType = typeOfKeywords(text);


		Hashtable kwPositionsHashtable = getKeywordPositions(text);
		Vector kw1Positions = (Vector)kwPositionsHashtable.get("kwset1");
		Vector kw2Positions = (Vector)kwPositionsHashtable.get("kwset2");

		try
		{
			int size = kw1Positions.size();
			for(int i = 0; i<size; i++)
			{
				styledDoc.setCharacterAttributes( ((KeywordPosition)kw1Positions.elementAt(i)).begin + docLengthBeforeInsert,  
					((KeywordPosition)kw1Positions.elementAt(i)).end-((KeywordPosition)kw1Positions.elementAt(i)).begin,
					styledDoc.getStyle("keyword1Style"),
					false);

				//..//System.outprintln("ML.... Set KW1 Style Offset : "+ ((KeywordPosition)kw1Positions.elementAt(i)).begin + docLengthBeforeInsert + " Length : "+ ( ((KeywordPosition)kw1Positions.elementAt(i)).end-((KeywordPosition)kw1Positions.elementAt(i)).begin ));
			}

			size = kw2Positions.size();

			for(int i = 0; i<size; i++)
			{
				styledDoc.setCharacterAttributes( ((KeywordPosition)kw2Positions.elementAt(i)).begin + docLengthBeforeInsert,  
					((KeywordPosition)kw2Positions.elementAt(i)).end-((KeywordPosition)kw2Positions.elementAt(i)).begin,
					styledDoc.getStyle("keyword2Style"),
					false);

				//..//System.outprintln("ML.... Set KW2 Style Offset : "+ ((KeywordPosition)kw2Positions.elementAt(i)).begin + docLengthBeforeInsert + " Length : "+ ( ((KeywordPosition)kw2Positions.elementAt(i)).end-((KeywordPosition)kw2Positions.elementAt(i)).begin ));
			}

		}
		catch(Exception exc)
		{
			//exc.printStackTrace();
		}

		/*
		//if(text.contains("error"))
		if(text.indexOf("error") != -1 || text.indexOf("Error") != -1 )
		//if(keywordType == 0)
		{

			////System.outprintln("...KEYWORD...");

			//textArea.setBackground(Color.red);
			//textArea.append(text);
			try
			{
				styledDoc.insertString(styledDoc.getLength(), text,styledDoc.getStyle("keyword1Style"));
				////System.outprintln("...KEYWORD inserted...");
			}
			catch (BadLocationException ble) 
			{
				System.err.println("Couldn't insert initial text into text pane.");
			}

			//textArea.setBackground(tempBg);
			//textArea.setForeground(tempFg);
		}
		else
		{
			////System.outprintln("ML...NON...KEYWORD");
			//textArea.append(text);
			try
			{
				styledDoc.insertString(styledDoc.getLength(), text,styledDoc.getStyle("regular"));
				////System.outprintln("...Regular word inserted...");
			}
			catch (BadLocationException ble) 
			{
				System.err.println("Couldn't insert initial text into text pane.");
			}

		}
		*/

		//textArea.setCaretPosition(textArea.getDocument().getLength());
		textPane.setCaretPosition(textPane.getDocument().getLength());
	}


	public void setEOFReached()
	{
		stopFileDetailsThread = true;
		//this.setFrameIcon(new ImageIcon(cl.getResource("green-ball-static.gif")));

		String text = "-----------End Of File Reached - MakeLogic Tail-----------";
		try
		{
			styledDoc.insertString(styledDoc.getLength(), text,styledDoc.getStyle("eofStyle"));
			////System.outprintln("...Regular word inserted...");
		}
		catch (BadLocationException ble) 
		{
			System.err.println("Couldn't insert initial text into text pane.");
		}
	}

	//..The thread that runs and updates the file size and last modified date
	public void run()
	{
		////System.outprintln("FileName : "+fileName);
		File file = new File(fileName);
		//String fileSize = "";
		//String fileLastModifiedDate = "";
		long fileSize = 0;
		long fileLastModifiedDate = 0;

		Date date = new Date();
		String tempString="";

		try
		{

			do
			{
				fileSize = file.length();
				////System.outprintln("Length : "+fileSize);

				if(fileSize<1024)
				{
					fileSizeLabel.setText( "Size: "+fileSize +" Bytes  ");
				}
				else if( fileSize< (1024*1024))
				{
					tempString = (fileSize/1024.0)+"";
					tempString = tempString.substring(0,tempString.indexOf(".")+3);

					fileSizeLabel.setText( "Size: "+ tempString +" KB  ");
				}
				else
				{
					tempString = (fileSize/(1024.0*1024.0))+"";
					tempString = tempString.substring(0,tempString.indexOf(".")+3);

					fileSizeLabel.setText( "Size: "+ tempString +" MB  ");
				}

				fileLastModifiedDate = file.lastModified();
				////System.outprintln("Last Modified : "+fileLastModifiedDate);
				date = new Date(fileLastModifiedDate);
				fileLastModifiedDateLabel.setText(" Last Modified : "+date.toString()+"  ");

				Thread.sleep(500);

			}while(true);
			//}while(!stopFileDetailsThread);
		}
		catch(Exception exc)
		{
			//exc.printStackTrace();
		}
	}

	//..Return the TextPane
	public JTextPane getTextPane(){

		return textPane;
	}

	//..Return the Line no at caret
	public int getLineAtCaret(JTextComponent component)
	{
		int caretPosition = component.getCaretPosition();
		Element root = component.getDocument().getDefaultRootElement();
 
		return root.getElementIndex( caretPosition ) + 1;
	}
 

	//..Return the Column no at caret
	public int getColumnAtCaret(JTextComponent component)
	{
		int caretPosition = component.getCaretPosition();
		Element root = component.getDocument().getDefaultRootElement();
		int line = root.getElementIndex( caretPosition );
		int lineStart = root.getElement( line ).getStartOffset();
 
		return caretPosition - lineStart + 1;
	
	}

	//..CaretUpdate event
	public void caretUpdate(CaretEvent ce)
	{
		////System.outprintln("..ML.. Caret Update");

		caretPosLabel.setText("Ln "+(getLineAtCaret(textPane)+initialLineNo-1)+"  Col "+getColumnAtCaret(textPane));
	}

	//..return whether it contains keywords set1 or set2
	public Hashtable getKeywordPositions(String text)
	{
		//..Create a hashTable
		Hashtable hashtable = new Hashtable();
		Vector kwSet1Vector = new Vector();
		Vector kwSet2Vector = new Vector();

		Properties keySetValues = Tail.tailMDI.keySetValues;

		//..Verify for the kwset1 elements if exists, store 
		//..the begin and end points in KeywordsPosition Class and store it in vector

		int verifyUpto = keySetValues.size()+1;
		for(int i = 1 ; i < verifyUpto ; i++)
		{
			try
			{
				String tempString = keySetValues.getProperty(""+i);

				//..remove kwset[]=
				tempString = tempString.substring(tempString.indexOf("=")+1);

				//..//System.outprintln("..ML.. Property -> "+tempString);
				
				int offSet = 0;
				//..Verify if it contains kwset1= in the string, and add as key words set 1
				//if(text.indexOf(tempString) != -1 )
				while(text.indexOf(tempString,offSet) != -1 )
				{
					//..Store the offSet
					offSet = text.indexOf(tempString,offSet) + tempString.length();

					//..Verify whether it is set1 or set2
					if(keySetValues.getProperty(""+i).indexOf("kwset1") != -1 )
					{
						//..Starting pos
						int end = offSet; 
						int begin = end - tempString.length();
						
						KeywordPosition keyPos = new KeywordPosition(begin,end);

						//..Add it to the vector
						kwSet1Vector.addElement(keyPos);

						//..Debug
						//..//System.outprintln("..ML.. "+"Offset -> "+offSet+" POSITIONS BEGIN ->"+begin+" END ->"+end+"\n text->"+text);
						//..//System.outprintln("text is ->"+text.substring(begin,end));
					}
					else if(keySetValues.getProperty(""+i).indexOf("kwset2") != -1 )
					{
						//..Starting pos
						int end = offSet; 
						int begin = end - tempString.length();
						
						KeywordPosition keyPos = new KeywordPosition(begin,end);

						//..Add it to the vector
						kwSet2Vector.addElement(keyPos);

						//..Debug
						//..//System.outprintln("..ML.. "+"Offset -> "+offSet+" POSITIONS BEGIN ->"+begin+" END ->"+end+"\n text->"+text);
						//..//System.outprintln("text is ->"+text.substring(begin,end));
					}
				}

				if(tempString.trim().equals(""))
				{
					verifyUpto++;
				}
			}
			catch(Exception exp)
			{
				//..Exception thrown when the property value does not exists
				verifyUpto++;
			}
		}

		//..Store the vector into the Hashtable
		hashtable.put("kwset1",kwSet1Vector);
		hashtable.put("kwset2",kwSet2Vector);

		//..Key word doesnot exists
		return hashtable;
	}

}



//..Class to store beginning and ending points of keywords
class KeywordPosition
{
	public int begin;
	public int end;

	KeywordPosition(int begin, int end)
	{
		this.begin = begin;
		this.end = end;
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
India India
Founder of MakeLogic - A Mobile Solutions and XML Web Services Company. B-Tech engineer from India's reputed IITs.

Designed and Authored products like MicroGraphs, MakeLogic VersionManager and MakeLogic Device Broker. Pls see http://www.makelogic.com

MakeLogic is a strategic business partner of Microsoft, Sun, IBM, HP and Citrix.

Contact : madanuuk@makelogic.com OR +91 - 40 - 55322433

Comments and Discussions