/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.designer.ui.tail; /** * Created by IntelliJ IDEA. * User: mihai.panaitescu * Date: Jun 1, 2006 * Time: 4:43:28 PM */ import java.io.File; import java.io.RandomAccessFile; import java.util.HashSet; import java.util.Set; /** * A log file tailer is designed to monitor a log file and send notifications * when new lines are added to the log file. This class has a notification * strategy similar to a SAX parser: implement the LogFileTailerListener interface, * create a LogFileTailer to tail your log file, add yourself as a listener, and * start the LogFileTailer. It is your job to interpret the results, build meaningful * sets of data, etc. This tailer simply fires notifications containing new log file lines, * one at a time. */ public class LogFileTailer extends Thread { /** * How frequently to check for file changes; defaults to 5 seconds */ private long sampleInterval = 5000; /** * The log file to tail */ private File logfile; /** * Defines whether the log file tailer should include the entire contents * of the exising log file or tail from the end of the file when the tailer starts */ private boolean startAtBeginning = false; /** * Is the tailer currently tailing? */ private boolean tailing = false; /** * Set of listeners */ private Set<LogFileTailerListener> listeners = new HashSet<LogFileTailerListener>(); /** * Creates a new log file tailer that tails an existing file and checks the file for * updates every 5000ms */ public LogFileTailer(File file) { setName("NEXT : " + getClass().getSimpleName()); this.logfile = file; } /** * Creates a new log file tailer * * @param file The file to tail * @param sampleInterval How often to check for updates to the log file (default = 5000ms) * @param startAtBeginning Should the tailer simply tail or should it process the entire * file and continue tailing (true) or simply start tailing from the * end of the file */ public LogFileTailer(File file, long sampleInterval, boolean startAtBeginning) { setName("NEXT : " + getClass().getSimpleName()); this.logfile = file; this.sampleInterval = sampleInterval; this.startAtBeginning = startAtBeginning; } public void addLogFileTailerListener(LogFileTailerListener l) { this.listeners.add(l); } public void removeLogFileTailerListener(LogFileTailerListener l) { this.listeners.remove(l); } protected void fireNewLogFileLine(String line) { for (LogFileTailerListener listener : this.listeners) { listener.newLogFileLine(line); } } public void stopTailing() { this.tailing = false; } public void run() { // The file pointer keeps track of where we are in the file long filePointer = 0; // Determine start point if (this.startAtBeginning) { filePointer = 0; } else { filePointer = this.logfile.length(); } try { // Start tailing this.tailing = true; RandomAccessFile file = new RandomAccessFile(logfile, "r"); while (this.tailing) { try { // Compare the length of the file to the file pointer long fileLength = this.logfile.length(); if (fileLength < filePointer) { // Log file must have been rotated or deleted; // reopen the file and reset the file pointer file = new RandomAccessFile(logfile, "r"); filePointer = 0; } if (fileLength > filePointer) { // There is data to read file.seek(filePointer); String line = file.readLine(); while (line != null) { this.fireNewLogFileLine(line); line = file.readLine(); } filePointer = file.getFilePointer(); } // Sleep for the specified interval sleep(this.sampleInterval); } catch (Exception e) { e.printStackTrace(); } } // Close the file that we are tailing file.close(); } catch (Exception e) { e.printStackTrace(); } } }