package org.oddjob.tools; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.oddjob.OddjobConsole; import org.oddjob.logging.LogArchive; import org.oddjob.logging.LogEvent; import org.oddjob.logging.LogLevel; import org.oddjob.logging.LogListener; /** * Capturing Oddjob.CONSOLE: Because tests append to the console log to * avoid capturing test logging then the Logger class must be Loaded before * the Oddjob class is loaded. This is because Oddjob's static initialiser * replaces the default stdout with it's own console capture. If the Logger * class loads first it will be appending to original stdout, not the * new stdout. * <p> * This is most easily achieved by including a logger in the test. * * @author rob * */ public class ConsoleCapture { private int dumped; private int logged; private Log4jConsoleThresholdChanger thresholdChanger; private boolean leaveLogging; class Console implements LogListener { List<String> lines = new ArrayList<String>(); public synchronized void logEvent(LogEvent logEvent) { lines.add(logEvent.getMessage()); } } private final Console console = new Console(); private LogArchive archive; public Close captureConsole() { if (!leaveLogging) { thresholdChanger = new Log4jConsoleThresholdChanger(); } final OddjobConsole.Close oddjobConsoleClose = OddjobConsole.initialise(); final Close consoleArchiveClose = capture(OddjobConsole.console()); return new Close() { @Override public void close() { consoleArchiveClose.close(); oddjobConsoleClose.close(); if (thresholdChanger != null) { thresholdChanger.close(); thresholdChanger = null; } } }; } public Close capture(LogArchive archive) { if (this.archive != null) { throw new IllegalStateException("Already listening to " + archive); } this.archive = archive; archive.addListener(console, LogLevel.INFO, -1, 0); return new Close() { @Override public void close() { ConsoleCapture.this.close(); } }; } private void close() { if (archive != null) { archive.removeListener(console); archive = null; } } public String[] getLines() { return console.lines.toArray(new String[console.lines.size()]); } public String getAll() { StringBuilder builder = new StringBuilder(); for (String line : console.lines) { builder.append(line); } return builder.toString(); } public int size() { return console.lines.size(); } public boolean isLeaveLogging() { return leaveLogging; } public void setLeaveLogging(boolean leaveLogging) { this.leaveLogging = leaveLogging; } public void dump() { System.out.println("******************"); for (; dumped < console.lines.size(); ++dumped) { System.out.print(console.lines.get(dumped)); } System.out.println("******************"); } public void dump(Logger logger) { logger.info("******************"); for (; logged < console.lines.size(); ++logged) { logger.info(console.lines.get(logged).replaceFirst("\r?\n?$", "")); } logger.info("******************"); } public static interface Close extends AutoCloseable { public void close(); } }