001/*
002 * #%L
003 * Netarchivesuite - common
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.common.utils;
024
025import java.io.IOException;
026import java.io.OutputStream;
027
028import org.slf4j.Logger;
029
030/**
031 * OutputStream which can be used to redirect all stdout and stderr to a logger. Usage: System.setOut(new
032 * PrintStream(new LoggingOutputStream(LoggingOutputStream.LoggingLevel.INFO, log, "StdOut: "))); System.setErr(new
033 * PrintStream(new LoggingOutputStream(LoggingOutputStream.LoggingLevel.WARN, log, "StdErr: ")));
034 */
035public class LoggingOutputStream extends OutputStream {
036
037    /** Enum representing the standard logging levels for commons logging. */
038    public static enum LoggingLevel {
039        TRACE, DEBUG, INFO, WARN, ERROR
040    }
041
042    ;
043
044    /** The level at which messages are logged. */
045    private LoggingLevel loggingLevel;
046
047    private final Logger logger;
048
049    /** A prefix by which log-messages from this class can be recognised. */
050    private String prefix;
051
052    private String lineSeparator = System.getProperty("line.separator");
053    private StringBuffer buffer = new StringBuffer();
054
055    /**
056     * Constructor for the class.
057     *
058     * @param loggingLevel The logging level at which to log messages from this instance.
059     * @param logger The logger to which messages will be logged.
060     * @param prefix A prefix by which output from this instance can be identified.
061     */
062    public LoggingOutputStream(LoggingLevel loggingLevel, Logger logger, String prefix) {
063        this.loggingLevel = loggingLevel;
064        this.logger = logger;
065        this.prefix = prefix;
066    }
067
068    // FIXME cosmically ineffective not to implemente the other write methods.
069    @Override
070    public void write(int b) throws IOException {
071        this.buffer.append((char) b);
072        String s = buffer.toString();
073        // This next line is an optimisation. Only convert the whole buffer to string
074        // if the most recent character might be the end of the line separator.
075        if ((lineSeparator.indexOf(b) != -1) && s.contains(lineSeparator)) {
076            s = prefix + "'" + s + "'";
077            switch (loggingLevel) {
078            case TRACE:
079                logger.trace(s);
080                break;
081            case DEBUG:
082                logger.debug(s);
083                break;
084            case INFO:
085                logger.info(s);
086                break;
087            case WARN:
088                logger.warn(s);
089                break;
090            case ERROR:
091                logger.error(s);
092                break;
093            }
094            buffer.setLength(0);
095        }
096    }
097}