package de.unioninvestment.eai.portal.robot; import java.io.File; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.io.input.Tailer; import org.apache.commons.io.input.TailerListener; import org.apache.commons.io.input.TailerListenerAdapter; public class LogfileLibrary { private static final int MINIMUM_DELAY_TO_DETECT_CHANGES = 1000; private Map<String, List<String>> rows = new ConcurrentHashMap<String, List<String>>(); private Map<String, Tailer> tailers = new ConcurrentHashMap<String, Tailer>(); private long retryInterval = 500; public void monitorLogFile(final String filename) throws InterruptedException { TailerListener listener = new TailerListenerAdapter() { @Override public void fileNotFound() { throw new IllegalArgumentException("Logfile '" + filename + "' not found"); } @Override public void handle(String line) { addLogRow(filename, line); System.out.println(line); } @Override public void handle(Exception ex) { throw new RuntimeException("Error tailing file", ex); } }; Tailer tailer = new Tailer(new File(filename), listener, retryInterval, true, true); rows.put(filename, new LinkedList<String>()); tailers.put(filename, tailer); Thread thread = new Thread(tailer); thread.setDaemon(true); thread.start(); // this is required, because the file modification date granularity may // be too low so that immediate changes are not detected Thread.sleep(MINIMUM_DELAY_TO_DETECT_CHANGES); } private void addLogRow(final String filename, String line) { List<String> rowList = rows.get(filename); if (rowList != null) { synchronized (rowList) { rowList.add(line); } } } private boolean hasLogFileEntry(String filename, String entry) { List<String> rowList = rows.get(filename); synchronized (rowList) { for (String row : rowList) { if (row.contains(entry)) { return true; } } } return false; } private int countLogFileEntries(String filename, String entry) { List<String> rowList = rows.get(filename); int count = 0; synchronized (rowList) { for (String row : rowList) { if (row.contains(entry)) { count++; } } } return count; } public void shouldNotHaveLogFileEntry(String filename, String entry, int seconds) throws InterruptedException { boolean found = waitForLogFileEntry(filename, entry, seconds); if (found) { throw new IllegalStateException("Entry '" + entry + "' should not exist in log file '" + filename + "'"); } } public void shouldHaveLogFileEntry(String filename, String entry, int seconds) throws InterruptedException { boolean found = waitForLogFileEntry(filename, entry, seconds); if (!found) { throw new IllegalStateException("Entry '" + entry + "' not found in log file '" + filename + "'"); } } public void shouldHaveNumberOfLogFileEntries(String filename, int expectedCount, String entry) throws InterruptedException { Thread.sleep(MINIMUM_DELAY_TO_DETECT_CHANGES); int count = countLogFileEntries(filename, entry); if (count != expectedCount) { throw new IllegalStateException("Expected " + expectedCount + " entries of '" + entry + "', found " + count); } } private boolean waitForLogFileEntry(String filename, String entry, int seconds) throws InterruptedException { long start = System.currentTimeMillis(); boolean found = hasLogFileEntry(filename, entry); while (!found) { if ((System.currentTimeMillis() - start) > (seconds * 1000)) { break; } Thread.sleep(retryInterval); found = hasLogFileEntry(filename, entry); } return found; } public void stopLogFileMonitoring(String filename) { tailers.get(filename).stop(); tailers.remove(filename); rows.remove(filename); } public void setRetryInterval(long retryInterval) { this.retryInterval = retryInterval; } }