001: package net.sourceforge.tracelog.listeners;
002:
003: import java.io.BufferedReader;
004: import java.io.ByteArrayInputStream;
005: import java.io.File;
006: import java.io.FileNotFoundException;
007: import java.io.InputStreamReader;
008: import java.io.RandomAccessFile;
009:
010: import org.apache.log4j.Logger;
011:
012: public class FileListener implements Runnable {
013: private static Logger log = Logger.getLogger(FileListener.class);
014: private long filePointerOffset;
015: private File logFile;
016:
017: private String logPath;
018: private LogViewerHandler logViewerHandler;
019: private long previousFileSize;
020:
021: public FileListener(LogViewerHandler logViewerHandler,
022: String logPath) {
023: this .logPath = logPath;
024: this .logViewerHandler = logViewerHandler;
025:
026: this .logFile = new File(logPath);
027: this .previousFileSize = this .logFile.length();
028: }
029:
030: /**
031: * Polls the log file size to check if new content is written to the file.
032: * If the file size has changed, then new log messages are read from the
033: * file and written in the log viewer.
034: */
035: public void run() {
036: try {
037: // the first read basically fastforward the file pointer offset to
038: // the very end of the file without displaying any old contents in
039: // the log viewer yet
040: readLogFile();
041:
042: // prepares to write incoming log contents
043: logViewerHandler.write("Listening on " + logPath + "...");
044:
045: while (!Thread.interrupted()) {
046: // need to check if the file exists because the file could be
047: // renamed during some backup process. If the file goes missing
048: // in the middle of this running application, then sleep it for
049: // 5 seconds then try it again
050: if (!logFile.exists()) {
051: Thread.sleep(5000);
052: continue;
053: }
054: // as long as the log file size changes, then we know the file
055: // content changes.
056: else if (previousFileSize != logFile.length()) {
057: previousFileSize = logFile.length();
058: byte[] buf = readLogFile();
059: writeLogMessages(buf);
060: }
061:
062: Thread.sleep(1000);
063: }
064: } catch (InterruptedException ignored) {
065: logViewerHandler.write("Stopping log... done.");
066: } catch (Exception e) {
067: log.error("Unexpected error has occured: " + logPath);
068: log.error("Error message: " + e);
069: e.printStackTrace();
070: }
071: }
072:
073: /**
074: * Reads a chunk of log messages from the log file.
075: *
076: * @return Log messages.
077: * @throws Exception
078: */
079: private byte[] readLogFile() throws Exception {
080: RandomAccessFile raf = null;
081: byte[] buf = null;
082:
083: try {
084: raf = new RandomAccessFile(logFile, "r");
085:
086: long currentFileLen = raf.length();
087:
088: // this happen when new lines are appended into the existing log
089: // file, then continue reading from the last time it was stopped
090: if (filePointerOffset < currentFileLen) {
091: buf = new byte[(int) (currentFileLen - filePointerOffset)];
092: raf.seek(filePointerOffset);
093: }
094: // this happen when the content in the log file is deleted or the
095: // log file is re-created, then read everything from the file
096: else {
097: buf = new byte[(int) currentFileLen];
098: }
099:
100: raf.read(buf);
101:
102: filePointerOffset = currentFileLen;
103: } catch (FileNotFoundException e) {
104: logViewerHandler.write("ERROR: Log file not found: "
105: + logPath);
106: logViewerHandler
107: .write("ERROR: Please make sure this log path is correct and you have enough privilege to access this log path.");
108: } catch (Exception e) {
109: log.error("Error reading log file: " + logPath);
110: log.error("Error message: " + e);
111: e.printStackTrace();
112: } finally {
113: try {
114: raf.close();
115: } catch (Exception ignored) {
116: }
117: }
118:
119: return buf;
120: }
121:
122: /**
123: * Separate out each line from the byte buffer and write each of them to the
124: * log viewer.
125: *
126: * @param buf
127: * Log messages to be written.
128: * @throws Exception
129: */
130: private void writeLogMessages(byte[] buf) throws Exception {
131: if (buf != null) {
132: BufferedReader br = null;
133:
134: try {
135: br = new BufferedReader(new InputStreamReader(
136: new ByteArrayInputStream(buf)));
137: String line = "";
138:
139: // separate out each line
140: while ((line = br.readLine()) != null) {
141: logViewerHandler.write(line);
142: }
143: } catch (Exception e) {
144: log.error("Error writing log messages: " + logPath);
145: log.error("Error message: " + e);
146: e.printStackTrace();
147: } finally {
148: try {
149: br.close();
150: } catch (Exception ignored) {
151: }
152: }
153: }
154: }
155: }
|