001/*
002 * (C) Copyright 2011-2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Julien Carsique
016 *
017 */
018
019package org.nuxeo.log4j;
020
021import java.io.BufferedReader;
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.InputStreamReader;
025import java.io.OutputStream;
026import java.util.List;
027import java.util.concurrent.atomic.AtomicInteger;
028
029import org.apache.commons.io.IOUtils;
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.apache.commons.logging.impl.SimpleLog;
033
034/**
035 * Helper class for logging process output
036 *
037 * @since 5.4.1
038 */
039public class ThreadedStreamGobbler extends Thread {
040    static final Log log = LogFactory.getLog(ThreadedStreamGobbler.class);
041
042    private static final String DEFAULT_PREFIX = "Nuxeo-stream-gobbler-";
043
044    private static AtomicInteger threadNumber = new AtomicInteger();
045
046    private InputStream is;
047
048    private int logLevel;
049
050    private List<String> output;
051
052    private OutputStream outputStream;
053
054    public ThreadedStreamGobbler(String prefix, InputStream is, int logLevel) {
055        this.is = is;
056        this.logLevel = logLevel;
057        this.setDaemon(true);
058        setName(prefix + threadNumber.incrementAndGet());
059    }
060
061    public ThreadedStreamGobbler(InputStream is, int logLevel) {
062        this(DEFAULT_PREFIX, is, logLevel);
063    }
064
065    /**
066     * @param inputStream InputStream to read
067     * @param output List to store output instead of logging it.
068     * @since 5.5
069     */
070    public ThreadedStreamGobbler(InputStream inputStream, List<String> output) {
071        this(inputStream, SimpleLog.LOG_LEVEL_OFF);
072        this.output = output;
073    }
074
075    /**
076     * @param inputStream InputStream to read
077     * @param output OutputStream where to write.
078     * @since 5.5
079     */
080    public ThreadedStreamGobbler(InputStream inputStream, OutputStream output) {
081        this(inputStream, SimpleLog.LOG_LEVEL_OFF);
082        this.outputStream = output;
083    }
084
085    @Override
086    public void run() {
087        BufferedReader br = new BufferedReader(new InputStreamReader(is));
088        String line;
089        final byte[] newLine = "\n".getBytes();
090
091        try {
092            while ((line = br.readLine()) != null) {
093                switch (logLevel) {
094                case SimpleLog.LOG_LEVEL_DEBUG:
095                    log.debug(line);
096                    break;
097                case SimpleLog.LOG_LEVEL_INFO:
098                    log.info(line);
099                    break;
100                case SimpleLog.LOG_LEVEL_ERROR:
101                    log.error(line);
102                    break;
103                case SimpleLog.LOG_LEVEL_OFF:
104                    if (output != null) {
105                        output.add(line);
106                    }
107                    if (outputStream != null) {
108                        outputStream.write(line.getBytes());
109                        outputStream.write(newLine);
110                    }
111                default:
112                    break;
113                }
114            }
115        } catch (IOException e) {
116            log.error(e);
117        } finally {
118            IOUtils.closeQuietly(br);
119        }
120    }
121}